Merge branch 'rc/2015-07-14' into release

Conflicts:
	cms/djangoapps/contentstore/views/tests/test_import_export.py
	lms/djangoapps/commerce/urls.py
	lms/templates/courseware/progress.html
This commit is contained in:
Max Rothman
2015-07-17 16:29:55 -04:00
243 changed files with 8469 additions and 5395 deletions

View File

@@ -225,4 +225,5 @@ Alessandro Verdura <finalmente2@tin.it>
Sven Marnach <sven@marnach.net>
Richard Moch <richard.moch@gmail.com>
Albert Liang <albertliangcode@gmail.com>
Pa Luo <pan.luo@ubc.ca>
Tyler Nickerson <nickersoft@gmail.com>

View File

@@ -2,12 +2,3 @@ source 'https://rubygems.org'
gem 'sass', '3.3.5'
gem 'bourbon', '~> 4.0.2'
gem 'neat', '~> 1.6.0'
gem 'colorize', '~> 0.5.8'
gem 'launchy', '~> 2.1.2'
gem 'sys-proctable', '~> 0.9.3'
gem 'dalli', '~> 2.6.4'
# These gems aren't actually required; they are used by Linux and Mac to
# detect when files change. If these gems are not installed, the system
# will fall back to polling files.
gem 'rb-inotify', '~> 0.9'
gem 'rb-fsevent', '~> 0.9.3'

View File

@@ -1,23 +1,13 @@
GEM
remote: https://rubygems.org/
specs:
addressable (2.3.5)
bourbon (4.0.2)
sass (~> 3.3)
thor
colorize (0.5.8)
dalli (2.6.4)
ffi (1.9.0)
launchy (2.1.2)
addressable (~> 2.3)
neat (1.6.0)
bourbon (>= 3.1)
sass (>= 3.3)
rb-fsevent (0.9.3)
rb-inotify (0.9.2)
ffi (>= 0.5.0)
sass (3.3.5)
sys-proctable (0.9.3)
thor (0.19.1)
PLATFORMS
@@ -25,11 +15,5 @@ PLATFORMS
DEPENDENCIES
bourbon (~> 4.0.2)
colorize (~> 0.5.8)
dalli (~> 2.6.4)
launchy (~> 2.1.2)
neat (~> 1.6.0)
rb-fsevent (~> 0.9.3)
rb-inotify (~> 0.9)
sass (= 3.3.5)
sys-proctable (~> 0.9.3)

View File

@@ -35,7 +35,7 @@ The Open edX Portal
See the `Open edX Portal`_ to learn more about Open edX. You can find
information about the edX roadmap, as well as about hosting, extending, and
contributing to Open edX. In addition, the Open edX Portal provides product
announcements, the Open edX blog, and other rich community resources.
announcements, the Open edX blog, and other rich community resources.
To comment on blog posts or the edX roadmap, you must create an account and log
in. If you do not have an account, follow these steps.
@@ -55,9 +55,16 @@ Documentation is managed in the `edx-documentation`_ repository. Documentation
is built using `Sphinx`_: you can `view the built documentation on
ReadTheDocs`_.
You can also check out `Confluence`_, our wiki system. Once you sign up for
an account, you'll be able to create new pages and edit existing pages, just
like in any other wiki system. You only need one account for both Confluence
and `JIRA`_, our issue tracker.
.. _Sphinx: http://sphinx-doc.org/
.. _view the built documentation on ReadTheDocs: http://docs.edx.org/
.. _edx-documentation: https://github.com/edx/edx-documentation
.. _Confluence: http://openedx.atlassian.net/wiki/
.. _JIRA: https://openedx.atlassian.net/
Getting Help

View File

@@ -59,12 +59,12 @@ def click_new_component_button(step, component_button_css):
def _click_advanced():
css = 'ul.problem-type-tabs a[href="#tab3"]'
css = 'ul.problem-type-tabs a[href="#tab2"]'
world.css_click(css)
# Wait for the advanced tab items to be displayed
tab3_css = 'div.ui-tabs-panel#tab3'
world.wait_for_visible(tab3_css)
tab2_css = 'div.ui-tabs-panel#tab2'
world.wait_for_visible(tab2_css)
def _find_matching_link(category, component_type):

View File

@@ -7,6 +7,7 @@ Sample invocation: ./manage.py export_convert_format mycourse.tar.gz ~/newformat
import os
from path import path
from django.core.management.base import BaseCommand, CommandError
from django.conf import settings
from tempfile import mkdtemp
import tarfile
@@ -32,8 +33,8 @@ class Command(BaseCommand):
output_path = args[1]
# Create temp directories to extract the source and create the target archive.
temp_source_dir = mkdtemp()
temp_target_dir = mkdtemp()
temp_source_dir = mkdtemp(dir=settings.DATA_DIR)
temp_target_dir = mkdtemp(dir=settings.DATA_DIR)
try:
extract_source(source_archive, temp_source_dir)

View File

@@ -3,6 +3,7 @@ Test for export_convert_format.
"""
from unittest import TestCase
from django.core.management import call_command, CommandError
from django.conf import settings
from tempfile import mkdtemp
import shutil
from path import path
@@ -18,7 +19,7 @@ class ConvertExportFormat(TestCase):
""" Common setup. """
super(ConvertExportFormat, self).setUp()
self.temp_dir = mkdtemp()
self.temp_dir = mkdtemp(dir=settings.DATA_DIR)
self.addCleanup(shutil.rmtree, self.temp_dir)
self.data_dir = path(__file__).realpath().parent / 'data'
self.version0 = self.data_dir / "Version0_drafts.tar.gz"
@@ -52,8 +53,8 @@ class ConvertExportFormat(TestCase):
"""
Helper function for determining if 2 archives are equal.
"""
temp_dir_1 = mkdtemp()
temp_dir_2 = mkdtemp()
temp_dir_1 = mkdtemp(dir=settings.DATA_DIR)
temp_dir_2 = mkdtemp(dir=settings.DATA_DIR)
try:
extract_source(file1, temp_dir_1)
extract_source(file2, temp_dir_2)

View File

@@ -52,6 +52,7 @@ class CourseDetailsTestCase(CourseTestCase):
self.assertIsNone(details.intro_video, "intro_video somehow initialized" + str(details.intro_video))
self.assertIsNone(details.effort, "effort somehow initialized" + str(details.effort))
self.assertIsNone(details.language, "language somehow initialized" + str(details.language))
self.assertIsNone(details.has_cert_config)
def test_encoder(self):
details = CourseDetails.fetch(self.course.id)
@@ -1008,6 +1009,41 @@ class CourseMetadataEditingTest(CourseTestCase):
tab_list.append(self.notes_tab)
self.assertEqual(tab_list, course.tabs)
@override_settings(FEATURES={'CERTIFICATES_HTML_VIEW': True})
def test_web_view_certifcate_configuration_settings(self):
"""
Test that has_cert_config is updated based on cert_html_view_enabled setting.
"""
test_model = CourseMetadata.update_from_json(
self.course,
{
"cert_html_view_enabled": {"value": "true"}
},
user=self.user
)
self.assertIn('cert_html_view_enabled', test_model)
url = get_url(self.course.id)
response = self.client.get_json(url)
course_detail_json = json.loads(response.content)
self.assertFalse(course_detail_json['has_cert_config'])
# Now add a certificate configuration
certificates = [
{
'id': 1,
'name': 'Certificate Config Name',
'course_title': 'Title override',
'org_logo_path': '/c4x/test/CSS101/asset/org_logo.png',
'signatories': [],
'is_active': True
}
]
self.course.certificates = {'certificates': certificates}
modulestore().update_item(self.course, self.user.id)
response = self.client.get_json(url)
course_detail_json = json.loads(response.content)
self.assertTrue(course_detail_json['has_cert_config'])
class CourseGraderUpdatesTest(CourseTestCase):
"""

View File

@@ -1,25 +1,25 @@
""" Tests for utils. """
import collections
import copy
import mock
from datetime import datetime, timedelta
from pytz import UTC
import mock
import ddt
from pytz import UTC
from django.test import TestCase
from django.test.utils import override_settings
from contentstore import utils
from contentstore.tests.utils import CourseTestCase
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from xmodule.modulestore.django import modulestore
from contentstore import utils
from contentstore.tests.utils import CourseTestCase
class LMSLinksTestCase(TestCase):
""" Tests for LMS links. """
def about_page_test(self):
""" Get URL for about page, no marketing site """
# default for ENABLE_MKTG_SITE is False.
@@ -109,6 +109,7 @@ class ExtraPanelTabTestCase(TestCase):
return course
@ddt.ddt
class CourseImageTestCase(ModuleStoreTestCase):
"""Tests for course image URLs."""
@@ -146,6 +147,16 @@ class CourseImageTestCase(ModuleStoreTestCase):
utils.course_image_url(course)
)
@ddt.data(ModuleStoreEnum.Type.split, ModuleStoreEnum.Type.mongo)
def test_empty_image_name(self, default_store):
""" Verify that empty image names are cleaned """
course_image = u''
course = CourseFactory.create(course_image=course_image, default_store=default_store)
self.assertEquals(
course_image,
utils.course_image_url(course),
)
class XBlockVisibilityTestCase(ModuleStoreTestCase):
"""Tests for xblock visibility for students."""
@@ -386,6 +397,7 @@ class GroupVisibilityTest(CourseTestCase):
"""
Test content group access rules.
"""
def setUp(self):
super(GroupVisibilityTest, self).setUp()

View File

@@ -4,12 +4,12 @@ Common utility functions useful throughout the contentstore
# pylint: disable=no-member
import logging
from opaque_keys import InvalidKeyError
import re
from datetime import datetime
from pytz import UTC
from django.conf import settings
from django.utils.translation import ugettext as _
from django.core.urlresolvers import reverse
from django_comment_common.models import assign_default_role
from django_comment_common.utils import seed_permissions_roles
@@ -160,7 +160,10 @@ def get_lms_link_for_certificate_web_view(user_id, course_key, mode):
def course_image_url(course):
"""Returns the image url for the course."""
loc = StaticContent.compute_location(course.location.course_key, course.course_image)
try:
loc = StaticContent.compute_location(course.location.course_key, course.course_image)
except InvalidKeyError:
return ''
path = StaticContent.serialize_asset_key_with_slash(loc)
return path
@@ -310,3 +313,22 @@ def reverse_usage_url(handler_name, usage_key, kwargs=None):
Creates the URL for handlers that use usage_keys as URL parameters.
"""
return reverse_url(handler_name, 'usage_key_string', usage_key, kwargs)
def has_active_web_certificate(course):
"""
Returns True if given course has active web certificate configuration.
If given course has no active web certificate configuration returns False.
Returns None If `CERTIFICATES_HTML_VIEW` is not enabled of course has not enabled
`cert_html_view_enabled` settings.
"""
cert_config = None
if settings.FEATURES.get('CERTIFICATES_HTML_VIEW', False) and course.cert_html_view_enabled:
cert_config = False
certificates = getattr(course, 'certificates', {})
configurations = certificates.get('certificates', [])
for config in configurations:
if config.get('is_active'):
cert_config = True
break
return cert_config

View File

@@ -33,7 +33,7 @@ from django.views.decorators.http import require_http_methods
from contentstore.utils import reverse_course_url
from edxmako.shortcuts import render_to_response
from opaque_keys.edx.keys import CourseKey, AssetKey
from student.auth import has_studio_read_access
from student.auth import has_studio_write_access
from util.db import generate_int_id, MYSQL_MAX_INT
from util.json_request import JsonResponse
from xmodule.modulestore import EdxJSONEncoder
@@ -53,7 +53,7 @@ def _get_course_and_check_access(course_key, user, depth=0):
Internal method used to calculate and return the locator and
course module for the view functions in this file.
"""
if not has_studio_read_access(user, course_key):
if not has_studio_write_access(user, course_key):
raise PermissionDenied()
course_module = modulestore().get_course(course_key, depth=depth)
return course_module

View File

@@ -227,7 +227,7 @@ def get_component_templates(courselike, library=False):
"""
Returns the applicable component templates that can be used by the specified course or library.
"""
def create_template_dict(name, cat, boilerplate_name=None, tab="common"):
def create_template_dict(name, cat, boilerplate_name=None, tab="common", hinted=False):
"""
Creates a component template dict.
@@ -235,13 +235,15 @@ def get_component_templates(courselike, library=False):
display_name: the user-visible name of the component
category: the type of component (problem, html, etc.)
boilerplate_name: name of boilerplate for filling in default values. May be None.
tab: common(default)/advanced/hint, which tab it goes in
hinted: True if hinted problem else False
tab: common(default)/advanced, which tab it goes in
"""
return {
"display_name": name,
"category": cat,
"boilerplate_name": boilerplate_name,
"hinted": hinted,
"tab": tab
}
@@ -277,20 +279,20 @@ def get_component_templates(courselike, library=False):
for template in component_class.templates():
filter_templates = getattr(component_class, 'filter_templates', None)
if not filter_templates or filter_templates(template, courselike):
# Tab can be 'common' 'advanced' 'hint'
# Tab can be 'common' 'advanced'
# Default setting is common/advanced depending on the presence of markdown
tab = 'common'
if template['metadata'].get('markdown') is None:
tab = 'advanced'
# Then the problem can override that with a tab: attribute (note: not nested in metadata)
tab = template.get('tab', tab)
hinted = template.get('hinted', False)
templates_for_category.append(
create_template_dict(
_(template['metadata'].get('display_name')), # pylint: disable=translation-of-non-string
category,
template.get('template_id'),
tab
tab,
hinted,
)
)

View File

@@ -5,6 +5,7 @@ Group Configuration Tests.
"""
import json
import mock
import ddt
from django.conf import settings
from django.test.utils import override_settings
@@ -19,6 +20,7 @@ from xmodule.contentstore.django import contentstore
from xmodule.contentstore.content import StaticContent
from xmodule.exceptions import NotFoundError
from student.models import CourseEnrollment
from student.tests.factories import UserFactory
from contentstore.views.certificates import CertificateManager
from django.test.utils import override_settings
from contentstore.utils import get_lms_link_for_certificate_web_view
@@ -230,6 +232,19 @@ class CertificatesListHandlerTestCase(CourseTestCase, CertificatesBaseTestCase,
self._remove_ids(content) # pylint: disable=unused-variable
self.assertEqual(content, expected)
def test_cannot_create_certificate_if_user_has_no_write_permissions(self):
"""
Tests user without write permissions on course should not able to create certificate
"""
user = UserFactory()
self.client.login(username=user.username, password='test')
response = self.client.ajax_post(
self._url(),
data=CERTIFICATE_JSON
)
self.assertEqual(response.status_code, 403)
@override_settings(LMS_BASE=None)
def test_no_lms_base_for_certificate_web_view_link(self):
test_link = get_lms_link_for_certificate_web_view(
@@ -330,6 +345,7 @@ class CertificatesListHandlerTestCase(CourseTestCase, CertificatesBaseTestCase,
self.assertNotEqual(new_certificate.get('id'), prev_certificate.get('id'))
@ddt.ddt
@override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED)
class CertificatesDetailHandlerTestCase(CourseTestCase, CertificatesBaseTestCase, HelperMethods):
"""
@@ -433,6 +449,21 @@ class CertificatesDetailHandlerTestCase(CourseTestCase, CertificatesBaseTestCase
self.assertEqual(certificates[0].get('name'), 'Name 0')
self.assertEqual(certificates[0].get('description'), 'Description 0')
def test_delete_certificate_without_write_permissions(self):
"""
Tests certificate deletion without write permission on course.
"""
self._add_course_certificates(count=2, signatory_count=1)
user = UserFactory()
self.client.login(username=user.username, password='test')
response = self.client.delete(
self._url(cid=1),
content_type="application/json",
HTTP_ACCEPT="application/json",
HTTP_X_REQUESTED_WITH="XMLHttpRequest",
)
self.assertEqual(response.status_code, 403)
def test_delete_non_existing_certificate(self):
"""
Try to delete a non existing certificate. It should return status code 404 Not found.
@@ -523,6 +554,25 @@ class CertificatesDetailHandlerTestCase(CourseTestCase, CertificatesBaseTestCase
certificates = course.certificates['certificates']
self.assertEqual(certificates[0].get('is_active'), is_active)
@ddt.data(True, False)
def test_certificate_activation_without_write_permissions(self, activate):
"""
Tests certificate Activate and Deactivate should not be allowed if user
does not have write permissions on course.
"""
test_url = reverse_course_url('certificates.certificate_activation_handler', self.course.id)
self._add_course_certificates(count=1, signatory_count=2)
user = UserFactory()
self.client.login(username=user.username, password='test')
response = self.client.post(
test_url,
data=json.dumps({"is_active": activate}),
content_type="application/json",
HTTP_ACCEPT="application/json",
HTTP_X_REQUESTED_WITH="XMLHttpRequest"
)
self.assertEquals(response.status_code, 403)
def test_certificate_activation_failure(self):
"""
Certificate activation should fail when user has not read access to course then permission denied exception

View File

@@ -29,8 +29,8 @@ class CreditEligibilityTest(CourseTestCase):
"""
response = self.client.get_html(self.course_details_url)
self.assertEqual(response.status_code, 200)
self.assertNotContains(response, "Credit Eligibility Requirements")
self.assertNotContains(response, "Steps needed for credit eligibility")
self.assertNotContains(response, "Course Credit Requirements")
self.assertNotContains(response, "Steps required to earn course credit")
@mock.patch.dict("django.conf.settings.FEATURES", {'ENABLE_CREDIT_ELIGIBILITY': True})
def test_course_details_with_enabled_setting(self):
@@ -41,8 +41,8 @@ class CreditEligibilityTest(CourseTestCase):
# course is not set as credit course
response = self.client.get_html(self.course_details_url)
self.assertEqual(response.status_code, 200)
self.assertNotContains(response, "Credit Eligibility Requirements")
self.assertNotContains(response, "Steps needed for credit eligibility")
self.assertNotContains(response, "Course Credit Requirements")
self.assertNotContains(response, "Steps required to earn course credit")
# verify that credit eligibility requirements block shows if the
# course is set as credit course and it has eligibility requirements
@@ -55,5 +55,5 @@ class CreditEligibilityTest(CourseTestCase):
response = self.client.get_html(self.course_details_url)
self.assertEqual(response.status_code, 200)
self.assertContains(response, "Credit Eligibility Requirements")
self.assertContains(response, "Steps needed for credit eligibility")
self.assertContains(response, "Course Credit Requirements")
self.assertContains(response, "Steps required to earn course credit")

View File

@@ -209,6 +209,19 @@ class ImportTestCase(CourseTestCase):
return outside_tar
def _edx_platform_tar(self):
"""
Tarfile with file that extracts to edx-platform directory.
Extracting this tarfile in directory <dir> will also put its contents
directly in <dir> (rather than <dir/tarname>).
"""
outside_tar = self.unsafe_common_dir / "unsafe_file.tar.gz"
with tarfile.open(outside_tar, "w:gz") as tar:
tar.addfile(tarfile.TarInfo(os.path.join(os.path.abspath("."), "a_file")))
return outside_tar
def test_unsafe_tar(self):
"""
Check that safety measure work.
@@ -233,6 +246,12 @@ class ImportTestCase(CourseTestCase):
try_tar(self._symlink_tar())
try_tar(self._outside_tar())
try_tar(self._outside_tar2())
try_tar(self._edx_platform_tar())
# test trying to open a tar outside of the normal data directory
with self.settings(DATA_DIR='/not/the/data/dir'):
try_tar(self._edx_platform_tar())
# Check that `import_status` returns the appropriate stage (i.e.,
# either 3, indicating all previous steps are completed, or 0,
# indicating no upload in progress)
@@ -294,13 +313,19 @@ class ImportTestCase(CourseTestCase):
self.assertIn(test_block3.url_name, children)
self.assertIn(test_block4.url_name, children)
extract_dir = path(tempfile.mkdtemp())
extract_dir = path(tempfile.mkdtemp(dir=settings.DATA_DIR))
# the extract_dir needs to be passed as a relative dir to
# import_library_from_xml
extract_dir_relative = path.relpath(extract_dir, settings.DATA_DIR)
try:
tar = tarfile.open(path(TEST_DATA_DIR) / 'imports' / 'library.HhJfPD.tar.gz')
safetar_extractall(tar, extract_dir)
with tarfile.open(path(TEST_DATA_DIR) / 'imports' / 'library.HhJfPD.tar.gz') as tar:
safetar_extractall(tar, extract_dir)
library_items = import_library_from_xml(
self.store, self.user.id,
settings.GITHUB_REPO_ROOT, [extract_dir / 'library'],
self.store,
self.user.id,
settings.GITHUB_REPO_ROOT,
[extract_dir_relative / 'library'],
load_error_modules=False,
static_content_store=contentstore(),
target_id=lib_key

View File

@@ -8,7 +8,7 @@ from django.conf import settings
from opaque_keys.edx.locations import Location
from xmodule.modulestore.exceptions import ItemNotFoundError
from contentstore.utils import course_image_url
from contentstore.utils import course_image_url, has_active_web_certificate
from models.settings import course_grading
from xmodule.fields import Date
from xmodule.modulestore.django import modulestore
@@ -52,7 +52,8 @@ class CourseDetails(object):
self.entrance_exam_minimum_score_pct = settings.FEATURES.get(
'ENTRANCE_EXAM_MIN_SCORE_PCT',
'50'
) # minimum passing score for entrance exam content module/tree
) # minimum passing score for entrance exam content module/tree,
self.has_cert_config = None # course has active certificate configuration
@classmethod
def _fetch_about_attribute(cls, course_key, attribute):
@@ -84,6 +85,7 @@ class CourseDetails(object):
course_details.language = descriptor.language
# Default course license is "All Rights Reserved"
course_details.license = getattr(descriptor, "license", "all-rights-reserved")
course_details.has_cert_config = has_active_web_certificate(descriptor)
for attribute in ABOUT_ATTRIBUTES:
value = cls._fetch_about_attribute(course_key, attribute)

View File

@@ -39,6 +39,7 @@ INSTALLED_APPS += ('django_extensions',)
TEST_ROOT = REPO_ROOT / "test_root" # pylint: disable=no-value-for-parameter
GITHUB_REPO_ROOT = (TEST_ROOT / "data").abspath()
LOG_DIR = (TEST_ROOT / "log").abspath()
DATA_DIR = TEST_ROOT / "data"
# Configure modulestore to use the test folder within the repo
update_module_store_settings(

View File

@@ -97,6 +97,9 @@ FEATURES['ENABLE_COURSEWARE_INDEX'] = True
FEATURES['ENABLE_LIBRARY_INDEX'] = True
SEARCH_ENGINE = "search.elastic.ElasticSearchEngine"
########################## Certificates Web/HTML View #######################
FEATURES['CERTIFICATES_HTML_VIEW'] = True
################################# DJANGO-REQUIRE ###############################
# Whether to run django-require in debug mode.
@@ -115,6 +118,3 @@ MODULESTORE = convert_module_store_setting_if_needed(MODULESTORE)
# Dummy secret key for dev
SECRET_KEY = '85920908f28904ed733fe576320db18cabd7b6cd'
########################## Certificates Web/HTML View #######################
FEATURES['CERTIFICATES_HTML_VIEW'] = True

View File

@@ -65,6 +65,7 @@ TEST_ROOT = path('test_root')
STATIC_ROOT = TEST_ROOT / "staticfiles"
GITHUB_REPO_ROOT = TEST_ROOT / "data"
DATA_DIR = TEST_ROOT / "data"
COMMON_TEST_DATA_ROOT = COMMON_ROOT / "test" / "data"
# For testing "push to lms"

View File

@@ -28,7 +28,7 @@ require ["jquery", "backbone", "coffee/src/main", "common/js/spec_helpers/ajax_h
appendSetFixtures(sandbox({id: "page-notification"}))
it "successful AJAX request does not pop an error notification", ->
server = AjaxHelpers['server'](200, this)
server = AjaxHelpers.server(this, [200, {}, ''])
expect($("#page-notification")).toBeEmpty()
$.ajax("/test")
@@ -37,7 +37,7 @@ require ["jquery", "backbone", "coffee/src/main", "common/js/spec_helpers/ajax_h
expect($("#page-notification")).toBeEmpty()
it "AJAX request with error should pop an error notification", ->
server = AjaxHelpers['server'](500, this)
server = AjaxHelpers.server(this, [500, {}, ''])
$.ajax("/test")
server.respond()
@@ -45,7 +45,7 @@ require ["jquery", "backbone", "coffee/src/main", "common/js/spec_helpers/ajax_h
expect($("#page-notification")).toContain('div.wrapper-notification-error')
it "can override AJAX request with error so it does not pop an error notification", ->
server = AjaxHelpers['server'](500, this)
server = AjaxHelpers.server(this, [500, {}, ''])
$.ajax
url: "/test"

View File

@@ -34,7 +34,7 @@ define ["js/models/section", "common/js/spec_helpers/ajax_helpers", "js/utils/mo
})
it "show/hide a notification when it saves to the server", ->
server = AjaxHelpers['server'](200, this)
server = AjaxHelpers.server(this, [200, {}, ''])
@model.save()
expect(Section.prototype.showNotification).toHaveBeenCalled()
@@ -43,7 +43,7 @@ define ["js/models/section", "common/js/spec_helpers/ajax_helpers", "js/utils/mo
it "don't hide notification when saving fails", ->
# this is handled by the global AJAX error handler
server = AjaxHelpers['server'](500, this)
server = AjaxHelpers.server(this, [500, {}, ''])
@model.save()
server.respond()

View File

@@ -167,22 +167,23 @@ define ["js/views/course_info_handout", "js/views/course_info_update", "js/model
@courseInfoEdit.render()
@event = {preventDefault : () -> 'no op'}
@courseInfoEdit.onNew(@event)
@requests = AjaxHelpers["requests"](this)
it "shows push notification checkbox as selected by default", ->
expect(@courseInfoEdit.$el.find('.toggle-checkbox')).toBeChecked()
it "sends correct default value for push_notification_selected", ->
requests = AjaxHelpers.requests(this);
@courseInfoEdit.$el.find('.save-button').click()
requestSent = JSON.parse(@requests[@requests.length - 1].requestBody)
requestSent = JSON.parse(requests[requests.length - 1].requestBody)
expect(requestSent.push_notification_selected).toEqual(true)
it "sends correct value for push_notification_selected when it is unselected", ->
requests = AjaxHelpers.requests(this);
# unselect push notification
@courseInfoEdit.$el.find('.toggle-checkbox').attr('checked', false);
@courseInfoEdit.$el.find('.save-button').click()
requestSent = JSON.parse(@requests[@requests.length - 1].requestBody)
requestSent = JSON.parse(requests[requests.length - 1].requestBody)
expect(requestSent.push_notification_selected).toEqual(false)
describe "Course Handouts", ->

View File

@@ -32,6 +32,11 @@ define(["backbone"], function (Backbone) {
return -1;
} else if (isPrimaryBlankTemplate(b)) {
return 1;
// Hinted problems should be shown at the end
} else if (a.hinted && !b.hinted) {
return 1;
} else if (!a.hinted && b.hinted) {
return -1;
} else if (a.display_name > b.display_name) {
return 1;
} else if (a.display_name < b.display_name) {

View File

@@ -1,5 +1,5 @@
define(["backbone", "underscore", "gettext", "js/models/validation_helpers"],
function(Backbone, _, gettext, ValidationHelpers) {
define(["backbone", "underscore", "gettext", "js/models/validation_helpers", "js/utils/date_utils"],
function(Backbone, _, gettext, ValidationHelpers, DateUtils) {
var CourseDetails = Backbone.Model.extend({
defaults: {
@@ -28,14 +28,21 @@ var CourseDetails = Backbone.Model.extend({
// Returns either nothing (no return call) so that validate works or an object of {field: errorstring} pairs
// A bit funny in that the video key validation is asynchronous; so, it won't stop the validation.
var errors = {};
newattrs = DateUtils.convertDateStringsToObjects(
newattrs, ["start_date", "end_date", "enrollment_start", "enrollment_end"]
);
if (newattrs.start_date === null) {
errors.start_date = gettext("The course must have an assigned start date.");
}
if (this.hasChanged("start_date") && this.get("has_cert_config") === false){
errors.start_date = gettext("The course must have at least one active certificate configuration before it can be started.");
}
if (newattrs.start_date && newattrs.end_date && newattrs.start_date >= newattrs.end_date) {
errors.end_date = gettext("The course end date cannot be before the course start 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 cannot be before the enrollment start date.");
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.");

View File

@@ -1,8 +1,8 @@
define(
[
'jquery', 'underscore', 'common/js/spec_helpers/ajax_helpers', 'squire'
'jquery', 'underscore', 'squire'
],
function ($, _, AjaxHelpers, Squire) {
function ($, _, Squire) {
'use strict';
describe('FileUploader', function () {
var FileUploaderTemplate = readFixtures(

View File

@@ -4,9 +4,10 @@ define(
'js/views/video/transcripts/utils',
'js/views/video/transcripts/metadata_videolist', 'js/models/metadata',
'js/views/abstract_editor',
'sinon', 'xmodule', 'jasmine-jquery'
'common/js/spec_helpers/ajax_helpers',
'xmodule', 'jasmine-jquery'
],
function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, AjaxHelpers) {
'use strict';
describe('CMS.Views.Metadata.VideoList', function () {
var videoListEntryTemplate = readFixtures(
@@ -50,24 +51,13 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
status: 'Success',
subs: 'video_id'
}),
view, sinonXhr, MessageManager, messenger;
MessageManager, messenger;
beforeEach(function () {
sinonXhr = sinon.fakeServer.create();
sinonXhr.respondWith([
200,
{ 'Content-Type': 'application/json'},
response
]);
sinonXhr.autoRespond = true;
var tpl = sandbox({
'class': 'component',
'data-locator': component_locator
}),
model = new MetadataModel(modelStub),
$el;
});
setFixtures(tpl);
@@ -99,14 +89,6 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
return messenger;
};
$el = $('.component');
view = new VideoList({
el: $el,
model: model,
MessageManager: MessageManager
});
this.addMatchers({
assertValueInView: function(expected) {
var actualValue = this.actual.getValueFromEditor();
@@ -129,11 +111,29 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
});
});
afterEach(function () {
sinonXhr.restore();
});
var createMockAjaxServer = function (test) {
var mockServer = AjaxHelpers.server(
test,
[
200,
{ 'Content-Type': 'application/json'},
response
]
);
mockServer.autoRespond = true;
return mockServer;
};
var waitsForResponse = function (expectFunc, prep) {
var createVideoListView = function () {
var model = new MetadataModel(modelStub);
return new VideoList({
el: $('.component'),
model: model,
MessageManager: MessageManager
});
};
var waitsForResponse = function (mockServer, expectFunc, prep) {
var flag = false;
if (prep) {
@@ -141,10 +141,10 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
}
waitsFor(function() {
var req = sinonXhr.requests,
len = req.length;
var requests = mockServer.requests,
len = requests.length;
if (len && req[0].readyState === 4) {
if (len && requests[0].readyState === 4) {
flag = true;
}
@@ -156,7 +156,9 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
it('Initialize', function () {
waitsForResponse(function () {
var mockServer = createMockAjaxServer(this),
view = createVideoListView();
waitsForResponse(mockServer, function () {
expect(abstractEditor.initialize).toHaveBeenCalled();
expect(messenger.initialize).toHaveBeenCalled();
expect(view.component_locator).toBe(component_locator);
@@ -175,20 +177,24 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
expect(messenger.render).toHaveBeenCalled();
},
resetSpies = function() {
resetSpies = function(mockServer) {
abstractEditor.render.reset();
Utils.command.reset();
messenger.render.reset();
sinonXhr.requests.length = 0;
mockServer.requests.length = 0;
};
it('is rendered in correct way', function () {
waitsForResponse(function () {
var mockServer = createMockAjaxServer(this);
createVideoListView();
waitsForResponse(mockServer, function () {
assertToHaveBeenRendered(videoList);
});
});
it('is rendered with opened extra videos bar', function () {
var mockServer = createMockAjaxServer(this),
view = createVideoListView();
var videoListLength = [
{
mode: 'youtube',
@@ -213,24 +219,26 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
spyOn(view, 'openExtraVideosBar');
waitsForResponse(
mockServer,
function () {
assertToHaveBeenRendered(videoListLength);
view.getVideoObjectsList.andReturn(videoListLength);
expect(view.openExtraVideosBar).toHaveBeenCalled();
},
function () {
resetSpies();
resetSpies(mockServer);
view.render();
}
);
waitsForResponse(
mockServer,
function () {
assertToHaveBeenRendered(videoListHtml5mode);
expect(view.openExtraVideosBar).toHaveBeenCalled();
},
function () {
resetSpies();
resetSpies(mockServer);
view.openExtraVideosBar.reset();
view.getVideoObjectsList.andReturn(videoListHtml5mode);
view.render();
@@ -240,7 +248,9 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
});
it('is rendered without opened extra videos bar', function () {
var videoList = [
var mockServer = createMockAjaxServer(this),
view = createVideoListView(),
videoList = [
{
mode: 'youtube',
type: 'youtube',
@@ -252,12 +262,13 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
spyOn(view, 'closeExtraVideosBar');
waitsForResponse(
mockServer,
function () {
assertToHaveBeenRendered(videoList);
expect(view.closeExtraVideosBar).toHaveBeenCalled();
},
function () {
resetSpies();
resetSpies(mockServer);
view.render();
}
);
@@ -267,13 +278,14 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
describe('isUniqOtherVideos', function () {
it('Unique data - return true', function () {
var data = videoList.concat([{
mode: 'html5',
type: 'other',
video: 'pxxZrg'
}]);
waitsForResponse(function () {
var mockServer = createMockAjaxServer(this),
view = createVideoListView(),
data = videoList.concat([{
mode: 'html5',
type: 'other',
video: 'pxxZrg'
}]);
waitsForResponse(mockServer, function () {
var result = view.isUniqOtherVideos(data);
expect(result).toBe(true);
@@ -282,7 +294,9 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
});
it('Not Unique data - return false', function () {
var data = [
var mockServer = createMockAjaxServer(this),
view = createVideoListView(),
data = [
{
mode: 'html5',
type: 'mp4',
@@ -309,8 +323,7 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
video: '12345678901'
}
];
waitsForResponse(function () {
waitsForResponse(mockServer, function () {
var result = view.isUniqOtherVideos(data);
expect(result).toBe(false);
@@ -321,18 +334,20 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
describe('isUniqVideoTypes', function () {
it('Unique data - return true', function () {
var data = videoList;
waitsForResponse(function () {
var mockServer = createMockAjaxServer(this),
view = createVideoListView(),
data = videoList;
waitsForResponse(mockServer, function () {
var result = view.isUniqVideoTypes(data);
expect(result).toBe(true);
});
});
it('Not Unique data - return false', function () {
var data = [
var mockServer = createMockAjaxServer(this),
view = createVideoListView(),
data = [
{
mode: 'html5',
type: 'mp4',
@@ -354,8 +369,7 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
video: '12345678901'
}
];
waitsForResponse(function () {
waitsForResponse(mockServer, function () {
var result = view.isUniqVideoTypes(data);
expect(result).toBe(false);
@@ -365,7 +379,9 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
describe('checkIsUniqVideoTypes', function () {
it('Error is shown', function () {
var data = [
var mockServer = createMockAjaxServer(this),
view = createVideoListView(),
data = [
{
mode: 'html5',
type: 'mp4',
@@ -388,7 +404,7 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
}
];
waitsForResponse(function () {
waitsForResponse(mockServer, function () {
var result = view.checkIsUniqVideoTypes(data);
expect(messenger.showError).toHaveBeenCalled();
@@ -397,9 +413,10 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
});
it('All works okay if arguments are not passed', function () {
var mockServer = createMockAjaxServer(this),
view = createVideoListView();
spyOn(view, 'getVideoObjectsList').andReturn(videoList);
waitsForResponse(function () {
waitsForResponse(mockServer, function () {
var result = view.checkIsUniqVideoTypes();
expect(view.getVideoObjectsList).toHaveBeenCalled();
@@ -410,12 +427,11 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
});
describe('checkValidity', function () {
beforeEach(function () {
spyOn(view, 'checkIsUniqVideoTypes').andReturn(true);
});
it('Error message is shown', function () {
waitsForResponse(function () {
var mockServer = createMockAjaxServer(this),
view = createVideoListView();
spyOn(view, 'checkIsUniqVideoTypes').andReturn(true);
waitsForResponse(mockServer, function () {
var data = { mode: 'incorrect' },
result = view.checkValidity(data, true);
@@ -426,7 +442,10 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
});
it('Error message is shown when flag is not passed', function () {
waitsForResponse(function () {
var mockServer = createMockAjaxServer(this),
view = createVideoListView();
spyOn(view, 'checkIsUniqVideoTypes').andReturn(true);
waitsForResponse(mockServer, function () {
var data = { mode: 'incorrect' },
result = view.checkValidity(data);
@@ -437,7 +456,10 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
});
it('All works okay if correct data is passed', function () {
waitsForResponse(function () {
var mockServer = createMockAjaxServer(this),
view = createVideoListView();
spyOn(view, 'checkIsUniqVideoTypes').andReturn(true);
waitsForResponse(mockServer, function () {
var data = videoList,
result = view.checkValidity(data);
@@ -449,7 +471,9 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
});
it('openExtraVideosBar', function () {
waitsForResponse(function () {
var mockServer = createMockAjaxServer(this),
view = createVideoListView();
waitsForResponse(mockServer, function () {
view.$extraVideosBar.removeClass('is-visible');
view.openExtraVideosBar();
@@ -458,7 +482,9 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
});
it('closeExtraVideosBar', function () {
waitsForResponse(function () {
var mockServer = createMockAjaxServer(this),
view = createVideoListView();
waitsForResponse(mockServer, function () {
view.$extraVideosBar.addClass('is-visible');
view.closeExtraVideosBar();
@@ -467,7 +493,9 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
});
it('toggleExtraVideosBar', function () {
waitsForResponse(function () {
var mockServer = createMockAjaxServer(this),
view = createVideoListView();
waitsForResponse(mockServer, function () {
view.$extraVideosBar.addClass('is-visible');
view.toggleExtraVideosBar();
expect(view.$extraVideosBar).not.toHaveClass('is-visible');
@@ -477,18 +505,24 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
});
it('getValueFromEditor', function () {
waitsForResponse(function () {
var mockServer = createMockAjaxServer(this),
view = createVideoListView();
waitsForResponse(mockServer, function () {
expect(view).assertValueInView(modelStub.value);
});
});
it('setValueInEditor', function () {
waitsForResponse(function () {
var mockServer = createMockAjaxServer(this),
view = createVideoListView();
waitsForResponse(mockServer, function () {
expect(view).assertCanUpdateView(['abc.mp4']);
});
});
it('getVideoObjectsList', function () {
var mockServer = createMockAjaxServer(this),
view = createVideoListView();
var value = [
{
mode: 'youtube',
@@ -507,7 +541,7 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
}
];
waitsForResponse(function () {
waitsForResponse(mockServer, function () {
view.setValueInEditor([
'http://youtu.be/12345678901',
'video.mp4',
@@ -519,14 +553,12 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
});
describe('getPlaceholders', function () {
var defaultPlaceholders;
beforeEach(function () {
defaultPlaceholders = view.placeholders;
});
it('All works okay if empty values are passed', function () {
waitsForResponse(function () {
var mockServer = createMockAjaxServer(this),
view = createVideoListView(),
defaultPlaceholders = view.placeholders;
waitsForResponse(mockServer, function () {
var result = view.getPlaceholders([]),
expectedResult = _.values(defaultPlaceholders).reverse();
@@ -534,10 +566,12 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
});
});
it('On filling less than 3 fields, remaining fields should have ' +
'placeholders for video types that were not filled yet',
function () {
var mockServer = createMockAjaxServer(this),
view = createVideoListView(),
defaultPlaceholders = view.placeholders;
var dataDict = {
youtube: {
value: [modelStub.value[0]],
@@ -564,8 +598,8 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
]
}
};
waitsForResponse(function () {
defaultPlaceholders = view.placeholders;
waitsForResponse(mockServer, function () {
$.each(dataDict, function(index, val) {
var result = view.getPlaceholders(val.value);
@@ -579,13 +613,13 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
describe('inputHandler', function () {
var eventObject;
var resetSpies = function () {
var resetSpies = function (view) {
messenger.hideError.reset();
view.updateModel.reset();
view.closeExtraVideosBar.reset();
};
beforeEach(function () {
var setUp = function (view) {
eventObject = jQuery.Event('input');
spyOn(view, 'updateModel');
@@ -597,15 +631,18 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
spyOn($.fn, 'prop').andCallThrough();
spyOn(_, 'isEqual');
resetSpies();
});
resetSpies(view);
};
it('Field has invalid value - nothing should happen',
function () {
var mockServer = createMockAjaxServer(this),
view = createVideoListView();
setUp(view);
$.fn.hasClass.andReturn(false);
view.checkValidity.andReturn(false);
waitsForResponse(function () {
waitsForResponse(mockServer, function () {
view.inputHandler(eventObject);
expect(messenger.hideError).not.toHaveBeenCalled();
expect(view.updateModel).not.toHaveBeenCalled();
@@ -622,10 +659,13 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
it('Main field has invalid value - extra Videos Bar is closed',
function () {
var mockServer = createMockAjaxServer(this),
view = createVideoListView();
setUp(view);
$.fn.hasClass.andReturn(true);
view.checkValidity.andReturn(false);
waitsForResponse(function () {
waitsForResponse(mockServer, function () {
view.inputHandler(eventObject);
expect(messenger.hideError).not.toHaveBeenCalled();
expect(view.updateModel).not.toHaveBeenCalled();
@@ -642,10 +682,13 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
it('Model is updated if value is valid',
function () {
var mockServer = createMockAjaxServer(this),
view = createVideoListView();
setUp(view);
view.checkValidity.andReturn(true);
_.isEqual.andReturn(false);
waitsForResponse(function () {
waitsForResponse(mockServer, function () {
view.inputHandler(eventObject);
expect(messenger.hideError).not.toHaveBeenCalled();
expect(view.updateModel).toHaveBeenCalled();
@@ -662,10 +705,12 @@ function ($, _, Utils, VideoList, MetadataModel, AbstractEditor, sinon) {
it('Corner case: Error is hided',
function () {
var mockServer = createMockAjaxServer(this),
view = createVideoListView();
setUp(view);
view.checkValidity.andReturn(true);
_.isEqual.andReturn(true);
waitsForResponse(function () {
waitsForResponse(mockServer, function () {
view.inputHandler(eventObject);
expect(messenger.hideError).toHaveBeenCalled();
expect(view.updateModel).not.toHaveBeenCalled();

View File

@@ -1,8 +1,8 @@
define(
[
'jquery', 'underscore', 'common/js/spec_helpers/ajax_helpers', 'squire'
'jquery', 'underscore', 'squire'
],
function ($, _, AjaxHelpers, Squire) {
function ($, _, Squire) {
'use strict';
// TODO: fix BLD-1100 Disabled due to intermittent failure on master and in PR builds
xdescribe('VideoTranslations', function () {

View File

@@ -47,7 +47,8 @@ define([
});
describe('Initial display', function() {
it('can render itself', function() {
// TODO fix this, see TNL-1475
xit('can render itself', function() {
var view = initializePage();
expect(view.$('.ui-loading')).toBeVisible();
view.render();

View File

@@ -31,7 +31,8 @@ define([
entrance_exam_enabled : '',
entrance_exam_minimum_score_pct: '50',
license: null,
language: ''
language: '',
has_cert_config: false
},
mockSettingsPage = readFixtures('mock/mock-settings-page.underscore');
@@ -71,6 +72,13 @@ define([
);
});
it('Changing course start date without active certificate configuration should result in error', function () {
this.view.$el.find('#course-start-date')
.val('10/06/2014')
.trigger('change');
expect(this.view.$el.find('span.message-error').text()).toContain("course must have at least one active certificate configuration");
});
it('Selecting a course in pre-requisite drop down should save it as part of course details', function () {
var pre_requisite_courses = ['test/CSS101/2012_T1'];
var requests = AjaxHelpers.requests(this),

View File

@@ -35,9 +35,29 @@ define(["jquery", "date", "jquery.ui", "jquery.timepicker"], function($, date) {
);
};
var parseDateFromString = function(stringDate){
if (stringDate && typeof stringDate === "string"){
return new Date(stringDate);
}
else {
return stringDate;
}
};
var convertDateStringsToObjects = function(obj, dateFields){
for (var i = 0; i < dateFields.length; i++){
if (obj[dateFields[i]]){
obj[dateFields[i]] = parseDateFromString(obj[dateFields[i]]);
}
}
return obj;
};
return {
getDate: getDate,
setDate: setDate,
renderDate: renderDate
renderDate: renderDate,
convertDateStringsToObjects: convertDateStringsToObjects,
parseDateFromString: parseDateFromString
};
});

View File

@@ -54,8 +54,8 @@ var DetailsView = ValidatingView.extend({
if (options.showMinGradeWarning || false) {
new NotificationView.Warning({
title: gettext("Credit Eligibility Requirements"),
message: gettext("Minimum passing grade for credit is not set."),
title: gettext("Course Credit Requirements"),
message: gettext("The minimum grade for course credit is not set."),
closeIcon: true
}).show();
}

View File

@@ -124,11 +124,11 @@
// green button
.add-xblock-component-button {
@extend %t-action3;
@include margin-right($baseline*0.75);
position: relative;
display: inline-block;
width: ($baseline*5);
height: ($baseline*5);
margin-right: ($baseline*0.75);
margin-bottom: ($baseline/2);
border: 1px solid $green-d2;
border-radius: ($baseline/4);
@@ -164,7 +164,7 @@
.cancel-button {
@include white-button;
margin: $baseline 0 ($baseline/2) ($baseline/2);
@include margin($baseline, 0, ($baseline/2), ($baseline/2));
}
.problem-type-tabs {
@@ -225,13 +225,13 @@
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.2) inset, 0 -1px 0 $shadow inset;
li:first-child {
margin-left: $baseline;
@include margin-left($baseline);
}
li {
@include linear-gradient(top, rgba(255, 255, 255, .4), rgba(255, 255, 255, 0));
opacity: 0.8;
float: left;
@include float(left);
display: inline-block;
width: auto;
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.2) inset, 0 -1px 0 $shadow inset;
@@ -248,6 +248,11 @@
border: 0px;
opacity: 1.0;
}
// reset to remove jquery-ui float
a.link-tab {
float: none;
}
}
a {
@@ -286,7 +291,7 @@ $outline-indent-width: $baseline;
.icon {
display: inline-block;
vertical-align: middle;
margin-right: ($baseline/2);
@include margin-right($baseline/2);
}
}
}

View File

@@ -97,6 +97,10 @@
}
// in form -UI hints/tips/messages
.header-help {
margin: 0 0 $baseline 0;
}
.instructions {
@extend %t-copy-sub1;
margin: 0 0 $baseline 0;

View File

@@ -4,10 +4,7 @@
<a class="link-tab" href="#tab1"><%= gettext("Common Problem Types") %></a>
</li>
<li>
<a class="link-tab" href="#tab2"><%= gettext("Common Problems with Hints and Feedback") %></a>
</li>
<li>
<a class="link-tab" href="#tab3"><%= gettext("Advanced") %></a>
<a class="link-tab" href="#tab2"><%= gettext("Advanced") %></a>
</li>
</ul>
<div class="tab current" id="tab1">
@@ -33,20 +30,6 @@
</ul>
</div>
<div class="tab" id="tab2">
<ul class="new-component-template">
<% for (var i = 0; i < templates.length; i++) { %>
<% if (templates[i].tab == "hint") { %>
<li class="editor-manual">
<a href="#" data-category="<%= templates[i].category %>"
data-boilerplate="<%= templates[i].boilerplate_name %>">
<span class="name"><%= templates[i].display_name %></span>
</a>
</li>
<% } %>
<% } %>
</ul>
</div>
<div class="tab" id="tab3">
<ul class="new-component-template">
<% for (var i = 0; i < templates.length; i++) { %>
<% if (templates[i].tab == "advanced") { %>

View File

@@ -22,7 +22,7 @@
<div class="input-wrap field text add-certificate-course-title">
<label for="certificate-course-title-<%= uniqueId %>"><%= gettext("Course Title Override") %></label>
<input id="certificate-course-title-<%= uniqueId %>" class="certificate-course-title-input input-text" name="certificate-course-title" type="text" placeholder="<%= gettext("Course title") %>" value="<%= course_title %>" aria-describedby="certificate-course-title-<%=uniqueId %>-tip" />
<span id="certificate-course-title-<%= uniqueId %>-tip" class="tip tip-stacked"><%= gettext("Title of the course") %></span>
<span id="certificate-course-title-<%= uniqueId %>-tip" class="tip tip-stacked"><%= gettext("Specify an alternative to the official course title to display on certificates. Leave blank to use the official course title.") %></span>
</div>
<div class="input-wrap field text add-org-logo">
<label for="certificate-org-logo-<%= uniqueId %>"><%= gettext("Organization Logo") %></label>

View File

@@ -22,7 +22,7 @@
<div class="input-wrap field text add-signatory-name <% if(error && error.name) { print('error'); } %>">
<label for="signatory-name-<%= signatory_number %>"><%= gettext("Name ") %></label>
<input id="signatory-name-<%= signatory_number %>" class="collection-name-input input-text signatory-name-input" name="signatory-name" type="text" placeholder="<%= gettext("Name of the signatory") %>" value="<%= name %>" aria-describedby="signatory-name-<%= signatory_number %>-tip" maxlength="40" />
<span id="signatory-name-<%= signatory_number %>-tip" class="tip tip-stacked"><%= gettext("Maximum 40 characters") %></span>
<span id="signatory-name-<%= signatory_number %>-tip" class="tip tip-stacked"><%= gettext("The name of this signatory as it should appear on certificates. Maximum 40 characters.") %></span>
<% if(error && error.name) { %>
<span class="message-error"><%= error.name %></span>
<% } %>
@@ -30,7 +30,7 @@
<div class="input-wrap field text add-signatory-title <% if(error && error.title) { print('error'); } %>">
<label for="signatory-title-<%= signatory_number %>"><%= gettext("Title ") %></label>
<textarea id="signatory-title-<%= signatory_number %>" class="collection-name-input text input-text signatory-title-input" name="signatory-title" cols="40" rows="2" placeholder="<%= gettext("Title of the signatory") %>" aria-describedby="signatory-title-<%= signatory_number %>-tip" maxlength="80"><%= title %></textarea>
<span id="signatory-title-<%= signatory_number %>-tip" class="tip tip-stacked"><%= gettext("2 Lines, 40 characters each") %></span>
<span id="signatory-title-<%= signatory_number %>-tip" class="tip tip-stacked"><%= gettext("The title of this signatory as it should appear on certificates. Maximum 2 lines, 40 characters each.") %></span>
<% if(error && error.title) { %>
<span class="message-error"><%= error.title %></span>
<% } %>
@@ -38,7 +38,7 @@
<div class="input-wrap field text add-signatory-organization <% if(error && error.organization) { print('error'); } %>">
<label for="signatory-organization-<%= signatory_number %>"><%= gettext("Organization ") %></label>
<input id="signatory-organization-<%= signatory_number %>" class="collection-name-input input-text signatory-organization-input" name="signatory-organization" type="text" placeholder="<%= gettext("Organization of the signatory") %>" value="<%= organization %>" aria-describedby="signatory-organization-<%= signatory_number %>-tip" maxlength="40" />
<span id="signatory-organization-<%= signatory_number %>-tip" class="tip tip-stacked"><%= gettext("Maximum 40 characters") %></span>
<span id="signatory-organization-<%= signatory_number %>-tip" class="tip tip-stacked"><%= gettext("The organization that this signatory belongs to, as it should appear on certificates. Maximum 40 characters.") %></span>
<% if(error && error.organization) { %>
<span class="message-error"><%= error.organization %></span>
<% } %>

View File

@@ -53,7 +53,7 @@ from django.core.urlresolvers import reverse
<li class="field text required create-user-email">
<label for="user-email-input">${_("User's Email Address")}</label>
<input id="user-email-input" class="user-email-input" name="user-email" type="text" placeholder="${_('example: username@domain.com')}" value="">
<span class="tip tip-stacked">${_("Please provide the email address of the course staff member you'd like to add")}</span>
<span class="tip tip-stacked">${_("Provide the email address of the user you want to add as Staff")}</span>
</li>
</ol>
</fieldset>
@@ -94,14 +94,15 @@ from django.core.urlresolvers import reverse
<aside class="content-supplementary" role="complementary">
<div class="bit">
<h3 class="title-3">${_("Course Team Roles")}</h3>
<p>${_("Course team members, or staff, are course co-authors. They have full writing and editing privileges on all course content.")}</p>
<p>${_("Course team members with the Staff role are course co-authors. They have full writing and editing privileges on all course content.")}</p>
<p>${_("Admins are course team members who can add and remove other course team members.")}</p>
<p>${_("All course team members are automatically enrolled in the course and can access content in Studio, the LMS, and Insights.")}</p>
</div>
% if show_transfer_ownership_hint:
<div class="bit">
<h3 class="title-3">${_("Transferring Ownership")}</h3>
<p>${_("Every course must have an Admin. If you're the Admin and you want transfer ownership of the course, click Add admin access to make another user the Admin, then ask that user to remove you from the Course Team list.")}</p>
<p>${_("Every course must have an Admin. If you are the Admin and you want to transfer ownership of the course, click <strong>Add admin access</strong> to make another user the Admin, then ask that user to remove you from the Course Team list.")}</p>
</div>
% endif
</aside>

View File

@@ -95,9 +95,9 @@ from django.core.urlresolvers import reverse
<div class="bit">
<h3 class="title-3">${_("Library Access Roles")}</h3>
<p>${_("There are three access roles for libraries: User, Staff, and Admin.")}</p>
<p>${_("Users can view library content and can reference or use library components in their courses, but they cannot edit the contents of a library.")}</p>
<p>${_("Staff are content co-authors. They have full editing privileges on the contents of a library.")}</p>
<p>${_("Admins have full editing privileges and can also add and remove other team members. There must be at least one user with Admin privileges in a library.")}</p>
<p>${_("Library Users can view library content and can reference or use library components in their courses, but they cannot edit the contents of a library.")}</p>
<p>${_("Library Staff are content co-authors. They have full editing privileges on the contents of a library.")}</p>
<p>${_("Library Admins have full editing privileges and can also add and remove other team members. There must be at least one user with the Admin role in a library.")}</p>
</div>
</aside>
</section>

View File

@@ -112,8 +112,8 @@ CMS.URL.UPLOAD_ASSET = '${upload_asset_url}';
<p>${_(
'Your course summary page will not be viewable until your course '
'has been announced. To provide content for the page and preview '
'it, follow the instructions provided by your Program Manager.')
}</p>
'it, follow the instructions provided by your Program Manager.')}
</p>
</div>
</div>
% endif
@@ -123,16 +123,18 @@ CMS.URL.UPLOAD_ASSET = '${upload_asset_url}';
% if credit_eligibility_enabled and is_credit_course:
<section class="group-settings basic">
<header>
<h2 class="title-2">${_("Credit Eligibility Requirements")}</h2>
<span class="tip">${_("Steps needed for credit eligibility")}</span>
<h2 class="title-2">${_("Course Credit Requirements")}</h2>
<span class="tip">${_("Steps required to earn course credit")}</span>
</header>
<span class="header-help tip">A requirement appears in this list when you publish the unit that contains the requirement.</span>
% if credit_requirements:
<ol class="list-input">
% if 'grade' in credit_requirements:
<li class="field text is-not-editable" id="credit-minimum-passing-grade">
<label>${_("Minimum Passing Grade")}</label>
<label>${_("Minimum Grade")}</label>
% for requirement in credit_requirements['grade']:
<label for="${requirement['name']}" class="sr">${_("Minimum Passing Grade")}</label>
<label for="${requirement['name']}" class="sr">${_("Minimum Grade")}</label>
<input title="${_('This field is disabled: this information cannot be changed.')}" type="text"
class="long" id="${requirement['name']}" value="${'{0:.0f}%'.format(float(requirement['criteria']['min_grade'] or 0)*100)}" readonly />
% endfor
@@ -152,12 +154,11 @@ CMS.URL.UPLOAD_ASSET = '${upload_asset_url}';
% if 'reverification' in credit_requirements:
<li class="field text is-not-editable" id="credit-reverification-requirements">
<label>${_("Successful In-Course Reverification")}</label>
<label>${_("ID Verification")}</label>
% for requirement in credit_requirements['reverification']:
## Translators: 'Access to Assessment 1' means the access for a requirement with name 'Assessment 1'
<label for="${requirement['name']}" class="sr">${_('In-Course Reverification {number}').format(number=loop.index+1)}</label>
<input title="${_('This field is disabled: this information cannot be changed.')}" type="text"
class="long" id="${requirement['name']}" value="${_('Access to {display_name}').format(display_name=requirement['display_name'])}" readonly />
class="long" id="${requirement['name']}" value="${requirement['display_name']}" readonly />
% endfor
</li>
% endif

View File

@@ -79,15 +79,15 @@
% if settings.FEATURES.get("ENABLE_CREDIT_ELIGIBILITY", False) and is_credit_course:
<section class="group-settings grade-rules">
<header>
<h2 class="title-2">${_("Credit Grade &amp; Eligibility")}</h2>
<span class="tip">${_("Settings for credit eligibility")}</span>
<h2 class="title-2">${_("Credit Eligibility")}</h2>
<span class="tip">${_("Settings for course credit eligibility")}</span>
</header>
<ol class="list-input">
<li class="field text" id="field-course-minimum_grade_credit">
<label for="course-minimum_grade_credit">${_("Minimum Passing Grade to Earn Credit:")}</label>
<label for="course-minimum_grade_credit">${_("Minimum Credit-Eligible Grade:")}</label>
<input type="text" class="short time" id="course-minimum_grade_credit" value="0" placeholder="80%" autocomplete="off" aria-describedby="minimum_grade_description"/>
<span class="tip tip-inline" id="minimum_grade_description">${_("Must be greater than or equal to passing grade")}</span>
<span class="tip tip-inline" id="minimum_grade_description">${_("Must be greater than or equal to the course passing grade")}</span>
</li>
</ol>
</section>

View File

@@ -86,6 +86,11 @@ class CourseMode(models.Model):
""" meta attributes of this model """
unique_together = ('course_id', 'mode_slug', 'currency')
def save(self, force_insert=False, force_update=False, using=None):
# Ensure currency is always lowercase.
self.currency = self.currency.lower()
super(CourseMode, self).save(force_insert, force_update, using)
@classmethod
def all_modes_for_courses(cls, course_id_list):
"""Find all modes for a list of course IDs, including expired modes.
@@ -308,7 +313,7 @@ class CourseMode(models.Model):
"""
modes = cls.modes_for_course(course_id)
for mode in modes:
if (mode.currency == currency) and (mode.slug == 'verified'):
if (mode.currency.lower() == currency.lower()) and (mode.slug == 'verified'):
return mode.min_price
return 0
@@ -490,7 +495,7 @@ class CourseMode(models.Model):
If there is no mode found, will return the price of DEFAULT_MODE, which is 0
"""
modes = cls.modes_for_course(course_id)
return min(mode.min_price for mode in modes if mode.currency == currency)
return min(mode.min_price for mode in modes if mode.currency.lower() == currency.lower())
@classmethod
def enrollment_mode_display(cls, mode, verification_status):

View File

@@ -39,6 +39,15 @@ class CourseModeModelTest(TestCase):
currency=currency,
)
def test_save(self):
""" Verify currency is always lowercase. """
cm, __ = self.create_mode('honor', 'honor', 0, '', 'USD')
self.assertEqual(cm.currency, 'usd')
cm.currency = 'GHS'
cm.save()
self.assertEqual(cm.currency, 'ghs')
def test_modes_for_course_empty(self):
"""
If we can't find any modes, we should get back the default mode

View File

@@ -325,6 +325,22 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase):
self.assertEquals(course_modes, expected_modes)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
@patch.dict(settings.FEATURES, {"IS_EDX_DOMAIN": True})
def test_hide_nav(self):
# Create the course modes
for mode in ["honor", "verified"]:
CourseModeFactory(mode_slug=mode, course_id=self.course.id)
# Load the track selection page
url = reverse('course_modes_choose', args=[unicode(self.course.id)])
response = self.client.get(url)
# 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")
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
class TrackSelectionEmbargoTest(UrlResetMixin, ModuleStoreTestCase):

View File

@@ -119,7 +119,8 @@ class ChooseModeView(View):
"course_num": course.display_number_with_default,
"chosen_price": chosen_price,
"error": error,
"responsive": True
"responsive": True,
"nav_hidden": True,
}
if "verified" in modes:
context["suggested_prices"] = [

View File

@@ -53,7 +53,7 @@ def marketing_link(name):
if link_map[name] is not None:
return reverse(link_map[name])
else:
log.warning("Cannot find corresponding link for name: {name}".format(name=name))
log.debug("Cannot find corresponding link for name: %s", name)
return '#'

View File

@@ -5,8 +5,8 @@ course level, such as available course modes.
"""
from django.utils import importlib
import logging
from django.core.cache import cache
from django.conf import settings
from django.core.cache import cache
from enrollment import errors
log = logging.getLogger(__name__)
@@ -181,7 +181,7 @@ def add_enrollment(user_id, course_id, mode='honor', is_active=True):
return _data_api().create_course_enrollment(user_id, course_id, mode, is_active)
def update_enrollment(user_id, course_id, mode=None, is_active=None):
def update_enrollment(user_id, course_id, mode=None, is_active=None, enrollment_attributes=None):
"""Updates the course mode for the enrolled user.
Update a course enrollment for the given user and course.
@@ -232,6 +232,10 @@ def update_enrollment(user_id, course_id, mode=None, is_active=None):
msg = u"Course Enrollment not found for user {user} in course {course}".format(user=user_id, course=course_id)
log.warn(msg)
raise errors.EnrollmentNotFoundError(msg)
else:
if enrollment_attributes is not None:
set_enrollment_attributes(user_id, course_id, enrollment_attributes)
return enrollment
@@ -302,6 +306,53 @@ def get_course_enrollment_details(course_id, include_expired=False):
return course_enrollment_details
def set_enrollment_attributes(user_id, course_id, attributes):
"""Set enrollment attributes for the enrollment of given user in the
course provided.
Args:
course_id (str): The Course to set enrollment attributes for.
user_id (str): The User to set enrollment attributes for.
attributes (list): Attributes to be set.
Example:
>>>set_enrollment_attributes(
"Bob",
"course-v1-edX-DemoX-1T2015",
[
{
"namespace": "credit",
"name": "provider_id",
"value": "hogwarts",
},
]
)
"""
_data_api().add_or_update_enrollment_attr(user_id, course_id, attributes)
def get_enrollment_attributes(user_id, course_id):
"""Retrieve enrollment attributes for given user for provided course.
Args:
user_id: The User to get enrollment attributes for
course_id (str): The Course to get enrollment attributes for.
Example:
>>>get_enrollment_attributes("Bob", "course-v1-edX-DemoX-1T2015")
[
{
"namespace": "credit",
"name": "provider_id",
"value": "hogwarts",
},
]
Returns: list
"""
return _data_api().get_enrollment_attributes(user_id, course_id)
def _validate_course_mode(course_id, mode):
"""Checks to see if the specified course mode is valid for the course.

View File

@@ -9,12 +9,12 @@ from opaque_keys.edx.keys import CourseKey
from xmodule.modulestore.django import modulestore
from enrollment.errors import (
CourseNotFoundError, CourseEnrollmentClosedError, CourseEnrollmentFullError,
CourseEnrollmentExistsError, UserNotFoundError,
CourseEnrollmentExistsError, UserNotFoundError, InvalidEnrollmentAttribute
)
from enrollment.serializers import CourseEnrollmentSerializer, CourseField
from student.models import (
CourseEnrollment, NonExistentCourseError, EnrollmentClosedError,
CourseFullError, AlreadyEnrolledError,
CourseFullError, AlreadyEnrolledError, CourseEnrollmentAttribute
)
log = logging.getLogger(__name__)
@@ -136,12 +136,112 @@ def update_course_enrollment(username, course_id, mode=None, is_active=None):
return None
def add_or_update_enrollment_attr(user_id, course_id, attributes):
"""Set enrollment attributes for the enrollment of given user in the
course provided.
Args:
course_id (str): The Course to set enrollment attributes for.
user_id (str): The User to set enrollment attributes for.
attributes (list): Attributes to be set.
Example:
>>>add_or_update_enrollment_attr(
"Bob",
"course-v1-edX-DemoX-1T2015",
[
{
"namespace": "credit",
"name": "provider_id",
"value": "hogwarts",
},
]
)
"""
course_key = CourseKey.from_string(course_id)
user = _get_user(user_id)
enrollment = CourseEnrollment.get_enrollment(user, course_key)
if not _invalid_attribute(attributes) and enrollment is not None:
CourseEnrollmentAttribute.add_enrollment_attr(enrollment, attributes)
def get_enrollment_attributes(user_id, course_id):
"""Retrieve enrollment attributes for given user for provided course.
Args:
user_id: The User to get enrollment attributes for
course_id (str): The Course to get enrollment attributes for.
Example:
>>>get_enrollment_attributes("Bob", "course-v1-edX-DemoX-1T2015")
[
{
"namespace": "credit",
"name": "provider_id",
"value": "hogwarts",
},
]
Returns: list
"""
course_key = CourseKey.from_string(course_id)
user = _get_user(user_id)
enrollment = CourseEnrollment.get_enrollment(user, course_key)
return CourseEnrollmentAttribute.get_enrollment_attributes(enrollment)
def _get_user(user_id):
"""Retrieve user with provided user_id
Args:
user_id(str): username of the user for which object is to retrieve
Returns: obj
"""
try:
return User.objects.get(username=user_id)
except User.DoesNotExist:
msg = u"Not user with username '{username}' found.".format(username=user_id)
log.warn(msg)
raise UserNotFoundError(msg)
def _update_enrollment(enrollment, is_active=None, mode=None):
enrollment.update_enrollment(is_active=is_active, mode=mode)
enrollment.save()
return CourseEnrollmentSerializer(enrollment).data # pylint: disable=no-member
def _invalid_attribute(attributes):
"""Validate enrollment attribute
Args:
attributes(dict): dict of attribute
Return:
list of invalid attributes
"""
invalid_attributes = []
for attribute in attributes:
if "namespace" not in attribute:
msg = u"'namespace' not in enrollment attribute"
log.warn(msg)
invalid_attributes.append("namespace")
raise InvalidEnrollmentAttribute(msg)
if "name" not in attribute:
msg = u"'name' not in enrollment attribute"
log.warn(msg)
invalid_attributes.append("name")
raise InvalidEnrollmentAttribute(msg)
if "value" not in attribute:
msg = u"'value' not in enrollment attribute"
log.warn(msg)
invalid_attributes.append("value")
raise InvalidEnrollmentAttribute(msg)
return invalid_attributes
def get_course_enrollment_info(course_id, include_expired=False):
"""Returns all course enrollment information for the given course.

View File

@@ -50,3 +50,8 @@ class EnrollmentNotFoundError(CourseEnrollmentError):
class EnrollmentApiLoadError(CourseEnrollmentError):
"""The data API could not be loaded."""
pass
class InvalidEnrollmentAttribute(CourseEnrollmentError):
"""Enrollment Attributes could not be validated"""
pass

View File

@@ -19,6 +19,8 @@ _ENROLLMENTS = []
_COURSES = []
_ENROLLMENT_ATTRIBUTES = []
# pylint: disable=unused-argument
def get_course_enrollments(student_id):
@@ -78,6 +80,23 @@ def add_enrollment(student_id, course_id, is_active=True, mode='honor'):
return enrollment
# pylint: disable=unused-argument
def add_or_update_enrollment_attr(user_id, course_id, attributes):
"""Add or update enrollment attribute array"""
for attribute in attributes:
_ENROLLMENT_ATTRIBUTES.append({
'namespace': attribute['namespace'],
'name': attribute['name'],
'value': attribute['value']
})
# pylint: disable=unused-argument
def get_enrollment_attributes(user_id, course_id):
"""Retrieve enrollment attribute array"""
return _ENROLLMENT_ATTRIBUTES
def add_course(course_id, enrollment_start=None, enrollment_end=None, invite_only=False, course_modes=None):
"""Append course to the courses array."""
course_info = {

View File

@@ -143,6 +143,29 @@ class EnrollmentTest(TestCase):
result = api.update_enrollment(self.USERNAME, self.COURSE_ID, mode='verified')
self.assertEquals('verified', result['mode'])
def test_update_enrollment_attributes(self):
# Add fake course enrollment information to the fake data API
fake_data_api.add_course(self.COURSE_ID, course_modes=['honor', 'verified', 'audit', 'credit'])
# Enroll in the course and verify the URL we get sent to
result = api.add_enrollment(self.USERNAME, self.COURSE_ID, mode='audit')
get_result = api.get_enrollment(self.USERNAME, self.COURSE_ID)
self.assertEquals(result, get_result)
enrollment_attributes = [
{
"namespace": "credit",
"name": "provider_id",
"value": "hogwarts",
}
]
result = api.update_enrollment(
self.USERNAME, self.COURSE_ID, mode='credit', enrollment_attributes=enrollment_attributes
)
self.assertEquals('credit', result['mode'])
attributes = api.get_enrollment_attributes(self.USERNAME, self.COURSE_ID)
self.assertEquals(enrollment_attributes[0], attributes[0])
def test_get_course_details(self):
# Add a fake course enrollment information to the fake data API
fake_data_api.add_course(self.COURSE_ID, course_modes=['honor', 'verified', 'audit'])

View File

@@ -170,6 +170,45 @@ class EnrollmentDataTest(ModuleStoreTestCase):
self.assertEqual(self.user.username, result['user'])
self.assertEqual(enrollment, result)
@ddt.data(
# Default (no course modes in the database)
# Expect that users are automatically enrolled as "honor".
([], 'credit'),
# Audit / Verified / Honor
# We should always go to the "choose your course" page.
# We should also be enrolled as "honor" by default.
(['honor', 'verified', 'audit', 'credit'], 'credit'),
)
@ddt.unpack
def test_add_or_update_enrollment_attr(self, course_modes, enrollment_mode):
# Create the course modes (if any) required for this test case
self._create_course_modes(course_modes)
data.create_course_enrollment(self.user.username, unicode(self.course.id), enrollment_mode, True)
enrollment_attributes = [
{
"namespace": "credit",
"name": "provider_id",
"value": "hogwarts",
}
]
data.add_or_update_enrollment_attr(self.user.username, unicode(self.course.id), enrollment_attributes)
enrollment_attr = data.get_enrollment_attributes(self.user.username, unicode(self.course.id))
self.assertEqual(enrollment_attr[0], enrollment_attributes[0])
enrollment_attributes = [
{
"namespace": "credit",
"name": "provider_id",
"value": "ASU",
}
]
data.add_or_update_enrollment_attr(self.user.username, unicode(self.course.id), enrollment_attributes)
enrollment_attr = data.get_enrollment_attributes(self.user.username, unicode(self.course.id))
self.assertEqual(enrollment_attr[0], enrollment_attributes[0])
@raises(CourseNotFoundError)
def test_non_existent_course(self):
data.get_course_enrollment_info("this/is/bananas")

View File

@@ -46,6 +46,7 @@ class EnrollmentTestMixin(object):
as_server=False,
mode=CourseMode.HONOR,
is_active=None,
enrollment_attributes=None,
):
"""
Enroll in the course and verify the response's status code. If the expected status is 200, also validates
@@ -62,7 +63,8 @@ class EnrollmentTestMixin(object):
'course_details': {
'course_id': course_id
},
'user': username
'user': username,
'enrollment_attributes': enrollment_attributes
}
if is_active is not None:
@@ -547,6 +549,78 @@ class EnrollmentTest(EnrollmentTestMixin, ModuleStoreTestCase, APITestCase):
self.assertTrue(is_active)
self.assertEqual(course_mode, CourseMode.VERIFIED)
def test_enrollment_with_credit_mode(self):
"""With the right API key, update an existing enrollment with credit
mode and set enrollment attributes.
"""
for mode in [CourseMode.HONOR, CourseMode.CREDIT_MODE]:
CourseModeFactory.create(
course_id=self.course.id,
mode_slug=mode,
mode_display_name=mode,
)
# Create an enrollment
self.assert_enrollment_status(as_server=True)
# Check that the enrollment is honor.
self.assertTrue(CourseEnrollment.is_enrolled(self.user, self.course.id))
course_mode, is_active = CourseEnrollment.enrollment_mode_for_user(self.user, self.course.id)
self.assertTrue(is_active)
self.assertEqual(course_mode, CourseMode.HONOR)
# Check that the enrollment upgraded to credit.
enrollment_attributes = [{
"namespace": "credit",
"name": "provider_id",
"value": "hogwarts",
}]
self.assert_enrollment_status(
as_server=True,
mode=CourseMode.CREDIT_MODE,
expected_status=status.HTTP_200_OK,
enrollment_attributes=enrollment_attributes
)
course_mode, is_active = CourseEnrollment.enrollment_mode_for_user(self.user, self.course.id)
self.assertTrue(is_active)
self.assertEqual(course_mode, CourseMode.CREDIT_MODE)
def test_enrollment_with_invalid_attr(self):
"""Check response status is bad request when invalid enrollment
attributes are passed
"""
for mode in [CourseMode.HONOR, CourseMode.CREDIT_MODE]:
CourseModeFactory.create(
course_id=self.course.id,
mode_slug=mode,
mode_display_name=mode,
)
# Create an enrollment
self.assert_enrollment_status(as_server=True)
# Check that the enrollment is honor.
self.assertTrue(CourseEnrollment.is_enrolled(self.user, self.course.id))
course_mode, is_active = CourseEnrollment.enrollment_mode_for_user(self.user, self.course.id)
self.assertTrue(is_active)
self.assertEqual(course_mode, CourseMode.HONOR)
# Check that the enrollment upgraded to credit.
enrollment_attributes = [{
"namespace": "credit",
"name": "invalid",
"value": "hogwarts",
}]
self.assert_enrollment_status(
as_server=True,
mode=CourseMode.CREDIT_MODE,
expected_status=status.HTTP_400_BAD_REQUEST,
enrollment_attributes=enrollment_attributes
)
course_mode, is_active = CourseEnrollment.enrollment_mode_for_user(self.user, self.course.id)
self.assertTrue(is_active)
self.assertEqual(course_mode, CourseMode.HONOR)
def test_downgrade_enrollment_with_mode(self):
"""With the right API key, downgrade an existing enrollment with a new mode. """
# Create an honor and verified mode for a course. This allows an update.

View File

@@ -5,7 +5,6 @@ consist primarily of authentication, request validation, and serialization.
"""
import logging
from ipware.ip import get_ip
from django.core.exceptions import ObjectDoesNotExist
from django.utils.decorators import method_decorator
from opaque_keys import InvalidKeyError
@@ -33,7 +32,11 @@ from enrollment.errors import (
)
from student.models import User
log = logging.getLogger(__name__)
REQUIRED_ATTRIBUTES = {
"credit": ["credit:provider_id"],
}
class EnrollmentCrossDomainSessionAuth(SessionAuthenticationAllowInactiveUser, SessionAuthenticationCrossDomainCsrf):
@@ -264,9 +267,13 @@ class EnrollmentListView(APIView, ApiKeyPermissionMixIn):
If honor mode is not supported for the course, the request fails and returns the available modes.
A server-to-server call can be used by this command to enroll a user in other modes, such as "verified"
or "professional". If the mode is not supported for the course, the request will fail and return the
available modes.
A server-to-server call can be used by this command to enroll a user in other modes, such as "verified",
"professional" or "credit". If the mode is not supported for the course, the request will fail and
return the available modes.
You can include other parameters as enrollment attributes for specific course mode as needed. For
example, for credit mode, you can include parameters namespace:'credit', name:'provider_id',
value:'UniversityX' to specify credit provider attribute.
**Example Requests**:
@@ -274,6 +281,12 @@ class EnrollmentListView(APIView, ApiKeyPermissionMixIn):
POST /api/enrollment/v1/enrollment{"mode": "honor", "course_details":{"course_id": "edX/DemoX/Demo_Course"}}
POST /api/enrollment/v1/enrollment{
"mode": "credit",
"course_details":{"course_id": "edX/DemoX/Demo_Course"},
"enrollment_attributes":[{"namespace": "credit","name": "provider_id","value": "hogwarts",},]
}
**Post Parameters**
* user: The username of the currently logged in user. Optional.
@@ -292,6 +305,12 @@ class EnrollmentListView(APIView, ApiKeyPermissionMixIn):
* email_opt_in: A Boolean indicating whether the user
wishes to opt into email from the organization running this course. Optional.
* enrollment_attributes: A list of dictionary that contains:
* namespace: Namespace of the attribute
* name: Name of the attribute
* value: Value of the attribute
**Response Values**
A collection of course enrollments for the user, or for the newly created enrollment.
@@ -335,7 +354,6 @@ class EnrollmentListView(APIView, ApiKeyPermissionMixIn):
* user: The username of the user.
"""
authentication_classes = OAuth2AuthenticationAllowInactiveUser, EnrollmentCrossDomainSessionAuth
permission_classes = ApiKeyHeaderPermissionIsAuthenticated,
throttle_classes = EnrollmentUserThrottle,
@@ -370,6 +388,7 @@ class EnrollmentListView(APIView, ApiKeyPermissionMixIn):
go through `add_enrollment()`, which allows creation of new and reactivation of old enrollments.
"""
# Get the User, Course ID, and Mode from the request.
username = request.DATA.get('user', request.user.username)
course_id = request.DATA.get('course_details', {}).get('course_id')
@@ -438,9 +457,17 @@ class EnrollmentListView(APIView, ApiKeyPermissionMixIn):
}
)
enrollment_attributes = request.DATA.get('enrollment_attributes')
enrollment = api.get_enrollment(username, unicode(course_id))
mode_changed = enrollment and mode is not None and enrollment['mode'] != mode
active_changed = enrollment and is_active is not None and enrollment['is_active'] != is_active
missing_attrs = []
if enrollment_attributes:
actual_attrs = [
u"{namespace}:{name}".format(**attr)
for attr in enrollment_attributes
]
missing_attrs = set(REQUIRED_ATTRIBUTES.get(mode, [])) - set(actual_attrs)
if has_api_key_permissions and (mode_changed or active_changed):
if mode_changed and active_changed and not is_active:
# if the requester wanted to deactivate but specified the wrong mode, fail
@@ -451,7 +478,21 @@ class EnrollmentListView(APIView, ApiKeyPermissionMixIn):
)
log.warning(msg)
return Response(status=status.HTTP_400_BAD_REQUEST, data={"message": msg})
response = api.update_enrollment(username, unicode(course_id), mode=mode, is_active=is_active)
if len(missing_attrs) > 0:
msg = u"Missing enrollment attributes: requested mode={} required attributes={}".format(
mode, REQUIRED_ATTRIBUTES.get(mode)
)
log.warning(msg)
return Response(status=status.HTTP_400_BAD_REQUEST, data={"message": msg})
response = api.update_enrollment(
username,
unicode(course_id),
mode=mode,
is_active=is_active,
enrollment_attributes=enrollment_attributes
)
else:
# Will reactivate inactive enrollments.
response = api.add_enrollment(username, unicode(course_id), mode=mode, is_active=is_active)

View File

@@ -23,8 +23,9 @@ VERIFY_STATUS_MISSED_DEADLINE = "verify_missed_deadline"
VERIFY_STATUS_NEED_TO_REVERIFY = "verify_need_to_reverify"
def check_verify_status_by_course(user, course_enrollment_pairs, all_course_modes):
"""Determine the per-course verification statuses for a given user.
def check_verify_status_by_course(user, course_enrollments, all_course_modes):
"""
Determine the per-course verification statuses for a given user.
The possible statuses are:
* VERIFY_STATUS_NEED_TO_VERIFY: The student has not yet submitted photos for verification.
@@ -46,8 +47,7 @@ def check_verify_status_by_course(user, course_enrollment_pairs, all_course_mode
Arguments:
user (User): The currently logged-in user.
course_enrollment_pairs (list): The courses the user is enrolled in.
The list should contain tuples of `(Course, CourseEnrollment)`.
course_enrollments (list[CourseEnrollment]): The courses the user is enrolled in.
all_course_modes (list): List of all course modes for the student's enrolled courses,
including modes that have expired.
@@ -75,15 +75,15 @@ def check_verify_status_by_course(user, course_enrollment_pairs, all_course_mode
recent_verification_datetime = None
for course, enrollment in course_enrollment_pairs:
for enrollment in course_enrollments:
# Get the verified mode (if any) for this course
# We pass in the course modes we have already loaded to avoid
# another database hit, as well as to ensure that expired
# course modes are included in the search.
verified_mode = CourseMode.verified_mode_for_course(
course.id,
modes=all_course_modes[course.id]
enrollment.course_id,
modes=all_course_modes[enrollment.course_id]
)
# If no verified mode has ever been offered, or the user hasn't enrolled
@@ -156,7 +156,7 @@ def check_verify_status_by_course(user, course_enrollment_pairs, all_course_mode
if deadline is not None and deadline > now:
days_until_deadline = (deadline - now).days
status_by_course[course.id] = {
status_by_course[enrollment.course_id] = {
'status': status,
'days_until_deadline': days_until_deadline
}

View File

@@ -850,6 +850,13 @@ class CourseEnrollment(models.Model):
unique_together = (('user', 'course_id'),)
ordering = ('user', 'course_id')
def __init__(self, *args, **kwargs):
super(CourseEnrollment, self).__init__(*args, **kwargs)
# Private variable for storing course_overview to minimize calls to the database.
# When the property .course_overview is accessed for the first time, this variable will be set.
self._course_overview = None
def __unicode__(self):
return (
"[CourseEnrollment] {}: {} ({}); active: ({})"
@@ -1318,10 +1325,21 @@ class CourseEnrollment(models.Model):
@property
def course_overview(self):
"""
Return a CourseOverview of this enrollment's course.
"""
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
return CourseOverview.get_from_id(self.course_id)
Returns a CourseOverview of the course to which this enrollment refers.
Returns None if an error occurred while trying to load the course.
Note:
If the course is re-published within the lifetime of this
CourseEnrollment object, then the value of this property will
become stale.
"""
if not self._course_overview:
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
try:
self._course_overview = CourseOverview.get_from_id(self.course_id)
except (CourseOverview.DoesNotExist, IOError):
self._course_overview = None
return self._course_overview
def is_verified_enrollment(self):
"""
@@ -1854,3 +1872,47 @@ class CourseEnrollmentAttribute(models.Model):
name=self.name,
value=self.value,
)
@classmethod
def add_enrollment_attr(cls, enrollment, data_list):
"""Delete all the enrollment attributes for the given enrollment and
add new attributes.
Args:
enrollment(CourseEnrollment): 'CourseEnrollment' for which attribute is to be added
data(list): list of dictionaries containing data to save
"""
cls.objects.filter(enrollment=enrollment).delete()
attributes = [
cls(enrollment=enrollment, namespace=data['namespace'], name=data['name'], value=data['value'])
for data in data_list
]
cls.objects.bulk_create(attributes)
@classmethod
def get_enrollment_attributes(cls, enrollment):
"""Retrieve list of all enrollment attributes.
Args:
enrollment(CourseEnrollment): 'CourseEnrollment' for which list is to retrieve
Returns: list
Example:
>>> CourseEnrollmentAttribute.get_enrollment_attributes(CourseEnrollment)
[
{
"namespace": "credit",
"name": "provider_id",
"value": "hogwarts",
},
]
"""
return [
{
"namespace": attribute.namespace,
"name": attribute.name,
"value": attribute.value,
}
for attribute in cls.objects.filter(enrollment=enrollment)
]

View File

@@ -47,9 +47,14 @@ class CertificateDisplayTest(ModuleStoreTestCase):
@patch.dict('django.conf.settings.FEATURES', {'CERTIFICATES_HTML_VIEW': True})
def test_display_download_certificate_button(self, enrollment_mode):
"""
Tests if CERTIFICATES_HTML_VIEW is True and there is no active certificate configuration available
Tests if CERTIFICATES_HTML_VIEW is True
and course has enabled web certificates via cert_html_view_enabled setting
and no active certificate configuration available
then any of the Download certificate button should not be visible.
"""
self.course.cert_html_view_enabled = True
self.course.save()
self.store.update_item(self.course, self.user.id)
self._create_certificate(enrollment_mode)
self._check_can_not_download_certificate()
@@ -59,8 +64,7 @@ class CertificateDisplayTest(ModuleStoreTestCase):
def test_linked_student_to_web_view_credential(self, enrollment_mode):
test_url = get_certificate_url(
user_id=self.user.id,
course_id=unicode(self.course.id),
verify_uuid='abcdefg12345678'
course_id=unicode(self.course.id)
)
self._create_certificate(enrollment_mode)
@@ -75,6 +79,7 @@ class CertificateDisplayTest(ModuleStoreTestCase):
}
]
self.course.certificates = {'certificates': certificates}
self.course.cert_html_view_enabled = True
self.course.save() # pylint: disable=no-member
self.store.update_item(self.course, self.user.id)

View File

@@ -14,7 +14,7 @@ from xmodule.modulestore.django import modulestore
from xmodule.error_module import ErrorDescriptor
from django.test.client import Client
from student.models import CourseEnrollment
from student.views import get_course_enrollment_pairs
from student.views import get_course_enrollments
from util.milestones_helpers import (
get_pre_requisite_courses_not_completed,
set_prerequisite_courses,
@@ -73,13 +73,13 @@ class TestCourseListing(ModuleStoreTestCase):
self._create_course_with_access_groups(course_location)
# get dashboard
courses_list = list(get_course_enrollment_pairs(self.student, None, []))
courses_list = list(get_course_enrollments(self.student, None, []))
self.assertEqual(len(courses_list), 1)
self.assertEqual(courses_list[0][0].id, course_location)
self.assertEqual(courses_list[0].course_id, course_location)
CourseEnrollment.unenroll(self.student, course_location)
# get dashboard
courses_list = list(get_course_enrollment_pairs(self.student, None, []))
courses_list = list(get_course_enrollments(self.student, None, []))
self.assertEqual(len(courses_list), 0)
def test_errored_course_regular_access(self):
@@ -95,7 +95,7 @@ class TestCourseListing(ModuleStoreTestCase):
self.assertIsInstance(modulestore().get_course(course_key), ErrorDescriptor)
# get courses through iterating all courses
courses_list = list(get_course_enrollment_pairs(self.student, None, []))
courses_list = list(get_course_enrollments(self.student, None, []))
self.assertEqual(courses_list, [])
def test_course_listing_errored_deleted_courses(self):
@@ -112,9 +112,9 @@ class TestCourseListing(ModuleStoreTestCase):
self._create_course_with_access_groups(course_location, default_store=ModuleStoreEnum.Type.mongo)
mongo_store.delete_course(course_location, ModuleStoreEnum.UserID.test)
courses_list = list(get_course_enrollment_pairs(self.student, None, []))
courses_list = list(get_course_enrollments(self.student, None, []))
self.assertEqual(len(courses_list), 1, courses_list)
self.assertEqual(courses_list[0][0].id, good_location)
self.assertEqual(courses_list[0].course_id, good_location)
@mock.patch.dict("django.conf.settings.FEATURES", {'ENABLE_PREREQUISITE_COURSES': True, 'MILESTONES_APP': True})
def test_course_listing_has_pre_requisite_courses(self):
@@ -142,9 +142,11 @@ class TestCourseListing(ModuleStoreTestCase):
set_prerequisite_courses(course_location, pre_requisite_courses)
# get dashboard
course_enrollment_pairs = list(get_course_enrollment_pairs(self.student, None, []))
courses_having_prerequisites = frozenset(course.id for course, _enrollment in course_enrollment_pairs
if course.pre_requisite_courses)
course_enrollments = list(get_course_enrollments(self.student, None, []))
courses_having_prerequisites = frozenset(
enrollment.course_id for enrollment in course_enrollments
if enrollment.course_overview.pre_requisite_courses
)
courses_requirements_not_met = get_pre_requisite_courses_not_completed(
self.student,
courses_having_prerequisites

View File

@@ -4,6 +4,7 @@ Tests for credit courses on the student dashboard.
import unittest
import datetime
from mock import patch
import pytz
from mock import patch

View File

@@ -15,7 +15,7 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
from course_modes.tests.factories import CourseModeFactory
from student.models import CourseEnrollment, DashboardConfiguration
from student.views import get_course_enrollment_pairs, _get_recently_enrolled_courses
from student.views import get_course_enrollments, _get_recently_enrolled_courses # pylint: disable=protected-access
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
@@ -67,7 +67,7 @@ class TestRecentEnrollments(ModuleStoreTestCase):
self._configure_message_timeout(60)
# get courses through iterating all courses
courses_list = list(get_course_enrollment_pairs(self.student, None, []))
courses_list = list(get_course_enrollments(self.student, None, []))
self.assertEqual(len(courses_list), 2)
recent_course_list = _get_recently_enrolled_courses(courses_list)
@@ -78,7 +78,7 @@ class TestRecentEnrollments(ModuleStoreTestCase):
Tests that the recent enrollment list is empty if configured to zero seconds.
"""
self._configure_message_timeout(0)
courses_list = list(get_course_enrollment_pairs(self.student, None, []))
courses_list = list(get_course_enrollments(self.student, None, []))
self.assertEqual(len(courses_list), 2)
recent_course_list = _get_recently_enrolled_courses(courses_list)
@@ -106,16 +106,16 @@ class TestRecentEnrollments(ModuleStoreTestCase):
enrollment.save()
courses.append(course)
courses_list = list(get_course_enrollment_pairs(self.student, None, []))
courses_list = list(get_course_enrollments(self.student, None, []))
self.assertEqual(len(courses_list), 6)
recent_course_list = _get_recently_enrolled_courses(courses_list)
self.assertEqual(len(recent_course_list), 5)
self.assertEqual(recent_course_list[1][0], courses[0])
self.assertEqual(recent_course_list[2][0], courses[1])
self.assertEqual(recent_course_list[3][0], courses[2])
self.assertEqual(recent_course_list[4][0], courses[3])
self.assertEqual(recent_course_list[1].course, courses[0])
self.assertEqual(recent_course_list[2].course, courses[1])
self.assertEqual(recent_course_list[3].course, courses[2])
self.assertEqual(recent_course_list[4].course, courses[3])
def test_dashboard_rendering(self):
"""

View File

@@ -1,9 +1,6 @@
# -*- coding: utf-8 -*-
"""
This file demonstrates writing tests using the unittest module. These will pass
when you run "manage.py test".
Replace this with more appropriate tests for your application.
Miscellaneous tests for the student app.
"""
from datetime import datetime, timedelta
import logging
@@ -28,8 +25,8 @@ from student.views import (process_survey_link, _cert_info,
from student.tests.factories import UserFactory, CourseModeFactory
from util.testing import EventTestMixin
from util.model_utils import USER_SETTINGS_CHANGED_EVENT_NAME
from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, check_mongo_calls
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, ModuleStoreEnum
# These imports refer to lms djangoapps.
# Their testcases are only run under lms.
@@ -193,6 +190,7 @@ class CourseEndingTest(TestCase):
self.assertIsNone(_cert_info(user, course2, cert_status, course_mode))
@ddt.ddt
class DashboardTest(ModuleStoreTestCase):
"""
Tests for dashboard utility functions
@@ -487,6 +485,61 @@ class DashboardTest(ModuleStoreTestCase):
)
self.assertContains(response, expected_url)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
@ddt.data((ModuleStoreEnum.Type.mongo, 1), (ModuleStoreEnum.Type.split, 3))
@ddt.unpack
def test_dashboard_metadata_caching(self, modulestore_type, expected_mongo_calls):
"""
Check that the student dashboard makes use of course metadata caching.
The first time the student dashboard displays a specific course, it will
make a call to the module store. After that first request, though, the
course's metadata should be cached as a CourseOverview.
Arguments:
modulestore_type (ModuleStoreEnum.Type): Type of modulestore to create
test course in.
expected_mongo_calls (int >=0): Number of MongoDB queries expected for
a single call to the module store.
Note to future developers:
If you break this test so that the "check_mongo_calls(0)" fails,
please do NOT change it to "check_mongo_calls(n>1)". Instead, change
your code to not load courses from the module store. This may
involve adding fields to CourseOverview so that loading a full
CourseDescriptor isn't necessary.
"""
# Create a course, log in the user, and enroll them in the course.
test_course = CourseFactory.create(default_store=modulestore_type)
self.client.login(username="jack", password="test")
CourseEnrollment.enroll(self.user, test_course.id)
# The first request will result in a modulestore query.
with check_mongo_calls(expected_mongo_calls):
response_1 = self.client.get(reverse('dashboard'))
self.assertEquals(response_1.status_code, 200)
# Subsequent requests will only result in SQL queries to load the
# CourseOverview object that has been created.
with check_mongo_calls(0):
response_2 = self.client.get(reverse('dashboard'))
self.assertEquals(response_2.status_code, 200)
response_3 = self.client.get(reverse('dashboard'))
self.assertEquals(response_3.status_code, 200)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
@patch.dict(settings.FEATURES, {"IS_EDX_DOMAIN": True})
def test_dashboard_header_nav_has_find_courses(self):
self.client.login(username="jack", password="test")
response = self.client.get(reverse("dashboard"))
# "Find courses" is shown in the side panel
self.assertContains(response, "Find courses")
# But other links are hidden in the navigation
self.assertNotContains(response, "How it Works")
self.assertNotContains(response, "Schools & Partners")
class UserSettingsEventTestMixin(EventTestMixin):
"""

View File

@@ -4,7 +4,6 @@ Student Views
import datetime
import logging
import uuid
import time
import json
import warnings
from datetime import timedelta
@@ -59,7 +58,11 @@ from student.forms import AccountCreationForm, PasswordResetFormNoActive
from verify_student.models import SoftwareSecurePhotoVerification # pylint: disable=import-error
from certificates.models import CertificateStatuses, certificate_status_for_student
from certificates.api import get_certificate_url, get_active_web_certificate # pylint: disable=import-error
from certificates.api import ( # pylint: disable=import-error
get_certificate_url,
get_active_web_certificate,
has_html_certificates_enabled,
)
from dark_lang.models import DarkLangConfig
from xmodule.modulestore.django import modulestore
@@ -111,7 +114,6 @@ from student.helpers import (
)
from student.cookies import set_logged_in_cookies, delete_logged_in_cookies
from student.models import anonymous_id_for_user
from xmodule.error_module import ErrorDescriptor
from shoppingcart.models import DonationConfiguration, CourseRegistrationCode
from embargo import api as embargo_api
@@ -181,33 +183,42 @@ def process_survey_link(survey_link, user):
return survey_link.format(UNIQUE_ID=unique_id_for_user(user))
def cert_info(user, course, course_mode):
def cert_info(user, course_overview, course_mode):
"""
Get the certificate info needed to render the dashboard section for the given
student and course. Returns a dictionary with keys:
student and course.
'status': one of 'generating', 'ready', 'notpassing', 'processing', 'restricted'
'show_download_url': bool
'download_url': url, only present if show_download_url is True
'show_disabled_download_button': bool -- true if state is 'generating'
'show_survey_button': bool
'survey_url': url, only if show_survey_button is True
'grade': if status is not 'processing'
Arguments:
user (User): A user.
course_overview (CourseOverview): A course.
course_mode (str): The enrollment mode (honor, verified, audit, etc.)
Returns:
dict: A dictionary with keys:
'status': one of 'generating', 'ready', 'notpassing', 'processing', 'restricted'
'show_download_url': bool
'download_url': url, only present if show_download_url is True
'show_disabled_download_button': bool -- true if state is 'generating'
'show_survey_button': bool
'survey_url': url, only if show_survey_button is True
'grade': if status is not 'processing'
"""
if not course.may_certify():
if not course_overview.may_certify():
return {}
return _cert_info(user, course, certificate_status_for_student(user, course.id), course_mode)
return _cert_info(
user,
course_overview,
certificate_status_for_student(user, course_overview.id),
course_mode
)
def reverification_info(course_enrollment_pairs, user, statuses):
def reverification_info(statuses):
"""
Returns reverification-related information for *all* of user's enrollments whose
reverification status is in status_list
reverification status is in statuses.
Args:
course_enrollment_pairs (list): list of (course, enrollment) tuples
user (User): the user whose information we want
statuses (list): a list of reverification statuses we want information for
example: ["must_reverify", "denied"]
@@ -225,39 +236,56 @@ def reverification_info(course_enrollment_pairs, user, statuses):
return reverifications
def get_course_enrollment_pairs(user, course_org_filter, org_filter_out_set):
def get_course_enrollments(user, org_to_include, orgs_to_exclude):
"""
Get the relevant set of (Course, CourseEnrollment) pairs to be displayed on
a student's dashboard.
Given a user, return a filtered set of his or her course enrollments.
Arguments:
user (User): the user in question.
org_to_include (str): for use in Microsites. If not None, ONLY courses
of this org will be returned.
orgs_to_exclude (list[str]): If org_to_include is not None, this
argument is ignored. Else, courses of this org will be excluded.
Returns:
generator[CourseEnrollment]: a sequence of enrollments to be displayed
on the user's dashboard.
"""
for enrollment in CourseEnrollment.enrollments_for_user(user):
store = modulestore()
with store.bulk_operations(enrollment.course_id):
course = store.get_course(enrollment.course_id)
if course and not isinstance(course, ErrorDescriptor):
# if we are in a Microsite, then filter out anything that is not
# attributed (by ORG) to that Microsite
if course_org_filter and course_org_filter != course.location.org:
continue
# Conversely, if we are not in a Microsite, then let's filter out any enrollments
# with courses attributed (by ORG) to Microsites
elif course.location.org in org_filter_out_set:
continue
# If the course is missing or broken, log an error and skip it.
course_overview = enrollment.course_overview
if not course_overview:
log.error(
"User %s enrolled in broken or non-existent course %s",
user.username,
enrollment.course_id
)
continue
yield (course, enrollment)
else:
log.error(
u"User %s enrolled in %s course %s",
user.username,
"broken" if course else "non-existent",
enrollment.course_id
)
# If we are in a Microsite, then filter out anything that is not
# attributed (by ORG) to that Microsite.
if org_to_include and course_overview.location.org != org_to_include:
continue
# Conversely, if we are not in a Microsite, then filter out any enrollments
# with courses attributed (by ORG) to Microsites.
elif course_overview.location.org in orgs_to_exclude:
continue
# Else, include the enrollment.
else:
yield enrollment
def _cert_info(user, course, cert_status, course_mode):
def _cert_info(user, course_overview, cert_status, course_mode): # pylint: disable=unused-argument
"""
Implements the logic for cert_info -- split out for testing.
Arguments:
user (User): A user.
course_overview (CourseOverview): A course.
course_mode (str): The enrollment mode (honor, verified, audit, etc.)
"""
# simplify the status for the template using this lookup table
template_state = {
@@ -281,7 +309,7 @@ def _cert_info(user, course, cert_status, course_mode):
is_hidden_status = cert_status['status'] in ('unavailable', 'processing', 'generating', 'notpassing')
if course.certificates_display_behavior == 'early_no_info' and is_hidden_status:
if course_overview.certificates_display_behavior == 'early_no_info' and is_hidden_status:
return None
status = template_state.get(cert_status['status'], default_status)
@@ -295,21 +323,20 @@ def _cert_info(user, course, cert_status, course_mode):
}
if (status in ('generating', 'ready', 'notpassing', 'restricted') and
course.end_of_course_survey_url is not None):
course_overview.end_of_course_survey_url is not None):
status_dict.update({
'show_survey_button': True,
'survey_url': process_survey_link(course.end_of_course_survey_url, user)})
'survey_url': process_survey_link(course_overview.end_of_course_survey_url, user)})
else:
status_dict['show_survey_button'] = False
if status == 'ready':
# showing the certificate web view button if certificate is ready state and feature flags are enabled.
if settings.FEATURES.get('CERTIFICATES_HTML_VIEW', False):
if get_active_web_certificate(course) is not None:
if has_html_certificates_enabled(course_overview.id, course_overview):
if course_overview.has_any_active_web_certificate:
certificate_url = get_certificate_url(
user_id=user.id,
course_id=unicode(course.id),
verify_uuid=None
course_id=unicode(course_overview.id),
)
status_dict.update({
'show_cert_web_view': True,
@@ -322,7 +349,7 @@ def _cert_info(user, course, cert_status, course_mode):
log.warning(
u"User %s has a downloadable cert for %s, but no download url",
user.username,
course.id
course_overview.id
)
return default_info
else:
@@ -334,8 +361,8 @@ def _cert_info(user, course, cert_status, course_mode):
linkedin_config = LinkedInAddToProfileConfiguration.current()
if linkedin_config.enabled:
status_dict['linked_in_url'] = linkedin_config.add_to_profile_url(
course.id,
course.display_name,
course_overview.id,
course_overview.display_name,
cert_status.get('mode'),
cert_status['download_url']
)
@@ -503,13 +530,13 @@ def dashboard(request):
# Build our (course, enrollment) list for the user, but ignore any courses that no
# longer exist (because the course IDs have changed). Still, we don't delete those
# enrollments, because it could have been a data push snafu.
course_enrollment_pairs = list(get_course_enrollment_pairs(user, course_org_filter, org_filter_out_set))
course_enrollments = list(get_course_enrollments(user, course_org_filter, org_filter_out_set))
# sort the enrollment pairs by the enrollment date
course_enrollment_pairs.sort(key=lambda x: x[1].created, reverse=True)
course_enrollments.sort(key=lambda x: x.created, reverse=True)
# Retrieve the course modes for each course
enrolled_course_ids = [course.id for course, __ in course_enrollment_pairs]
enrolled_course_ids = [enrollment.course_id for enrollment in course_enrollments]
all_course_modes, unexpired_course_modes = CourseMode.all_and_unexpired_modes_for_courses(enrolled_course_ids)
course_modes_by_course = {
course_id: {
@@ -522,14 +549,9 @@ def dashboard(request):
# Check to see if the student has recently enrolled in a course.
# If so, display a notification message confirming the enrollment.
enrollment_message = _create_recent_enrollment_message(
course_enrollment_pairs, course_modes_by_course
course_enrollments, course_modes_by_course
)
# Retrieve the course modes for each course
enrolled_courses_dict = {}
for course, __ in course_enrollment_pairs:
enrolled_courses_dict[unicode(course.id)] = course
course_optouts = Optout.objects.filter(user=user).values_list('course_id', flat=True)
message = ""
@@ -548,20 +570,20 @@ def dashboard(request):
errored_courses = modulestore().get_errored_courses()
show_courseware_links_for = frozenset(
course.id for course, _enrollment in course_enrollment_pairs
if has_access(request.user, 'load', course)
and has_access(request.user, 'view_courseware_with_prerequisites', course)
enrollment.course_id for enrollment in course_enrollments
if has_access(request.user, 'load', enrollment.course_overview)
and has_access(request.user, 'view_courseware_with_prerequisites', enrollment.course_overview)
)
# Construct a dictionary of course mode information
# used to render the course list. We re-use the course modes dict
# we loaded earlier to avoid hitting the database.
course_mode_info = {
course.id: complete_course_mode_info(
course.id, enrollment,
modes=course_modes_by_course[course.id]
enrollment.course_id: complete_course_mode_info(
enrollment.course_id, enrollment,
modes=course_modes_by_course[enrollment.course_id]
)
for course, enrollment in course_enrollment_pairs
for enrollment in course_enrollments
}
# Determine the per-course verification status
@@ -580,20 +602,20 @@ def dashboard(request):
# there is no verification messaging to display.
verify_status_by_course = check_verify_status_by_course(
user,
course_enrollment_pairs,
course_enrollments,
all_course_modes
)
cert_statuses = {
course.id: cert_info(request.user, course, _enrollment.mode)
for course, _enrollment in course_enrollment_pairs
enrollment.course_id: cert_info(request.user, enrollment.course_overview, enrollment.mode)
for enrollment in course_enrollments
}
# only show email settings for Mongo course and when bulk email is turned on
show_email_settings_for = frozenset(
course.id for course, _enrollment in course_enrollment_pairs if (
enrollment.course_id for enrollment in course_enrollments if (
settings.FEATURES['ENABLE_INSTRUCTOR_EMAIL'] and
modulestore().get_modulestore_type(course.id) != ModuleStoreEnum.Type.xml and
CourseAuthorization.instructor_email_enabled(course.id)
modulestore().get_modulestore_type(enrollment.course_id) != ModuleStoreEnum.Type.xml and
CourseAuthorization.instructor_email_enabled(enrollment.course_id)
)
)
@@ -603,16 +625,29 @@ def dashboard(request):
# Gets data for midcourse reverifications, if any are necessary or have failed
statuses = ["approved", "denied", "pending", "must_reverify"]
reverifications = reverification_info(course_enrollment_pairs, user, statuses)
reverifications = reverification_info(statuses)
show_refund_option_for = frozenset(course.id for course, _enrollment in course_enrollment_pairs
if _enrollment.refundable())
show_refund_option_for = frozenset(
enrollment.course_id for enrollment in course_enrollments
if enrollment.refundable()
)
block_courses = frozenset(course.id for course, enrollment in course_enrollment_pairs
if is_course_blocked(request, CourseRegistrationCode.objects.filter(course_id=course.id, registrationcoderedemption__redeemed_by=request.user), course.id))
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(course.id for course, _enrollment in course_enrollment_pairs
if _enrollment.is_paid_course())
enrolled_courses_either_paid = frozenset(
enrollment.course_id for enrollment in course_enrollments
if enrollment.is_paid_course()
)
# If there are *any* denied reverifications that have not been toggled off,
# we'll display the banner
@@ -622,8 +657,10 @@ def dashboard(request):
order_history_list = order_history(user, course_org_filter=course_org_filter, org_filter_out_set=org_filter_out_set)
# get list of courses having pre-requisites yet to be completed
courses_having_prerequisites = frozenset(course.id for course, _enrollment in course_enrollment_pairs
if course.pre_requisite_courses)
courses_having_prerequisites = frozenset(
enrollment.course_id for enrollment in course_enrollments
if enrollment.course_overview.pre_requisite_courses
)
courses_requirements_not_met = get_pre_requisite_courses_not_completed(user, courses_having_prerequisites)
ccx_membership_triplets = []
@@ -635,7 +672,7 @@ def dashboard(request):
context = {
'enrollment_message': enrollment_message,
'course_enrollment_pairs': course_enrollment_pairs,
'course_enrollments': course_enrollments,
'course_optouts': course_optouts,
'message': message,
'staff_access': staff_access,
@@ -643,7 +680,7 @@ def dashboard(request):
'show_courseware_links_for': show_courseware_links_for,
'all_course_modes': course_mode_info,
'cert_statuses': cert_statuses,
'credit_statuses': _credit_statuses(user, course_enrollment_pairs),
'credit_statuses': _credit_statuses(user, course_enrollments),
'show_email_settings_for': show_email_settings_for,
'reverifications': reverifications,
'verification_status': verification_status,
@@ -661,18 +698,21 @@ def dashboard(request):
'order_history_list': order_history_list,
'courses_requirements_not_met': courses_requirements_not_met,
'ccx_membership_triplets': ccx_membership_triplets,
'nav_hidden': True,
}
return render_to_response('dashboard.html', context)
def _create_recent_enrollment_message(course_enrollment_pairs, course_modes):
"""Builds a recent course enrollment message
def _create_recent_enrollment_message(course_enrollments, course_modes): # pylint: disable=invalid-name
"""
Builds a recent course enrollment message.
Constructs a new message template based on any recent course enrollments for the student.
Constructs a new message template based on any recent course enrollments
for the student.
Args:
course_enrollment_pairs (list): A list of tuples containing courses, and the associated enrollment information.
course_enrollments (list[CourseEnrollment]): a list of course enrollments.
course_modes (dict): Mapping of course ID's to course mode dictionaries.
Returns:
@@ -680,16 +720,16 @@ def _create_recent_enrollment_message(course_enrollment_pairs, course_modes):
None if there are no recently enrolled courses.
"""
recently_enrolled_courses = _get_recently_enrolled_courses(course_enrollment_pairs)
recently_enrolled_courses = _get_recently_enrolled_courses(course_enrollments)
if recently_enrolled_courses:
messages = [
{
"course_id": course.id,
"course_name": course.display_name,
"allow_donation": _allow_donation(course_modes, course.id, enrollment)
"course_id": enrollment.course_overview.id,
"course_name": enrollment.course_overview.display_name,
"allow_donation": _allow_donation(course_modes, enrollment.course_overview.id, enrollment)
}
for course, enrollment in recently_enrolled_courses
for enrollment in recently_enrolled_courses
]
platform_name = microsite.get_value('platform_name', settings.PLATFORM_NAME)
@@ -700,22 +740,20 @@ def _create_recent_enrollment_message(course_enrollment_pairs, course_modes):
)
def _get_recently_enrolled_courses(course_enrollment_pairs):
"""Checks to see if the student has recently enrolled in courses.
Checks to see if any of the enrollments in the course_enrollment_pairs have been recently created and activated.
def _get_recently_enrolled_courses(course_enrollments):
"""
Given a list of enrollments, filter out all but recent enrollments.
Args:
course_enrollment_pairs (list): A list of tuples containing courses, and the associated enrollment information.
course_enrollments (list[CourseEnrollment]): A list of course enrollments.
Returns:
A list of courses
list[CourseEnrollment]: A list of recent course enrollments.
"""
seconds = DashboardConfiguration.current().recent_enrollment_time_delta
time_delta = (datetime.datetime.now(UTC) - datetime.timedelta(seconds=seconds))
return [
(course, enrollment) for course, enrollment in course_enrollment_pairs
enrollment for enrollment in course_enrollments
# If the enrollment has no created date, we are explicitly excluding the course
# from the list of recent enrollments.
if enrollment.is_active and enrollment.created > time_delta
@@ -749,7 +787,7 @@ def _update_email_opt_in(request, org):
preferences_api.update_email_opt_in(request.user, org, email_opt_in_boolean)
def _credit_statuses(user, course_enrollment_pairs):
def _credit_statuses(user, course_enrollments):
"""
Retrieve the status for credit courses.
@@ -765,7 +803,8 @@ def _credit_statuses(user, course_enrollment_pairs):
Arguments:
user (User): The currently logged-in user.
course_enrollment_pairs (list): List of (Course, CourseEnrollment) tuples.
course_enrollments (list[CourseEnrollment]): List of enrollments for the
user.
Returns: dict
@@ -782,7 +821,7 @@ def _credit_statuses(user, course_enrollment_pairs):
so the user should contact the support team.
Example:
>>> _credit_statuses(user, course_enrollment_pairs)
>>> _credit_statuses(user, course_enrollments)
{
CourseKey.from_string("edX/DemoX/Demo_Course"): {
"course_key": "edX/DemoX/Demo_Course",
@@ -809,8 +848,8 @@ def _credit_statuses(user, course_enrollment_pairs):
}
credit_enrollments = {
course.id: enrollment
for course, enrollment in course_enrollment_pairs
enrollment.course_id: enrollment
for enrollment in course_enrollments
if enrollment.mode == "credit"
}
@@ -842,6 +881,7 @@ def _credit_statuses(user, course_enrollment_pairs):
"purchased": course_key in credit_enrollments,
"provider_name": None,
"provider_status_url": None,
"provider_id": None,
"request_status": request_status_by_course.get(course_key),
"error": False,
}
@@ -865,6 +905,7 @@ def _credit_statuses(user, course_enrollment_pairs):
provider_info = provider_info_by_id.get(provider_id, {})
status["provider_name"] = provider_info.get("display_name")
status["provider_status_url"] = provider_info.get("status_url")
status["provider_id"] = provider_id
statuses[course_key] = status

View File

@@ -9,6 +9,7 @@ from django.utils.translation import ugettext as _
from opaque_keys import InvalidKeyError
from opaque_keys.edx.keys import CourseKey
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
from xmodule.modulestore.django import modulestore
NAMESPACE_CHOICES = {
@@ -86,33 +87,46 @@ 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):
def get_pre_requisite_courses_not_completed(user, enrolled_courses): # pylint: disable=invalid-name
"""
It would make dict of prerequisite courses not completed by user among courses
user has enrolled in. It calls the fulfilment api of milestones app and
iterates over all fulfilment milestones not achieved to make dict of
prerequisite courses yet to be completed.
"""
pre_requisite_courses = {}
if settings.FEATURES.get('ENABLE_PREREQUISITE_COURSES', False):
from milestones import api as milestones_api
for course_key in enrolled_courses:
required_courses = []
fulfilment_paths = milestones_api.get_course_milestones_fulfillment_paths(course_key, {'id': user.id})
for milestone_key, milestone_value in fulfilment_paths.items(): # pylint: disable=unused-variable
for key, value in milestone_value.items():
if key == 'courses' and value:
for required_course in value:
required_course_key = CourseKey.from_string(required_course)
required_course_descriptor = modulestore().get_course(required_course_key)
required_courses.append({
'key': required_course_key,
'display': get_course_display_name(required_course_descriptor)
})
Makes a dict mapping courses to their unfulfilled milestones using the
fulfillment API of the milestones app.
Arguments:
user (User): the user for whom we are checking prerequisites.
enrolled_courses (CourseKey): a list of keys for the courses to be
checked. The given user must be enrolled in all of these courses.
Returns:
dict[CourseKey: dict[
'courses': list[dict['key': CourseKey, 'display': str]]
]]
If a course has no incomplete prerequisites, it will be excluded from the
dictionary.
"""
if not settings.FEATURES.get('ENABLE_PREREQUISITE_COURSES', False):
return {}
from milestones import api as milestones_api
pre_requisite_courses = {}
for course_key in enrolled_courses:
required_courses = []
fulfillment_paths = milestones_api.get_course_milestones_fulfillment_paths(course_key, {'id': user.id})
for __, milestone_value in fulfillment_paths.items():
for key, value in milestone_value.items():
if key == 'courses' and value:
for required_course in value:
required_course_key = CourseKey.from_string(required_course)
required_course_overview = CourseOverview.get_from_id(required_course_key)
required_courses.append({
'key': required_course_key,
'display': get_course_display_string(required_course_overview)
})
# If there are required courses, add them to the result dict.
if required_courses:
pre_requisite_courses[course_key] = {'courses': required_courses}
# if there are required courses add to dict
if required_courses:
pre_requisite_courses[course_key] = {'courses': required_courses}
return pre_requisite_courses
@@ -129,15 +143,18 @@ def get_prerequisite_courses_display(course_descriptor):
required_course_descriptor = modulestore().get_course(course_key)
prc = {
'key': course_key,
'display': get_course_display_name(required_course_descriptor)
'display': get_course_display_string(required_course_descriptor)
}
pre_requisite_courses.append(prc)
return pre_requisite_courses
def get_course_display_name(descriptor):
def get_course_display_string(descriptor):
"""
It would return display name from given course descriptor
Returns a string to display for a course or course overview.
Arguments:
descriptor (CourseDescriptor|CourseOverview): a course or course overview.
"""
return ' '.join([
descriptor.display_org_with_default,

View File

@@ -8,6 +8,6 @@ setup(
"pyparsing==2.0.1",
"numpy",
"scipy",
"nltk==2.0.5",
"nltk<3.0",
],
)

View File

@@ -20,6 +20,7 @@ from xmodule.tabs import CourseTabList
from xmodule.mixin import LicenseMixin
import json
from xblock.core import XBlock
from xblock.fields import Scope, List, String, Dict, Boolean, Integer, Float
from .fields import Date
from django.utils.timezone import UTC
@@ -712,6 +713,12 @@ class CourseFields(object):
scope=Scope.settings,
default=""
)
cert_html_view_enabled = Boolean(
display_name=_("Certificate Web/HTML View Enabled"),
help=_("If true, certificate Web/HTML views are enabled for the course."),
scope=Scope.settings,
default=False,
)
cert_html_view_overrides = Dict(
# Translators: This field is the container for course-specific certifcate configuration values
display_name=_("Certificate Web/HTML View Overrides"),
@@ -1315,11 +1322,15 @@ class CourseDescriptor(CourseFields, SequenceDescriptor, LicenseMixin):
except UndefinedContext:
module = self
def possibly_scored(usage_key):
"""Can this XBlock type can have a score or children?"""
return usage_key.block_type in self.block_types_affecting_grading
all_descriptors = []
graded_sections = {}
def yield_descriptor_descendents(module_descriptor):
for child in module_descriptor.get_children():
for child in module_descriptor.get_children(usage_key_filter=possibly_scored):
yield child
for module_descriptor in yield_descriptor_descendents(child):
yield module_descriptor
@@ -1345,6 +1356,15 @@ class CourseDescriptor(CourseFields, SequenceDescriptor, LicenseMixin):
return {'graded_sections': graded_sections,
'all_descriptors': all_descriptors, }
@lazy
def block_types_affecting_grading(self):
"""Return all block types that could impact grading (i.e. scored, or having children)."""
return frozenset(
cat for (cat, xblock_class) in XBlock.load_classes() if (
getattr(xblock_class, 'has_score', False) or getattr(xblock_class, 'has_children', False)
)
)
@staticmethod
def make_id(org, course, url_name):
return '/'.join([org, course, url_name])

View File

@@ -333,6 +333,30 @@ function (VideoPlayer) {
});
});
describe('onSeek Youtube', function(){
beforeEach(function () {
state = jasmine.initializePlayerYouTube();
state.videoEl = $('video, iframe');
});
describe('when the video is playing', function () {
beforeEach(function(){
state.videoPlayer.onStateChange({
data: YT.PlayerState.PLAYING
});
});
it('Video has started playing', function () {
expect($('.video_control')).toHaveClass('pause');
});
it('seek the player', function () {
state.videoPlayer.seekTo(10);
expect(state.videoPlayer.currentTime).toBe(10);
});
});
});
describe('onSeek', function () {
beforeEach(function () {
state = jasmine.initializePlayer();

View File

@@ -493,8 +493,6 @@ function (HTML5Video, Resizer) {
if (this.videoPlayer.isPlaying()) {
this.videoPlayer.stopTimer();
} else {
this.videoPlayer.currentTime = time;
}
var isUnplayed = this.videoPlayer.isUnstarted() ||
this.videoPlayer.isCued();
@@ -521,6 +519,8 @@ function (HTML5Video, Resizer) {
if (this.videoPlayer.isPlaying()) {
this.videoPlayer.runTimer();
}
// Update the the current time when user seek. (YoutubePlayer)
this.videoPlayer.currentTime = time;
}
function runTimer() {

View File

@@ -2397,6 +2397,8 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
parent_block.edit_info.edited_by = user_id
parent_block.edit_info.previous_version = parent_block.edit_info.update_version
parent_block.edit_info.update_version = new_id
# remove the source_version reference
parent_block.edit_info.source_version = None
self.decache_block(usage_locator.course_key, new_id, parent_block_key)
self._remove_subtree(BlockKey.from_usage_key(usage_locator), new_blocks)

View File

@@ -592,6 +592,49 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
# Verify that changes are present
self.assertTrue(self.store.has_changes(component))
@ddt.data('draft', 'split')
def test_unit_stuck_in_published_mode_after_delete(self, default_ms):
"""
Test that a unit does not get stuck in published mode
after discarding a component changes and deleting a component
"""
self.initdb(default_ms)
test_course = self.store.create_course('testx', 'GreekHero', 'test_run', self.user_id)
# Create a dummy vertical & html component to test against
vertical = self.store.create_item(
self.user_id,
test_course.id,
'vertical',
block_id='test_vertical'
)
component = self.store.create_child(
self.user_id,
vertical.location,
'html',
block_id='html_component'
)
# publish vertical changes
self.store.publish(vertical.location, self.user_id)
self.assertFalse(self._has_changes(vertical.location))
# Change a component, then check that there now are changes
component = self.store.get_item(component.location)
component.display_name = 'Changed Display Name'
self.store.update_item(component, self.user_id)
self.assertTrue(self._has_changes(vertical.location))
# Discard changes and verify that there are no changes
self.store.revert_to_published(vertical.location, self.user_id)
self.assertFalse(self._has_changes(vertical.location))
# Delete the component and verify that the unit has changes
self.store.delete_item(component.location, self.user_id)
vertical = self.store.get_item(vertical.location)
self.assertTrue(self._has_changes(vertical.location))
def setup_has_changes(self, default_ms):
"""
Common set up for has_changes tests below.

View File

@@ -41,9 +41,7 @@ class RandomizeModule(RandomizeFields, XModule):
def __init__(self, *args, **kwargs):
super(RandomizeModule, self).__init__(*args, **kwargs)
# NOTE: calling self.get_children() creates a circular reference--
# it calls get_child_descriptors() internally, but that doesn't work until
# we've picked a choice
# NOTE: calling self.get_children() doesn't work until we've picked a choice
num_choices = len(self.descriptor.get_children())
if self.choice > num_choices:
@@ -59,14 +57,23 @@ class RandomizeModule(RandomizeFields, XModule):
self.choice = random.randrange(0, num_choices)
if self.choice is not None:
self.child_descriptor = self.descriptor.get_children()[self.choice]
# Now get_children() should return a list with one element
log.debug("children of randomize module (should be only 1): %s",
self.get_children())
self.child = self.get_children()[0]
else:
self.child_descriptor = None
self.child = None
log.debug("children of randomize module (should be only 1): %s", self.child)
@property
def child_descriptor(self):
""" Return descriptor of selected choice """
if self.choice is None:
return None
return self.descriptor.get_children()[self.choice]
@property
def child(self):
""" Return module instance of selected choice """
child_descriptor = self.child_descriptor
if child_descriptor is None:
return None
return self.system.get_module(child_descriptor)
def get_child_descriptors(self):
"""

View File

@@ -27,7 +27,7 @@ metadata:
||A fruit is the fertilized ovary from a flower.||
||A fruit contains seeds of the plant.||
tab: hint
hinted: true
data: |
<problem>

View File

@@ -20,7 +20,7 @@ metadata:
||A fruit is the fertilized ovary from a flower.||
||A fruit contains seeds of the plant.||
tab: hint
hinted: true
data: |
<problem>

View File

@@ -24,7 +24,7 @@ metadata:
The mean is calculated by summing the set of numbers and dividing by n. In this case: (1 + 5 + 6 + 3 + 5) / 5 = 20 / 5 = 4.
[explanation]
tab: hint
hinted: true
data: |
<problem>

View File

@@ -23,7 +23,7 @@ metadata:
||A fruit is the fertilized ovary from a flower.||
||A fruit contains seeds of the plant.||
tab: hint
hinted: true
data: |
<problem>

View File

@@ -23,7 +23,7 @@ metadata:
||Consider the square miles, not population.||
||Consider all 50 states, not just the continental United States.||
tab: hint
hinted: true
data: |
<problem>

View File

@@ -1,36 +1,55 @@
import unittest
from datetime import datetime, timedelta
from django.utils.timezone import UTC
from opaque_keys.edx.locator import BlockUsageLocator
from xblock.fields import ScopeIds
from xmodule.randomize_module import RandomizeModule
from .test_course_module import DummySystem as DummyImportSystem
ORG = 'test_org'
COURSE = 'test_course'
START = '2013-01-01T01:00:00'
_TODAY = datetime.now(UTC())
_LAST_WEEK = _TODAY - timedelta(days=7)
_NEXT_WEEK = _TODAY + timedelta(days=7)
class RandomizeModuleTestCase(unittest.TestCase):
"""Make sure the randomize module works"""
@staticmethod
def get_dummy_course(start):
def setUp(self):
"""
Initialize dummy testing course.
"""
super(RandomizeModuleTestCase, self).setUp()
self.system = DummyImportSystem(load_error_modules=True)
self.system.seed = None
self.course = self.get_dummy_course()
self.modulestore = self.system.modulestore
def get_dummy_course(self, start=_TODAY):
"""Get a dummy course"""
system = DummyImportSystem(load_error_modules=True)
start_xml = '''
self.start_xml = '''
<course org="{org}" course="{course}"
graceperiod="1 day" url_name="test"
start="{start}"
>
<chapter url="hi" url_name="ch" display_name="CH">
start="{start}">
<chapter url="ch1" url_name="chapter1" display_name="CH1">
<randomize url_name="my_randomize">
<html url_name="a" display_name="A">Two houses, ...</html>
<html url_name="b" display_name="B">Three houses, ...</html>
</randomize>
</chapter>
<chapter url="ch2" url_name="chapter2" display_name="CH2">
</chapter>
</course>
'''.format(org=ORG, course=COURSE, start=start)
return system.process_xml(start_xml)
return self.system.process_xml(self.start_xml)
def test_import(self):
"""
@@ -38,5 +57,48 @@ class RandomizeModuleTestCase(unittest.TestCase):
"""
self.get_dummy_course(START)
# TODO: add tests that create a module and check. Passing state is a good way to
# check that child access works...
def test_course_has_started(self):
"""
Test CourseDescriptor.has_started.
"""
self.course.start = _LAST_WEEK
self.assertTrue(self.course.has_started())
self.course.start = _NEXT_WEEK
self.assertFalse(self.course.has_started())
def test_children(self):
""" Check course/randomize module works fine """
self.assertTrue(self.course.has_children)
self.assertEquals(len(self.course.get_children()), 2)
def inner_get_module(descriptor):
"""
Override systems.get_module
This method will be called when any call is made to self.system.get_module
"""
if isinstance(descriptor, BlockUsageLocator):
location = descriptor
descriptor = self.modulestore.get_item(location, depth=None)
descriptor.xmodule_runtime = self.get_dummy_course()
descriptor.xmodule_runtime.descriptor_runtime = descriptor._runtime # pylint: disable=protected-access
descriptor.xmodule_runtime.get_module = inner_get_module
return descriptor
self.system.get_module = inner_get_module
# Get randomize_descriptor from the course & verify its children
randomize_descriptor = inner_get_module(self.course.id.make_usage_key('randomize', 'my_randomize'))
self.assertTrue(randomize_descriptor.has_children)
self.assertEquals(len(randomize_descriptor.get_children()), 2)
# Call RandomizeModule which will select an element from the list of available items
randomize_module = RandomizeModule(
randomize_descriptor,
self.system,
scope_ids=ScopeIds(None, None, self.course.id, self.course.id)
)
# Verify the selected child
self.assertEquals(len(randomize_module.get_child_descriptors()), 1, "No child is chosen")
self.assertIn(randomize_module.child.display_name, ['A', 'B'], "Unwanted child selected")

View File

@@ -587,6 +587,12 @@ class XModuleMixin(XModuleFields, XBlock):
if field.scope.user == UserScope.ONE:
field._del_cached_value(self) # pylint: disable=protected-access
# not the most elegant way of doing this, but if we're removing
# a field from the module's field_data_cache, we should also
# remove it from its _dirty_fields
# pylint: disable=protected-access
if field in self._dirty_fields:
del self._dirty_fields[field]
# Set the new xmodule_runtime and field_data (which are user-specific)
self.xmodule_runtime = xmodule_runtime

View File

@@ -18,12 +18,12 @@ define(['sinon', 'underscore'], function(sinon, _) {
* Get a reference to the mocked server, and respond
* to all requests with the specified statusCode.
*/
fakeServer = function (statusCode, that) {
fakeServer = function (that, response) {
var server = sinon.fakeServer.create();
that.after(function() {
server.restore();
});
server.respondWith([statusCode, {}, '']);
server.respondWith(response);
return server;
};

View File

@@ -1,94 +0,0 @@
/**
* Adds rwd classes and click handlers.
*/
(function($) {
'use strict';
var rwd = (function() {
var _fn = {
header: 'header.global-new',
resultsUrl: 'course-search',
init: function() {
_fn.$header = $( _fn.header );
_fn.$footer = $( _fn.footer );
_fn.$navContainer = _fn.$header.find('.nav-container');
_fn.$globalNav = _fn.$header.find('.nav-global');
_fn.add.elements();
_fn.add.classes();
_fn.eventHandlers.init();
},
add: {
classes: function() {
// Add any RWD-specific classes
_fn.$header.addClass('rwd');
},
elements: function() {
_fn.add.burger();
_fn.add.registerLink();
},
burger: function() {
_fn.$navContainer.prepend([
'<a href="#" class="mobile-menu-button" aria-label="menu">',
'<i class="icon fa fa-bars" aria-hidden="true"></i>',
'</a>'
].join(''));
},
registerLink: function() {
var $register = _fn.$header.find('.cta-register'),
$li = {},
$a = {},
count = 0;
// Add if register link is shown
if ( $register.length > 0 ) {
count = _fn.$globalNav.find('li').length + 1;
// Create new li
$li = $('<li/>');
$li.addClass('desktop-hide nav-global-0' + count);
// Clone register link and remove classes
$a = $register.clone();
$a.removeClass();
// append to DOM
$a.appendTo( $li );
_fn.$globalNav.append( $li );
}
}
},
eventHandlers: {
init: function() {
_fn.eventHandlers.click();
},
click: function() {
// Toggle menu
_fn.$header.on( 'click', '.mobile-menu-button', _fn.toggleMenu );
}
},
toggleMenu: function( event ) {
event.preventDefault();
_fn.$globalNav.toggleClass('show');
}
};
return {
init: _fn.init
};
})();
rwd.init();
})(jQuery);

View File

@@ -56,4 +56,4 @@ class CertificatePage(PageObject):
"""
returns Facebook share button
"""
return self.q(css='a.action-share-facebook')
return self.q(css='button.action-share-facebook')

View File

@@ -49,20 +49,6 @@ class DashboardPage(PageObject):
return self.q(css='h3.course-title > a').map(_get_course_name).results
@property
def sidebar_menu_title(self):
"""
Return the title value for sidebar menu.
"""
return self.q(css='.user-info span.title').text[0]
@property
def sidebar_menu_description(self):
"""
Return the description text for sidebar menu.
"""
return self.q(css='.user-info span.copy').text[0]
def get_enrollment_mode(self, course_name):
"""Get the enrollment mode for a given course on the dashboard.

View File

@@ -281,6 +281,36 @@ class ContainerPage(PageObject):
"""
return "is-editing" in self.q(css=self.NAME_FIELD_WRAPPER_SELECTOR).first.attrs("class")[0]
def get_category_tab_names(self, category_type):
"""
Returns list of tab name in a category.
Arguments:
category_type (str): category type
Returns:
list
"""
self.q(css='.add-xblock-component-button[data-type={}]'.format(category_type)).first.click()
return self.q(css='.{}-type-tabs>li>a'.format(category_type)).text
def get_category_tab_components(self, category_type, tab_index):
"""
Return list of component names in a tab in a category.
Arguments:
category_type (str): category type
tab_index (int): tab index in a category
Returns:
list
"""
css = '#tab{tab_index} a[data-category={category_type}] span'.format(
tab_index=tab_index,
category_type=category_type
)
return self.q(css=css).html
class XBlockWrapper(PageObject):
"""

View File

@@ -256,6 +256,9 @@ class StudioLibraryContainerXBlockWrapper(XBlockWrapper):
self.q(css=btn_selector).first.click()
# This causes a reload (see cms/static/xmodule_js/public/js/library_content_edit.js)
# Check that the ajax request that caused the reload is done.
self.wait_for_ajax()
# Then check that we are still on the right page.
self.wait_for(lambda: self.is_browser_on_page(), 'StudioLibraryContainerXBlockWrapper has reloaded.')
# Wait longer than the default 60 seconds, because this was intermittently failing on jenkins
# with the screenshot showing that the Loading indicator was still visible. See TE-745.

View File

@@ -201,4 +201,5 @@ class AdvancedSettingsPage(CoursePage):
'social_sharing_url',
'teams_configuration',
'video_bumper',
'cert_html_view_enabled',
]

View File

@@ -36,8 +36,11 @@ class CertificateWebViewTest(EventsTestMixin, UniqueCourseTest):
self.course_info["display_name"],
settings=course_settings
)
self.course_fixture.add_advanced_settings({
"cert_html_view_enabled": {"value": "true"}
})
self.course_fixture.install()
self.user_id = "99" # we have createad a user with this id in fixture
self.user_id = "99" # we have created a user with this id in fixture
self.cert_fixture = CertificateConfigFixture(self.course_id, test_certificate_config)
# Load certificate web view page for use by the tests

View File

@@ -468,6 +468,7 @@ class OwnLearnerProfilePageTest(LearnerProfileTestMixin, WebAppTest):
self.assert_default_image_has_public_access(profile_page)
@flaky # TODO fix this, see TNL-2704
def test_user_can_upload_the_profile_image_with_success(self):
"""
Scenario: Upload profile image works correctly.

View File

@@ -268,12 +268,6 @@ class RegisterFromCombinedPageTest(UniqueCourseTest):
course_names = self.dashboard_page.wait_for_page().available_courses
self.assertIn(self.course_info["display_name"], course_names)
self.assertEqual("want to change your account settings?", self.dashboard_page.sidebar_menu_title.lower())
self.assertEqual(
"click the arrow next to your username above.",
self.dashboard_page.sidebar_menu_description.lower()
)
def test_register_failure(self):
# Navigate to the registration page
self.register_page.visit()

View File

@@ -8,6 +8,7 @@ from unittest import skip
from ...fixtures.course import XBlockFixtureDesc
from ...pages.studio.component_editor import ComponentEditorView, ComponentVisibilityEditorView
from ...pages.studio.container import ContainerPage
from ...pages.studio.html_component_editor import HtmlComponentEditorView
from ...pages.studio.utils import add_discussion, drag
from ...pages.lms.courseware import CoursewarePage
@@ -1056,3 +1057,61 @@ class DisplayNameTest(ContainerBase):
title_on_unit_page = test_block.name
container = test_block.go_to_container()
self.assertEqual(container.name, title_on_unit_page)
class ProblemCategoryTabsTest(ContainerBase):
"""
Test to verify tabs in problem category.
"""
def setUp(self, is_staff=True):
super(ProblemCategoryTabsTest, self).setUp(is_staff=is_staff)
def populate_course_fixture(self, course_fixture):
"""
Sets up course structure.
"""
course_fixture.add_children(
XBlockFixtureDesc('chapter', 'Test Section').add_children(
XBlockFixtureDesc('sequential', 'Test Subsection').add_children(
XBlockFixtureDesc('vertical', 'Test Unit')
)
)
)
def test_correct_tabs_present(self):
"""
Scenario: Verify that correct tabs are present in problem category.
Given I am a staff user
When I go to unit page
Then I only see `Common Problem Types` and `Advanced` tabs in `problem` category
"""
self.go_to_unit_page()
page = ContainerPage(self.browser, None)
self.assertEqual(page.get_category_tab_names('problem'), ['Common Problem Types', 'Advanced'])
def test_common_problem_types_tab(self):
"""
Scenario: Verify that correct components are present in Common Problem Types tab.
Given I am a staff user
When I go to unit page
Then I see correct components under `Common Problem Types` tab in `problem` category
"""
self.go_to_unit_page()
page = ContainerPage(self.browser, None)
expected_components = [
"Blank Common Problem",
"Checkboxes",
"Dropdown",
"Multiple Choice",
"Numerical Input",
"Text Input",
"Checkboxes with Hints and Feedback",
"Dropdown with Hints and Feedback",
"Multiple Choice with Hints and Feedback",
"Numerical Input with Hints and Feedback",
"Text Input with Hints and Feedback",
]
self.assertEqual(page.get_category_tab_components('problem', 1), expected_components)

View File

@@ -1,6 +1,7 @@
"""
Acceptance tests for course in studio
"""
from flaky import flaky
from nose.plugins.attrib import attr
from .base_studio_test import StudioCourseTest
@@ -126,6 +127,7 @@ class CourseTeamPageTest(StudioCourseTest):
self.log_in(self.other_user)
self._assert_current_course(visible=True)
@flaky # TODO fix this, see TNL-2667
def test_added_users_cannot_add_or_delete_other_users(self):
"""
Scenario: Added users cannot delete or add other users

View File

@@ -2,7 +2,6 @@
Acceptance tests for Library Content in LMS
"""
import ddt
from flaky import flaky
from nose.plugins.attrib import attr
import textwrap
@@ -138,7 +137,6 @@ class StudioLibraryContainerTest(StudioLibraryTest, UniqueCourseTest, TestWithSe
self.assertIn(expected_text, library_container.validation_not_configured_warning_text)
self.assertIn(expected_action, library_container.validation_not_configured_warning_text)
@flaky # TODO fix this, see TE-745
def test_out_of_date_message(self):
"""
Scenario: Given I have a library, a course and library content xblock in a course
@@ -149,6 +147,7 @@ class StudioLibraryContainerTest(StudioLibraryTest, UniqueCourseTest, TestWithSe
When I click on the update link
Then I can see that the content no longer needs to be updated
"""
# Formerly flaky: see TE-745
expected_text = "This component is out of date. The library has new content."
library_block = self._get_library_xblock_wrapper(self.unit_page.xblocks[1])

View File

@@ -1,7 +1,6 @@
"""
Acceptance tests for Studio's Settings Details pages
"""
from flaky import flaky
from unittest import skip
from .base_studio_test import StudioCourseTest
@@ -41,7 +40,7 @@ class SettingsMilestonesTest(StudioCourseTest):
self.assertTrue(self.settings_detail.pre_requisite_course_options)
@flaky # TODO: fix this. SOL-449
@skip # TODO: fix this. SOL-449
def test_prerequisite_course_save_successfully(self):
"""
Scenario: Selecting course from Pre-Requisite course drop down save the selected course as pre-requisite

Binary file not shown.

View File

@@ -125,10 +125,10 @@ msgid ""
msgstr ""
"Project-Id-Version: edx-platform\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
"POT-Creation-Date: 2015-07-06 12:02+0000\n"
"POT-Creation-Date: 2015-07-13 04:33+0000\n"
"PO-Revision-Date: 2015-06-30 03:58+0000\n"
"Last-Translator: Nabeel El-Dughailib <nabeel@qordoba.com>\n"
"Language-Team: Arabic (http://www.transifex.com/projects/p/edx-platform/language/ar/)\n"
"Language-Team: Arabic (http://www.transifex.com/p/edx-platform/language/ar/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -2889,6 +2889,14 @@ msgstr ""
msgid "Certificate Name (Long)"
msgstr "اسم الشهادة (طويل)"
#: common/lib/xmodule/xmodule/course_module.py
msgid "Certificate Web/HTML View Enabled"
msgstr ""
#: common/lib/xmodule/xmodule/course_module.py
msgid "If true, certificate Web/HTML views are enabled for the course."
msgstr ""
#. Translators: This field is the container for course-specific certifcate
#. configuration values
#: common/lib/xmodule/xmodule/course_module.py
@@ -5079,16 +5087,16 @@ msgstr "النتيجة"
msgid "problems"
msgstr "المسائل"
#: lms/djangoapps/commerce/signals.py lms/djangoapps/shoppingcart/models.py
msgid "[Refund] User-Requested Refund"
msgstr "[Refund] استرداد المال بطلب من المستخدم "
#: lms/djangoapps/commerce/signals.py
msgid ""
"A refund request has been initiated for {username} ({email}). To process "
"this request, please visit the link(s) below."
msgstr ""
#: lms/djangoapps/commerce/signals.py lms/djangoapps/shoppingcart/models.py
msgid "[Refund] User-Requested Refund"
msgstr "[Refund] استرداد المال بطلب من المستخدم "
#: lms/djangoapps/commerce/views.py lms/djangoapps/shoppingcart/pdf.py
msgid "Receipt"
msgstr "الإيصال"
@@ -5643,12 +5651,13 @@ msgstr "ملاحظات"
msgid "{platform_name} Staff"
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/membership.html
#: lms/djangoapps/instructor/paidcourse_enrollment_report.py
msgid "Course Staff"
msgstr "طاقم المساق "
msgstr ""
#: lms/templates/courseware/course_navigation.html
#: lms/templates/discussion/_underscore_templates.html
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Staff"
msgstr "طاقم المساق"
@@ -5848,32 +5857,27 @@ msgstr "المجموعة"
#: lms/djangoapps/instructor/views/api.py
msgid ""
"Your enrolled student profile report is being generated! You can view the "
"status of the generation task in the 'Pending Instructor Tasks' section."
"status of the generation task in the 'Pending Tasks' section."
msgstr ""
"يجري حاليًّا إعداد تقريرك حول الملف الشخصي للطالب المسجَّل. يمكنك متابعة "
"حالة مهمّة هذا الإعداد في قسم ’مهام الأستاذ المعلَّقة‘."
#: lms/djangoapps/instructor/views/api.py
msgid ""
"An enrolled student profile report generation task is already in progress. "
"Check the 'Pending Instructor Tasks' table for the status of the task. When "
"completed, the report will be available for download in the table below."
"Check the 'Pending Tasks' table for the status of the task. When completed, "
"the report will be available for download in the table below."
msgstr ""
"سبق أن بدأت معالجة مهمّة إعداد تقرير حول الملف الشخصي للطالب المسجَّل. يُرجى"
" التحقق من جدول ’مهام الأستاذ المعلَّقة‘ لمتابعة حالة المهمة. وعندما تكتمل، "
"سيصبح التقرير متاحًا للتنزيل في الجدول أدناه."
#: lms/djangoapps/instructor/views/api.py
msgid ""
"Your students who may enroll report is being generated! You can view the "
"status of the generation task in the 'Pending Instructor Tasks' section."
"status of the generation task in the 'Pending Tasks' section."
msgstr ""
#: lms/djangoapps/instructor/views/api.py
msgid ""
"A students who may enroll report generation task is already in progress. "
"Check the 'Pending Instructor Tasks' table for the status of the task. When "
"completed, the report will be available for download in the table below."
"Check the 'Pending Tasks' table for the status of the task. When completed, "
"the report will be available for download in the table below."
msgstr ""
#: lms/djangoapps/instructor/views/api.py
@@ -5934,28 +5938,28 @@ msgstr ""
#: lms/djangoapps/instructor/views/api.py
msgid ""
"Your detailed enrollment report is being generated! You can view the status "
"of the generation task in the 'Pending Instructor Tasks' section."
"of the generation task in the 'Pending Tasks' section."
msgstr ""
#: lms/djangoapps/instructor/views/api.py
msgid ""
"A detailed enrollment report generation task is already in progress. Check "
"the 'Pending Instructor Tasks' table for the status of the task. When "
"completed, the report will be available for download in the table below."
"the 'Pending Tasks' table for the status of the task. When completed, the "
"report will be available for download in the table below."
msgstr ""
#: lms/djangoapps/instructor/views/api.py
msgid ""
"Your executive summary report is being created. To view the status of the "
"report, see the 'Pending Instructor Tasks' section."
"report, see the 'Pending Tasks' section."
msgstr ""
#: lms/djangoapps/instructor/views/api.py
msgid ""
"An executive summary report is currently in progress. To view the status of "
"the report, see the 'Pending Instructor Tasks' section. When completed, the "
"report will be available for download in the table below. You will be able "
"to download the report when it is complete."
"the report, see the 'Pending Tasks' section. When completed, the report will"
" be available for download in the table below. You will be able to download "
"the report when it is complete."
msgstr ""
#: lms/djangoapps/instructor/views/api.py
@@ -6010,32 +6014,27 @@ msgstr ""
#: lms/djangoapps/instructor/views/api.py
msgid ""
"Your grade report is being generated! You can view the status of the "
"generation task in the 'Pending Instructor Tasks' section."
"generation task in the 'Pending Tasks' section."
msgstr ""
"يجري حاليًّا إعداد تقريرك حول الدرجات. يمكنك متابعة حالة مهمة هذا الإعداد في"
" قسم ’مهام الأستاذ المعلَّقة‘."
#: lms/djangoapps/instructor/views/api.py
msgid ""
"A grade report generation task is already in progress. Check the 'Pending "
"Instructor Tasks' table for the status of the task. When completed, the "
"report will be available for download in the table below."
"Tasks' table for the status of the task. When completed, the report will be "
"available for download in the table below."
msgstr ""
"سبق أن بدأت معالجة مهمّة إعداد تقرير حول الدرجات. يُرجى تفقّد قسم ’مهام "
"الأستاذ المعلَّقة‘ لمتابعة حالة تلك المهمّة. وعندما تكتمل، سيصبح التقرير "
"متاحًا للتنزيل في الجدول أدناه."
#: lms/djangoapps/instructor/views/api.py
msgid ""
"Your problem grade report is being generated! You can view the status of the"
" generation task in the 'Pending Instructor Tasks' section."
" generation task in the 'Pending Tasks' section."
msgstr ""
#: lms/djangoapps/instructor/views/api.py
msgid ""
"A problem grade report is already being generated. Check the 'Pending "
"Instructor Tasks' table for the status of the task. When completed, the "
"report will be available for download in the table below."
"A problem grade report is already being generated. Check the 'Pending Tasks'"
" table for the status of the task. When completed, the report will be "
"available for download in the table below."
msgstr ""
#: lms/djangoapps/instructor/views/api.py
@@ -8165,10 +8164,6 @@ msgstr ""
msgid "Subscribe to the {platform_name} YouTube channel"
msgstr ""
#: lms/envs/common.py
msgid "Taiwan"
msgstr "تايوان"
#: cms/templates/course-create-rerun.html cms/templates/index.html
#: cms/templates/settings.html
msgid "Organization"
@@ -8875,22 +8870,21 @@ msgid ""
"requested credit."
msgstr ""
#: openedx/core/djangoapps/credit/models.py
msgid "Description for the credit provider displayed to users."
msgstr ""
#: openedx/core/djangoapps/credit/models.py
msgid ""
"Plain text or html content for displaying further steps on receipt page "
"*after* paying for the credit to get credit for a credit course against a "
"credit provider."
msgstr ""
#: openedx/core/djangoapps/credit/models.py
msgid "Deadline for purchasing and requesting credit."
msgstr ""
#: openedx/core/djangoapps/import_export/courses/views.py
msgid "We only support uploading a .tar.gz file."
msgstr ""
#: openedx/core/djangoapps/import_export/courses/views.py
msgid "File upload corrupted. Please try again"
msgstr ""
#: openedx/core/djangoapps/import_export/courses/views.py
msgid "Could not find the {root_xml_file} file in the package."
msgstr ""
#: openedx/core/djangoapps/profile_images/images.py
msgid "bytes"
msgstr ""
@@ -9286,9 +9280,15 @@ msgid "Empty"
msgstr "خالية"
#: cms/djangoapps/contentstore/views/import_export.py
msgid ""
"An invalid parent key was supplied: \"{supplied_key}\" is not a valid course"
" unit."
msgid "We only support uploading a .tar.gz file."
msgstr ""
#: cms/djangoapps/contentstore/views/import_export.py
msgid "File upload corrupted. Please try again"
msgstr ""
#: cms/djangoapps/contentstore/views/import_export.py
msgid "Could not find the {0} file in the package."
msgstr ""
#: cms/djangoapps/contentstore/views/item.py
@@ -12146,6 +12146,7 @@ msgid "Psychometrics"
msgstr "المقاييس النفسية "
#: lms/templates/courseware/legacy_instructor_dashboard.html
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Admin"
msgstr "مشرف"
@@ -12381,11 +12382,6 @@ msgstr ""
"عبر الخادم 1 (بالشكل الموضَّح هنا كمثال):"
#: lms/templates/courseware/legacy_instructor_dashboard.html
#: lms/templates/instructor/instructor_dashboard_2/course_info.html
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html
#: lms/templates/instructor/instructor_dashboard_2/send_email.html
#: lms/templates/instructor/instructor_dashboard_2/student_admin.html
msgid "Pending Instructor Tasks"
msgstr "مهام الأستاذ المعلَّقة "
@@ -12510,8 +12506,7 @@ msgstr ""
#: lms/templates/courseware/progress.html
msgid ""
"You can now access your certificate. If you keep working and receive a "
"higher grade,you can request an {link_start} updated certificate {link_end}."
"You can keep working for a higher grade, or request your certificate now."
msgstr ""
#: lms/templates/courseware/progress.html
@@ -12544,11 +12539,6 @@ msgstr ""
msgid "Congratulations, you qualified for a certificate!"
msgstr ""
#: lms/templates/courseware/progress.html
msgid ""
"You can keep working for a higher grade, or request your certificate now."
msgstr ""
#: lms/templates/courseware/progress.html
msgid "Request Certificate"
msgstr ""
@@ -12574,7 +12564,11 @@ msgid "Go to your dashboard"
msgstr ""
#: lms/templates/courseware/progress.html
msgid "You have not yet met the requirements for credit."
msgid "{student_name}, you have not yet met the requirements for credit."
msgstr ""
#: lms/templates/courseware/progress.html
msgid "Information about course credit requirements"
msgstr ""
#: lms/templates/courseware/progress.html
@@ -12922,18 +12916,37 @@ msgid ""
"information, see {provider_link}."
msgstr ""
#: lms/templates/dashboard/_dashboard_credit_info.html
msgid ""
"Thank you for your payment! To receive your course credit, go to the "
"{provider_link} website. You may have to complete some additional steps "
"depending on the institution"
msgstr ""
#: lms/templates/dashboard/_dashboard_credit_info.html
msgid "Complete Credit"
msgstr ""
#: lms/templates/dashboard/_dashboard_credit_info.html
msgid ""
"Congratulations - you have received credit for this course! For more "
"information, see {provider_link}."
msgstr ""
#: lms/templates/dashboard/_dashboard_credit_info.html
msgid "Access credit"
msgstr ""
#: lms/templates/dashboard/_dashboard_credit_info.html
msgid ""
"{provider_name} has declined your request for course credit. For more "
"information, contact {provider_link}."
msgstr ""
#: lms/templates/dashboard/_dashboard_credit_info.html
msgid "Contact {provider_link}"
msgstr ""
#: lms/templates/dashboard/_dashboard_info_language.html
msgid "edit"
msgstr "تعديل"
@@ -14429,6 +14442,11 @@ msgid "Generate Certificates"
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/certificates.html
#: lms/templates/instructor/instructor_dashboard_2/course_info.html
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html
#: lms/templates/instructor/instructor_dashboard_2/send_email.html
#: lms/templates/instructor/instructor_dashboard_2/student_admin.html
msgid "Pending Tasks"
msgstr ""
@@ -14447,9 +14465,8 @@ msgstr "معلومات التسجيل"
#. Translators: 'track' refers to the enrollment type ('honor', 'verified', or
#. 'audit')
#: lms/templates/instructor/instructor_dashboard_2/course_info.html
msgid ""
"Number of enrollees (instructors, staff members, and students) by track"
msgstr "إجمالي عدد المسجلين (موجّهوا المساق، أعضاء طاقم المساق، والطلاّب)"
msgid "Number of enrollees (admins, staff, and students) by track"
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/course_info.html
msgid "Audit"
@@ -15300,10 +15317,8 @@ msgstr "إضافة دفعة مختبر النسخة التجريبية"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid ""
"Note: Users must have an activated {platform_name} account before they can "
"be enrolled as a beta tester."
"be enrolled as beta testers."
msgstr ""
"ملاحظة: يجب أن يكون لدى المستخدمين حساباً مفعّلاً على المنصة {platform_name}"
" قبل أن يتم تسجيلهم كأعضاء مختبر النسخة التجريبية."
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid ""
@@ -15330,15 +15345,15 @@ msgstr "إلغاء أفراد من مختبر النسخة التجريبية"
#. Translators: an "Administration List" is a list, such as Course Staff, that
#. users can be added to.
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Administration List Management"
msgstr "إدارة قائمة الإشراف"
msgid "Course Team Management"
msgstr ""
#. Translators: an "Administrator Group" is a group, such as Course Staff,
#. that
#. users can be added to.
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Select an Administrator Group:"
msgstr "اختيار أحد مجموعات الإشراف:"
msgid "Select a course team role:"
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Getting available lists..."
@@ -15346,46 +15361,35 @@ msgstr "الحصول على القوائم المتاحة... "
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid ""
"Staff cannot modify staff or beta tester lists. To modify these lists, "
"contact your instructor and ask them to add you as an instructor for staff "
"and beta lists, or a discussion admin for discussion management."
"Staff cannot modify these lists. To manage course team membership, a course "
"Admin must give you the Admin role to add Staff or Beta Testers, or the "
"Discussion Admin role to add discussion moderators and TAs."
msgstr ""
"لا يمكن لطاقم المساق تعديل قوائم أعضاء الطاقم أو مختبر النسخة التجريبية "
"الأولي للنظام. ولتعديل هذه القوائم، الرجاء الاتصال بموجِّهك وطلب إضافتك بصفة"
" موجّه في قوائم أعضاء الطاقم أو فريق الاختبار الأولي للنظام، أو مشرف "
"النقاشات بغرض إدارة النقاشات."
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid ""
"Course staff can help you manage limited aspects of your course. Staff can "
"enroll and unenroll students, as well as modify their grades and see all "
"course data. Course staff are not automatically given access to Studio and "
"will not be able to edit your course."
"Course team members with the Staff role help you manage your course. Staff "
"can enroll and unenroll learners, as well as modify their grades and access "
"all course data. Staff also have access to your course in Studio and "
"Insights. You can only give course team roles to enrolled users."
msgstr ""
"بإمكان طاقم المساق مساعدتك على إدارة جوانب محدودة فقط من مساقك. حيث يستطيع "
"الطاقم تسجيل الطلاب وإلغاء تسجيلهم، بالإضافة إلى تعديل درجاتهم والاطلاع على "
"كافة بيانات المساق. لكن لا يعطى طاقم المساق إذن الدخول للاستوديو بشكلٍ "
"تلقائي، ولن يكونوا قادرين على تعديل مساقك. "
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Add Staff"
msgstr "إضافة أعضاء إلى طاقم المساق"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Instructors"
msgstr "موجّهوا المساق"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid ""
"Instructors are the core administration of your course. Instructors can add "
"and remove course staff, as well as administer discussion access."
"Course team members with the Admin role help you manage your course. They "
"can do all of the tasks that Staff can do, and can also add and remove the "
"Staff and Admin roles, discussion moderation roles, and the beta tester role"
" to manage course team membership. You can only give course team roles to "
"enrolled users."
msgstr ""
"يعتبر طاقم موجّهوا المساق جوهر إدارة المساق الخاص بك. ويستطيع الموجّهون "
"إضافة وحذف أعضاء طاقم المساق، بالإضافة إلى الإشراف على استخدام النقاشات."
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Add Instructor"
msgstr "إضافة موجّه المساق "
msgid "Add Admin"
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Beta Testers"
@@ -15393,12 +15397,10 @@ msgstr "مختبر النسخة التجريبية"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid ""
"Beta testers can see course content before the rest of the students. They "
"can make sure that the content works, but have no additional privileges."
"Beta Testers can see course content before other learners. They can make "
"sure that the content works, but have no additional privileges. You can only"
" give course team roles to enrolled users."
msgstr ""
"يمكن لمختبر النسخة التجريبية رؤية محتوى المساق قبل غيرهم من الطلاب، وبذلك "
"يستطيعون التأكد من صحة عمل البرنامج ومن المحتوى، لكنهم لا يملكون صلاحياتٍ "
"إضافية."
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Add Beta Tester"
@@ -15410,14 +15412,12 @@ msgstr "مشرفو النقاشات"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid ""
"Discussion admins can edit or delete any post, clear misuse flags, close and"
" re-open threads, endorse responses, and see posts from all cohorts. They "
"CAN add/delete other moderators and their posts are marked as 'staff'."
"Discussion Admins can edit or delete any post, clear misuse flags, close and"
" re-open threads, endorse responses, and see posts from all cohorts. Their "
"posts are marked as 'staff'. They can also add and remove the discussion "
"moderation roles to manage course team membership. You can only give course "
"team roles to enrolled users."
msgstr ""
"يمكن للمشرفين على النقاشات تعديل أو حذف أي منشور، وإزالة إشارات إساءة "
"الاستخدام، وإغلاق وإعادة فتح المواضيع، وتأييد ردود، ورؤية المواد المنشورة من"
" قبل كافة المجموعات. كما بإمكانهم إضافة وحذف مشرفي المنتدى الآخرين ويتم "
"الإشارة على المواد المنشورة من قبلهم بأنها من قبل ’طاقم المساق‘."
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Add Discussion Admin"
@@ -15429,15 +15429,12 @@ msgstr "مشرفوا المنتدى النقاش"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid ""
"Discussion moderators can edit or delete any post, clear misuse flags, close"
"Discussion Moderators can edit or delete any post, clear misuse flags, close"
" and re-open threads, endorse responses, and see posts from all cohorts. "
"They CANNOT add/delete other moderators and their posts are marked as "
"'staff'."
"Their posts are marked as 'staff'. They cannot manage course team membership"
" by adding or removing discussion moderation roles. You can only give course"
" team roles to enrolled users."
msgstr ""
"يمكن لمشرفي المنتدى تعديل أو حذف أي منشور، وإزالة إشارات إساءة الاستخدام، "
"وإغلاق وإعادة فتح المواضيع، وتأييد ردود، ورؤية المواد المنشورة من قبل كافة "
"المجموعات. لكن لا يمكنهم إضافة وحذف وسطاء آخرين ويتم الإشارة على المواد "
"المنشورة من قبلهم بأنها من قبل ’طاقم المساق‘."
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Add Moderator"
@@ -15452,13 +15449,9 @@ msgid ""
"Community TA's are members of the community whom you deem particularly "
"helpful on the discussion boards. They can edit or delete any post, clear "
"misuse flags, close and re-open threads, endorse responses, and see posts "
"from all cohorts. Their posts are marked 'Community TA'."
"from all cohorts. Their posts are marked as 'Community TA'. You can only "
"give course team roles to enrolled users."
msgstr ""
"مساعدو أستاذ لشؤون المتعلمين هم أعضاء مجتمع المنتدى الذين تعتقد بأنهم "
"سيشكّلون عنصراً مساعداً للغاية على صفحات النقاشات. وهم مخولون بتعديل أو حذف "
"أي منشور، وإزالة إشارات إساءة الاستخدام، وفتح وإغلاق المواضيع، وتأييد ردود، "
"ورؤية المواد المنشورة من كافة المجموعات. ويتم الإشارة إلى المواد التي يقومون"
" بنشرها على أنها خاصة بـ’مساعد المشرف للمجموعة‘. "
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Add Community TA"
@@ -15556,12 +15549,12 @@ msgid "Myself"
msgstr "نفسي "
#: lms/templates/instructor/instructor_dashboard_2/send_email.html
msgid "Staff and instructors"
msgstr "الطاقم وموجّهوا المساق"
msgid "Staff and admins"
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/send_email.html
msgid "All (students, staff and instructors)"
msgstr "الجميع (الطلاب، الطاقم، وموجّهوا المساق) "
msgid "All (students, staff, and admins)"
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/send_email.html
msgid "Subject: "
@@ -15726,12 +15719,9 @@ msgstr "حذف حالة الطالب بالنسبة لمسألة محددة "
#: lms/templates/instructor/instructor_dashboard_2/student_admin.html
msgid ""
"Rescoring runs in the background, and status for active tasks will appear in"
" the 'Pending Instructor Tasks' table. To see status for all tasks submitted"
" for this problem and student, click on this button:"
" the 'Pending Tasks' table. To see status for all tasks submitted for this "
"problem and student, click on this button:"
msgstr ""
"تجري عمليات إعادة التقييم في الخلفية، بينما تظهر حالة أي مهمّات مفعّلة في "
"جدول ’المهمّات معلّقة لموجّه المساق‘. لاستعراض الحالة الخاصة بكافة المهمّات "
"التي تم تقديمها لهذه المسألة وهذا الطالب، اضغط هذا الزر:"
#: lms/templates/instructor/instructor_dashboard_2/student_admin.html
msgid "Show Background Task History for Student"
@@ -15919,20 +15909,12 @@ msgid ""
"{p_tag}You currently do not have any peer grading to do. In order to have peer grading to do:\n"
"{ul_tag}\n"
"{li_tag}You need to have submitted a response to a peer grading problem.{end_li_tag}\n"
"{li_tag}The instructor needs to score the essays that are used to help you better understand the grading\n"
"{li_tag}The course team needs to score the essays that are used to help you better understand the grading\n"
"criteria.{end_li_tag}\n"
"{li_tag}There must be submissions that are waiting for grading.{end_li_tag}\n"
"{end_ul_tag}\n"
"{end_p_tag}\n"
msgstr ""
"\n"
"{p_tag}ليس لديك حالياً أية مهمّات تقييم الزملاء تنتظرك. وحتى تصلك مهمّات تقييم نظراء:\n"
"{ul_tag}\n"
"{li_tag}يجب أن تكون قد قدّمت رداً على إحدى مسائل تقييم النظراء{end_li_tag}\n"
"{li_tag}يتعيّن أن يقوم موجّه المساق بتقييم المقالات المستخدمة بغرض مساعدتك على فهم معايير التقييم بشكلٍ أفضل.{end_li_tag}\n"
"{li_tag}يتعيّن وجود تسليمات تنتظر التقييم.{end_li_tag}\n"
"{end_ul_tag}\n"
"{end_p_tag}\n"
#: lms/templates/peer_grading/peer_grading.html
#: lms/templates/peer_grading/peer_grading_closed.html
@@ -18993,12 +18975,8 @@ msgid "User's Email Address"
msgstr "عنوان البريد الإلكتروني الخاص بالمستخدم"
#: cms/templates/manage_users.html
msgid ""
"Please provide the email address of the course staff member you'd like to "
"add"
msgid "Provide the email address of the user you want to add as Staff"
msgstr ""
"يُرجى تزويدنا بعنوان البريد الإلكتروني الخاص بعضو طاقم المساق الذي تودّ أن "
"تضيفه "
#: cms/templates/manage_users.html cms/templates/manage_users_lib.html
msgid "Add User"
@@ -19026,11 +19004,9 @@ msgstr "أدوار فريق المساق"
#: cms/templates/manage_users.html
msgid ""
"Course team members, or staff, are course co-authors. They have full writing"
" and editing privileges on all course content."
"Course team members with the Staff role are course co-authors. They have "
"full writing and editing privileges on all course content."
msgstr ""
"يُعدّ أعضاء الفريق، أو الطاقم، مؤلّفين مشاركين للمساق. ويتمتّعون بكامل "
"امتيازات الكتابة والتعديل في كافة أقسام محتوى المساق."
#: cms/templates/manage_users.html
msgid ""
@@ -19040,19 +19016,23 @@ msgstr ""
"المشرفون هم من أعضاء فريق المساق ويمكنهم إضافة أو إقصاء أعضاء آخرين من "
"الفريق."
#: cms/templates/manage_users.html
msgid ""
"All course team members are automatically enrolled in the course and can "
"access content in Studio, the LMS, and Insights."
msgstr ""
#: cms/templates/manage_users.html
msgid "Transferring Ownership"
msgstr "نقل الملكية"
#: cms/templates/manage_users.html
msgid ""
"Every course must have an Admin. If you're the Admin and you want transfer "
"ownership of the course, click Add admin access to make another user the "
"Admin, then ask that user to remove you from the Course Team list."
"Every course must have an Admin. If you are the Admin and you want to "
"transfer ownership of the course, click <strong>Add admin access</strong> to"
" make another user the Admin, then ask that user to remove you from the "
"Course Team list."
msgstr ""
"يجب أن يكون لكل مساق مشرف. وإذا كنت أنت هو المشرف وأردت نقل ملكية المساق إلى"
" الغير، يُرجى النقر على ’إضافة‘ حقّ دخول مشرف لتوكّل مستخدمًا آخر بدور "
"المشرف، ثمّ اطلب من هذا المستخدم أن يزيل اسمك من قائمة فريق المساق."
#: cms/templates/manage_users_lib.html
msgid "Library User Access"
@@ -19097,28 +19077,22 @@ msgstr ""
#: cms/templates/manage_users_lib.html
msgid ""
"Users can view library content and can reference or use library components "
"in their courses, but they cannot edit the contents of a library."
"Library Users can view library content and can reference or use library "
"components in their courses, but they cannot edit the contents of a library."
msgstr ""
"يمكن للمستخدمين مشاهدة محتوى المكتبة والرجوع إلى مكوِّناتها في مساقاتهم، لكن"
" لا يمكنهم تعديل محتويات أي مكتبة."
#: cms/templates/manage_users_lib.html
msgid ""
"Staff are content co-authors. They have full editing privileges on the "
"contents of a library."
"Library Staff are content co-authors. They have full editing privileges on "
"the contents of a library."
msgstr ""
"يُعدّ طاقم المساق مجموعة من المؤلّفين المشارِكين للمحتوى، ويتمتّع هؤلاء "
"بكامل صلاحيات تحرير محتويات المكتبة."
#: cms/templates/manage_users_lib.html
msgid ""
"Admins have full editing privileges and can also add and remove other team "
"members. There must be at least one user with Admin privileges in a library."
"Library Admins have full editing privileges and can also add and remove "
"other team members. There must be at least one user with the Admin role in a"
" library."
msgstr ""
"يتمتّع المشرفون بكامل صلاحيات التحرير، كما يمكنهم إضافة/حذف أعضاء الفريق "
"الآخرين. ويجب أن يوجد مستخدم واحد على الأقلّ يتمتّع بصلاحيات المشرِف في أي "
"مكتبة."
#: cms/templates/register.html cms/templates/widgets/header.html
msgid "Sign Up"
@@ -19283,15 +19257,15 @@ msgid ""
msgstr ""
#: cms/templates/settings.html
msgid "Credit Eligibility Requirements"
msgid "Course Credit Requirements"
msgstr ""
#: cms/templates/settings.html
msgid "Steps needed for credit eligibility"
msgid "Steps required to earn course credit"
msgstr ""
#: cms/templates/settings.html
msgid "Minimum Passing Grade"
msgid "Minimum Grade"
msgstr ""
#: cms/templates/settings.html
@@ -19303,19 +19277,13 @@ msgid "Proctored Exam {number}"
msgstr ""
#: cms/templates/settings.html
msgid "Successful In-Course Reverification"
msgid "ID Verification"
msgstr ""
#. Translators: 'Access to Assessment 1' means the access for a requirement
#. with name 'Assessment 1'
#: cms/templates/settings.html
msgid "In-Course Reverification {number}"
msgstr ""
#: cms/templates/settings.html
msgid "Access to {display_name}"
msgstr ""
#: cms/templates/settings.html
msgid "Course Schedule"
msgstr "جدول المساق"
@@ -19639,19 +19607,19 @@ msgid "Your overall grading scale for student final grades"
msgstr "مقياسك للتقييم العام لدرجات الطلّاب النهائية"
#: cms/templates/settings_graders.html
msgid "Credit Grade &amp; Eligibility"
msgid "Credit Eligibility"
msgstr ""
#: cms/templates/settings_graders.html
msgid "Settings for credit eligibility"
msgid "Settings for course credit eligibility"
msgstr ""
#: cms/templates/settings_graders.html
msgid "Minimum Passing Grade to Earn Credit:"
msgid "Minimum Credit-Eligible Grade:"
msgstr ""
#: cms/templates/settings_graders.html
msgid "Must be greater than or equal to passing grade"
msgid "Must be greater than or equal to the course passing grade"
msgstr ""
#: cms/templates/settings_graders.html

View File

@@ -75,10 +75,10 @@ msgid ""
msgstr ""
"Project-Id-Version: edx-platform\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
"POT-Creation-Date: 2015-07-06 12:00+0000\n"
"PO-Revision-Date: 2015-06-30 04:09+0000\n"
"Last-Translator: Nabeel El-Dughailib <nabeel@qordoba.com>\n"
"Language-Team: Arabic (http://www.transifex.com/projects/p/edx-platform/language/ar/)\n"
"POT-Creation-Date: 2015-07-13 04:31+0000\n"
"PO-Revision-Date: 2015-07-10 19:12+0000\n"
"Last-Translator: Sarina Canelake <sarina@edx.org>\n"
"Language-Team: Arabic (http://www.transifex.com/p/edx-platform/language/ar/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -1583,7 +1583,6 @@ msgstr "مسافة عمودية"
#. 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
#: lms/djangoapps/teams/static/teams/js/views/topic_card.js
#: lms/templates/search/course_search_item.underscore
#: lms/templates/search/dashboard_search_item.underscore
msgid "View"
@@ -2141,44 +2140,12 @@ msgstr "نأسف لحدوث مشكلة في حذف هذا التعليق. يُر
msgid "Are you sure you want to delete this response?"
msgstr "هل أنت واثق من أنّك تودّ حذف هذا الرد؟"
#. Translators: sample result:
#. "Showing 0-9 out of 25 total, filtered by Images, sorted by Date Added
#. ascending"
#: common/static/common/js/components/views/paging_header.js
msgid ""
"Showing %(current_item_range)s out of %(total_items_count)s, filtered by "
"%(asset_type)s, sorted by %(sort_name)s ascending"
msgid "Showing %(first_index)s out of %(num_items)s total"
msgstr ""
#. Translators: sample result:
#. "Showing 0-9 out of 25 total, filtered by Images, sorted by Date Added
#. descending"
#: common/static/common/js/components/views/paging_header.js
msgid ""
"Showing %(current_item_range)s out of %(total_items_count)s, filtered by "
"%(asset_type)s, sorted by %(sort_name)s descending"
msgstr ""
#. Translators: sample result:
#. "Showing 0-9 out of 25 total, sorted by Date Added ascending"
#: common/static/common/js/components/views/paging_header.js
msgid ""
"Showing %(current_item_range)s out of %(total_items_count)s, sorted by "
"%(sort_name)s ascending"
msgstr ""
#. Translators: sample result:
#. "Showing 0-9 out of 25 total, sorted by Date Added descending"
#: common/static/common/js/components/views/paging_header.js
msgid ""
"Showing %(current_item_range)s out of %(total_items_count)s, sorted by "
"%(sort_name)s descending"
msgstr ""
#. Translators: turns into "25 total" to be used in other sentences, e.g.
#. "Showing 0-9 out of 25 total".
#: common/static/common/js/components/views/paging_header.js
msgid "%(total_items)s total"
msgid "Showing %(first_index)s-%(last_index)s out of %(num_items)s total"
msgstr ""
#: common/static/js/capa/drag_and_drop/base_image.js
@@ -2436,6 +2403,14 @@ msgstr "الرد"
msgid "Tags:"
msgstr "العلامات: "
#: lms/templates/edxnotes/tab-item.underscore
msgid "name"
msgstr "الاسم "
#: lms/djangoapps/teams/static/teams/js/collections/topic.js
msgid "team count"
msgstr ""
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid ""
"Course teams are organized into topics created by course instructors. Try to"
@@ -2464,6 +2439,10 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
#: lms/djangoapps/teams/static/teams/js/views/topic_card.js
msgid "View Teams in the %(topic_name)s Topic"
msgstr ""
#: lms/static/coffee/src/calculator.js
msgid "Open Calculator"
msgstr "فتح الآلة الحاسبة "
@@ -4389,12 +4368,18 @@ msgid "The course must have an assigned start date."
msgstr "يجب أن يكون للمساق تاريخ بدء معيّن."
#: cms/static/js/models/settings/course_details.js
msgid "The course end date cannot be before the course start date."
msgstr "لايمكن لتاريخ انتهاء المساق أن يسبق تاريخ بدئه."
msgid ""
"The course must have at least one active certificate configuration before it"
" can be started."
msgstr ""
#: cms/static/js/models/settings/course_details.js
msgid "The course start date cannot be before the enrollment start date."
msgstr "لايمكن لتاريخ بدء المساق أن يسبق تاريخ التسجيل فيه."
msgid "The course end date must be later than the course start date."
msgstr ""
#: cms/static/js/models/settings/course_details.js
msgid "The course start date must be later than the enrollment start date."
msgstr ""
#: cms/static/js/models/settings/course_details.js
msgid "The enrollment start date cannot be after the enrollment end date."
@@ -4768,6 +4753,46 @@ msgstr "غير مقيَّم"
msgid "Date added"
msgstr "تاريخ الإضافة "
#. Translators: sample result:
#. "Showing 0-9 out of 25 total, filtered by Images, sorted by Date Added
#. ascending"
#: cms/static/js/views/paging_header.js
msgid ""
"Showing %(current_item_range)s out of %(total_items_count)s, filtered by "
"%(asset_type)s, sorted by %(sort_name)s ascending"
msgstr ""
#. Translators: sample result:
#. "Showing 0-9 out of 25 total, filtered by Images, sorted by Date Added
#. descending"
#: cms/static/js/views/paging_header.js
msgid ""
"Showing %(current_item_range)s out of %(total_items_count)s, filtered by "
"%(asset_type)s, sorted by %(sort_name)s descending"
msgstr ""
#. Translators: sample result:
#. "Showing 0-9 out of 25 total, sorted by Date Added ascending"
#: cms/static/js/views/paging_header.js
msgid ""
"Showing %(current_item_range)s out of %(total_items_count)s, sorted by "
"%(sort_name)s ascending"
msgstr ""
#. Translators: sample result:
#. "Showing 0-9 out of 25 total, sorted by Date Added descending"
#: cms/static/js/views/paging_header.js
msgid ""
"Showing %(current_item_range)s out of %(total_items_count)s, sorted by "
"%(sort_name)s descending"
msgstr ""
#. Translators: turns into "25 total" to be used in other sentences, e.g.
#. "Showing 0-9 out of 25 total".
#: cms/static/js/views/paging_header.js
msgid "%(total_items)s total"
msgstr ""
#. Translators: This is listed as the duration for a video
#. that has not yet reached the point in its processing by
#. the servers where its duration is determined.
@@ -4985,11 +5010,11 @@ msgstr ""
"بك غير مطبّقة بعد. وفي حال كنت تواجه أي مشاكل، يُرجى مراجعة أزواج سياستك. . "
#: cms/static/js/views/settings/main.js
msgid "Credit Eligibility Requirements"
msgid "Course Credit Requirements"
msgstr ""
#: cms/static/js/views/settings/main.js
msgid "Minimum passing grade for credit is not set."
msgid "The minimum grade for course credit is not set."
msgstr ""
#: cms/static/js/views/settings/main.js
@@ -5272,10 +5297,6 @@ msgstr "لوحِظ في:"
msgid "Last Edited:"
msgstr "آخر مراجعة في:"
#: lms/templates/edxnotes/tab-item.underscore
msgid "name"
msgstr "الاسم "
#: lms/templates/edxnotes/tab-item.underscore
msgid "Clear search results"
msgstr "حذف نتائج البحث"
@@ -6309,7 +6330,9 @@ msgid "Course title"
msgstr ""
#: cms/templates/js/certificate-editor.underscore
msgid "Title of the course"
msgid ""
"Specify an alternative to the official course title to display on "
"certificates. Leave blank to use the official course title."
msgstr ""
#: cms/templates/js/certificate-editor.underscore
@@ -6757,6 +6780,10 @@ msgstr "لم تُضِف بعد أي كتب إلى هذا المساق."
msgid "Add your first textbook"
msgstr "أضِف أوّل كتاب لك."
#: cms/templates/js/paging-header.underscore
msgid "Previous"
msgstr ""
#: cms/templates/js/previous-video-upload-list.underscore
msgid "Previous Uploads"
msgstr "تحميلات سابقة"
@@ -6893,7 +6920,9 @@ msgid "Name of the signatory"
msgstr ""
#: cms/templates/js/signatory-editor.underscore
msgid "Maximum 40 characters"
msgid ""
"The name of this signatory as it should appear on certificates. Maximum 40 "
"characters."
msgstr ""
#: cms/templates/js/signatory-editor.underscore
@@ -6901,13 +6930,21 @@ msgid "Title of the signatory"
msgstr ""
#: cms/templates/js/signatory-editor.underscore
msgid "2 Lines, 40 characters each"
msgid ""
"The title of this signatory as it should appear on certificates. Maximum 2 "
"lines, 40 characters each."
msgstr ""
#: cms/templates/js/signatory-editor.underscore
msgid "Organization of the signatory"
msgstr ""
#: cms/templates/js/signatory-editor.underscore
msgid ""
"The organization that this signatory belongs to, as it should appear on "
"certificates. Maximum 40 characters."
msgstr ""
#: cms/templates/js/signatory-editor.underscore
msgid "Signature Image"
msgstr ""

Binary file not shown.

View File

@@ -37,8 +37,8 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.1a\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
"POT-Creation-Date: 2015-07-06 12:11+0000\n"
"PO-Revision-Date: 2015-07-06 12:11:43.963099\n"
"POT-Creation-Date: 2015-07-13 04:42+0000\n"
"PO-Revision-Date: 2015-07-13 04:42:08.333956\n"
"Last-Translator: \n"
"Language-Team: openedx-translation <openedx-translation@googlegroups.com>\n"
"MIME-Version: 1.0\n"
@@ -3237,6 +3237,17 @@ msgstr ""
msgid "Certificate Name (Long)"
msgstr "Çértïfïçäté Nämé (Löng) Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σ#"
#: common/lib/xmodule/xmodule/course_module.py
msgid "Certificate Web/HTML View Enabled"
msgstr ""
"Çértïfïçäté Wéß/HTML Vïéw Énäßléd Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тє#"
#: common/lib/xmodule/xmodule/course_module.py
msgid "If true, certificate Web/HTML views are enabled for the course."
msgstr ""
"Ìf trüé, çértïfïçäté Wéß/HTML vïéws äré énäßléd för thé çöürsé. Ⱡ'σяєм ιρѕυм"
" ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α#"
#. Translators: This field is the container for course-specific certifcate
#. configuration values
#: common/lib/xmodule/xmodule/course_module.py
@@ -5936,10 +5947,6 @@ msgstr "Sçöré Ⱡ'σяєм ιρѕ#"
msgid "problems"
msgstr "prößléms Ⱡ'σяєм ιρѕυм ∂#"
#: lms/djangoapps/commerce/signals.py lms/djangoapps/shoppingcart/models.py
msgid "[Refund] User-Requested Refund"
msgstr "[Réfünd] Ûsér-Réqüéstéd Réfünd Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢т#"
#: lms/djangoapps/commerce/signals.py
msgid ""
"A refund request has been initiated for {username} ({email}). To process "
@@ -5948,6 +5955,10 @@ 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/signals.py lms/djangoapps/shoppingcart/models.py
msgid "[Refund] User-Requested Refund"
msgstr "[Réfünd] Ûsér-Réqüéstéd Réfünd Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢т#"
#: lms/djangoapps/commerce/views.py lms/djangoapps/shoppingcart/pdf.py
msgid "Receipt"
msgstr "Réçéïpt Ⱡ'σяєм ιρѕυм #"
@@ -6562,13 +6573,13 @@ msgid "{platform_name} Staff"
msgstr "{platform_name} Stäff Ⱡ'σяєм ιρѕυм ∂σł#"
#: lms/djangoapps/instructor/paidcourse_enrollment_report.py
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Course Staff"
msgstr "Çöürsé Stäff Ⱡ'σяєм ιρѕυм ∂σłσя ѕ#"
#: lms/djangoapps/instructor/paidcourse_enrollment_report.py
#: lms/templates/courseware/course_navigation.html
#: lms/templates/discussion/_underscore_templates.html
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Staff"
msgstr "Stäff Ⱡ'σяєм ιρѕ#"
@@ -6793,60 +6804,60 @@ msgstr "Çöhört Ⱡ'σяєм ιρѕυ#"
#: lms/djangoapps/instructor/views/api.py
msgid ""
"Your enrolled student profile report is being generated! You can view the "
"status of the generation task in the 'Pending Instructor Tasks' section."
"status of the generation task in the 'Pending Tasks' section."
msgstr ""
"Ýöür énrölléd stüdént pröfïlé répört ïs ßéïng générätéd! Ýöü çän vïéw thé "
"stätüs öf thé générätïön täsk ïn thé 'Péndïng Ìnstrüçtör Täsks' séçtïön. "
"Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ "
"тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм,"
" qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ "
"stätüs öf thé générätïön täsk ïn thé 'Péndïng Täsks' séçtïön. Ⱡ'σяєм ιρѕυм "
"∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя "
"ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ "
"ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ "
σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє "
"¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт "
"ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕєяυηт мσłłιт αηιм ι#"
"ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕєяυηт мσłłιт αηιм ι∂ єѕт łαвσяυ#"
#: lms/djangoapps/instructor/views/api.py
msgid ""
"An enrolled student profile report generation task is already in progress. "
"Check the 'Pending Instructor Tasks' table for the status of the task. When "
"completed, the report will be available for download in the table below."
"Check the 'Pending Tasks' table for the status of the task. When completed, "
"the report will be available for download in the table below."
msgstr ""
"Àn énrölléd stüdént pröfïlé répört générätïön täsk ïs älréädý ïn prögréss. "
"Çhéçk thé 'Péndïng Ìnstrüçtör Täsks' täßlé för thé stätüs öf thé täsk. Whén "
"çömplétéd, thé répört wïll ßé äväïläßlé för döwnlöäd ïn thé täßlé ßélöw. "
"Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ "
"тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм,"
" qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ "
"Çhéçk thé 'Péndïng Täsks' täßlé för thé stätüs öf thé täsk. Whén çömplétéd, "
"thé répört wïll ßé äväïläßlé för döwnlöäd ïn thé täßlé ßélöw. Ⱡ'σяєм ιρѕυм "
"∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя "
"ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ "
"ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ "
σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє "
"¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυ#"
"¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢є#"
#: lms/djangoapps/instructor/views/api.py
msgid ""
"Your students who may enroll report is being generated! You can view the "
"status of the generation task in the 'Pending Instructor Tasks' section."
"status of the generation task in the 'Pending Tasks' section."
msgstr ""
"Ýöür stüdénts whö mäý énröll répört ïs ßéïng générätéd! Ýöü çän vïéw thé "
"stätüs öf thé générätïön täsk ïn thé 'Péndïng Ìnstrüçtör Täsks' séçtïön. "
"Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ "
"тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм,"
" qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ "
"stätüs öf thé générätïön täsk ïn thé 'Péndïng Täsks' séçtïön. Ⱡ'σяєм ιρѕυм "
"∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя "
"ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ "
"ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ "
σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє "
"¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт "
"ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕєяυηт мσłłιт αηιм ι∂#"
"ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕєяυηт мσłłιт αηιм ι∂ єѕт łαвσяυм#"
#: lms/djangoapps/instructor/views/api.py
msgid ""
"A students who may enroll report generation task is already in progress. "
"Check the 'Pending Instructor Tasks' table for the status of the task. When "
"completed, the report will be available for download in the table below."
"Check the 'Pending Tasks' table for the status of the task. When completed, "
"the report will be available for download in the table below."
msgstr ""
"À stüdénts whö mäý énröll répört générätïön täsk ïs älréädý ïn prögréss. "
"Çhéçk thé 'Péndïng Ìnstrüçtör Täsks' täßlé för thé stätüs öf thé täsk. Whén "
"çömplétéd, thé répört wïll ßé äväïläßlé för döwnlöäd ïn thé täßlé ßélöw. "
"Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ "
"тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм,"
" qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ "
"Çhéçk thé 'Péndïng Täsks' täßlé för thé stätüs öf thé täsk. Whén çömplétéd, "
"thé répört wïll ßé äväïläßlé för döwnlöäd ïn thé täßlé ßélöw. Ⱡ'σяєм ιρѕυм "
"∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя "
"ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ "
"ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ "
σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє "
"¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα#"
"¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтє#"
#: lms/djangoapps/instructor/views/api.py
msgid "The file must contain a 'cohort' column containing cohort names."
@@ -6909,54 +6920,48 @@ msgstr "Tötäl Dïsçöüntéd Àmöünt Ⱡ'σяєм ιρѕυм ∂σłσя ѕ
#: lms/djangoapps/instructor/views/api.py
msgid ""
"Your detailed enrollment report is being generated! You can view the status "
"of the generation task in the 'Pending Instructor Tasks' section."
"of the generation task in the 'Pending Tasks' section."
msgstr ""
"Ýöür détäïléd énröllmént répört ïs ßéïng générätéd! Ýöü çän vïéw thé stätüs "
"öf thé générätïön täsk ïn thé 'Péndïng Ìnstrüçtör Täsks' séçtïön. Ⱡ'σяєм "
"ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя "
"ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ "
"ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ "
σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє "
"¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт "
"ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕєяυηт мσłłιт αηιм ι∂ єѕт #"
"öf thé générätïön täsk ïn thé 'Péndïng Täsks' séçtïön. Ⱡ'#"
#: lms/djangoapps/instructor/views/api.py
msgid ""
"A detailed enrollment report generation task is already in progress. Check "
"the 'Pending Instructor Tasks' table for the status of the task. When "
"completed, the report will be available for download in the table below."
"the 'Pending Tasks' table for the status of the task. When completed, the "
"report will be available for download in the table below."
msgstr ""
"À détäïléd énröllmént répört générätïön täsk ïs älréädý ïn prögréss. Çhéçk "
"thé 'Péndïng Ìnstrüçtör Täsks' täßlé för thé stätüs öf thé täsk. Whén "
"çömplétéd, thé répört wïll ßé äväïläßlé för döwnlöäd ïn thé täßlé ßélöw. "
"Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ "
"тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм,"
" qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ "
"¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє "
"¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαт#"
"thé 'Péndïng Täsks' täßlé för thé stätüs öf thé täsk. Whén çömplétéd, thé "
"répört wïll ßé äväïläßlé för döwnlöäd ïn thé täßlé ßélöw. Ⱡ'σяєм ιρѕυм ∂σłσя"
" ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт"
" łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ "
"єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ "
"αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ "
υgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт#"
#: lms/djangoapps/instructor/views/api.py
msgid ""
"Your executive summary report is being created. To view the status of the "
"report, see the 'Pending Instructor Tasks' section."
"report, see the 'Pending Tasks' section."
msgstr ""
"Ýöür éxéçütïvé sümmärý répört ïs ßéïng çréätéd. Tö vïéw thé stätüs öf thé "
"répört, séé thé 'Péndïng Ìnstrüçtör Täsks' séçtïön. Ⱡ'σяєм #"
"répört, séé thé 'Péndïng Täsks' séçtïön. Ⱡ'σяєм ιρѕυм ∂σł#"
#: lms/djangoapps/instructor/views/api.py
msgid ""
"An executive summary report is currently in progress. To view the status of "
"the report, see the 'Pending Instructor Tasks' section. When completed, the "
"report will be available for download in the table below. You will be able "
"to download the report when it is complete."
"the report, see the 'Pending Tasks' section. When completed, the report will"
" be available for download in the table below. You will be able to download "
"the report when it is complete."
msgstr ""
"Àn éxéçütïvé sümmärý répört ïs çürréntlý ïn prögréss. Tö vïéw thé stätüs öf "
"thé répört, séé thé 'Péndïng Ìnstrüçtör Täsks' séçtïön. Whén çömplétéd, thé "
"répört wïll ßé äväïläßlé för döwnlöäd ïn thé täßlé ßélöw. Ýöü wïll ßé äßlé "
"tö döwnlöäd thé répört whén ït ïs çömplété. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт "
"∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση "
"υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂#"
"thé répört, séé thé 'Péndïng Täsks' séçtïön. Whén çömplétéd, thé répört wïll"
" ßé äväïläßlé för döwnlöäd ïn thé täßlé ßélöw. Ýöü wïll ßé äßlé tö döwnlöäd "
"thé répört whén ït ïs çömplété. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя "
"αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαα"
" αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ "
"ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ι#"
#: lms/djangoapps/instructor/views/api.py
msgid "Could not parse amount as a decimal"
@@ -7027,54 +7032,48 @@ msgstr ""
#: lms/djangoapps/instructor/views/api.py
msgid ""
"Your grade report is being generated! You can view the status of the "
"generation task in the 'Pending Instructor Tasks' section."
"generation task in the 'Pending Tasks' section."
msgstr ""
"Ýöür grädé répört ïs ßéïng générätéd! Ýöü çän vïéw thé stätüs öf thé "
"générätïön täsk ïn thé 'Péndïng Ìnstrüçtör Täsks' séçtïön. Ⱡ'σяє#"
"générätïön täsk ïn thé 'Péndïng Täsks' séçtïön. Ⱡ'σяєм ιρѕυм ∂σ#"
#: lms/djangoapps/instructor/views/api.py
msgid ""
"A grade report generation task is already in progress. Check the 'Pending "
"Instructor Tasks' table for the status of the task. When completed, the "
"report will be available for download in the table below."
"Tasks' table for the status of the task. When completed, the report will be "
"available for download in the table below."
msgstr ""
"À grädé répört générätïön täsk ïs älréädý ïn prögréss. Çhéçk thé 'Péndïng "
"Ìnstrüçtör Täsks' täßlé för thé stätüs öf thé täsk. Whén çömplétéd, thé "
"répört wïll ßé äväïläßlé för döwnlöäd ïn thé täßlé ßélöw. Ⱡ'σяєм ιρѕυм ∂σłσя"
" ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт"
" łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ "
"єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ "
"αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ "
"ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢α#"
"Täsks' täßlé för thé stätüs öf thé täsk. Whén çömplétéd, thé répört wïll ßé "
"äväïläßlé för döwnlöäd ïn thé täßlé ßélöw. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт "
"∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση "
"υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє "
"∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα"
" ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт ησ#"
#: lms/djangoapps/instructor/views/api.py
msgid ""
"Your problem grade report is being generated! You can view the status of the"
" generation task in the 'Pending Instructor Tasks' section."
" generation task in the 'Pending Tasks' section."
msgstr ""
"Ýöür prößlém grädé répört ïs ßéïng générätéd! Ýöü çän vïéw thé stätüs öf thé"
" générätïön täsk ïn thé 'Péndïng Ìnstrüçtör Täsks' séçtïön. Ⱡ'σяєм ιρѕυм "
"∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя "
"ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ "
"ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ "
σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє "
"¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт "
"ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕєяυηт мσłłιт αηιм ι∂ єѕт łαвσяυ#"
" générätïön täsk ïn thé 'Péndïng Täsks' séçtïön. Ⱡ'σяєм ι#"
#: lms/djangoapps/instructor/views/api.py
msgid ""
"A problem grade report is already being generated. Check the 'Pending "
"Instructor Tasks' table for the status of the task. When completed, the "
"report will be available for download in the table below."
"A problem grade report is already being generated. Check the 'Pending Tasks'"
" table for the status of the task. When completed, the report will be "
"available for download in the table below."
msgstr ""
"À prößlém grädé répört ïs älréädý ßéïng générätéd. Çhéçk thé 'Péndïng "
"Ìnstrüçtör Täsks' täßlé för thé stätüs öf thé täsk. Whén çömplétéd, thé "
"répört wïll ßé äväïläßlé för döwnlöäd ïn thé täßlé ßélöw. Ⱡ'σяєм ιρѕυм ∂σłσя"
" ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт"
" łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ "
"єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ "
"αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ "
"ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢#"
"À prößlém grädé répört ïs älréädý ßéïng générätéd. Çhéçk thé 'Péndïng Täsks'"
" täßlé för thé stätüs öf thé täsk. Whén çömplétéd, thé répört wïll ßé "
"äväïläßlé för döwnlöäd ïn thé täßlé ßélöw. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт "
"∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση "
"υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє "
"∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα"
" ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт ηση ρяσ#"
#: lms/djangoapps/instructor/views/api.py
msgid "Successfully changed due date for student {0} for {1} to {2}"
@@ -9603,10 +9602,6 @@ msgstr ""
"Süßsçrïßé tö thé {platform_name} ÝöüTüßé çhännél Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт "
"αмєт, ¢σηѕє¢тєтυ#"
#: lms/envs/common.py
msgid "Taiwan"
msgstr "Täïwän Ⱡ'σяєм ιρѕυ#"
#: lms/envs/devstack.py cms/templates/course-create-rerun.html
#: cms/templates/index.html cms/templates/settings.html
msgid "Organization"
@@ -10411,30 +10406,33 @@ msgstr ""
" νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт "
"¢υρι∂αтαт ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια#"
#: openedx/core/djangoapps/credit/models.py
msgid "Description for the credit provider displayed to users."
msgstr ""
"Désçrïptïön för thé çrédït prövïdér dïspläýéd tö üsérs. Ⱡ'σяєм ιρѕυм ∂σłσя "
"ѕιт αмєт, ¢σηѕє¢тєтυя α#"
#: openedx/core/djangoapps/credit/models.py
msgid ""
"Plain text or html content for displaying further steps on receipt page "
"*after* paying for the credit to get credit for a credit course against a "
"credit provider."
msgstr ""
"Pläïn téxt ör html çöntént för dïspläýïng fürthér stéps ön réçéïpt pägé "
"*äftér* päýïng för thé çrédït tö gét çrédït för ä çrédït çöürsé ägäïnst ä "
"çrédït prövïdér. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, "
"ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм "
"α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ "
"єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє"
" νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт "
"¢υρι∂αтαт ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕ#"
#: openedx/core/djangoapps/credit/models.py
msgid "Deadline for purchasing and requesting credit."
msgstr ""
"Déädlïné för pürçhäsïng änd réqüéstïng çrédït. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя α#"
#: openedx/core/djangoapps/import_export/courses/views.py
msgid "We only support uploading a .tar.gz file."
msgstr ""
"Wé önlý süppört üplöädïng ä .tär.gz fïlé. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя #"
#: openedx/core/djangoapps/import_export/courses/views.py
msgid "File upload corrupted. Please try again"
msgstr ""
"Fïlé üplöäd çörrüptéd. Pléäsé trý ägäïn Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя#"
#: openedx/core/djangoapps/import_export/courses/views.py
msgid "Could not find the {root_xml_file} file in the package."
msgstr ""
"Çöüld nöt fïnd thé {root_xml_file} fïlé ïn thé päçkägé. Ⱡ'σяєм ιρѕυм ∂σłσя "
"ѕιт αмєт, ¢σηѕє¢тєтυя #"
#: openedx/core/djangoapps/profile_images/images.py
msgid "bytes"
msgstr "ßýtés Ⱡ'σяєм ιρѕ#"
@@ -10892,12 +10890,22 @@ msgid "Empty"
msgstr "Émptý Ⱡ'σяєм ιρѕ#"
#: cms/djangoapps/contentstore/views/import_export.py
msgid ""
"An invalid parent key was supplied: \"{supplied_key}\" is not a valid course"
" unit."
msgid "We only support uploading a .tar.gz file."
msgstr ""
"Àn ïnvälïd pärént kéý wäs süpplïéd: \"{supplied_key}\" ïs nöt ä välïd çöürsé"
" ünït. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя #"
"Wé önlý süppört üplöädïng ä .tär.gz fïlé. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя #"
#: cms/djangoapps/contentstore/views/import_export.py
msgid "File upload corrupted. Please try again"
msgstr ""
"Fïlé üplöäd çörrüptéd. Pléäsé trý ägäïn Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя#"
#: cms/djangoapps/contentstore/views/import_export.py
msgid "Could not find the {0} file in the package."
msgstr ""
"Çöüld nöt fïnd thé {0} fïlé ïn thé päçkägé. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя #"
#: cms/djangoapps/contentstore/views/item.py
msgid "Invalid data"
@@ -14091,6 +14099,7 @@ msgid "Psychometrics"
msgstr "Psýçhömétrïçs Ⱡ'σяєм ιρѕυм ∂σłσя ѕι#"
#: lms/templates/courseware/legacy_instructor_dashboard.html
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Admin"
msgstr "Àdmïn Ⱡ'σяєм ιρѕ#"
@@ -14375,11 +14384,6 @@ msgstr ""
"(shöwn héré äs än éxämplé): Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмє#"
#: lms/templates/courseware/legacy_instructor_dashboard.html
#: lms/templates/instructor/instructor_dashboard_2/course_info.html
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html
#: lms/templates/instructor/instructor_dashboard_2/send_email.html
#: lms/templates/instructor/instructor_dashboard_2/student_admin.html
msgid "Pending Instructor Tasks"
msgstr "Péndïng Ìnstrüçtör Täsks Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢ση#"
@@ -14509,12 +14513,10 @@ msgstr "Ýöür çértïfïçäté ïs äväïläßlé Ⱡ'σяєм ιρѕυм
#: lms/templates/courseware/progress.html
msgid ""
"You can now access your certificate. If you keep working and receive a "
"higher grade,you can request an {link_start} updated certificate {link_end}."
"You can keep working for a higher grade, or request your certificate now."
msgstr ""
"Ýöü çän nöw äççéss ýöür çértïfïçäté. Ìf ýöü kéép wörkïng änd réçéïvé ä "
"hïghér grädé,ýöü çän réqüést än {link_start} üpdätéd çértïfïçäté {link_end}."
" Ⱡ#"
"Ýöü çän kéép wörkïng för ä hïghér grädé, ör réqüést ýöür çértïfïçäté nöw. "
"Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя#"
#: lms/templates/courseware/progress.html
msgid "View certificate in a new browser window or tab."
@@ -14560,13 +14562,6 @@ msgstr ""
"Çöngrätülätïöns, ýöü qüälïfïéd för ä çértïfïçäté! Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт "
"αмєт, ¢σηѕє¢тєтυя α#"
#: lms/templates/courseware/progress.html
msgid ""
"You can keep working for a higher grade, or request your certificate now."
msgstr ""
"Ýöü çän kéép wörkïng för ä hïghér grädé, ör réqüést ýöür çértïfïçäté nöw. "
"Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя#"
#: lms/templates/courseware/progress.html
msgid "Request Certificate"
msgstr "Réqüést Çértïfïçäté Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт,#"
@@ -14597,10 +14592,16 @@ msgid "Go to your dashboard"
msgstr "Gö tö ýöür däshßöärd Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #"
#: lms/templates/courseware/progress.html
msgid "You have not yet met the requirements for credit."
msgid "{student_name}, you have not yet met the requirements for credit."
msgstr ""
"Ýöü hävé nöt ýét mét thé réqüïréménts för çrédït. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт "
"αмєт, ¢σηѕє¢тєтυя α#"
"{student_name}, ýöü hävé nöt ýét mét thé réqüïréménts för çrédït. Ⱡ'σяєм "
"ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α#"
#: lms/templates/courseware/progress.html
msgid "Information about course credit requirements"
msgstr ""
"Ìnförmätïön äßöüt çöürsé çrédït réqüïréménts Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя #"
#: lms/templates/courseware/progress.html
msgid "display_name"
@@ -15028,6 +15029,26 @@ msgstr ""
"ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι "
"σƒƒι¢ια ∂є#"
#: lms/templates/dashboard/_dashboard_credit_info.html
msgid ""
"Thank you for your payment! To receive your course credit, go to the "
"{provider_link} website. You may have to complete some additional steps "
"depending on the institution"
msgstr ""
"Thänk ýöü för ýöür päýmént! Tö réçéïvé ýöür çöürsé çrédït, gö tö thé "
"{provider_link} wéßsïté. Ýöü mäý hävé tö çömplété sömé äddïtïönäl stéps "
"dépéndïng ön thé ïnstïtütïön Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя "
"αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαα"
" αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ "
"ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη "
"яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα "
"ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι "
"σƒƒι¢ια ∂єѕєяυηт #"
#: lms/templates/dashboard/_dashboard_credit_info.html
msgid "Complete Credit"
msgstr "Çömplété Çrédït Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт α#"
#: lms/templates/dashboard/_dashboard_credit_info.html
msgid ""
"Congratulations - you have received credit for this course! For more "
@@ -15036,6 +15057,10 @@ msgstr ""
"Çöngrätülätïöns - ýöü hävé réçéïvéd çrédït för thïs çöürsé! För möré "
"ïnförmätïön, séé {provider_link}. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕ#"
#: lms/templates/dashboard/_dashboard_credit_info.html
msgid "Access credit"
msgstr "Àççéss çrédït Ⱡ'σяєм ιρѕυм ∂σłσя ѕι#"
#: lms/templates/dashboard/_dashboard_credit_info.html
msgid ""
"{provider_name} has declined your request for course credit. For more "
@@ -15044,6 +15069,10 @@ msgstr ""
"{provider_name} häs déçlïnéd ýöür réqüést för çöürsé çrédït. För möré "
"ïnförmätïön, çöntäçt {provider_link}. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢т#"
#: lms/templates/dashboard/_dashboard_credit_info.html
msgid "Contact {provider_link}"
msgstr "Çöntäçt {provider_link} Ⱡ'σяєм ιρѕυм ∂σłσя #"
#: lms/templates/dashboard/_dashboard_info_language.html
msgid "edit"
msgstr "édït Ⱡ'σяєм ι#"
@@ -16797,6 +16826,11 @@ msgid "Generate Certificates"
msgstr "Généräté Çértïfïçätés Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #"
#: lms/templates/instructor/instructor_dashboard_2/certificates.html
#: lms/templates/instructor/instructor_dashboard_2/course_info.html
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html
#: lms/templates/instructor/instructor_dashboard_2/send_email.html
#: lms/templates/instructor/instructor_dashboard_2/student_admin.html
msgid "Pending Tasks"
msgstr "Péndïng Täsks Ⱡ'σяєм ιρѕυм ∂σłσя ѕι#"
@@ -16817,11 +16851,10 @@ msgstr "Énröllmént Ìnförmätïön Ⱡ'σяєм ιρѕυм ∂σłσя ѕι
#. Translators: 'track' refers to the enrollment type ('honor', 'verified', or
#. 'audit')
#: lms/templates/instructor/instructor_dashboard_2/course_info.html
msgid ""
"Number of enrollees (instructors, staff members, and students) by track"
msgid "Number of enrollees (admins, staff, and students) by track"
msgstr ""
"Nümßér öf énrölléés (ïnstrüçtörs, stäff mémßérs, änd stüdénts) ßý träçk "
"Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя#"
"Nümßér öf énrölléés (ädmïns, stäff, änd stüdénts) ßý träçk Ⱡ'σяєм ιρѕυм "
"∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α#"
#: lms/templates/instructor/instructor_dashboard_2/course_info.html
msgid "Audit"
@@ -17830,10 +17863,10 @@ msgstr "Bätçh Bétä Téstér Àddïtïön Ⱡ'σяєм ιρѕυм ∂σłσя
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid ""
"Note: Users must have an activated {platform_name} account before they can "
"be enrolled as a beta tester."
"be enrolled as beta testers."
msgstr ""
"Nöté: Ûsérs müst hävé än äçtïvätéd {platform_name} äççöünt ßéföré théý çän "
"ßé énrölléd äs ä ßétä téstér. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢ση#"
"ßé énrölléd äs ßétä téstérs. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢ση#"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid ""
@@ -17860,15 +17893,15 @@ msgstr "Rémövé ßétä téstérs Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт
#. Translators: an "Administration List" is a list, such as Course Staff, that
#. users can be added to.
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Administration List Management"
msgstr "Àdmïnïsträtïön Lïst Mänägémént Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢т#"
msgid "Course Team Management"
msgstr "Çöürsé Téäm Mänägémént Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢#"
#. Translators: an "Administrator Group" is a group, such as Course Staff,
#. that
#. users can be added to.
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Select an Administrator Group:"
msgstr "Séléçt än Àdmïnïsträtör Gröüp: Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢т#"
msgid "Select a course team role:"
msgstr "Séléçt ä çöürsé téäm rölé: Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕ#"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Getting available lists..."
@@ -17876,60 +17909,57 @@ msgstr "Géttïng äväïläßlé lïsts... Ⱡ'σяєм ιρѕυм ∂σłσя
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid ""
"Staff cannot modify staff or beta tester lists. To modify these lists, "
"contact your instructor and ask them to add you as an instructor for staff "
"and beta lists, or a discussion admin for discussion management."
"Staff cannot modify these lists. To manage course team membership, a course "
"Admin must give you the Admin role to add Staff or Beta Testers, or the "
"Discussion Admin role to add discussion moderators and TAs."
msgstr ""
"Stäff çännöt mödïfý stäff ör ßétä téstér lïsts. Tö mödïfý thésé lïsts, "
"çöntäçt ýöür ïnstrüçtör änd äsk thém tö ädd ýöü äs än ïnstrüçtör för stäff "
"änd ßétä lïsts, ör ä dïsçüssïön ädmïn för dïsçüssïön mänägémént. Ⱡ'σяєм "
"ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя "
"Stäff çännöt mödïfý thésé lïsts. Tö mänägé çöürsé téäm mémßérshïp, ä çöürsé "
"Àdmïn müst gïvé ýöü thé Àdmïn rölé tö ädd Stäff ör Bétä Téstérs, ör thé "
"Dïsçüssïön Àdmïn rölé tö ädd dïsçüssïön mödérätörs änd TÀs. Ⱡ'σяєм ιρѕυм "
"∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя "
"ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ "
"ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ "
σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє "
"¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтє#"
"¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕι#"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid ""
"Course staff can help you manage limited aspects of your course. Staff can "
"enroll and unenroll students, as well as modify their grades and see all "
"course data. Course staff are not automatically given access to Studio and "
"will not be able to edit your course."
"Course team members with the Staff role help you manage your course. Staff "
"can enroll and unenroll learners, as well as modify their grades and access "
"all course data. Staff also have access to your course in Studio and "
"Insights. You can only give course team roles to enrolled users."
msgstr ""
"Çöürsé stäff çän hélp ýöü mänägé lïmïtéd äspéçts öf ýöür çöürsé. Stäff çän "
"énröll änd ünénröll stüdénts, äs wéll äs mödïfý théïr grädés änd séé äll "
"çöürsé dätä. Çöürsé stäff äré nöt äütömätïçällý gïn äççéss tö Stüdïö änd "
"wïll nöt ßé äßlé tö édït ýöür çöürsé. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт "
"∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση "
"υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє "
"∂σłσя#"
"Çöürsé téäm mémßérs wïth thé Stäff rölé hélp ýöü mänägé ýöür çöürsé. Stäff "
"çän énröll änd ünénröll léärnérs, äs wéll äs mödïfý théïr grädés änd äççéss "
"äll çöürsé dätä. Stäff älsö hävé äççéss tö ýöür çöürsé ïn Stüdïö änd "
"Ìnsïghts. Ýöü çän önlý gïvé çöürsé téäm rös tö énrölléd üsérs. Ⱡ'σяєм "
"ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя "
"ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ "
"ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυ#"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Add Staff"
msgstr "Àdd Stäff Ⱡ'σяєм ιρѕυм ∂σł#"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Instructors"
msgstr "Ìnstrüçtörs Ⱡ'σяєм ιρѕυм ∂σłσя #"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid ""
"Instructors are the core administration of your course. Instructors can add "
"and remove course staff, as well as administer discussion access."
"Course team members with the Admin role help you manage your course. They "
"can do all of the tasks that Staff can do, and can also add and remove the "
"Staff and Admin roles, discussion moderation roles, and the beta tester role"
" to manage course team membership. You can only give course team roles to "
"enrolled users."
msgstr ""
"Ìnstrüçtörs äré thé çöré ädmïnïsträtïön öf ýöür çöürsé. Ìnstrüçtörs çän ädd "
"änd rémövé çöürsé stäff, äs wéll äs ädmïnïstér dïsçüssïön äççéss. Ⱡ'σяєм "
"ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя "
"ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ "
"ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ "
"¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє "
"¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт "
"ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕєяυηт мσłłιт αηιм ι∂ єѕт #"
"Çöürsé téäm mémßérs wïth thé Àdmïn rölé hélp ýöü mänägé ýöür çöürsé. Théý "
"çän dö äll öf thé täsks thät Stäff çän dö, änd çän älsö ädd änd rémövé thé "
"Stäff änd Àdmïn rölés, dïsçüssïön mödérätïön rölés, änd thé ßétä téstér rölé"
" tö mänägé çöürsé téäm mémßérshïp. Ýöü çän önlý gïvé çöürsé téäm rölés tö "
"énrölléd üsérs. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, "
"ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм "
"α∂ мιηι#"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Add Instructor"
msgstr "Àdd Ìnstrüçtör Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт#"
msgid "Add Admin"
msgstr "Àdd Àdmïn Ⱡ'σяєм ιρѕυм ∂σł#"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Beta Testers"
@@ -17937,17 +17967,18 @@ msgstr "Bétä Téstérs Ⱡ'σяєм ιρѕυм ∂σłσя ѕ#"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid ""
"Beta testers can see course content before the rest of the students. They "
"can make sure that the content works, but have no additional privileges."
"Beta Testers can see course content before other learners. They can make "
"sure that the content works, but have no additional privileges. You can only"
" give course team roles to enrolled users."
msgstr ""
"Bétä téstérs çän séé çöürsé çöntént ßéföré thé rést öf thé stüdénts. Théý "
"çän mäké süré thät thé çöntént wörks, ßüt hävé nö äddïtïönäl prïvïlégés. "
"Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ "
"тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм,"
" qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ "
σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє "
"¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт "
"ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕєяυηт мσłłιт αηιм ι#"
"Bétä Téstérs çän séé çöürsé çöntént ßéföré öthér léärnérs. Théý çän mäké "
"süré thät thé çöntént wörks, ßüt hävé nö äddïtïönäl prïvïlégés. Ýöü çän önlý"
" gïvé çöürsé téäm rölés tö énrölléd üsérs. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт "
"∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση "
"υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє "
"∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα"
" ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт ηση#"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Add Beta Tester"
@@ -17959,18 +17990,18 @@ msgstr "Dïsçüssïön Àdmïns Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid ""
"Discussion admins can edit or delete any post, clear misuse flags, close and"
" re-open threads, endorse responses, and see posts from all cohorts. They "
"CAN add/delete other moderators and their posts are marked as 'staff'."
"Discussion Admins can edit or delete any post, clear misuse flags, close and"
" re-open threads, endorse responses, and see posts from all cohorts. Their "
"posts are marked as 'staff'. They can also add and remove the discussion "
"moderation roles to manage course team membership. You can only give course "
"team roles to enrolled users."
msgstr ""
"Dïsçüssïön ädmïns çän édït ör délété äný pöst, çléär mïsüsé flägs, çlösé änd"
" ré-öpén thréäds, éndörsé réspönsés, änd séé pösts fröm äll çöhörts. Théý "
"ÇÀN ädd/délété öthér mödérätörs änd théïr pösts äré märkéd äs 'stäff'. "
"Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ "
"тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм,"
" qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ "
σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє "
"¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ρ#"
"Dïsçüssïön Àdmïns çän édït ör délété äný pöst, çléär mïsüsé flägs, çlösé änd"
" ré-öpén thréäds, éndörsé réspönsés, änd séé pösts fröm äll çöhörts. Théïr "
"pösts äré märkéd äs 'stäff'. Théý çän älsö ädd änd rémövé thé dïsçüssïön "
"mödérätïön rölés tö mänägé çöürsé téäm mémßérshïp. Ýöü çän önlý gïvé çöürsé "
"téäm rölés tö énrölléd üsérs. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя "
"αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σł#"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Add Discussion Admin"
@@ -17982,19 +18013,18 @@ msgstr "Dïsçüssïön Mödérätörs Ⱡ'σяєм ιρѕυм ∂σłσя ѕι
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid ""
"Discussion moderators can edit or delete any post, clear misuse flags, close"
"Discussion Moderators can edit or delete any post, clear misuse flags, close"
" and re-open threads, endorse responses, and see posts from all cohorts. "
"They CANNOT add/delete other moderators and their posts are marked as "
"'staff'."
"Their posts are marked as 'staff'. They cannot manage course team membership"
" by adding or removing discussion moderation roles. You can only give course"
" team roles to enrolled users."
msgstr ""
"Dïsçüssïön mödérätörs çän édït ör délété äný pöst, çléär mïsüsé flägs, çlösé"
"Dïsçüssïön Mödérätörs çän édït ör délété äný pöst, çléär mïsüsé flägs, çlösé"
" änd ré-öpén thréäds, éndörsé réspönsés, änd séé pösts fröm äll çöhörts. "
"Théý ÇÀNNÖT ädd/délété öthér mödérätörs änd théïr pösts äré märkéd äs "
"'stäff'. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ "
"єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм"
" νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα "
"¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт"
" єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυ#"
"Théïr pösts äré märkéd äs 'stäff'. Théý çännöt mänägé çöürsé téäm mémßérshïp"
" ßý äddïng ör rémövïng dïsçüssïön mödérätïön rölés. Ýöü çän önlý gïvé çöürsé"
" téäm rölés tö énrölléd üsérs. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя "
"αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє є#"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Add Moderator"
@@ -18009,15 +18039,15 @@ msgid ""
"Community TA's are members of the community whom you deem particularly "
"helpful on the discussion boards. They can edit or delete any post, clear "
"misuse flags, close and re-open threads, endorse responses, and see posts "
"from all cohorts. Their posts are marked 'Community TA'."
"from all cohorts. Their posts are marked as 'Community TA'. You can only "
"give course team roles to enrolled users."
msgstr ""
"Çömmünïtý TÀ's äré mémßérs öf thé çömmünïtý whöm ýöü déém pärtïçülärlý "
"hélpfül ön thé dïsçüssïön ßöärds. Théý çän édït ör délété äný pöst, çléär "
"mïsüsé flägs, çlösé änd ré-öpén thréäds, éndörsé réspönsés, änd séé pösts "
"fröm äll çöhörts. Théïr pösts äré märkéd 'Çömmünïtý TÀ'. Ⱡ'σяєм ιρѕυм ∂σłσя "
"ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт "
"łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ "
"єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σ#"
"fröm äll çöhörts. Théïr pösts äré märkéd äs 'Çömmünïtý TÀ'. Ýöü çän önlý "
"gïvé çöürsé téäm rölés tö énrölléd üsérs. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσ#"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Add Community TA"
@@ -18139,14 +18169,13 @@ msgid "Myself"
msgstr "Mýsélf Ⱡ'σяєм ιρѕυ#"
#: lms/templates/instructor/instructor_dashboard_2/send_email.html
msgid "Staff and instructors"
msgstr "Stäff änd ïnstrüçtörs Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #"
msgid "Staff and admins"
msgstr "Stäff änd ädmïns Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#"
#: lms/templates/instructor/instructor_dashboard_2/send_email.html
msgid "All (students, staff and instructors)"
msgid "All (students, staff, and admins)"
msgstr ""
"Àll (stüdénts, stäff änd ïnstrüçtörs) Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυ#"
"Àll (stüdénts, stäff, änd ädmïns) Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тє#"
#: lms/templates/instructor/instructor_dashboard_2/send_email.html
msgid "Subject: "
@@ -18343,17 +18372,17 @@ msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/student_admin.html
msgid ""
"Rescoring runs in the background, and status for active tasks will appear in"
" the 'Pending Instructor Tasks' table. To see status for all tasks submitted"
" for this problem and student, click on this button:"
" the 'Pending Tasks' table. To see status for all tasks submitted for this "
"problem and student, click on this button:"
msgstr ""
"Résçörïng rüns ïn thé ßäçkgröünd, änd stätüs för äçtïvé täsks wïll äppéär ïn"
" thé 'Péndïng Ìnstrüçtör Täsks' täßlé. Tö séé stätüs för äll täsks süßmïttéd"
" för thïs prößlém änd stüdént, çlïçk ön thïs ßüttön: Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт "
"αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт "
"łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ "
"єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ "
"αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ "
"ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢#"
" thé 'Péndïng Täsks' täßlé. Tö séé stätüs för äll täsks süßmïttéd för thïs "
"prößlém änd stüdént, çlïçk ön thïs ßüttön: Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт "
"∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση "
"υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє "
"∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα"
" ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт #"
#: lms/templates/instructor/instructor_dashboard_2/student_admin.html
msgid "Show Background Task History for Student"
@@ -18576,7 +18605,7 @@ msgid ""
"{p_tag}You currently do not have any peer grading to do. In order to have peer grading to do:\n"
"{ul_tag}\n"
"{li_tag}You need to have submitted a response to a peer grading problem.{end_li_tag}\n"
"{li_tag}The instructor needs to score the essays that are used to help you better understand the grading\n"
"{li_tag}The course team needs to score the essays that are used to help you better understand the grading\n"
"criteria.{end_li_tag}\n"
"{li_tag}There must be submissions that are waiting for grading.{end_li_tag}\n"
"{end_ul_tag}\n"
@@ -18586,12 +18615,12 @@ msgstr ""
"{p_tag}Ýöü çürréntlý dö nöt hävé äný péér grädïng tö dö. Ìn ördér tö hävé péér grädïng tö dö:\n"
"{ul_tag}\n"
"{li_tag}Ýöü nééd tö hävé süßmïttéd ä réspönsé tö ä péér grädïng prößlém.{end_li_tag}\n"
"{li_tag}Thé ïnstrüçtör nééds tö sçöré thé éssäýs thät äré üséd tö hélp ýöü ßéttér ündérständ thé grädïng\n"
"{li_tag}Thé çöürsé téäm nééds tö sçöré thé éssäýs thät äré üséd tö hélp ýöü ßéttér ündérständ thé grädïng\n"
"çrïtérïä.{end_li_tag}\n"
"{li_tag}Théré müst ßé süßmïssïöns thät äré wäïtïng för grädïng.{end_li_tag}\n"
"{end_ul_tag}\n"
"{end_p_tag}\n"
" Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт,#\n"
" Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłι#\n"
#: lms/templates/peer_grading/peer_grading.html
#: lms/templates/peer_grading/peer_grading_closed.html
@@ -22340,12 +22369,10 @@ msgid "User's Email Address"
msgstr "Ûsér's Émäïl Àddréss Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #"
#: cms/templates/manage_users.html
msgid ""
"Please provide the email address of the course staff member you'd like to "
"add"
msgid "Provide the email address of the user you want to add as Staff"
msgstr ""
"Pléäsé prövïdé thé émäïl äddréss öf thé çöürsé stäff mémßér ýöü'd lïké tö "
"ädd Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєт#"
"Prövïdé thé émäïl äddréss öf thé üsér ýöü wänt tö ädd äs Stäff Ⱡ'σяєм ιρѕυм "
"∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α#"
#: cms/templates/manage_users.html cms/templates/manage_users_lib.html
msgid "Add User"
@@ -22373,11 +22400,11 @@ msgstr "Çöürsé Téäm Rölés Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт α
#: cms/templates/manage_users.html
msgid ""
"Course team members, or staff, are course co-authors. They have full writing"
" and editing privileges on all course content."
"Course team members with the Staff role are course co-authors. They have "
"full writing and editing privileges on all course content."
msgstr ""
"Çöürsé téäm mémßérs, ör stäff, äré çöürsé çö-äüthörs. Théý hävé füll wrïtïng"
" änd édïtïng prïvïlégés ön äll çöürsé çöntént. Ⱡ'σяєм ιρѕ#"
"Çöürsé téäm mémßérs wïth thé Stäff rölé äré çöürsé çö-äüthörs. Théý hävé "
"füll wrïtïng änd édïtïng prïvïlégés ön äll çöürsé çöntént. Ⱡ#"
#: cms/templates/manage_users.html
msgid ""
@@ -22387,24 +22414,33 @@ msgstr ""
"Àdmïns äré çöürsé téäm mémßérs whö çän ädd änd rémövé öthér çöürsé téäm "
"mémßérs. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тє#"
#: cms/templates/manage_users.html
msgid ""
"All course team members are automatically enrolled in the course and can "
"access content in Studio, the LMS, and Insights."
msgstr ""
"Àll çöürsé téäm mémßérs äré äütömätïçällý énrölléd ïn thé çöürsé änd çän "
"äççéss çöntént ïn Stüdïö, thé LMS, änd Ìnsïghts. Ⱡ'σяєм ιρѕυ#"
#: cms/templates/manage_users.html
msgid "Transferring Ownership"
msgstr "Tränsférrïng Öwnérshïp Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢#"
#: cms/templates/manage_users.html
msgid ""
"Every course must have an Admin. If you're the Admin and you want transfer "
"ownership of the course, click Add admin access to make another user the "
"Admin, then ask that user to remove you from the Course Team list."
"Every course must have an Admin. If you are the Admin and you want to "
"transfer ownership of the course, click <strong>Add admin access</strong> to"
" make another user the Admin, then ask that user to remove you from the "
"Course Team list."
msgstr ""
"Évérý çöürsé müst hävé än Àdmïn. Ìf ýöü'ré thé Àdmïn änd ýöü wänt tränsfér "
"öwnérshïp öf thé çöürsé, çlïçk Àdd ädmïn äççéss tö mäké änöthér üsér thé "
"Àdmïn, thén äsk thät üsér tö rémövé ýöü fröm thé Çöürsé Téäm lïst. Ⱡ'σяєм "
"ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя "
"ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ "
"ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ "
σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє "
"¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. є#"
"Évérý çöürsé müst hävé än Àdmïn. Ìf ýöü äré thé Àdmïn änd ýöü wänt tö "
"tränsfér öwnérshïp öf thé çöürsé, çlïçk <strong>Àdd ädmïn äççéss</strong> tö"
" mäké änöthér üsér thé Àdmïn, thén äsk thät üsér tö rémövé ýöü fröm thé "
"Çöürsé Téäm lïst. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт,"
" ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм "
"α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ "
"єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє"
" νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυgιαт #"
#: cms/templates/manage_users_lib.html
msgid "Library User Access"
@@ -22452,39 +22488,40 @@ msgstr ""
#: cms/templates/manage_users_lib.html
msgid ""
"Users can view library content and can reference or use library components "
"in their courses, but they cannot edit the contents of a library."
"Library Users can view library content and can reference or use library "
"components in their courses, but they cannot edit the contents of a library."
msgstr ""
"Ûsérs çän vïéw lïßrärý çöntént änd çän référénçé ör üsé lïßrärý çömpönénts "
"ïn théïr çöürsés, ßüt théý çännöt édït thé çönténts öf ä lïßrärý. Ⱡ'σяєм "
"ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя "
"ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ "
"ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ "
σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє "
"¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт "
"ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕєяυηт мσłłιт αηιм ι∂ єѕт ł#"
#: cms/templates/manage_users_lib.html
msgid ""
"Staff are content co-authors. They have full editing privileges on the "
"contents of a library."
msgstr ""
"Stäff äré çöntént çö-äüthörs. Théý hävé füll édïtïng prïvïlégés ön thé "
"çönténts öf ä lïßrärý. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σ#"
#: cms/templates/manage_users_lib.html
msgid ""
"Admins have full editing privileges and can also add and remove other team "
"members. There must be at least one user with Admin privileges in a library."
msgstr ""
"Àdmïns hävé füll édïtïng prïvïlégés änd çän älsö ädd änd rémövé öthér téäm "
"mémßérs. Théré müst ßé ät léäst öné üsér wïth Àdmïn prïvïlégés ïn ä lïßrärý."
"Lïßrärý Ûsérs çän vïéw lïßrärý çöntént änd çän référénçé ör üsé lïßrärý "
"çömpönénts ïn théïr çöürsés, ßüt théý çännöt édït thé çönténts öf ä lïßrärý."
" Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ "
"тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм νєηιαм,"
" qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ "
σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє "
"¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт "
"ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕєяυηт мσłłιт α#"
"ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕєяυηт мσłłιт αηιм#"
#: cms/templates/manage_users_lib.html
msgid ""
"Library Staff are content co-authors. They have full editing privileges on "
"the contents of a library."
msgstr ""
"Lïßrärý Stäff äré çöntént çö-äüthörs. Théý hävé füll édïtïng prïvïlégés ön "
"thé çönténts öf ä lïßrärý. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмє#"
#: cms/templates/manage_users_lib.html
msgid ""
"Library Admins have full editing privileges and can also add and remove "
"other team members. There must be at least one user with the Admin role in a"
" library."
msgstr ""
"Lïßrärý Àdmïns hävé füll édïtïng prïvïlégés änd çän älsö ädd änd rémövé "
"öthér téäm mémßérs. Théré müst ßé ät léäst öné üsér wïth thé Àdmïn rölé ïn ä"
" lïßrärý. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя αιριѕι¢ιηg єłιт, ѕє∂ ∂σ "
"єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαα αłιqυα. υт єηιм α∂ мιηιм"
" νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα "
"¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт"
" єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт "
"¢υρι∂αтαт ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕєяυηт #"
#: cms/templates/register.html cms/templates/widgets/header.html
msgid "Sign Up"
@@ -22684,17 +22721,18 @@ msgstr ""
" ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт ηση ρя#"
#: cms/templates/settings.html
msgid "Credit Eligibility Requirements"
msgstr "Çrédït Élïgïßïlïtý Réqüïréménts Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢т#"
msgid "Course Credit Requirements"
msgstr "Çöürsé Çrédït Réqüïréménts Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕ#"
#: cms/templates/settings.html
msgid "Steps needed for credit eligibility"
msgid "Steps required to earn course credit"
msgstr ""
"Stéps néédéd för çrédït élïgïßïlïtý Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєт#"
"Stéps réqüïréd tö éärn çöürsé çrédït Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυ#"
#: cms/templates/settings.html
msgid "Minimum Passing Grade"
msgstr "Mïnïmüm Pässïng Grädé Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #"
msgid "Minimum Grade"
msgstr "Mïnïmüm Grädé Ⱡ'σяєм ιρѕυм ∂σłσя ѕι#"
#: cms/templates/settings.html
msgid "Successful Proctored Exam"
@@ -22705,21 +22743,14 @@ msgid "Proctored Exam {number}"
msgstr "Pröçtöréd Éxäm {number} Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт#"
#: cms/templates/settings.html
msgid "Successful In-Course Reverification"
msgstr ""
"Süççéssfül Ìn-Çöürsé Révérïfïçätïön Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєт#"
msgid "ID Verification"
msgstr "ÌD Vérïfïçätïön Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт α#"
#. Translators: 'Access to Assessment 1' means the access for a requirement
#. with name 'Assessment 1'
#: cms/templates/settings.html
msgid "In-Course Reverification {number}"
msgstr ""
"Ìn-Çöürsé Révérïfïçätïön {number} Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢#"
#: cms/templates/settings.html
msgid "Access to {display_name}"
msgstr "Àççéss tö {display_name} Ⱡ'σяєм ιρѕυм ∂σłσя ѕι#"
#: cms/templates/settings.html
msgid "Course Schedule"
msgstr "Çöürsé Sçhédülé Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт α#"
@@ -23109,24 +23140,24 @@ msgstr ""
"αмєт, ¢σηѕє¢тєтυя α#"
#: cms/templates/settings_graders.html
msgid "Credit Grade &amp; Eligibility"
msgstr "Çrédït Grädé &amp; Élïgïßïlïtý Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢#"
msgid "Credit Eligibility"
msgstr "Çrédït Élïgïßïlïtý Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт#"
#: cms/templates/settings_graders.html
msgid "Settings for credit eligibility"
msgstr "Séttïngs för çrédït élïgïßïlïtý Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢т#"
#: cms/templates/settings_graders.html
msgid "Minimum Passing Grade to Earn Credit:"
msgid "Settings for course credit eligibility"
msgstr ""
"Mïnïmüm Pässïng Grädé tö Éärn Çrédït: Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυ#"
"Séttïngs för çöürsé çrédït élïgïßïlïtý Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя#"
#: cms/templates/settings_graders.html
msgid "Must be greater than or equal to passing grade"
msgid "Minimum Credit-Eligible Grade:"
msgstr "Mïnïmüm Çrédït-Élïgïßlé Grädé: Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢т#"
#: cms/templates/settings_graders.html
msgid "Must be greater than or equal to the course passing grade"
msgstr ""
"Müst ßé gréätér thän ör éqüäl tö pässïng grädé Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя α#"
"Müst ßé gréätér thän ör éqüäl tö thé çöürsé pässïng grädé Ⱡ'σяєм ιρѕυм ∂σłσя"
" ѕιт αмєт, ¢σηѕє¢тєтυя α#"
#: cms/templates/settings_graders.html
msgid "Grading Rules &amp; Policies"

View File

@@ -26,8 +26,8 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.1a\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
"POT-Creation-Date: 2015-07-06 12:10+0000\n"
"PO-Revision-Date: 2015-07-06 12:11:44.276660\n"
"POT-Creation-Date: 2015-07-13 04:40+0000\n"
"PO-Revision-Date: 2015-07-13 04:42:08.623413\n"
"Last-Translator: \n"
"Language-Team: openedx-translation <openedx-translation@googlegroups.com>\n"
"MIME-Version: 1.0\n"
@@ -1140,9 +1140,11 @@ msgstr "Néw döçümént Ⱡ'σяєм ιρѕυм ∂σłσя ѕ#"
msgid "New window"
msgstr "Néw wïndöw Ⱡ'σяєм ιρѕυм ∂σłσ#"
#. #-#-#-#-# djangojs-partial.po (0.1a) #-#-#-#-#
#. Translators: this is a message from the raw HTML editor displayed in the
#. browser when a user needs to edit HTML
#: common/lib/xmodule/xmodule/js/src/html/edit.js
#: cms/templates/js/paging-header.underscore
msgid "Next"
msgstr "Néxt Ⱡ'σяєм ι#"
@@ -1559,7 +1561,6 @@ msgstr "Vértïçäl späçé Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт#"
#. 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
#: lms/djangoapps/teams/static/teams/js/views/topic_card.js
#: lms/templates/search/course_search_item.underscore
#: lms/templates/search/dashboard_search_item.underscore
msgid "View"
@@ -2140,55 +2141,17 @@ msgstr ""
"Àré ýöü süré ýöü wänt tö délété thïs réspönsé? Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя α#"
#. Translators: sample result:
#. "Showing 0-9 out of 25 total, filtered by Images, sorted by Date Added
#. ascending"
#: common/static/common/js/components/views/paging_header.js
msgid ""
"Showing %(current_item_range)s out of %(total_items_count)s, filtered by "
"%(asset_type)s, sorted by %(sort_name)s ascending"
msgid "Showing %(first_index)s out of %(num_items)s total"
msgstr ""
"Shöwïng %(current_item_range)s öüt öf %(total_items_count)s, fïltéréd ßý "
"%(asset_type)s, sörtéd ßý %(sort_name)s äsçéndïng Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт "
"αмєт, ¢σηѕє¢тєтυя α#"
"Shöwïng %(first_index)s öüt öf %(num_items)s tötäl Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт "
"αмєт, ¢σηѕє¢#"
#. Translators: sample result:
#. "Showing 0-9 out of 25 total, filtered by Images, sorted by Date Added
#. descending"
#: common/static/common/js/components/views/paging_header.js
msgid ""
"Showing %(current_item_range)s out of %(total_items_count)s, filtered by "
"%(asset_type)s, sorted by %(sort_name)s descending"
msgid "Showing %(first_index)s-%(last_index)s out of %(num_items)s total"
msgstr ""
"Shöwïng %(current_item_range)s öüt öf %(total_items_count)s, fïltéréd ßý "
"%(asset_type)s, sörtéd ßý %(sort_name)s désçéndïng Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт "
"αмєт, ¢σηѕє¢тєтυя α#"
#. Translators: sample result:
#. "Showing 0-9 out of 25 total, sorted by Date Added ascending"
#: common/static/common/js/components/views/paging_header.js
msgid ""
"Showing %(current_item_range)s out of %(total_items_count)s, sorted by "
"%(sort_name)s ascending"
msgstr ""
"Shöwïng %(current_item_range)s öüt öf %(total_items_count)s, sörtéd ßý "
"%(sort_name)s äsçéndïng Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α#"
#. Translators: sample result:
#. "Showing 0-9 out of 25 total, sorted by Date Added descending"
#: common/static/common/js/components/views/paging_header.js
msgid ""
"Showing %(current_item_range)s out of %(total_items_count)s, sorted by "
"%(sort_name)s descending"
msgstr ""
"Shöwïng %(current_item_range)s öüt öf %(total_items_count)s, sörtéd ßý "
"%(sort_name)s désçéndïng Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α#"
#. Translators: turns into "25 total" to be used in other sentences, e.g.
#. "Showing 0-9 out of 25 total".
#: common/static/common/js/components/views/paging_header.js
msgid "%(total_items)s total"
msgstr "%(total_items)s tötäl Ⱡ'σяєм ιρѕυм ∂σł#"
"Shöwïng %(first_index)s-%(last_index)s öüt öf %(num_items)s tötäl Ⱡ'σяєм "
"ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тє#"
#: common/static/js/capa/drag_and_drop/base_image.js
msgid "Drop target image"
@@ -2429,6 +2392,15 @@ msgstr "Réplý Ⱡ'σяєм ιρѕ#"
msgid "Tags:"
msgstr "Tägs: Ⱡ'σяєм ιρѕ#"
#: lms/djangoapps/teams/static/teams/js/collections/topic.js
#: lms/templates/edxnotes/tab-item.underscore
msgid "name"
msgstr "nämé Ⱡ'σяєм ι#"
#: lms/djangoapps/teams/static/teams/js/collections/topic.js
msgid "team count"
msgstr "téäm çöünt Ⱡ'σяєм ιρѕυм ∂σłσ#"
#: lms/djangoapps/teams/static/teams/js/views/teams_tab.js
msgid ""
"Course teams are organized into topics created by course instructors. Try to"
@@ -2461,6 +2433,11 @@ msgid_plural "%(team_count)s Teams"
msgstr[0] "%(team_count)s Téäm Ⱡ'σяєм ιρѕυм ∂#"
msgstr[1] "%(team_count)s Téäms Ⱡ'σяєм ιρѕυм ∂σł#"
#: lms/djangoapps/teams/static/teams/js/views/topic_card.js
msgid "View Teams in the %(topic_name)s Topic"
msgstr ""
"Vïéw Téäms ïn thé %(topic_name)s Töpïç Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє#"
#: lms/static/coffee/src/calculator.js
msgid "Open Calculator"
msgstr "Öpén Çälçülätör Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт α#"
@@ -4752,16 +4729,24 @@ msgstr ""
"¢σηѕє¢тєтυя #"
#: cms/static/js/models/settings/course_details.js
msgid "The course end date cannot be before the course start date."
msgid ""
"The course must have at least one active certificate configuration before it"
" can be started."
msgstr ""
"Thé çöürsé énd däté çännöt ßé ßéföré thé çöürsé stärt däté. Ⱡ'σяєм ιρѕυм "
"Thé çöürsé müst hävé ät léäst öné äçtïvé çértïfïçäté çönfïgürätïön ßéföré ït"
" çän ßé stärtéd. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢ση#"
#: cms/static/js/models/settings/course_details.js
msgid "The course end date must be later than the course start date."
msgstr ""
"Thé çöürsé énd däté müst ßé lätér thän thé çöürsé stärt däté. Ⱡ'σяєм ιρѕυм "
"∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α#"
#: cms/static/js/models/settings/course_details.js
msgid "The course start date cannot be before the enrollment start date."
msgid "The course start date must be later than the enrollment start date."
msgstr ""
"Thé çöürsé stärt däté çännöt ßé ßéföré thé énröllmént stärt däté. Ⱡ'σяєм "
"ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α#"
"Thé çöürsé stärt däté müst ßé lätér thän thé énröllmént stärt däté. Ⱡ'σяєм "
"ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя #"
#: cms/static/js/models/settings/course_details.js
msgid "The enrollment start date cannot be after the enrollment end date."
@@ -5200,6 +5185,56 @@ msgstr "Nöt Grädéd Ⱡ'σяєм ιρѕυм ∂σłσ#"
msgid "Date added"
msgstr "Däté äddéd Ⱡ'σяєм ιρѕυм ∂σłσ#"
#. Translators: sample result:
#. "Showing 0-9 out of 25 total, filtered by Images, sorted by Date Added
#. ascending"
#: cms/static/js/views/paging_header.js
msgid ""
"Showing %(current_item_range)s out of %(total_items_count)s, filtered by "
"%(asset_type)s, sorted by %(sort_name)s ascending"
msgstr ""
"Shöwïng %(current_item_range)s öüt öf %(total_items_count)s, fïltéréd ßý "
"%(asset_type)s, sörtéd ßý %(sort_name)s äsçéndïng Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт "
"αмєт, ¢σηѕє¢тєтυя α#"
#. Translators: sample result:
#. "Showing 0-9 out of 25 total, filtered by Images, sorted by Date Added
#. descending"
#: cms/static/js/views/paging_header.js
msgid ""
"Showing %(current_item_range)s out of %(total_items_count)s, filtered by "
"%(asset_type)s, sorted by %(sort_name)s descending"
msgstr ""
"Shöwïng %(current_item_range)s öüt öf %(total_items_count)s, fïltéréd ßý "
"%(asset_type)s, sörtéd ßý %(sort_name)s désçéndïng Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт "
"αмєт, ¢σηѕє¢тєтυя α#"
#. Translators: sample result:
#. "Showing 0-9 out of 25 total, sorted by Date Added ascending"
#: cms/static/js/views/paging_header.js
msgid ""
"Showing %(current_item_range)s out of %(total_items_count)s, sorted by "
"%(sort_name)s ascending"
msgstr ""
"Shöwïng %(current_item_range)s öüt öf %(total_items_count)s, sörtéd ßý "
"%(sort_name)s äsçéndïng Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α#"
#. Translators: sample result:
#. "Showing 0-9 out of 25 total, sorted by Date Added descending"
#: cms/static/js/views/paging_header.js
msgid ""
"Showing %(current_item_range)s out of %(total_items_count)s, sorted by "
"%(sort_name)s descending"
msgstr ""
"Shöwïng %(current_item_range)s öüt öf %(total_items_count)s, sörtéd ßý "
"%(sort_name)s désçéndïng Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α#"
#. Translators: turns into "25 total" to be used in other sentences, e.g.
#. "Showing 0-9 out of 25 total".
#: cms/static/js/views/paging_header.js
msgid "%(total_items)s total"
msgstr "%(total_items)s tötäl Ⱡ'σяєм ιρѕυм ∂σł#"
#. Translators: This is listed as the duration for a video
#. that has not yet reached the point in its processing by
#. the servers where its duration is determined.
@@ -5446,14 +5481,14 @@ msgstr ""
"¢υρι∂αтαт ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕєяυηт#"
#: cms/static/js/views/settings/main.js
msgid "Credit Eligibility Requirements"
msgstr "Çrédït Élïgïßïlïtý Réqüïréménts Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢т#"
msgid "Course Credit Requirements"
msgstr "Çöürsé Çrédït Réqüïréménts Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕ#"
#: cms/static/js/views/settings/main.js
msgid "Minimum passing grade for credit is not set."
msgid "The minimum grade for course credit is not set."
msgstr ""
"Mïnïmüm pässïng grädé för çrédït ïs nöt sét. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя #"
"Thé mïnïmüm grädé för çöürsé çrédït ïs nöt sét. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт,"
" ¢σηѕє¢тєтυя α#"
#: cms/static/js/views/settings/main.js
msgid "%(hours)s:%(minutes)s (current UTC time)"
@@ -5760,10 +5795,6 @@ msgstr "Nötéd ïn: Ⱡ'σяєм ιρѕυм ∂σł#"
msgid "Last Edited:"
msgstr "Läst Édïtéd: Ⱡ'σяєм ιρѕυм ∂σłσя ѕ#"
#: lms/templates/edxnotes/tab-item.underscore
msgid "name"
msgstr "nämé Ⱡ'σяєм ι#"
#: lms/templates/edxnotes/tab-item.underscore
msgid "Clear search results"
msgstr "Çléär séärçh résülts Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #"
@@ -6973,8 +7004,12 @@ msgid "Course title"
msgstr "Çöürsé tïtlé Ⱡ'σяєм ιρѕυм ∂σłσя ѕ#"
#: cms/templates/js/certificate-editor.underscore
msgid "Title of the course"
msgstr "Tïtlé öf thé çöürsé Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт,#"
msgid ""
"Specify an alternative to the official course title to display on "
"certificates. Leave blank to use the official course title."
msgstr ""
"Spéçïfý än ältérnätïvé tö thé öffïçïäl çöürsé tïtlé tö dïspläý ön "
"çértïfïçätés. Léävé ßlänk tö üsé thé öffïçïäl çöürsé tïtlé. Ⱡ'σяєм #"
#: cms/templates/js/certificate-editor.underscore
msgid "Organization Logo"
@@ -7474,6 +7509,10 @@ msgstr ""
msgid "Add your first textbook"
msgstr "Àdd ýöür fïrst téxtßöök Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σ#"
#: cms/templates/js/paging-header.underscore
msgid "Previous"
msgstr "Prévïöüs Ⱡ'σяєм ιρѕυм ∂#"
#: cms/templates/js/previous-video-upload-list.underscore
msgid "Previous Uploads"
msgstr "Prévïöüs Ûplöäds Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#"
@@ -7617,21 +7656,37 @@ msgid "Name of the signatory"
msgstr "Nämé öf thé sïgnätörý Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #"
#: cms/templates/js/signatory-editor.underscore
msgid "Maximum 40 characters"
msgstr "Mäxïmüm 40 çhäräçtérs Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #"
msgid ""
"The name of this signatory as it should appear on certificates. Maximum 40 "
"characters."
msgstr ""
"Thé nämé öf thïs sïgnätörý äs ït shöüld äppéär ön çértïfïçätés. Mäxïmüm 40 "
"çhäräçtérs. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢#"
#: cms/templates/js/signatory-editor.underscore
msgid "Title of the signatory"
msgstr "Tïtlé öf thé sïgnätörý Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢#"
#: cms/templates/js/signatory-editor.underscore
msgid "2 Lines, 40 characters each"
msgstr "2 Lïnés, 40 çhäräçtérs éäçh Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє#"
msgid ""
"The title of this signatory as it should appear on certificates. Maximum 2 "
"lines, 40 characters each."
msgstr ""
"Thé tïtlé öf thïs sïgnätörý äs ït shöüld äppéär ön çértïfïçätés. Mäxïmüm 2 "
"lïnés, 40 çhäräçtérs éäçh. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмє#"
#: cms/templates/js/signatory-editor.underscore
msgid "Organization of the signatory"
msgstr "Örgänïzätïön öf thé sïgnätörý Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢#"
#: cms/templates/js/signatory-editor.underscore
msgid ""
"The organization that this signatory belongs to, as it should appear on "
"certificates. Maximum 40 characters."
msgstr ""
"Thé örgänïzätïön thät thïs sïgnätörý ßélöngs tö, äs ït shöüld äppéär ön "
"çértïfïçätés. Mäxïmüm 40 çhäräçtérs. Ⱡ'σяєм ιρѕυм ∂σłσя ѕι#"
#: cms/templates/js/signatory-editor.underscore
msgid "Signature Image"
msgstr "Sïgnätüré Ìmägé Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт α#"

View File

@@ -168,10 +168,10 @@ msgid ""
msgstr ""
"Project-Id-Version: edx-platform\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
"POT-Creation-Date: 2015-07-06 12:02+0000\n"
"POT-Creation-Date: 2015-07-13 04:33+0000\n"
"PO-Revision-Date: 2015-06-29 17:10+0000\n"
"Last-Translator: Cristian Salamea <ovnicraft@gmail.com>\n"
"Language-Team: Spanish (Latin America) (http://www.transifex.com/projects/p/edx-platform/language/es_419/)\n"
"Language-Team: Spanish (Latin America) (http://www.transifex.com/p/edx-platform/language/es_419/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -3033,6 +3033,14 @@ msgstr ""
msgid "Certificate Name (Long)"
msgstr "Nombre (largo) para el certificado"
#: common/lib/xmodule/xmodule/course_module.py
msgid "Certificate Web/HTML View Enabled"
msgstr ""
#: common/lib/xmodule/xmodule/course_module.py
msgid "If true, certificate Web/HTML views are enabled for the course."
msgstr ""
#. Translators: This field is the container for course-specific certifcate
#. configuration values
#: common/lib/xmodule/xmodule/course_module.py
@@ -5396,10 +5404,6 @@ msgstr "Puntaje"
msgid "problems"
msgstr "problemas"
#: lms/djangoapps/commerce/signals.py lms/djangoapps/shoppingcart/models.py
msgid "[Refund] User-Requested Refund"
msgstr "[Refund] Devolución solicitada por el usuario"
#: lms/djangoapps/commerce/signals.py
msgid ""
"A refund request has been initiated for {username} ({email}). To process "
@@ -5408,6 +5412,10 @@ 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/signals.py lms/djangoapps/shoppingcart/models.py
msgid "[Refund] User-Requested Refund"
msgstr "[Refund] Devolución solicitada por el usuario"
#: lms/djangoapps/commerce/views.py lms/djangoapps/shoppingcart/pdf.py
msgid "Receipt"
msgstr "Recibo"
@@ -5956,13 +5964,13 @@ msgid "{platform_name} Staff"
msgstr "El equipo de {platform_name}"
#: lms/djangoapps/instructor/paidcourse_enrollment_report.py
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Course Staff"
msgstr "Equipo del curso"
#: lms/djangoapps/instructor/paidcourse_enrollment_report.py
#: lms/templates/courseware/course_navigation.html
#: lms/templates/discussion/_underscore_templates.html
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Staff"
msgstr "Equipo"
@@ -6167,42 +6175,28 @@ msgstr "Cohorte"
#: lms/djangoapps/instructor/views/api.py
msgid ""
"Your enrolled student profile report is being generated! You can view the "
"status of the generation task in the 'Pending Instructor Tasks' section."
"status of the generation task in the 'Pending Tasks' section."
msgstr ""
"Su reporte de perfiles de inscritos está siendo generado! Puede ver el "
"estado de la tarea de generación en la sección de 'Tareas Pendientes de "
"Instructor'"
#: lms/djangoapps/instructor/views/api.py
msgid ""
"An enrolled student profile report generation task is already in progress. "
"Check the 'Pending Instructor Tasks' table for the status of the task. When "
"completed, the report will be available for download in the table below."
"Check the 'Pending Tasks' table for the status of the task. When completed, "
"the report will be available for download in the table below."
msgstr ""
"Una tarea de reporte de perfiles de inscritos ya está en progreso. Verifique"
" la tabla de 'Tareas pendientes de instructor' para ver el estado de esta "
"tarea. Cuando se haya completado, el reporte estará disponible para ser "
"descargado en la tabla a continuación."
#: lms/djangoapps/instructor/views/api.py
msgid ""
"Your students who may enroll report is being generated! You can view the "
"status of the generation task in the 'Pending Instructor Tasks' section."
"status of the generation task in the 'Pending Tasks' section."
msgstr ""
"Su reporte de estudiantes que se pueden inscribir está siendo generado! "
"Puede ver el estado de la tarea de generación en la sección de 'Tareas "
"Pendientes de Instructor'"
#: lms/djangoapps/instructor/views/api.py
msgid ""
"A students who may enroll report generation task is already in progress. "
"Check the 'Pending Instructor Tasks' table for the status of the task. When "
"completed, the report will be available for download in the table below."
"Check the 'Pending Tasks' table for the status of the task. When completed, "
"the report will be available for download in the table below."
msgstr ""
"Una tarea de reporte de estudiantes que pueden inscribirse ya está en "
"progreso. Verifique la tabla de 'Tareas pendientes de instructor' para ver "
"el estado de esta tarea. Cuando se haya completado, el reporte estará "
"disponible para ser descargado en la tabla a continuación."
#: lms/djangoapps/instructor/views/api.py
msgid "The file must contain a 'cohort' column containing cohort names."
@@ -6265,42 +6259,29 @@ msgstr "Cantidad Total descontada"
#: lms/djangoapps/instructor/views/api.py
msgid ""
"Your detailed enrollment report is being generated! You can view the status "
"of the generation task in the 'Pending Instructor Tasks' section."
"of the generation task in the 'Pending Tasks' section."
msgstr ""
"Su reporte detallado de inscripciones está siendo generado! Puede ver el "
"estado de la tarea de generación en la sección de 'Tareas Pendientes de "
"Instructor'"
#: lms/djangoapps/instructor/views/api.py
msgid ""
"A detailed enrollment report generation task is already in progress. Check "
"the 'Pending Instructor Tasks' table for the status of the task. When "
"completed, the report will be available for download in the table below."
"the 'Pending Tasks' table for the status of the task. When completed, the "
"report will be available for download in the table below."
msgstr ""
"Una tarea de reporte detallado de inscripciones ya está en progreso. "
"Verifique la tabla de 'Tareas pendientes de instructor' para ver el estado "
"de esta tarea. Cuando se haya completado, el reporte estará disponible para "
"ser descargado en la tabla a continuación."
#: lms/djangoapps/instructor/views/api.py
msgid ""
"Your executive summary report is being created. To view the status of the "
"report, see the 'Pending Instructor Tasks' section."
"report, see the 'Pending Tasks' section."
msgstr ""
"Su resumen ejecutivo está siendo generado. Puede ver el estado de la tarea "
"de generación en la sección de 'Tareas Pendientes de Instructor'."
#: lms/djangoapps/instructor/views/api.py
msgid ""
"An executive summary report is currently in progress. To view the status of "
"the report, see the 'Pending Instructor Tasks' section. When completed, the "
"report will be available for download in the table below. You will be able "
"to download the report when it is complete."
"the report, see the 'Pending Tasks' section. When completed, the report will"
" be available for download in the table below. You will be able to download "
"the report when it is complete."
msgstr ""
"Una tarea de resumen ejecutivo ya está en progreso. Verifique la tabla de "
"'Tareas pendientes de instructor' para ver el estado de esta tarea. Cuando "
"se haya completado, el reporte estará disponible para ser descargado en la "
"tabla a continuación."
#: lms/djangoapps/instructor/views/api.py
msgid "Could not parse amount as a decimal"
@@ -6358,40 +6339,28 @@ msgstr "No se puede repuntuar con all_students y unique_student_identifier."
#: lms/djangoapps/instructor/views/api.py
msgid ""
"Your grade report is being generated! You can view the status of the "
"generation task in the 'Pending Instructor Tasks' section."
"generation task in the 'Pending Tasks' section."
msgstr ""
"Su reporte de notas está siendo generado! Puede ver el estado de la tarea de"
" generación en la sección de 'Tareas Pendientes de Instructor'"
#: lms/djangoapps/instructor/views/api.py
msgid ""
"A grade report generation task is already in progress. Check the 'Pending "
"Instructor Tasks' table for the status of the task. When completed, the "
"report will be available for download in the table below."
"Tasks' table for the status of the task. When completed, the report will be "
"available for download in the table below."
msgstr ""
"Una tarea de reporte de notas ya está en progreso. Verifique la tabla de "
"'Tareas pendientes de instructor' para ver el estado de esta tarea. Cuando "
"se haya completado, el reporte estará disponible para ser descargado en la "
"tabla a continuación."
#: lms/djangoapps/instructor/views/api.py
msgid ""
"Your problem grade report is being generated! You can view the status of the"
" generation task in the 'Pending Instructor Tasks' section."
" generation task in the 'Pending Tasks' section."
msgstr ""
"Su reporte de calificaciones de problemas está siendo generado! Puede ver el"
" estado de la tarea en la sección 'Tareas de instructor pendientes'."
#: lms/djangoapps/instructor/views/api.py
msgid ""
"A problem grade report is already being generated. Check the 'Pending "
"Instructor Tasks' table for the status of the task. When completed, the "
"report will be available for download in the table below."
"A problem grade report is already being generated. Check the 'Pending Tasks'"
" table for the status of the task. When completed, the report will be "
"available for download in the table below."
msgstr ""
"Ya está siendo generado un reporte de calificaciones de problemas. Revise la"
" sección 'Tareas de instructor pendientes' para ver el estado de la tarea. "
"Cuando se haya completado, el reporte estará disponible para descargar en la"
" tabla a continuación."
#: lms/djangoapps/instructor/views/api.py
msgid "Successfully changed due date for student {0} for {1} to {2}"
@@ -8669,10 +8638,6 @@ msgstr "Youtube"
msgid "Subscribe to the {platform_name} YouTube channel"
msgstr "Suscríbase al canal YouTube de {platform_name}."
#: lms/envs/common.py
msgid "Taiwan"
msgstr "Taiwan"
#: lms/envs/devstack.py cms/templates/course-create-rerun.html
#: cms/templates/index.html cms/templates/settings.html
msgid "Organization"
@@ -9406,22 +9371,21 @@ msgid ""
"requested credit."
msgstr ""
#: openedx/core/djangoapps/credit/models.py
msgid "Description for the credit provider displayed to users."
msgstr ""
#: openedx/core/djangoapps/credit/models.py
msgid ""
"Plain text or html content for displaying further steps on receipt page "
"*after* paying for the credit to get credit for a credit course against a "
"credit provider."
msgstr ""
#: openedx/core/djangoapps/credit/models.py
msgid "Deadline for purchasing and requesting credit."
msgstr ""
#: openedx/core/djangoapps/import_export/courses/views.py
msgid "We only support uploading a .tar.gz file."
msgstr ""
#: openedx/core/djangoapps/import_export/courses/views.py
msgid "File upload corrupted. Please try again"
msgstr ""
#: openedx/core/djangoapps/import_export/courses/views.py
msgid "Could not find the {root_xml_file} file in the package."
msgstr ""
#: openedx/core/djangoapps/profile_images/images.py
msgid "bytes"
msgstr "bytes"
@@ -9835,9 +9799,15 @@ msgid "Empty"
msgstr "Vacío"
#: cms/djangoapps/contentstore/views/import_export.py
msgid ""
"An invalid parent key was supplied: \"{supplied_key}\" is not a valid course"
" unit."
msgid "We only support uploading a .tar.gz file."
msgstr ""
#: cms/djangoapps/contentstore/views/import_export.py
msgid "File upload corrupted. Please try again"
msgstr ""
#: cms/djangoapps/contentstore/views/import_export.py
msgid "Could not find the {0} file in the package."
msgstr ""
#: cms/djangoapps/contentstore/views/item.py
@@ -12762,6 +12732,7 @@ msgid "Psychometrics"
msgstr "Psicometría"
#: lms/templates/courseware/legacy_instructor_dashboard.html
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Admin"
msgstr "Administrador"
@@ -13006,11 +12977,6 @@ msgstr ""
" ejemplo del 12 de Septiembre al 17 de octubre, 1 servidor)."
#: lms/templates/courseware/legacy_instructor_dashboard.html
#: lms/templates/instructor/instructor_dashboard_2/course_info.html
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html
#: lms/templates/instructor/instructor_dashboard_2/send_email.html
#: lms/templates/instructor/instructor_dashboard_2/student_admin.html
msgid "Pending Instructor Tasks"
msgstr "Tareas de instructor pendientes"
@@ -13136,9 +13102,10 @@ msgstr "Su certificado está disponible"
#: lms/templates/courseware/progress.html
msgid ""
"You can now access your certificate. If you keep working and receive a "
"higher grade,you can request an {link_start} updated certificate {link_end}."
"You can keep working for a higher grade, or request your certificate now."
msgstr ""
"Puede seguir trabajando en el curso para obtener una calificación superior, "
"o puede solicitar su certificado ahora."
#: lms/templates/courseware/progress.html
msgid "View certificate in a new browser window or tab."
@@ -13173,13 +13140,6 @@ msgstr ""
msgid "Congratulations, you qualified for a certificate!"
msgstr "Felicitaciones, usted califica para recibir un certificado!"
#: lms/templates/courseware/progress.html
msgid ""
"You can keep working for a higher grade, or request your certificate now."
msgstr ""
"Puede seguir trabajando en el curso para obtener una calificación superior, "
"o puede solicitar su certificado ahora."
#: lms/templates/courseware/progress.html
msgid "Request Certificate"
msgstr "Solicitar certificado"
@@ -13205,9 +13165,12 @@ msgid "Go to your dashboard"
msgstr "Ir al panel principal"
#: lms/templates/courseware/progress.html
msgid "You have not yet met the requirements for credit."
msgid "{student_name}, you have not yet met the requirements for credit."
msgstr ""
#: lms/templates/courseware/progress.html
msgid "Information about course credit requirements"
msgstr ""
"No ha completado los requerimientos para obtener crédito por este curso."
#: lms/templates/courseware/progress.html
msgid "display_name"
@@ -13563,18 +13526,37 @@ msgid ""
"information, see {provider_link}."
msgstr ""
#: lms/templates/dashboard/_dashboard_credit_info.html
msgid ""
"Thank you for your payment! To receive your course credit, go to the "
"{provider_link} website. You may have to complete some additional steps "
"depending on the institution"
msgstr ""
#: lms/templates/dashboard/_dashboard_credit_info.html
msgid "Complete Credit"
msgstr ""
#: lms/templates/dashboard/_dashboard_credit_info.html
msgid ""
"Congratulations - you have received credit for this course! For more "
"information, see {provider_link}."
msgstr ""
#: lms/templates/dashboard/_dashboard_credit_info.html
msgid "Access credit"
msgstr ""
#: lms/templates/dashboard/_dashboard_credit_info.html
msgid ""
"{provider_name} has declined your request for course credit. For more "
"information, contact {provider_link}."
msgstr ""
#: lms/templates/dashboard/_dashboard_credit_info.html
msgid "Contact {provider_link}"
msgstr ""
#: lms/templates/dashboard/_dashboard_info_language.html
msgid "edit"
msgstr "editar"
@@ -15143,6 +15125,11 @@ msgid "Generate Certificates"
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/certificates.html
#: lms/templates/instructor/instructor_dashboard_2/course_info.html
#: lms/templates/instructor/instructor_dashboard_2/data_download.html
#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html
#: lms/templates/instructor/instructor_dashboard_2/send_email.html
#: lms/templates/instructor/instructor_dashboard_2/student_admin.html
msgid "Pending Tasks"
msgstr ""
@@ -15162,11 +15149,8 @@ msgstr "Información de inscripción"
#. Translators: 'track' refers to the enrollment type ('honor', 'verified', or
#. 'audit')
#: lms/templates/instructor/instructor_dashboard_2/course_info.html
msgid ""
"Number of enrollees (instructors, staff members, and students) by track"
msgid "Number of enrollees (admins, staff, and students) by track"
msgstr ""
"Número total de inscritos (incluye instructores, personal de apoyo y "
"estudiantes) por ruta:"
#: lms/templates/instructor/instructor_dashboard_2/course_info.html
msgid "Audit"
@@ -16064,10 +16048,8 @@ msgstr "Addición en lote de usuarios de prueba beta"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid ""
"Note: Users must have an activated {platform_name} account before they can "
"be enrolled as a beta tester."
"be enrolled as beta testers."
msgstr ""
"Nota: Los usuarios de prueba deben tener una cuenta activa en "
"{platform_name} antes de que puedan ser registrados como usuarios de prueba."
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid ""
@@ -16094,15 +16076,15 @@ msgstr "Eliminar usuario de prueba"
#. Translators: an "Administration List" is a list, such as Course Staff, that
#. users can be added to.
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Administration List Management"
msgstr "Gestión de listas de Administración"
msgid "Course Team Management"
msgstr ""
#. Translators: an "Administrator Group" is a group, such as Course Staff,
#. that
#. users can be added to.
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Select an Administrator Group:"
msgstr "Seleccione un Grupo de administradores:"
msgid "Select a course team role:"
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Getting available lists..."
@@ -16110,49 +16092,35 @@ msgstr "Obteniendo la listas disponibles..."
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid ""
"Staff cannot modify staff or beta tester lists. To modify these lists, "
"contact your instructor and ask them to add you as an instructor for staff "
"and beta lists, or a discussion admin for discussion management."
"Staff cannot modify these lists. To manage course team membership, a course "
"Admin must give you the Admin role to add Staff or Beta Testers, or the "
"Discussion Admin role to add discussion moderators and TAs."
msgstr ""
"El personal del curso no puede modificar las listas de personal o las listas"
" probadores beta. Para modificar estas listas, comuníquese con su instructor"
" y pídale que lo agregarle como un instructor para el gestionar las listas "
"de personal y las listas beta, o como administrador de foro para la gestión "
"de los foros."
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid ""
"Course staff can help you manage limited aspects of your course. Staff can "
"enroll and unenroll students, as well as modify their grades and see all "
"course data. Course staff are not automatically given access to Studio and "
"will not be able to edit your course."
"Course team members with the Staff role help you manage your course. Staff "
"can enroll and unenroll learners, as well as modify their grades and access "
"all course data. Staff also have access to your course in Studio and "
"Insights. You can only give course team roles to enrolled users."
msgstr ""
"El personal de apoyo del curso puede ayudarle a gestionar algunos aspectos "
"de su curso. El personal puede registrar y dar de baja a los estudiantes, "
"así como modificar sus calificaciones y ver todos los datos del curso. "
"Personal del curso no tendrá automáticamente el acceso a studio y no estará "
"en capacidad de modificar su curso."
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Add Staff"
msgstr "Adicionar personal de apoyo"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Instructors"
msgstr "Instructores"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid ""
"Instructors are the core administration of your course. Instructors can add "
"and remove course staff, as well as administer discussion access."
"Course team members with the Admin role help you manage your course. They "
"can do all of the tasks that Staff can do, and can also add and remove the "
"Staff and Admin roles, discussion moderation roles, and the beta tester role"
" to manage course team membership. You can only give course team roles to "
"enrolled users."
msgstr ""
"Los instructores son los administradores principales de un curso. Pueden "
"añadir y eliminar personal del curso, así como administrar el acceso a los "
"foros de discusión."
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Add Instructor"
msgstr "Adicionar instructor"
msgid "Add Admin"
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Beta Testers"
@@ -16160,12 +16128,10 @@ msgstr "Usuarios de pruebas beta"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid ""
"Beta testers can see course content before the rest of the students. They "
"can make sure that the content works, but have no additional privileges."
"Beta Testers can see course content before other learners. They can make "
"sure that the content works, but have no additional privileges. You can only"
" give course team roles to enrolled users."
msgstr ""
"Los Usuarios de pruebas beta pueden ver el contenido del curso antes de que "
"el resto de los alumnos. Pueden asegurarse de que el contenido funcione, "
"pero no tienen privilegios adicionales."
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Add Beta Tester"
@@ -16177,15 +16143,12 @@ msgstr "Administradores de foros de discusión"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid ""
"Discussion admins can edit or delete any post, clear misuse flags, close and"
" re-open threads, endorse responses, and see posts from all cohorts. They "
"CAN add/delete other moderators and their posts are marked as 'staff'."
"Discussion Admins can edit or delete any post, clear misuse flags, close and"
" re-open threads, endorse responses, and see posts from all cohorts. Their "
"posts are marked as 'staff'. They can also add and remove the discussion "
"moderation roles to manage course team membership. You can only give course "
"team roles to enrolled users."
msgstr ""
"Los administradores de los foros de discusión pueden editar o borrar "
"cualquier publicación, pueden borrar los reportes de abuso, cerrar y reabrir"
" discusiones, validar respuestas, y ver las publicaciones de todas las "
"cohortes de un curso. También pueden añadir o eliminar a otros moderadores y"
" sus comentarios quedarán marcados como 'Funcionario'."
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Add Discussion Admin"
@@ -16197,16 +16160,12 @@ msgstr "Moderadores de foros de discusión"
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid ""
"Discussion moderators can edit or delete any post, clear misuse flags, close"
"Discussion Moderators can edit or delete any post, clear misuse flags, close"
" and re-open threads, endorse responses, and see posts from all cohorts. "
"They CANNOT add/delete other moderators and their posts are marked as "
"'staff'."
"Their posts are marked as 'staff'. They cannot manage course team membership"
" by adding or removing discussion moderation roles. You can only give course"
" team roles to enrolled users."
msgstr ""
"Los moderadores pueden editar o borrar cualquier publicación en el foro, "
"quitar las marcas de uso indebido, cerrar o reabrir discusiones, validar "
"respuestas y ver las publicaciones de todas las cohortes. No pueden añadir o"
" borrar a otros moderadores, y sus publicaciones son marcadas como "
"'publicaciones de funcionarios'."
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Add Moderator"
@@ -16221,13 +16180,9 @@ msgid ""
"Community TA's are members of the community whom you deem particularly "
"helpful on the discussion boards. They can edit or delete any post, clear "
"misuse flags, close and re-open threads, endorse responses, and see posts "
"from all cohorts. Their posts are marked 'Community TA'."
"from all cohorts. Their posts are marked as 'Community TA'. You can only "
"give course team roles to enrolled users."
msgstr ""
"Los profesores asistentes son miembros de la comunidad a quienes encontrará "
"particularmente útiles en los foros. Ellos pueden editar o borrar cualquier "
"publicación, borrar los reportes de abuso, cerrar y reabrir discusiones, "
"validar respuestas, y ver las publicaciones de todas las cohortes de un "
"curso. Sus publicaciones estarán marcadas como \"Profesor asistente\"."
#: lms/templates/instructor/instructor_dashboard_2/membership.html
msgid "Add Community TA"
@@ -16331,12 +16286,12 @@ msgid "Myself"
msgstr "Mi mismo"
#: lms/templates/instructor/instructor_dashboard_2/send_email.html
msgid "Staff and instructors"
msgstr "El personal del curso y los instructores"
msgid "Staff and admins"
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/send_email.html
msgid "All (students, staff and instructors)"
msgstr "Todos (Estudiantes, personal del curso e instructores)"
msgid "All (students, staff, and admins)"
msgstr ""
#: lms/templates/instructor/instructor_dashboard_2/send_email.html
msgid "Subject: "
@@ -16512,13 +16467,9 @@ msgstr "Borrar el estado del estudiante para el problema"
#: lms/templates/instructor/instructor_dashboard_2/student_admin.html
msgid ""
"Rescoring runs in the background, and status for active tasks will appear in"
" the 'Pending Instructor Tasks' table. To see status for all tasks submitted"
" for this problem and student, click on this button:"
" the 'Pending Tasks' table. To see status for all tasks submitted for this "
"problem and student, click on this button:"
msgstr ""
"Las tareas de re puntuación en segundo plano y el estado de las tareas "
"activas aparecerán en la tabla de 'Tareas de instructor pendientes'. Para "
"ver el estado de todas las tareas enviadas para este problema y estudiantes,"
" haga clic en este botón:"
#: lms/templates/instructor/instructor_dashboard_2/student_admin.html
msgid "Show Background Task History for Student"
@@ -16712,20 +16663,12 @@ msgid ""
"{p_tag}You currently do not have any peer grading to do. In order to have peer grading to do:\n"
"{ul_tag}\n"
"{li_tag}You need to have submitted a response to a peer grading problem.{end_li_tag}\n"
"{li_tag}The instructor needs to score the essays that are used to help you better understand the grading\n"
"{li_tag}The course team needs to score the essays that are used to help you better understand the grading\n"
"criteria.{end_li_tag}\n"
"{li_tag}There must be submissions that are waiting for grading.{end_li_tag}\n"
"{end_ul_tag}\n"
"{end_p_tag}\n"
msgstr ""
"\n"
"{p_tag}Usted no tiene ninguna calificación de pares pendiente. Para tener calificaciones de pares:\n"
"{ul_tag}\n"
"{li_tag}Usted debe haber enviado una respuesta a un problema de calificación de pares.{end_li_tag}\n"
"{li_tag}El instructor debe haber calificado los ensayos que se usan para explicarle mejor a usted los criterios de calificación.{end_li_tag}\n"
"{li_tag}Debe haber envíos que estén pendientes de ser calificados.{end_li_tag}\n"
"{end_ul_tag}\n"
"{end_p_tag}\n"
#: lms/templates/peer_grading/peer_grading.html
#: lms/templates/peer_grading/peer_grading_closed.html
@@ -19986,12 +19929,8 @@ msgid "User's Email Address"
msgstr "Dirección de correo electrónico del usuario"
#: cms/templates/manage_users.html
msgid ""
"Please provide the email address of the course staff member you'd like to "
"add"
msgid "Provide the email address of the user you want to add as Staff"
msgstr ""
"Por favor proporcione la dirección de correo electrónico de los miembros de "
"equipo que quiere añadir"
#: cms/templates/manage_users.html cms/templates/manage_users_lib.html
msgid "Add User"
@@ -20020,12 +19959,9 @@ msgstr "Roles de equipo de apoyo para el curso"
#: cms/templates/manage_users.html
msgid ""
"Course team members, or staff, are course co-authors. They have full writing"
" and editing privileges on all course content."
"Course team members with the Staff role are course co-authors. They have "
"full writing and editing privileges on all course content."
msgstr ""
"Los miembros de el equipo del curso, o funcionarios, son coautores del "
"curso. Ellos tienen privilegios completos de edición y escritura sobre todo "
"el contenido del curso."
#: cms/templates/manage_users.html
msgid ""
@@ -20035,21 +19971,23 @@ msgstr ""
"Los administradores son miembros del equipo del curso que pueden añadir o "
"eliminar a otros miembros del equipo del curso."
#: cms/templates/manage_users.html
msgid ""
"All course team members are automatically enrolled in the course and can "
"access content in Studio, the LMS, and Insights."
msgstr ""
#: cms/templates/manage_users.html
msgid "Transferring Ownership"
msgstr "Transfiriendo la propiedad"
#: cms/templates/manage_users.html
msgid ""
"Every course must have an Admin. If you're the Admin and you want transfer "
"ownership of the course, click Add admin access to make another user the "
"Admin, then ask that user to remove you from the Course Team list."
"Every course must have an Admin. If you are the Admin and you want to "
"transfer ownership of the course, click <strong>Add admin access</strong> to"
" make another user the Admin, then ask that user to remove you from the "
"Course Team list."
msgstr ""
"Cada curso tiene que tener un administrador. Si usted es el administrador y "
"desea transferir la propiedad del curso, haga clic en añadir acceso de "
"administrador para nombrar a otro usuario como administrador, y luego "
"solicite a dicho usuario que lo elimine de la lista de miembros del equipo "
"del curso."
#: cms/templates/manage_users_lib.html
msgid "Library User Access"
@@ -20098,29 +20036,22 @@ msgstr ""
#: cms/templates/manage_users_lib.html
msgid ""
"Users can view library content and can reference or use library components "
"in their courses, but they cannot edit the contents of a library."
"Library Users can view library content and can reference or use library "
"components in their courses, but they cannot edit the contents of a library."
msgstr ""
"Los usuarios pueden ver el contenido de la librería y referenciar o hacer "
"uso de los componentes en sus cursos, pero no pueden editar los contenidos "
"de la librería."
#: cms/templates/manage_users_lib.html
msgid ""
"Staff are content co-authors. They have full editing privileges on the "
"contents of a library."
"Library Staff are content co-authors. They have full editing privileges on "
"the contents of a library."
msgstr ""
"Los miembros de el equipo del curso son coautores del curso. Tienen "
"privilegios completos de edición sobre el contenido de la librería."
#: cms/templates/manage_users_lib.html
msgid ""
"Admins have full editing privileges and can also add and remove other team "
"members. There must be at least one user with Admin privileges in a library."
"Library Admins have full editing privileges and can also add and remove "
"other team members. There must be at least one user with the Admin role in a"
" library."
msgstr ""
"Los administradores tienen privilegios de edición y también pueden añadir o "
"remover los roles a otros miembros. Una librería siempre debe tener al menos"
" un usuario administrador."
#: cms/templates/register.html cms/templates/widgets/header.html
msgid "Sign Up"
@@ -20290,16 +20221,16 @@ msgstr ""
"previsualizarla, siga las instrucciones entregadas por su administrador."
#: cms/templates/settings.html
msgid "Credit Eligibility Requirements"
msgstr "Requerimientos para elegibilidad para créditos"
msgid "Course Credit Requirements"
msgstr ""
#: cms/templates/settings.html
msgid "Steps needed for credit eligibility"
msgstr "Pasos necesarios para elegibilidad para créditos"
msgid "Steps required to earn course credit"
msgstr ""
#: cms/templates/settings.html
msgid "Minimum Passing Grade"
msgstr "Nota mínima para pasar"
msgid "Minimum Grade"
msgstr ""
#: cms/templates/settings.html
msgid "Successful Proctored Exam"
@@ -20310,19 +20241,13 @@ msgid "Proctored Exam {number}"
msgstr "Examen supervisado {number}"
#: cms/templates/settings.html
msgid "Successful In-Course Reverification"
msgstr "Re verificación dentro del curso exitosa"
msgid "ID Verification"
msgstr ""
#. Translators: 'Access to Assessment 1' means the access for a requirement
#. with name 'Assessment 1'
#: cms/templates/settings.html
msgid "In-Course Reverification {number}"
msgstr "Re verificación dentro del curso {number}"
#: cms/templates/settings.html
msgid "Access to {display_name}"
msgstr "Acceso a {display_name}"
#: cms/templates/settings.html
msgid "Course Schedule"
msgstr "Calendario del curso"
@@ -20669,20 +20594,20 @@ msgstr ""
"estudiantes"
#: cms/templates/settings_graders.html
msgid "Credit Grade &amp; Eligibility"
msgstr "Calificación para créditos y elegibilidad"
msgid "Credit Eligibility"
msgstr ""
#: cms/templates/settings_graders.html
msgid "Settings for credit eligibility"
msgstr "Configuración de elegibilidad para créditos"
msgid "Settings for course credit eligibility"
msgstr ""
#: cms/templates/settings_graders.html
msgid "Minimum Passing Grade to Earn Credit:"
msgstr "Calificación mínima para obtener créditos:"
msgid "Minimum Credit-Eligible Grade:"
msgstr ""
#: cms/templates/settings_graders.html
msgid "Must be greater than or equal to passing grade"
msgstr "Debe ser mayor o igual a la calificación mínima para aprobar."
msgid "Must be greater than or equal to the course passing grade"
msgstr ""
#: cms/templates/settings_graders.html
msgid "Grading Rules &amp; Policies"

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