diff --git a/cms/djangoapps/contentstore/management/commands/reindex_course.py b/cms/djangoapps/contentstore/management/commands/reindex_course.py
index f5b6b9fadd55..74317169957a 100644
--- a/cms/djangoapps/contentstore/management/commands/reindex_course.py
+++ b/cms/djangoapps/contentstore/management/commands/reindex_course.py
@@ -4,6 +4,7 @@
import logging
from textwrap import dedent
from time import time
+from datetime import date
from django.core.management import BaseCommand, CommandError
from elasticsearch import exceptions
@@ -38,6 +39,9 @@ def add_arguments(self, parser):
parser.add_argument('--all',
action='store_true',
help='Reindex all courses')
+ parser.add_argument('--active',
+ action='store_true',
+ help='Reindex active courses only')
parser.add_argument('--setup',
action='store_true',
help='Reindex all courses on developers stack setup')
@@ -65,12 +69,17 @@ def handle(self, *args, **options):
"""
course_ids = options['course_ids']
all_option = options['all']
+ active_option = options['active']
setup_option = options['setup']
readable_option = options['warning']
index_all_courses_option = all_option or setup_option
- if (not len(course_ids) and not index_all_courses_option) or (len(course_ids) and index_all_courses_option): # lint-amnesty, pylint: disable=len-as-condition
- raise CommandError("reindex_course requires one or more s OR the --all or --setup flags.")
+ if ((not course_ids and not (index_all_courses_option or active_option)) or
+ (course_ids and (index_all_courses_option or active_option))):
+ raise CommandError((
+ "reindex_course requires one or more s"
+ " OR the --all, --active or --setup flags."
+ ))
store = modulestore()
@@ -104,12 +113,28 @@ def handle(self, *args, **options):
course_keys = [course.id for course in modulestore().get_courses()]
else:
return
+ elif active_option:
+ # in case of --active, we get the list of course keys from all courses
+ # that are stored in the modulestore and filter out the non-active
+ course_keys = []
+
+ today = date.today()
+ all_courses = modulestore().get_courses()
+ for course in all_courses:
+ # Omitting courses without a start date as well as
+ # couses that already ended (end date is in the past)
+ if not course.start or (course.end and course.end.date() < today):
+ continue
+ course_keys.append(course.id)
+
+ logging.warning(f'Selected {len(course_keys)} active courses over a total of {len(all_courses)}.')
+
else:
# in case course keys are provided as arguments
course_keys = list(map(self._parse_course_key, course_ids))
total = len(course_keys)
- logging.warning(f'Reindexing {total} courses')
+ logging.warning(f'Reindexing {total} courses...')
reindexed = 0
start = time()
@@ -120,6 +145,6 @@ def handle(self, *args, **options):
if reindexed % 10 == 0 or reindexed == total:
now = time()
t = now - start
- logging.warning(f'{reindexed}/{total} reindexed in {t:.1f} seconds')
+ logging.warning(f'{reindexed}/{total} reindexed in {t:.1f} seconds.')
except Exception as exc: # lint-amnesty, pylint: disable=broad-except
- logging.exception('Error indexing course %s due to the error: %s', course_key, exc)
+ logging.exception('Error indexing course %s due to the error: %s.', course_key, exc)
diff --git a/cms/djangoapps/contentstore/management/commands/tests/test_reindex_courses.py b/cms/djangoapps/contentstore/management/commands/tests/test_reindex_courses.py
index 57534f30c4a0..13d33c48f92a 100644
--- a/cms/djangoapps/contentstore/management/commands/tests/test_reindex_courses.py
+++ b/cms/djangoapps/contentstore/management/commands/tests/test_reindex_courses.py
@@ -10,6 +10,7 @@
from xmodule.modulestore.django import modulestore # lint-amnesty, pylint: disable=wrong-import-order
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase # lint-amnesty, pylint: disable=wrong-import-order
from xmodule.modulestore.tests.factories import CourseFactory, LibraryFactory # lint-amnesty, pylint: disable=wrong-import-order
+from datetime import datetime, timedelta
@ddt.ddt
@@ -26,11 +27,18 @@ def setUp(self):
org="test", library="lib2", display_name="run2", default_store=ModuleStoreEnum.Type.split
)
+ yesterday = datetime.min.today() - timedelta(days=1)
+
self.first_course = CourseFactory.create(
- org="test", course="course1", display_name="run1"
+ org="test", course="course1", display_name="run1", start=yesterday, end=None
)
+
self.second_course = CourseFactory.create(
- org="test", course="course2", display_name="run1"
+ org="test", course="course2", display_name="run1", start=yesterday, end=yesterday
+ )
+
+ self.third_course = CourseFactory.create(
+ org="test", course="course3", display_name="run1", start=None, end=None
)
REINDEX_PATH_LOCATION = (
@@ -103,7 +111,7 @@ def test_given_all_key_prompts_and_reindexes_all_courses(self):
call_command('reindex_course', all=True)
patched_yes_no.assert_called_once_with(ReindexCommand.CONFIRMATION_PROMPT, default='no')
- expected_calls = self._build_calls(self.first_course, self.second_course)
+ expected_calls = self._build_calls(self.first_course, self.second_course, self.third_course)
self.assertCountEqual(patched_index.mock_calls, expected_calls)
def test_given_all_key_prompts_and_reindexes_all_courses_cancelled(self):
@@ -116,3 +124,15 @@ def test_given_all_key_prompts_and_reindexes_all_courses_cancelled(self):
patched_yes_no.assert_called_once_with(ReindexCommand.CONFIRMATION_PROMPT, default='no')
patched_index.assert_not_called()
+
+ def test_given_active_key_prompt(self):
+ """
+ Test that reindexes all active courses when --active key is given
+ Active courses have a start date but no end date, or the end date is in the future.
+ """
+ with mock.patch(self.REINDEX_PATH_LOCATION) as patched_index, \
+ mock.patch(self.MODULESTORE_PATCH_LOCATION, mock.Mock(return_value=self.store)):
+ call_command('reindex_course', active=True)
+
+ expected_calls = self._build_calls(self.first_course)
+ self.assertCountEqual(patched_index.mock_calls, expected_calls)
diff --git a/cms/djangoapps/contentstore/signals/handlers.py b/cms/djangoapps/contentstore/signals/handlers.py
index 20c14089e0a6..e0bc9fcc9558 100644
--- a/cms/djangoapps/contentstore/signals/handlers.py
+++ b/cms/djangoapps/contentstore/signals/handlers.py
@@ -127,6 +127,17 @@ def listen_for_course_publish(sender, course_key, **kwargs): # pylint: disable=
dump_course_to_neo4j
)
+ # DEVELOPER README: probably all tasks here should use transaction.on_commit
+ # to avoid stale data, but the tasks are owned by many teams and are often
+ # working well enough. Several instead use a waiting strategy.
+ # If you are in here trying to figure out why your task is not working correctly,
+ # consider whether it is getting stale data and if so choose to wait for the transaction
+ # like exams or put your task to sleep for a while like discussions.
+ # You will not be able to replicate these errors in an environment where celery runs
+ # in process because it will be inside the transaction. Use the settings from
+ # devstack_with_worker.py, and consider adding a time.sleep into send_bulk_published_signal
+ # if you really want to make sure that the task happens before the data is ready.
+
# register special exams asynchronously after the data is ready
course_key_str = str(course_key)
transaction.on_commit(lambda: update_special_exams_and_publish.delay(course_key_str))
@@ -139,10 +150,9 @@ def listen_for_course_publish(sender, course_key, **kwargs): # pylint: disable=
# Push the course out to CourseGraph asynchronously.
dump_course_to_neo4j.delay(course_key_str)
- # Finally, call into the course search subsystem
- # to kick off an indexing action
+ # Kick off a courseware indexing action after the data is ready
if CoursewareSearchIndexer.indexing_is_enabled() and CourseAboutSearchIndexer.indexing_is_enabled():
- update_search_index.delay(course_key_str, datetime.now(UTC).isoformat())
+ transaction.on_commit(lambda: update_search_index.delay(course_key_str, datetime.now(UTC).isoformat()))
update_discussions_settings_from_course_task.apply_async(
args=[course_key_str],
diff --git a/cms/djangoapps/contentstore/tests/test_courseware_index.py b/cms/djangoapps/contentstore/tests/test_courseware_index.py
index 7d7a0d533b07..98a60dce901f 100644
--- a/cms/djangoapps/contentstore/tests/test_courseware_index.py
+++ b/cms/djangoapps/contentstore/tests/test_courseware_index.py
@@ -5,7 +5,7 @@
import time
from datetime import datetime
from unittest import skip
-from unittest.mock import patch
+from unittest.mock import patch, Mock
import ddt
import pytest
@@ -585,6 +585,8 @@ def test_large_course_deletion(self):
self._test_large_course_deletion(self.store)
+@patch('cms.djangoapps.contentstore.signals.handlers.transaction.on_commit',
+ new=Mock(side_effect=lambda func: func()),) # run right away
class TestTaskExecution(SharedModuleStoreTestCase):
"""
Set of tests to ensure that the task code will do the right thing when
diff --git a/cms/djangoapps/contentstore/views/tests/test_course_index.py b/cms/djangoapps/contentstore/views/tests/test_course_index.py
index 73db1a10b944..b30f8c95a631 100644
--- a/cms/djangoapps/contentstore/views/tests/test_course_index.py
+++ b/cms/djangoapps/contentstore/views/tests/test_course_index.py
@@ -6,7 +6,6 @@
import datetime
import json
from unittest import mock, skip
-from unittest.mock import patch
import ddt
import lxml
@@ -644,7 +643,7 @@ def test_verify_warn_only_on_enabled_blocks(self, enabled_block_types, deprecate
)
@override_settings(FEATURES={'ENABLE_EXAM_SETTINGS_HTML_VIEW': True})
- @patch('cms.djangoapps.models.settings.course_metadata.CourseMetadata.validate_proctoring_settings')
+ @mock.patch('cms.djangoapps.models.settings.course_metadata.CourseMetadata.validate_proctoring_settings')
def test_proctoring_link_is_visible(self, mock_validate_proctoring_settings):
"""
Test to check proctored exam settings mfe url is rendering properly
@@ -685,9 +684,11 @@ class TestCourseReIndex(CourseTestCase):
ENABLED_SIGNALS = ['course_published']
+ @mock.patch('cms.djangoapps.contentstore.signals.handlers.transaction.on_commit',
+ new=mock.Mock(side_effect=lambda func: func()), ) # run index right away
def setUp(self):
"""
- Set up the for the course outline tests.
+ Set up the for the course reindex tests.
"""
super().setUp()
diff --git a/cms/templates/studio_xblock_wrapper.html b/cms/templates/studio_xblock_wrapper.html
index 328a0a37e90d..0d6cafc95d66 100644
--- a/cms/templates/studio_xblock_wrapper.html
+++ b/cms/templates/studio_xblock_wrapper.html
@@ -137,7 +137,7 @@
% endif
% if use_tagging:
- ${_("Manage tags")}
+ ${_("Manage Tags")}
% endif
% if is_course:
diff --git a/common/djangoapps/student/tests/test_email.py b/common/djangoapps/student/tests/test_email.py
index bcede1821376..9ece964ac388 100644
--- a/common/djangoapps/student/tests/test_email.py
+++ b/common/djangoapps/student/tests/test_email.py
@@ -406,10 +406,9 @@ def test_email_success(self):
subject='Request to change édX account e-mail',
body_fragments=[
'We received a request to change the e-mail associated with',
- 'your édX account from {old_email} to {new_email}.'.format(
- old_email=old_email,
- new_email=new_email,
- ),
+ 'your édX account from',
+ old_email,
+ new_email,
'If this is correct, please confirm your new e-mail address by visiting:',
f'http://edx.org/email_confirm/{registration_key}',
'Please do not reply to this e-mail; if you require assistance,',
@@ -467,13 +466,11 @@ def setUp(self):
# Text fragments we expect in the body of the confirmation email
self.email_fragments = [
- "This is to confirm that you changed the e-mail associated with {platform_name}"
- " from {old_email} to {new_email}. If you did not make this request, please contact us immediately."
- " Contact information is listed at:".format(
- platform_name=settings.PLATFORM_NAME,
- old_email=self.user.email,
- new_email=PendingEmailChange.objects.get(activation_key=self.key).new_email
- ),
+ "This is to confirm that you changed the e-mail associated with ",
+ str(settings.PLATFORM_NAME),
+ "If you did not make this request, please contact us immediately. Contact information is listed at:",
+ self.user.email,
+ PendingEmailChange.objects.get(activation_key=self.key).new_email,
"We keep a log of old e-mails, so if this request was unintentional, we can investigate."
]
diff --git a/common/templates/student/edx_ace/accountactivation/email/body.html b/common/templates/student/edx_ace/accountactivation/email/body.html
index 9709074cc3d4..2c78b6f4b998 100644
--- a/common/templates/student/edx_ace/accountactivation/email/body.html
+++ b/common/templates/student/edx_ace/accountactivation/email/body.html
@@ -50,7 +50,7 @@
{% blocktrans trimmed asvar assist_msg %}
If you need help, please use our web form at {start_anchor_web}{{ support_url }}{end_anchor} or email {start_anchor_email}{{ support_email }}{end_anchor}.
{% endblocktrans %}
- {% interpolate_html assist_msg start_anchor_web=''|safe start_anchor_email=''|safe end_anchor=''|safe %}
+ {% interpolate_html assist_msg start_anchor_web=''|safe start_anchor_email=''|safe end_anchor=''|safe %}
diff --git a/common/templates/student/edx_ace/emailchange/email/body.html b/common/templates/student/edx_ace/emailchange/email/body.html
index b5c2c5edf21e..d6290d2161e4 100644
--- a/common/templates/student/edx_ace/emailchange/email/body.html
+++ b/common/templates/student/edx_ace/emailchange/email/body.html
@@ -3,6 +3,7 @@
{% load i18n %}
{% load static %}
{% block content %}
+{% with old_email=''|add:old_email|add:''|safe new_email=''|add:new_email|add:''|safe %}
+{% endwith %}
{% endblock %}
diff --git a/common/templates/student/edx_ace/emailchangeconfirmation/email/body.html b/common/templates/student/edx_ace/emailchangeconfirmation/email/body.html
index 9fc9f5929c43..f62c8e71476b 100644
--- a/common/templates/student/edx_ace/emailchangeconfirmation/email/body.html
+++ b/common/templates/student/edx_ace/emailchangeconfirmation/email/body.html
@@ -3,6 +3,7 @@
{% load i18n %}
{% load static %}
{% block content %}
+{% with old_email=''|add:old_email|add:''|safe new_email=''|add:new_email|add:''|safe %}
+{% endwith %}
{% endblock %}
diff --git a/conf/locale/ar/LC_MESSAGES/django.po b/conf/locale/ar/LC_MESSAGES/django.po
index 2ff7b2d9034b..a3f8c67f9c78 100644
--- a/conf/locale/ar/LC_MESSAGES/django.po
+++ b/conf/locale/ar/LC_MESSAGES/django.po
@@ -70,7 +70,7 @@
# طاهر , 2014
# #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Arabic (http://app.transifex.com/open-edx/edx-platform/language/ar/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -110,7 +110,7 @@
# wd3bbas , 2014
# #-#-#-#-# mako.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Arabic (http://app.transifex.com/open-edx/edx-platform/language/ar/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -224,7 +224,7 @@
# طاهر , 2014
# #-#-#-#-# wiki.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Arabic (http://app.transifex.com/open-edx/edx-platform/language/ar/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -248,9 +248,9 @@
# SalmaGhazal , 2014
# #-#-#-#-# edx_proctoring_proctortrack.po (0.1a) #-#-#-#-#
# edX community translations have been downloaded from Arabic (https://app.transifex.com/open-edx/teams/6205/ar/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
-# EdX Team , 2023.
+# EdX Team , 2024.
#
# Translators:
# NELC Open edX Translation , 2020
@@ -259,7 +259,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.1a\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
-"POT-Creation-Date: 2023-12-24 20:43+0000\n"
+"POT-Creation-Date: 2024-01-14 20:43+0000\n"
"PO-Revision-Date: 2019-01-20 20:43+0000\n"
"Last-Translator: NELC Open edX Translation , 2020\n"
"Language-Team: Arabic (https://app.transifex.com/open-edx/teams/6205/ar/)\n"
@@ -8349,6 +8349,13 @@ msgstr "المهنة"
msgid "Specialty"
msgstr "التخصص"
+#. Translators: This label appears above a dropdown menu to select
+#. the user's work experience
+#: openedx/core/djangoapps/user_api/accounts/settings_views.py
+#: openedx/core/djangoapps/user_authn/api/form_fields.py
+msgid "Work experience"
+msgstr ""
+
#: openedx/core/djangoapps/user_api/accounts/utils.py
#, python-brace-format
msgid ""
@@ -13053,6 +13060,10 @@ msgstr "نسخة مطابقة لـ ’{0}‘"
msgid "Invalid prerequisite course key"
msgstr "رقم المساق الأساسي غير صالح"
+#: cms/djangoapps/contentstore/utils.py
+msgid "Set Date"
+msgstr "تعيين التاريخ"
+
#. #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
#. Translators: This is the status of an active video upload
#: cms/djangoapps/contentstore/video_storage_handlers.py
@@ -13268,10 +13279,6 @@ msgstr ""
msgid "Course has been successfully reindexed."
msgstr "جرى إعادة فهرسة المساق بنجاح."
-#: cms/djangoapps/contentstore/views/course.py
-msgid "Set Date"
-msgstr "تعيين التاريخ"
-
#: cms/djangoapps/contentstore/views/course.py
msgid ""
"Special characters not allowed in organization, course number, and course "
@@ -23977,6 +23984,10 @@ msgstr "تكبير أو تصغير"
msgid "Select this problem"
msgstr ""
+#: cms/templates/studio_xblock_wrapper.html
+msgid "Manage Tags"
+msgstr ""
+
#: cms/templates/studio_xblock_wrapper.html
msgid "Manage Access"
msgstr ""
@@ -24343,6 +24354,10 @@ msgstr "تصفّح المساق"
msgid "Outline"
msgstr "المخطّط الكلّي"
+#: cms/templates/widgets/header.html
+msgid "Videos"
+msgstr ""
+
#: cms/templates/widgets/header.html
msgid "Publisher"
msgstr "ناشر"
diff --git a/conf/locale/ar/LC_MESSAGES/djangojs.po b/conf/locale/ar/LC_MESSAGES/djangojs.po
index 6cab9e39272a..998f763d98e1 100644
--- a/conf/locale/ar/LC_MESSAGES/djangojs.po
+++ b/conf/locale/ar/LC_MESSAGES/djangojs.po
@@ -1,6 +1,6 @@
# #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Arabic (http://app.transifex.com/open-edx/edx-platform/language/ar/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
diff --git a/conf/locale/ca/LC_MESSAGES/django.po b/conf/locale/ca/LC_MESSAGES/django.po
index 1c80a4eddbe2..a4c7c0ff3296 100644
--- a/conf/locale/ca/LC_MESSAGES/django.po
+++ b/conf/locale/ca/LC_MESSAGES/django.po
@@ -16,7 +16,7 @@
# Susanna Pujol, 2021
# #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Catalan (http://app.transifex.com/open-edx/edx-platform/language/ca/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -26,7 +26,7 @@
# Xavi Armengol , 2016
# #-#-#-#-# mako.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Catalan (http://app.transifex.com/open-edx/edx-platform/language/ca/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -7497,6 +7497,13 @@ msgstr ""
msgid "Specialty"
msgstr ""
+#. Translators: This label appears above a dropdown menu to select
+#. the user's work experience
+#: openedx/core/djangoapps/user_api/accounts/settings_views.py
+#: openedx/core/djangoapps/user_authn/api/form_fields.py
+msgid "Work experience"
+msgstr ""
+
#: openedx/core/djangoapps/user_api/accounts/utils.py
#, python-brace-format
msgid ""
@@ -11665,6 +11672,10 @@ msgstr "Duplicat de '{0}'"
msgid "Invalid prerequisite course key"
msgstr "Clau del curs prèvia no vàlida"
+#: cms/djangoapps/contentstore/utils.py
+msgid "Set Date"
+msgstr ""
+
#. #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
#. Translators: This is the status of an active video upload
#: cms/djangoapps/contentstore/video_storage_handlers.py
@@ -11884,10 +11895,6 @@ msgstr ""
msgid "Course has been successfully reindexed."
msgstr "El curs ha estat correctament reindexat."
-#: cms/djangoapps/contentstore/views/course.py
-msgid "Set Date"
-msgstr ""
-
#: cms/djangoapps/contentstore/views/course.py
msgid ""
"Special characters not allowed in organization, course number, and course "
@@ -22747,6 +22754,10 @@ msgstr "Amplia o redueix"
msgid "Select this problem"
msgstr ""
+#: cms/templates/studio_xblock_wrapper.html
+msgid "Manage Tags"
+msgstr ""
+
#: cms/templates/studio_xblock_wrapper.html
msgid "Manage Access"
msgstr ""
@@ -23117,6 +23128,10 @@ msgstr "Navegació del curs"
msgid "Outline"
msgstr "Esbós"
+#: cms/templates/widgets/header.html
+msgid "Videos"
+msgstr ""
+
#: cms/templates/widgets/header.html
msgid "Publisher"
msgstr ""
diff --git a/conf/locale/ca/LC_MESSAGES/djangojs.po b/conf/locale/ca/LC_MESSAGES/djangojs.po
index d8a5612c6ec0..3520d91dacbe 100644
--- a/conf/locale/ca/LC_MESSAGES/djangojs.po
+++ b/conf/locale/ca/LC_MESSAGES/djangojs.po
@@ -1,6 +1,6 @@
# #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Catalan (http://app.transifex.com/open-edx/edx-platform/language/ca/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
diff --git a/conf/locale/de_DE/LC_MESSAGES/django.po b/conf/locale/de_DE/LC_MESSAGES/django.po
index 8543ceecd7f8..1fd02b4411f5 100644
--- a/conf/locale/de_DE/LC_MESSAGES/django.po
+++ b/conf/locale/de_DE/LC_MESSAGES/django.po
@@ -45,7 +45,7 @@
# Андрей Поляков , 2016
# #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from German (Germany) (http://app.transifex.com/open-edx/edx-platform/language/de_DE/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -72,7 +72,7 @@
# Vassili Simon , 2014
# #-#-#-#-# mako.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from German (Germany) (http://app.transifex.com/open-edx/edx-platform/language/de_DE/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -146,7 +146,7 @@
# Waheed Ahmed , 2019
# #-#-#-#-# wiki.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from German (Germany) (http://app.transifex.com/open-edx/edx-platform/language/de_DE/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -166,9 +166,9 @@
# Stefania Trabucchi , 2019
# #-#-#-#-# edx_proctoring_proctortrack.po (0.1a) #-#-#-#-#
# edX community translations have been downloaded from German (Germany) (https://app.transifex.com/open-edx/teams/6205/de_DE/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
-# EdX Team , 2023.
+# EdX Team , 2024.
#
# Translators:
# Stefania Trabucchi , 2019
@@ -177,7 +177,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.1a\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
-"POT-Creation-Date: 2023-12-24 20:43+0000\n"
+"POT-Creation-Date: 2024-01-14 20:43+0000\n"
"PO-Revision-Date: 2019-01-20 20:43+0000\n"
"Last-Translator: Stefania Trabucchi , 2019\n"
"Language-Team: German (Germany) (https://app.transifex.com/open-edx/teams/6205/de_DE/)\n"
@@ -8330,6 +8330,13 @@ msgstr "Beruf"
msgid "Specialty"
msgstr "Spezialgebiet"
+#. Translators: This label appears above a dropdown menu to select
+#. the user's work experience
+#: openedx/core/djangoapps/user_api/accounts/settings_views.py
+#: openedx/core/djangoapps/user_authn/api/form_fields.py
+msgid "Work experience"
+msgstr ""
+
#: openedx/core/djangoapps/user_api/accounts/utils.py
#, python-brace-format
msgid ""
@@ -13174,6 +13181,10 @@ msgstr "Duplikat von '{0}'"
msgid "Invalid prerequisite course key"
msgstr "Ungültiger Vorbedingungskursschlüssel."
+#: cms/djangoapps/contentstore/utils.py
+msgid "Set Date"
+msgstr "Datum festlegen"
+
#. #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
#. Translators: This is the status of an active video upload
#: cms/djangoapps/contentstore/video_storage_handlers.py
@@ -13391,10 +13402,6 @@ msgstr ""
msgid "Course has been successfully reindexed."
msgstr "Kurs wurde erfolgreich neuindiziert."
-#: cms/djangoapps/contentstore/views/course.py
-msgid "Set Date"
-msgstr "Datum festlegen"
-
#: cms/djangoapps/contentstore/views/course.py
msgid ""
"Special characters not allowed in organization, course number, and course "
@@ -24500,6 +24507,10 @@ msgstr "Aufklappen oder zusammenlegen"
msgid "Select this problem"
msgstr ""
+#: cms/templates/studio_xblock_wrapper.html
+msgid "Manage Tags"
+msgstr ""
+
#: cms/templates/studio_xblock_wrapper.html
msgid "Manage Access"
msgstr ""
@@ -24873,6 +24884,10 @@ msgstr "Kursnavigation"
msgid "Outline"
msgstr "Übersicht"
+#: cms/templates/widgets/header.html
+msgid "Videos"
+msgstr ""
+
#: cms/templates/widgets/header.html
msgid "Publisher"
msgstr "Herausgeber"
diff --git a/conf/locale/de_DE/LC_MESSAGES/djangojs.po b/conf/locale/de_DE/LC_MESSAGES/djangojs.po
index e71deeb0d49d..45884078f345 100644
--- a/conf/locale/de_DE/LC_MESSAGES/djangojs.po
+++ b/conf/locale/de_DE/LC_MESSAGES/djangojs.po
@@ -1,6 +1,6 @@
# #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from German (Germany) (http://app.transifex.com/open-edx/edx-platform/language/de_DE/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
diff --git a/conf/locale/el/LC_MESSAGES/django.po b/conf/locale/el/LC_MESSAGES/django.po
index 984bf341417d..912aca5f2def 100644
--- a/conf/locale/el/LC_MESSAGES/django.po
+++ b/conf/locale/el/LC_MESSAGES/django.po
@@ -22,10 +22,10 @@
# Panos Chronis , 2014
# Anestis, 2014
# kafroulitsa , 2014
-# Ειρήνη Απέργη, 2023
+# Ειρήνη Απέργη, 2023-2024
# #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Greek (http://app.transifex.com/open-edx/edx-platform/language/el/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -40,7 +40,7 @@
# Ειρήνη Απέργη, 2023
# #-#-#-#-# mako.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Greek (http://app.transifex.com/open-edx/edx-platform/language/el/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -76,7 +76,7 @@
# Ειρήνη Απέργη, 2023
# #-#-#-#-# wiki.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Greek (http://app.transifex.com/open-edx/edx-platform/language/el/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -7684,6 +7684,13 @@ msgstr ""
msgid "Specialty"
msgstr ""
+#. Translators: This label appears above a dropdown menu to select
+#. the user's work experience
+#: openedx/core/djangoapps/user_api/accounts/settings_views.py
+#: openedx/core/djangoapps/user_authn/api/form_fields.py
+msgid "Work experience"
+msgstr ""
+
#: openedx/core/djangoapps/user_api/accounts/utils.py
#, python-brace-format
msgid ""
@@ -11918,6 +11925,10 @@ msgstr ""
msgid "Invalid prerequisite course key"
msgstr ""
+#: cms/djangoapps/contentstore/utils.py
+msgid "Set Date"
+msgstr ""
+
#. #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
#. Translators: This is the status of an active video upload
#: cms/djangoapps/contentstore/video_storage_handlers.py
@@ -12125,10 +12136,6 @@ msgstr ""
msgid "Course has been successfully reindexed."
msgstr ""
-#: cms/djangoapps/contentstore/views/course.py
-msgid "Set Date"
-msgstr ""
-
#: cms/djangoapps/contentstore/views/course.py
msgid ""
"Special characters not allowed in organization, course number, and course "
@@ -21868,6 +21875,10 @@ msgstr ""
msgid "Select this problem"
msgstr ""
+#: cms/templates/studio_xblock_wrapper.html
+msgid "Manage Tags"
+msgstr ""
+
#: cms/templates/studio_xblock_wrapper.html
msgid "Manage Access"
msgstr ""
@@ -22193,6 +22204,10 @@ msgstr ""
msgid "Outline"
msgstr ""
+#: cms/templates/widgets/header.html
+msgid "Videos"
+msgstr ""
+
#: cms/templates/widgets/header.html
msgid "Publisher"
msgstr ""
diff --git a/conf/locale/el/LC_MESSAGES/djangojs.po b/conf/locale/el/LC_MESSAGES/djangojs.po
index 824494efd6fc..51b73a38f77b 100644
--- a/conf/locale/el/LC_MESSAGES/djangojs.po
+++ b/conf/locale/el/LC_MESSAGES/djangojs.po
@@ -1,6 +1,6 @@
# #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Greek (http://app.transifex.com/open-edx/edx-platform/language/el/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
diff --git a/conf/locale/en/LC_MESSAGES/django.po b/conf/locale/en/LC_MESSAGES/django.po
index 44254de34cd7..8382f851668b 100644
--- a/conf/locale/en/LC_MESSAGES/django.po
+++ b/conf/locale/en/LC_MESSAGES/django.po
@@ -38,8 +38,8 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.1a\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
-"POT-Creation-Date: 2024-01-14 20:36+0000\n"
-"PO-Revision-Date: 2024-01-14 20:36:07.128712\n"
+"POT-Creation-Date: 2024-01-21 20:36+0000\n"
+"PO-Revision-Date: 2024-01-21 20:36:14.373996\n"
"Last-Translator: \n"
"Language-Team: openedx-translation \n"
"Language: en\n"
@@ -21467,10 +21467,6 @@ msgstr ""
msgid "Manage Access"
msgstr ""
-#: cms/templates/studio_xblock_wrapper.html
-msgid "Manage tags"
-msgstr ""
-
#: cms/templates/studio_xblock_wrapper.html
msgid "Copy to Clipboard"
msgstr ""
diff --git a/conf/locale/en/LC_MESSAGES/djangojs.po b/conf/locale/en/LC_MESSAGES/djangojs.po
index c58571ee6258..aedc9458b52b 100644
--- a/conf/locale/en/LC_MESSAGES/djangojs.po
+++ b/conf/locale/en/LC_MESSAGES/djangojs.po
@@ -32,8 +32,8 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.1a\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
-"POT-Creation-Date: 2024-01-14 20:35+0000\n"
-"PO-Revision-Date: 2024-01-14 20:36:07.075048\n"
+"POT-Creation-Date: 2024-01-21 20:36+0000\n"
+"PO-Revision-Date: 2024-01-21 20:36:14.438254\n"
"Last-Translator: \n"
"Language-Team: openedx-translation \n"
"Language: en\n"
diff --git a/conf/locale/eo/LC_MESSAGES/django.mo b/conf/locale/eo/LC_MESSAGES/django.mo
index dd5dcf50d308..b1fd48c47e47 100644
Binary files a/conf/locale/eo/LC_MESSAGES/django.mo and b/conf/locale/eo/LC_MESSAGES/django.mo differ
diff --git a/conf/locale/eo/LC_MESSAGES/django.po b/conf/locale/eo/LC_MESSAGES/django.po
index f3606c227011..ee2c5f662c52 100644
--- a/conf/locale/eo/LC_MESSAGES/django.po
+++ b/conf/locale/eo/LC_MESSAGES/django.po
@@ -38,8 +38,8 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.1a\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
-"POT-Creation-Date: 2024-01-14 20:36+0000\n"
-"PO-Revision-Date: 2024-01-14 20:36:07.128712\n"
+"POT-Creation-Date: 2024-01-21 20:36+0000\n"
+"PO-Revision-Date: 2024-01-21 20:36:14.373996\n"
"Last-Translator: \n"
"Language-Team: openedx-translation \n"
"Language: eo\n"
@@ -27932,10 +27932,6 @@ msgstr "Mänägé Tägs Ⱡ'σяєм ιρѕυм ∂σłσя #"
msgid "Manage Access"
msgstr "Mänägé Àççéss Ⱡ'σяєм ιρѕυм ∂σłσя ѕι#"
-#: cms/templates/studio_xblock_wrapper.html
-msgid "Manage tags"
-msgstr "Mänägé tägs Ⱡ'σяєм ιρѕυм ∂σłσя #"
-
#: cms/templates/studio_xblock_wrapper.html
msgid "Copy to Clipboard"
msgstr "Çöpý tö Çlïpßöärd Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмє#"
diff --git a/conf/locale/eo/LC_MESSAGES/djangojs.mo b/conf/locale/eo/LC_MESSAGES/djangojs.mo
index 1333e405cf95..a6d62c869a55 100644
Binary files a/conf/locale/eo/LC_MESSAGES/djangojs.mo and b/conf/locale/eo/LC_MESSAGES/djangojs.mo differ
diff --git a/conf/locale/eo/LC_MESSAGES/djangojs.po b/conf/locale/eo/LC_MESSAGES/djangojs.po
index b6d224c027f8..090b10b2673c 100644
--- a/conf/locale/eo/LC_MESSAGES/djangojs.po
+++ b/conf/locale/eo/LC_MESSAGES/djangojs.po
@@ -32,8 +32,8 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.1a\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
-"POT-Creation-Date: 2024-01-14 20:35+0000\n"
-"PO-Revision-Date: 2024-01-14 20:36:07.075048\n"
+"POT-Creation-Date: 2024-01-21 20:36+0000\n"
+"PO-Revision-Date: 2024-01-21 20:36:14.438254\n"
"Last-Translator: \n"
"Language-Team: openedx-translation \n"
"Language: eo\n"
diff --git a/conf/locale/es_419/LC_MESSAGES/django.po b/conf/locale/es_419/LC_MESSAGES/django.po
index 35adf8066d05..73109db5ae40 100644
--- a/conf/locale/es_419/LC_MESSAGES/django.po
+++ b/conf/locale/es_419/LC_MESSAGES/django.po
@@ -100,7 +100,7 @@
# Zainab Amir , 2019
# #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Spanish (Latin America) (http://app.transifex.com/open-edx/edx-platform/language/es_419/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -140,7 +140,7 @@
# Valeria Freire , 2014
# #-#-#-#-# mako.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Spanish (Latin America) (http://app.transifex.com/open-edx/edx-platform/language/es_419/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -271,7 +271,7 @@
# Zimeng Chen, 2021
# #-#-#-#-# wiki.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Spanish (Latin America) (http://app.transifex.com/open-edx/edx-platform/language/es_419/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -284,9 +284,9 @@
# Leonardo J. Caballero G. , 2018
# #-#-#-#-# edx_proctoring_proctortrack.po (0.1a) #-#-#-#-#
# edX community translations have been downloaded from Spanish (Latin America) (https://app.transifex.com/open-edx/teams/6205/es_419/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
-# EdX Team , 2023.
+# EdX Team , 2024.
#
# Translators:
# Miguel Bonilla , 2019
@@ -296,7 +296,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.1a\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
-"POT-Creation-Date: 2023-12-24 20:43+0000\n"
+"POT-Creation-Date: 2024-01-14 20:43+0000\n"
"PO-Revision-Date: 2019-01-20 20:43+0000\n"
"Last-Translator: Albeiro Gonzalez , 2019\n"
"Language-Team: Spanish (Latin America) (https://app.transifex.com/open-edx/teams/6205/es_419/)\n"
@@ -8777,6 +8777,13 @@ msgstr "Profesión"
msgid "Specialty"
msgstr "Especialidad"
+#. Translators: This label appears above a dropdown menu to select
+#. the user's work experience
+#: openedx/core/djangoapps/user_api/accounts/settings_views.py
+#: openedx/core/djangoapps/user_authn/api/form_fields.py
+msgid "Work experience"
+msgstr ""
+
#: openedx/core/djangoapps/user_api/accounts/utils.py
#, python-brace-format
msgid ""
@@ -13704,6 +13711,10 @@ msgstr "Duplicado de '{0}'"
msgid "Invalid prerequisite course key"
msgstr "Clave inválida del curso prerrequisito"
+#: cms/djangoapps/contentstore/utils.py
+msgid "Set Date"
+msgstr "Establecer Fecha"
+
#. #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
#. Translators: This is the status of an active video upload
#: cms/djangoapps/contentstore/video_storage_handlers.py
@@ -13922,10 +13933,6 @@ msgstr "Solo Evaluación Par"
msgid "Course has been successfully reindexed."
msgstr "El curso ha sido reindexado correctamente."
-#: cms/djangoapps/contentstore/views/course.py
-msgid "Set Date"
-msgstr "Establecer Fecha"
-
#: cms/djangoapps/contentstore/views/course.py
msgid ""
"Special characters not allowed in organization, course number, and course "
@@ -25131,6 +25138,10 @@ msgstr "Expandir o Colapsar"
msgid "Select this problem"
msgstr "Seleccionar este problema"
+#: cms/templates/studio_xblock_wrapper.html
+msgid "Manage Tags"
+msgstr ""
+
#: cms/templates/studio_xblock_wrapper.html
msgid "Manage Access"
msgstr "Administrar acceso"
@@ -25504,6 +25515,10 @@ msgstr "Navegación del curso"
msgid "Outline"
msgstr "Estructura"
+#: cms/templates/widgets/header.html
+msgid "Videos"
+msgstr ""
+
#: cms/templates/widgets/header.html
msgid "Publisher"
msgstr "Editor"
diff --git a/conf/locale/es_419/LC_MESSAGES/djangojs.po b/conf/locale/es_419/LC_MESSAGES/djangojs.po
index f4be62ca19fd..5bb5965336f5 100644
--- a/conf/locale/es_419/LC_MESSAGES/djangojs.po
+++ b/conf/locale/es_419/LC_MESSAGES/djangojs.po
@@ -1,6 +1,6 @@
# #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Spanish (Latin America) (http://app.transifex.com/open-edx/edx-platform/language/es_419/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
diff --git a/conf/locale/eu_ES/LC_MESSAGES/django.po b/conf/locale/eu_ES/LC_MESSAGES/django.po
index dcd52ce8bc00..2fc51a561f03 100644
--- a/conf/locale/eu_ES/LC_MESSAGES/django.po
+++ b/conf/locale/eu_ES/LC_MESSAGES/django.po
@@ -12,7 +12,7 @@
# Pedro Lonbide , 2015
# #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Basque (Spain) (http://app.transifex.com/open-edx/edx-platform/language/eu_ES/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -21,7 +21,7 @@
# Pedro Lonbide , 2015
# #-#-#-#-# mako.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Basque (Spain) (http://app.transifex.com/open-edx/edx-platform/language/eu_ES/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -7627,6 +7627,13 @@ msgstr "Lanbidea"
msgid "Specialty"
msgstr "Espezialitatea"
+#. Translators: This label appears above a dropdown menu to select
+#. the user's work experience
+#: openedx/core/djangoapps/user_api/accounts/settings_views.py
+#: openedx/core/djangoapps/user_authn/api/form_fields.py
+msgid "Work experience"
+msgstr ""
+
#: openedx/core/djangoapps/user_api/accounts/utils.py
#, python-brace-format
msgid ""
@@ -11922,6 +11929,10 @@ msgstr ""
msgid "Invalid prerequisite course key"
msgstr ""
+#: cms/djangoapps/contentstore/utils.py
+msgid "Set Date"
+msgstr "Ezarri data"
+
#. #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
#. Translators: This is the status of an active video upload
#: cms/djangoapps/contentstore/video_storage_handlers.py
@@ -12129,10 +12140,6 @@ msgstr ""
msgid "Course has been successfully reindexed."
msgstr ""
-#: cms/djangoapps/contentstore/views/course.py
-msgid "Set Date"
-msgstr "Ezarri data"
-
#: cms/djangoapps/contentstore/views/course.py
msgid ""
"Special characters not allowed in organization, course number, and course "
@@ -21807,6 +21814,10 @@ msgstr "Zabaldu edo tolestu"
msgid "Select this problem"
msgstr ""
+#: cms/templates/studio_xblock_wrapper.html
+msgid "Manage Tags"
+msgstr ""
+
#: cms/templates/studio_xblock_wrapper.html
msgid "Manage Access"
msgstr ""
@@ -22131,6 +22142,10 @@ msgstr "Ikastaroaren nabigazioa"
msgid "Outline"
msgstr "Egitura"
+#: cms/templates/widgets/header.html
+msgid "Videos"
+msgstr ""
+
#: cms/templates/widgets/header.html
msgid "Publisher"
msgstr "Argitaratzailea"
diff --git a/conf/locale/eu_ES/LC_MESSAGES/djangojs.po b/conf/locale/eu_ES/LC_MESSAGES/djangojs.po
index b65cb4f92b87..9703a1a94066 100644
--- a/conf/locale/eu_ES/LC_MESSAGES/djangojs.po
+++ b/conf/locale/eu_ES/LC_MESSAGES/djangojs.po
@@ -1,6 +1,6 @@
# #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Basque (Spain) (http://app.transifex.com/open-edx/edx-platform/language/eu_ES/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
diff --git a/conf/locale/fa_IR/LC_MESSAGES/django.po b/conf/locale/fa_IR/LC_MESSAGES/django.po
index 021611fbad48..fe9186fa62d8 100644
--- a/conf/locale/fa_IR/LC_MESSAGES/django.po
+++ b/conf/locale/fa_IR/LC_MESSAGES/django.po
@@ -43,7 +43,7 @@
# Zahra Sadat Navabi , 2015
# #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Persian (Iran) (http://app.transifex.com/open-edx/edx-platform/language/fa_IR/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -60,7 +60,7 @@
# Somaye Joolaee, 2022
# #-#-#-#-# mako.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Persian (Iran) (http://app.transifex.com/open-edx/edx-platform/language/fa_IR/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -8318,6 +8318,13 @@ msgstr "حرفه"
msgid "Specialty"
msgstr "تخصص"
+#. Translators: This label appears above a dropdown menu to select
+#. the user's work experience
+#: openedx/core/djangoapps/user_api/accounts/settings_views.py
+#: openedx/core/djangoapps/user_authn/api/form_fields.py
+msgid "Work experience"
+msgstr ""
+
#: openedx/core/djangoapps/user_api/accounts/utils.py
#, python-brace-format
msgid ""
@@ -13099,6 +13106,10 @@ msgstr "کپی '{0}' "
msgid "Invalid prerequisite course key"
msgstr "کلید دوره پیشنیاز معتبر نیست"
+#: cms/djangoapps/contentstore/utils.py
+msgid "Set Date"
+msgstr "ثبت تاریخ"
+
#. #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
#. Translators: This is the status of an active video upload
#: cms/djangoapps/contentstore/video_storage_handlers.py
@@ -13312,10 +13323,6 @@ msgstr "فقط ارزیابی همتا"
msgid "Course has been successfully reindexed."
msgstr "دوره آموزشی با موفقیت دوباره نمایه شده است."
-#: cms/djangoapps/contentstore/views/course.py
-msgid "Set Date"
-msgstr "ثبت تاریخ"
-
#: cms/djangoapps/contentstore/views/course.py
msgid ""
"Special characters not allowed in organization, course number, and course "
@@ -24238,6 +24245,10 @@ msgstr "گسترده یا فشرده"
msgid "Select this problem"
msgstr ""
+#: cms/templates/studio_xblock_wrapper.html
+msgid "Manage Tags"
+msgstr ""
+
#: cms/templates/studio_xblock_wrapper.html
msgid "Manage Access"
msgstr "مدیریت دسترسی"
@@ -24607,6 +24618,10 @@ msgstr "پیمایش دوره آموزشی"
msgid "Outline"
msgstr "طرح کلی"
+#: cms/templates/widgets/header.html
+msgid "Videos"
+msgstr ""
+
#: cms/templates/widgets/header.html
msgid "Publisher"
msgstr "ناشر"
diff --git a/conf/locale/fa_IR/LC_MESSAGES/djangojs.po b/conf/locale/fa_IR/LC_MESSAGES/djangojs.po
index fe13c7e28753..8d31d1def536 100644
--- a/conf/locale/fa_IR/LC_MESSAGES/djangojs.po
+++ b/conf/locale/fa_IR/LC_MESSAGES/djangojs.po
@@ -1,6 +1,6 @@
# #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Persian (Iran) (http://app.transifex.com/open-edx/edx-platform/language/fa_IR/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
diff --git a/conf/locale/fr/LC_MESSAGES/django.po b/conf/locale/fr/LC_MESSAGES/django.po
index 32b0615503bd..26f88f42b87b 100644
--- a/conf/locale/fr/LC_MESSAGES/django.po
+++ b/conf/locale/fr/LC_MESSAGES/django.po
@@ -94,7 +94,7 @@
# d6910e756eb8532754192e6021dc9f83, 2014-2015
# #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from French (http://app.transifex.com/open-edx/edx-platform/language/fr/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -147,7 +147,7 @@
# d6910e756eb8532754192e6021dc9f83, 2015
# #-#-#-#-# mako.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from French (http://app.transifex.com/open-edx/edx-platform/language/fr/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -8744,6 +8744,13 @@ msgstr "Profession"
msgid "Specialty"
msgstr "Spécialité"
+#. Translators: This label appears above a dropdown menu to select
+#. the user's work experience
+#: openedx/core/djangoapps/user_api/accounts/settings_views.py
+#: openedx/core/djangoapps/user_authn/api/form_fields.py
+msgid "Work experience"
+msgstr ""
+
#: openedx/core/djangoapps/user_api/accounts/utils.py
#, python-brace-format
msgid ""
@@ -13638,6 +13645,10 @@ msgstr "Duplication de '{0}'"
msgid "Invalid prerequisite course key"
msgstr "Id du cours prérequis invalide"
+#: cms/djangoapps/contentstore/utils.py
+msgid "Set Date"
+msgstr "Définir une date"
+
#. #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
#. Translators: This is the status of an active video upload
#: cms/djangoapps/contentstore/video_storage_handlers.py
@@ -13857,10 +13868,6 @@ msgstr ""
msgid "Course has been successfully reindexed."
msgstr "Cours réindexé avec succès."
-#: cms/djangoapps/contentstore/views/course.py
-msgid "Set Date"
-msgstr "Définir une date"
-
#: cms/djangoapps/contentstore/views/course.py
msgid ""
"Special characters not allowed in organization, course number, and course "
@@ -25056,6 +25063,10 @@ msgstr "Déplier ou Replier"
msgid "Select this problem"
msgstr ""
+#: cms/templates/studio_xblock_wrapper.html
+msgid "Manage Tags"
+msgstr ""
+
#: cms/templates/studio_xblock_wrapper.html
msgid "Manage Access"
msgstr ""
@@ -25431,6 +25442,10 @@ msgstr "Navigation du cours"
msgid "Outline"
msgstr "Plan du Cours"
+#: cms/templates/widgets/header.html
+msgid "Videos"
+msgstr ""
+
#: cms/templates/widgets/header.html
msgid "Publisher"
msgstr "Éditeur"
diff --git a/conf/locale/fr/LC_MESSAGES/djangojs.po b/conf/locale/fr/LC_MESSAGES/djangojs.po
index ee42a0decbe7..a7343cf2dbc0 100644
--- a/conf/locale/fr/LC_MESSAGES/djangojs.po
+++ b/conf/locale/fr/LC_MESSAGES/djangojs.po
@@ -1,6 +1,6 @@
# #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from French (http://app.transifex.com/open-edx/edx-platform/language/fr/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
diff --git a/conf/locale/id/LC_MESSAGES/django.po b/conf/locale/id/LC_MESSAGES/django.po
index 7b04fdbbf15f..29ca5f46d609 100644
--- a/conf/locale/id/LC_MESSAGES/django.po
+++ b/conf/locale/id/LC_MESSAGES/django.po
@@ -22,7 +22,7 @@
# Waheed Ahmed , 2019
# #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Indonesian (http://app.transifex.com/open-edx/edx-platform/language/id/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -31,9 +31,10 @@
# Ahmad Sofyan , 2013
# Faizar Septiawan , 2020,2022-2023
# fizdoonk, 2013
+# oon arfiandwi (OonID) , 2024
# #-#-#-#-# mako.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Indonesian (http://app.transifex.com/open-edx/edx-platform/language/id/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -7861,6 +7862,13 @@ msgstr "Profesi"
msgid "Specialty"
msgstr "Keahlian"
+#. Translators: This label appears above a dropdown menu to select
+#. the user's work experience
+#: openedx/core/djangoapps/user_api/accounts/settings_views.py
+#: openedx/core/djangoapps/user_authn/api/form_fields.py
+msgid "Work experience"
+msgstr ""
+
#: openedx/core/djangoapps/user_api/accounts/utils.py
#, python-brace-format
msgid ""
@@ -12445,6 +12453,10 @@ msgstr "Duplikasi '{0}'"
msgid "Invalid prerequisite course key"
msgstr ""
+#: cms/djangoapps/contentstore/utils.py
+msgid "Set Date"
+msgstr ""
+
#. #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
#. Translators: This is the status of an active video upload
#: cms/djangoapps/contentstore/video_storage_handlers.py
@@ -12652,10 +12664,6 @@ msgstr ""
msgid "Course has been successfully reindexed."
msgstr ""
-#: cms/djangoapps/contentstore/views/course.py
-msgid "Set Date"
-msgstr ""
-
#: cms/djangoapps/contentstore/views/course.py
msgid ""
"Special characters not allowed in organization, course number, and course "
@@ -23116,6 +23124,10 @@ msgstr ""
msgid "Select this problem"
msgstr ""
+#: cms/templates/studio_xblock_wrapper.html
+msgid "Manage Tags"
+msgstr ""
+
#: cms/templates/studio_xblock_wrapper.html
msgid "Manage Access"
msgstr ""
@@ -23449,6 +23461,10 @@ msgstr "Navigasi kursus"
msgid "Outline"
msgstr "Garis Besar"
+#: cms/templates/widgets/header.html
+msgid "Videos"
+msgstr ""
+
#: cms/templates/widgets/header.html
msgid "Publisher"
msgstr ""
diff --git a/conf/locale/id/LC_MESSAGES/djangojs.po b/conf/locale/id/LC_MESSAGES/djangojs.po
index 10caa3808455..ff83e5b31f43 100644
--- a/conf/locale/id/LC_MESSAGES/djangojs.po
+++ b/conf/locale/id/LC_MESSAGES/djangojs.po
@@ -1,6 +1,6 @@
# #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Indonesian (http://app.transifex.com/open-edx/edx-platform/language/id/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -84,7 +84,7 @@ msgid ""
msgstr ""
"Project-Id-Version: edx-platform\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
-"POT-Creation-Date: 2024-01-07 20:43+0000\n"
+"POT-Creation-Date: 2024-01-14 20:43+0000\n"
"PO-Revision-Date: 2014-06-11 15:18+0000\n"
"Last-Translator: Faizar Septiawan , 2023\n"
"Language-Team: Indonesian (http://app.transifex.com/open-edx/edx-platform/language/id/)\n"
diff --git a/conf/locale/it_IT/LC_MESSAGES/django.po b/conf/locale/it_IT/LC_MESSAGES/django.po
index 9598f0b84827..cd95d82babbd 100644
--- a/conf/locale/it_IT/LC_MESSAGES/django.po
+++ b/conf/locale/it_IT/LC_MESSAGES/django.po
@@ -31,7 +31,7 @@
# Tiziana Longeri , 2015
# #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Italian (Italy) (http://app.transifex.com/open-edx/edx-platform/language/it_IT/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -46,7 +46,7 @@
# Pietro Lombardo , 2014-2015
# #-#-#-#-# mako.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Italian (Italy) (http://app.transifex.com/open-edx/edx-platform/language/it_IT/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -99,7 +99,7 @@
# e9bb8fb5ffc36b415d1216869d7411be_857723a <56bb50d0e16dd64ebfbee187920dfe4a_229834>, 2014
# #-#-#-#-# wiki.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Italian (Italy) (http://app.transifex.com/open-edx/edx-platform/language/it_IT/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -114,9 +114,9 @@
# Stefania Trabucchi , 2021
# #-#-#-#-# edx_proctoring_proctortrack.po (0.1a) #-#-#-#-#
# edX community translations have been downloaded from Italian (Italy) (https://app.transifex.com/open-edx/teams/6205/it_IT/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
-# EdX Team , 2023.
+# EdX Team , 2024.
#
# Translators:
# Waheed Ahmed , 2019
@@ -127,7 +127,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.1a\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
-"POT-Creation-Date: 2023-12-24 20:43+0000\n"
+"POT-Creation-Date: 2024-01-14 20:43+0000\n"
"PO-Revision-Date: 2019-01-20 20:43+0000\n"
"Last-Translator: Ilaria Botti , 2021\n"
"Language-Team: Italian (Italy) (https://app.transifex.com/open-edx/teams/6205/it_IT/)\n"
@@ -8587,6 +8587,13 @@ msgstr "Professione"
msgid "Specialty"
msgstr "Specializzazione"
+#. Translators: This label appears above a dropdown menu to select
+#. the user's work experience
+#: openedx/core/djangoapps/user_api/accounts/settings_views.py
+#: openedx/core/djangoapps/user_authn/api/form_fields.py
+msgid "Work experience"
+msgstr ""
+
#: openedx/core/djangoapps/user_api/accounts/utils.py
#, python-brace-format
msgid ""
@@ -13474,6 +13481,10 @@ msgstr "Duplicato di '{0}'"
msgid "Invalid prerequisite course key"
msgstr "Chiave corso richiesta non valida"
+#: cms/djangoapps/contentstore/utils.py
+msgid "Set Date"
+msgstr "Imposta data"
+
#. #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
#. Translators: This is the status of an active video upload
#: cms/djangoapps/contentstore/video_storage_handlers.py
@@ -13694,10 +13705,6 @@ msgstr "Solo valutazione dei colleghi "
msgid "Course has been successfully reindexed."
msgstr "Il corso è stato correttamente reindicizzato."
-#: cms/djangoapps/contentstore/views/course.py
-msgid "Set Date"
-msgstr "Imposta data"
-
#: cms/djangoapps/contentstore/views/course.py
msgid ""
"Special characters not allowed in organization, course number, and course "
@@ -24873,6 +24880,10 @@ msgstr "Espandi o comprimi "
msgid "Select this problem"
msgstr ""
+#: cms/templates/studio_xblock_wrapper.html
+msgid "Manage Tags"
+msgstr ""
+
#: cms/templates/studio_xblock_wrapper.html
msgid "Manage Access"
msgstr ""
@@ -25248,6 +25259,10 @@ msgstr "Indice del corso"
msgid "Outline"
msgstr "Struttura "
+#: cms/templates/widgets/header.html
+msgid "Videos"
+msgstr ""
+
#: cms/templates/widgets/header.html
msgid "Publisher"
msgstr "Publisher"
diff --git a/conf/locale/it_IT/LC_MESSAGES/djangojs.po b/conf/locale/it_IT/LC_MESSAGES/djangojs.po
index 36794d8fb791..45e9abb57b25 100644
--- a/conf/locale/it_IT/LC_MESSAGES/djangojs.po
+++ b/conf/locale/it_IT/LC_MESSAGES/djangojs.po
@@ -1,6 +1,6 @@
# #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Italian (Italy) (http://app.transifex.com/open-edx/edx-platform/language/it_IT/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
diff --git a/conf/locale/ja_JP/LC_MESSAGES/django.po b/conf/locale/ja_JP/LC_MESSAGES/django.po
index 7ced9c8d3027..071840df7641 100644
--- a/conf/locale/ja_JP/LC_MESSAGES/django.po
+++ b/conf/locale/ja_JP/LC_MESSAGES/django.po
@@ -24,7 +24,7 @@
# 鈴木 陽一 , 2017
# #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Japanese (Japan) (http://app.transifex.com/open-edx/edx-platform/language/ja_JP/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -40,7 +40,7 @@
# わたカフェの店長, 2013
# #-#-#-#-# mako.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Japanese (Japan) (http://app.transifex.com/open-edx/edx-platform/language/ja_JP/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -7547,6 +7547,13 @@ msgstr ""
msgid "Specialty"
msgstr ""
+#. Translators: This label appears above a dropdown menu to select
+#. the user's work experience
+#: openedx/core/djangoapps/user_api/accounts/settings_views.py
+#: openedx/core/djangoapps/user_authn/api/form_fields.py
+msgid "Work experience"
+msgstr ""
+
#: openedx/core/djangoapps/user_api/accounts/utils.py
#, python-brace-format
msgid ""
@@ -11781,6 +11788,10 @@ msgstr "'{0}' の重複"
msgid "Invalid prerequisite course key"
msgstr "無効な履習要件コースキー"
+#: cms/djangoapps/contentstore/utils.py
+msgid "Set Date"
+msgstr ""
+
#. #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
#. Translators: This is the status of an active video upload
#: cms/djangoapps/contentstore/video_storage_handlers.py
@@ -11989,10 +12000,6 @@ msgstr ""
msgid "Course has been successfully reindexed."
msgstr "講座の見出し再作成が完了しました。"
-#: cms/djangoapps/contentstore/views/course.py
-msgid "Set Date"
-msgstr ""
-
#: cms/djangoapps/contentstore/views/course.py
msgid ""
"Special characters not allowed in organization, course number, and course "
@@ -21749,6 +21756,10 @@ msgstr "開くまたは閉じる"
msgid "Select this problem"
msgstr ""
+#: cms/templates/studio_xblock_wrapper.html
+msgid "Manage Tags"
+msgstr ""
+
#: cms/templates/studio_xblock_wrapper.html
msgid "Manage Access"
msgstr ""
@@ -22083,6 +22094,10 @@ msgstr "講座ナビゲーション"
msgid "Outline"
msgstr "アウトライン"
+#: cms/templates/widgets/header.html
+msgid "Videos"
+msgstr ""
+
#: cms/templates/widgets/header.html
msgid "Publisher"
msgstr ""
diff --git a/conf/locale/ja_JP/LC_MESSAGES/djangojs.po b/conf/locale/ja_JP/LC_MESSAGES/djangojs.po
index 92d9f7422023..534d1af35d27 100644
--- a/conf/locale/ja_JP/LC_MESSAGES/djangojs.po
+++ b/conf/locale/ja_JP/LC_MESSAGES/djangojs.po
@@ -1,6 +1,6 @@
# #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Japanese (Japan) (http://app.transifex.com/open-edx/edx-platform/language/ja_JP/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
diff --git a/conf/locale/ka/LC_MESSAGES/django.po b/conf/locale/ka/LC_MESSAGES/django.po
index 6f7b323aa6b4..671a3e90e13b 100644
--- a/conf/locale/ka/LC_MESSAGES/django.po
+++ b/conf/locale/ka/LC_MESSAGES/django.po
@@ -12,7 +12,7 @@
# Simon Janashia , 2019
# #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Georgian (http://app.transifex.com/open-edx/edx-platform/language/ka/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -21,7 +21,7 @@
# Lasha Kokilashvili, 2018
# #-#-#-#-# mako.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Georgian (http://app.transifex.com/open-edx/edx-platform/language/ka/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -7725,6 +7725,13 @@ msgstr ""
msgid "Specialty"
msgstr ""
+#. Translators: This label appears above a dropdown menu to select
+#. the user's work experience
+#: openedx/core/djangoapps/user_api/accounts/settings_views.py
+#: openedx/core/djangoapps/user_authn/api/form_fields.py
+msgid "Work experience"
+msgstr ""
+
#: openedx/core/djangoapps/user_api/accounts/utils.py
#, python-brace-format
msgid ""
@@ -12279,6 +12286,10 @@ msgstr "'{0}'-ის ასლი"
msgid "Invalid prerequisite course key"
msgstr "სავალდებულო კურსის არასწორი გასაღები"
+#: cms/djangoapps/contentstore/utils.py
+msgid "Set Date"
+msgstr ""
+
#. #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
#. Translators: This is the status of an active video upload
#: cms/djangoapps/contentstore/video_storage_handlers.py
@@ -12486,10 +12497,6 @@ msgstr ""
msgid "Course has been successfully reindexed."
msgstr "კურსის ხელახალი ინდექსაცია წარმატებით დასრულდა."
-#: cms/djangoapps/contentstore/views/course.py
-msgid "Set Date"
-msgstr ""
-
#: cms/djangoapps/contentstore/views/course.py
msgid ""
"Special characters not allowed in organization, course number, and course "
@@ -22952,6 +22959,10 @@ msgstr "ჩამოშალე ან აკეცე"
msgid "Select this problem"
msgstr ""
+#: cms/templates/studio_xblock_wrapper.html
+msgid "Manage Tags"
+msgstr ""
+
#: cms/templates/studio_xblock_wrapper.html
msgid "Manage Access"
msgstr ""
@@ -23294,6 +23305,10 @@ msgstr "კურსის ნავიგაცია"
msgid "Outline"
msgstr "სტრუქტურა"
+#: cms/templates/widgets/header.html
+msgid "Videos"
+msgstr ""
+
#: cms/templates/widgets/header.html
msgid "Publisher"
msgstr ""
diff --git a/conf/locale/ka/LC_MESSAGES/djangojs.po b/conf/locale/ka/LC_MESSAGES/djangojs.po
index c517a7eb9081..9fb42fdad536 100644
--- a/conf/locale/ka/LC_MESSAGES/djangojs.po
+++ b/conf/locale/ka/LC_MESSAGES/djangojs.po
@@ -1,6 +1,6 @@
# #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Georgian (http://app.transifex.com/open-edx/edx-platform/language/ka/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
diff --git a/conf/locale/lt_LT/LC_MESSAGES/django.po b/conf/locale/lt_LT/LC_MESSAGES/django.po
index b23eaf5baef0..157e2085bbff 100644
--- a/conf/locale/lt_LT/LC_MESSAGES/django.po
+++ b/conf/locale/lt_LT/LC_MESSAGES/django.po
@@ -13,7 +13,7 @@
# 99ff332f197efc0398f769062a4c5442_2965e21 , 2013
# #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Lithuanian (Lithuania) (http://app.transifex.com/open-edx/edx-platform/language/lt_LT/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -24,7 +24,7 @@
# 99ff332f197efc0398f769062a4c5442_2965e21 , 2013
# #-#-#-#-# mako.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Lithuanian (Lithuania) (http://app.transifex.com/open-edx/edx-platform/language/lt_LT/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -7454,6 +7454,13 @@ msgstr ""
msgid "Specialty"
msgstr ""
+#. Translators: This label appears above a dropdown menu to select
+#. the user's work experience
+#: openedx/core/djangoapps/user_api/accounts/settings_views.py
+#: openedx/core/djangoapps/user_authn/api/form_fields.py
+msgid "Work experience"
+msgstr ""
+
#: openedx/core/djangoapps/user_api/accounts/utils.py
#, python-brace-format
msgid ""
@@ -11627,6 +11634,10 @@ msgstr " '{0}' kopija"
msgid "Invalid prerequisite course key"
msgstr "Neteisingas būtino kurso raktas"
+#: cms/djangoapps/contentstore/utils.py
+msgid "Set Date"
+msgstr ""
+
#. #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
#. Translators: This is the status of an active video upload
#: cms/djangoapps/contentstore/video_storage_handlers.py
@@ -11834,10 +11845,6 @@ msgstr ""
msgid "Course has been successfully reindexed."
msgstr "Kursas sėkmingai perindeksuotas."
-#: cms/djangoapps/contentstore/views/course.py
-msgid "Set Date"
-msgstr ""
-
#: cms/djangoapps/contentstore/views/course.py
msgid ""
"Special characters not allowed in organization, course number, and course "
@@ -22005,6 +22012,10 @@ msgstr "Išskleisti arba suskleisti"
msgid "Select this problem"
msgstr ""
+#: cms/templates/studio_xblock_wrapper.html
+msgid "Manage Tags"
+msgstr ""
+
#: cms/templates/studio_xblock_wrapper.html
msgid "Manage Access"
msgstr ""
@@ -22345,6 +22356,10 @@ msgstr "Kurso navigacija"
msgid "Outline"
msgstr "Planas"
+#: cms/templates/widgets/header.html
+msgid "Videos"
+msgstr ""
+
#: cms/templates/widgets/header.html
msgid "Publisher"
msgstr ""
diff --git a/conf/locale/lt_LT/LC_MESSAGES/djangojs.po b/conf/locale/lt_LT/LC_MESSAGES/djangojs.po
index dd018f0755b0..7b4b47ef61c5 100644
--- a/conf/locale/lt_LT/LC_MESSAGES/djangojs.po
+++ b/conf/locale/lt_LT/LC_MESSAGES/djangojs.po
@@ -1,6 +1,6 @@
# #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Lithuanian (Lithuania) (http://app.transifex.com/open-edx/edx-platform/language/lt_LT/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
diff --git a/conf/locale/lv/LC_MESSAGES/django.po b/conf/locale/lv/LC_MESSAGES/django.po
index b85fc9ed9623..ccd7345ed3b0 100644
--- a/conf/locale/lv/LC_MESSAGES/django.po
+++ b/conf/locale/lv/LC_MESSAGES/django.po
@@ -9,14 +9,14 @@
# LTMC Latvijas Tiesnešu mācību centrs , 2018
# #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Latvian (http://app.transifex.com/open-edx/edx-platform/language/lv/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
# LTMC Latvijas Tiesnešu mācību centrs , 2018
# #-#-#-#-# mako.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Latvian (http://app.transifex.com/open-edx/edx-platform/language/lv/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -7896,6 +7896,13 @@ msgstr "Profesija"
msgid "Specialty"
msgstr "Specialitāte"
+#. Translators: This label appears above a dropdown menu to select
+#. the user's work experience
+#: openedx/core/djangoapps/user_api/accounts/settings_views.py
+#: openedx/core/djangoapps/user_authn/api/form_fields.py
+msgid "Work experience"
+msgstr ""
+
#: openedx/core/djangoapps/user_api/accounts/utils.py
#, python-brace-format
msgid ""
@@ -12487,6 +12494,10 @@ msgstr ""
msgid "Invalid prerequisite course key"
msgstr ""
+#: cms/djangoapps/contentstore/utils.py
+msgid "Set Date"
+msgstr ""
+
#. #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
#. Translators: This is the status of an active video upload
#: cms/djangoapps/contentstore/video_storage_handlers.py
@@ -12694,10 +12705,6 @@ msgstr ""
msgid "Course has been successfully reindexed."
msgstr "Kurss ir veiksmīgi pārindeksots."
-#: cms/djangoapps/contentstore/views/course.py
-msgid "Set Date"
-msgstr ""
-
#: cms/djangoapps/contentstore/views/course.py
msgid ""
"Special characters not allowed in organization, course number, and course "
@@ -22833,6 +22840,10 @@ msgstr "Izvērst vai sakļaut"
msgid "Select this problem"
msgstr ""
+#: cms/templates/studio_xblock_wrapper.html
+msgid "Manage Tags"
+msgstr ""
+
#: cms/templates/studio_xblock_wrapper.html
msgid "Manage Access"
msgstr ""
@@ -23156,6 +23167,10 @@ msgstr ""
msgid "Outline"
msgstr ""
+#: cms/templates/widgets/header.html
+msgid "Videos"
+msgstr ""
+
#: cms/templates/widgets/header.html
msgid "Publisher"
msgstr ""
diff --git a/conf/locale/lv/LC_MESSAGES/djangojs.po b/conf/locale/lv/LC_MESSAGES/djangojs.po
index 601c4c00b728..988f9f8a051d 100644
--- a/conf/locale/lv/LC_MESSAGES/djangojs.po
+++ b/conf/locale/lv/LC_MESSAGES/djangojs.po
@@ -1,6 +1,6 @@
# #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Latvian (http://app.transifex.com/open-edx/edx-platform/language/lv/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
diff --git a/conf/locale/mn/LC_MESSAGES/django.po b/conf/locale/mn/LC_MESSAGES/django.po
index 15d00e9d0280..807ae88a0a09 100644
--- a/conf/locale/mn/LC_MESSAGES/django.po
+++ b/conf/locale/mn/LC_MESSAGES/django.po
@@ -14,13 +14,13 @@
# Otgontsetseg Sukhbaatar , 2018
# #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Mongolian (http://app.transifex.com/open-edx/edx-platform/language/mn/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
# #-#-#-#-# mako.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Mongolian (http://app.transifex.com/open-edx/edx-platform/language/mn/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -7525,6 +7525,13 @@ msgstr "Мэргэжил"
msgid "Specialty"
msgstr "Мэргэшил"
+#. Translators: This label appears above a dropdown menu to select
+#. the user's work experience
+#: openedx/core/djangoapps/user_api/accounts/settings_views.py
+#: openedx/core/djangoapps/user_authn/api/form_fields.py
+msgid "Work experience"
+msgstr ""
+
#: openedx/core/djangoapps/user_api/accounts/utils.py
#, python-brace-format
msgid ""
@@ -11716,6 +11723,10 @@ msgstr ""
msgid "Invalid prerequisite course key"
msgstr ""
+#: cms/djangoapps/contentstore/utils.py
+msgid "Set Date"
+msgstr ""
+
#. #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
#. Translators: This is the status of an active video upload
#: cms/djangoapps/contentstore/video_storage_handlers.py
@@ -11923,10 +11934,6 @@ msgstr ""
msgid "Course has been successfully reindexed."
msgstr ""
-#: cms/djangoapps/contentstore/views/course.py
-msgid "Set Date"
-msgstr ""
-
#: cms/djangoapps/contentstore/views/course.py
msgid ""
"Special characters not allowed in organization, course number, and course "
@@ -21568,6 +21575,10 @@ msgstr ""
msgid "Select this problem"
msgstr ""
+#: cms/templates/studio_xblock_wrapper.html
+msgid "Manage Tags"
+msgstr ""
+
#: cms/templates/studio_xblock_wrapper.html
msgid "Manage Access"
msgstr ""
@@ -21892,6 +21903,10 @@ msgstr "Хичээлийн навигаци "
msgid "Outline"
msgstr "Төлөвлөгөө"
+#: cms/templates/widgets/header.html
+msgid "Videos"
+msgstr ""
+
#: cms/templates/widgets/header.html
msgid "Publisher"
msgstr ""
diff --git a/conf/locale/mn/LC_MESSAGES/djangojs.po b/conf/locale/mn/LC_MESSAGES/djangojs.po
index 0162f00bad07..4878072ecaa5 100644
--- a/conf/locale/mn/LC_MESSAGES/djangojs.po
+++ b/conf/locale/mn/LC_MESSAGES/djangojs.po
@@ -1,6 +1,6 @@
# #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Mongolian (http://app.transifex.com/open-edx/edx-platform/language/mn/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
diff --git a/conf/locale/pl/LC_MESSAGES/django.po b/conf/locale/pl/LC_MESSAGES/django.po
index d2b20b4909bd..3dc5af467294 100644
--- a/conf/locale/pl/LC_MESSAGES/django.po
+++ b/conf/locale/pl/LC_MESSAGES/django.po
@@ -42,7 +42,7 @@
# Dyfeomorfizm , 2014
# #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Polish (http://app.transifex.com/open-edx/edx-platform/language/pl/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -58,7 +58,7 @@
# ajafo , 2014
# #-#-#-#-# mako.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Polish (http://app.transifex.com/open-edx/edx-platform/language/pl/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -7995,6 +7995,13 @@ msgstr "Zawód"
msgid "Specialty"
msgstr "Specjalność"
+#. Translators: This label appears above a dropdown menu to select
+#. the user's work experience
+#: openedx/core/djangoapps/user_api/accounts/settings_views.py
+#: openedx/core/djangoapps/user_authn/api/form_fields.py
+msgid "Work experience"
+msgstr ""
+
#: openedx/core/djangoapps/user_api/accounts/utils.py
#, python-brace-format
msgid ""
@@ -12622,6 +12629,10 @@ msgstr "Duplikat '{0}'"
msgid "Invalid prerequisite course key"
msgstr "Błędny klucz kursu poprzedzającego"
+#: cms/djangoapps/contentstore/utils.py
+msgid "Set Date"
+msgstr "Ustaw datę"
+
#. #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
#. Translators: This is the status of an active video upload
#: cms/djangoapps/contentstore/video_storage_handlers.py
@@ -12840,10 +12851,6 @@ msgstr ""
msgid "Course has been successfully reindexed."
msgstr "Kurs został pomyślnie przeindeksowany."
-#: cms/djangoapps/contentstore/views/course.py
-msgid "Set Date"
-msgstr "Ustaw datę"
-
#: cms/djangoapps/contentstore/views/course.py
msgid ""
"Special characters not allowed in organization, course number, and course "
@@ -23445,6 +23452,10 @@ msgstr "Rozwiń lub zwiń"
msgid "Select this problem"
msgstr ""
+#: cms/templates/studio_xblock_wrapper.html
+msgid "Manage Tags"
+msgstr ""
+
#: cms/templates/studio_xblock_wrapper.html
msgid "Manage Access"
msgstr ""
@@ -23814,6 +23825,10 @@ msgstr "Nawigacja po kursie"
msgid "Outline"
msgstr "Program"
+#: cms/templates/widgets/header.html
+msgid "Videos"
+msgstr ""
+
#: cms/templates/widgets/header.html
msgid "Publisher"
msgstr ""
diff --git a/conf/locale/pl/LC_MESSAGES/djangojs.po b/conf/locale/pl/LC_MESSAGES/djangojs.po
index f78408ec8dec..2d31dfb4d47e 100644
--- a/conf/locale/pl/LC_MESSAGES/djangojs.po
+++ b/conf/locale/pl/LC_MESSAGES/djangojs.po
@@ -1,6 +1,6 @@
# #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Polish (http://app.transifex.com/open-edx/edx-platform/language/pl/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
diff --git a/conf/locale/pt_BR/LC_MESSAGES/djangojs.po b/conf/locale/pt_BR/LC_MESSAGES/djangojs.po
index 9249f74382e6..9b19a103c729 100644
--- a/conf/locale/pt_BR/LC_MESSAGES/djangojs.po
+++ b/conf/locale/pt_BR/LC_MESSAGES/djangojs.po
@@ -1,6 +1,6 @@
# #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Portuguese (Brazil) (http://app.transifex.com/open-edx/edx-platform/language/pt_BR/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
diff --git a/conf/locale/pt_PT/LC_MESSAGES/django.po b/conf/locale/pt_PT/LC_MESSAGES/django.po
index 5005264e8fa3..4d9fb7918861 100644
--- a/conf/locale/pt_PT/LC_MESSAGES/django.po
+++ b/conf/locale/pt_PT/LC_MESSAGES/django.po
@@ -32,7 +32,7 @@
# Rui Ribeiro , 2018-2020
# #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Portuguese (Portugal) (http://app.transifex.com/open-edx/edx-platform/language/pt_PT/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -50,7 +50,7 @@
# Rui Ribeiro , 2018-2019
# #-#-#-#-# mako.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Portuguese (Portugal) (http://app.transifex.com/open-edx/edx-platform/language/pt_PT/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -104,7 +104,7 @@
# Rui Ribeiro , 2018-2019
# #-#-#-#-# wiki.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Portuguese (Portugal) (http://app.transifex.com/open-edx/edx-platform/language/pt_PT/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -130,9 +130,9 @@
# Rui Ribeiro , 2019
# #-#-#-#-# edx_proctoring_proctortrack.po (0.1a) #-#-#-#-#
# edX community translations have been downloaded from Portuguese (Portugal) (https://app.transifex.com/open-edx/teams/6205/pt_PT/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
-# EdX Team , 2023.
+# EdX Team , 2024.
#
# Translators:
# Cátia Lopes , 2019
@@ -141,7 +141,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.1a\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
-"POT-Creation-Date: 2023-12-24 20:43+0000\n"
+"POT-Creation-Date: 2024-01-14 20:43+0000\n"
"PO-Revision-Date: 2019-01-20 20:43+0000\n"
"Last-Translator: Cátia Lopes , 2019\n"
"Language-Team: Portuguese (Portugal) (https://app.transifex.com/open-edx/teams/6205/pt_PT/)\n"
@@ -8540,6 +8540,13 @@ msgstr "Profissão"
msgid "Specialty"
msgstr "Especialidade"
+#. Translators: This label appears above a dropdown menu to select
+#. the user's work experience
+#: openedx/core/djangoapps/user_api/accounts/settings_views.py
+#: openedx/core/djangoapps/user_authn/api/form_fields.py
+msgid "Work experience"
+msgstr ""
+
#: openedx/core/djangoapps/user_api/accounts/utils.py
#, python-brace-format
msgid ""
@@ -13400,6 +13407,10 @@ msgstr "Duplicado de '{0}'"
msgid "Invalid prerequisite course key"
msgstr "Chave do curso de pré-requisitos inválida"
+#: cms/djangoapps/contentstore/utils.py
+msgid "Set Date"
+msgstr "Definir Data"
+
#. #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
#. Translators: This is the status of an active video upload
#: cms/djangoapps/contentstore/video_storage_handlers.py
@@ -13621,10 +13632,6 @@ msgstr "Somente Avaliação por Pares"
msgid "Course has been successfully reindexed."
msgstr "O curso foi reindexado com sucesso."
-#: cms/djangoapps/contentstore/views/course.py
-msgid "Set Date"
-msgstr "Definir Data"
-
#: cms/djangoapps/contentstore/views/course.py
msgid ""
"Special characters not allowed in organization, course number, and course "
@@ -24707,6 +24714,10 @@ msgstr "Expandir ou Encolher"
msgid "Select this problem"
msgstr ""
+#: cms/templates/studio_xblock_wrapper.html
+msgid "Manage Tags"
+msgstr ""
+
#: cms/templates/studio_xblock_wrapper.html
msgid "Manage Access"
msgstr "Gerir o Acesso"
@@ -25082,6 +25093,10 @@ msgstr "Navegação do Curso"
msgid "Outline"
msgstr "Estrutura Geral"
+#: cms/templates/widgets/header.html
+msgid "Videos"
+msgstr ""
+
#: cms/templates/widgets/header.html
msgid "Publisher"
msgstr "Editor"
diff --git a/conf/locale/pt_PT/LC_MESSAGES/djangojs.po b/conf/locale/pt_PT/LC_MESSAGES/djangojs.po
index b33940f3322e..f7800ca32933 100644
--- a/conf/locale/pt_PT/LC_MESSAGES/djangojs.po
+++ b/conf/locale/pt_PT/LC_MESSAGES/djangojs.po
@@ -1,6 +1,6 @@
# #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Portuguese (Portugal) (http://app.transifex.com/open-edx/edx-platform/language/pt_PT/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
diff --git a/conf/locale/rtl/LC_MESSAGES/django.mo b/conf/locale/rtl/LC_MESSAGES/django.mo
index 18928966ac49..52bc1ec30493 100644
Binary files a/conf/locale/rtl/LC_MESSAGES/django.mo and b/conf/locale/rtl/LC_MESSAGES/django.mo differ
diff --git a/conf/locale/rtl/LC_MESSAGES/django.po b/conf/locale/rtl/LC_MESSAGES/django.po
index 5087b5a0e0ba..6b5e37a31f6d 100644
--- a/conf/locale/rtl/LC_MESSAGES/django.po
+++ b/conf/locale/rtl/LC_MESSAGES/django.po
@@ -38,8 +38,8 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.1a\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
-"POT-Creation-Date: 2024-01-14 20:36+0000\n"
-"PO-Revision-Date: 2024-01-14 20:36:07.128712\n"
+"POT-Creation-Date: 2024-01-21 20:36+0000\n"
+"PO-Revision-Date: 2024-01-21 20:36:14.373996\n"
"Last-Translator: \n"
"Language-Team: openedx-translation \n"
"Language: rtl\n"
@@ -24177,10 +24177,6 @@ msgstr "Mɐnɐƃǝ Ŧɐƃs"
msgid "Manage Access"
msgstr "Mɐnɐƃǝ Ⱥɔɔǝss"
-#: cms/templates/studio_xblock_wrapper.html
-msgid "Manage tags"
-msgstr "Mɐnɐƃǝ ʇɐƃs"
-
#: cms/templates/studio_xblock_wrapper.html
msgid "Copy to Clipboard"
msgstr "Ȼødʎ ʇø Ȼlᴉdbøɐɹd"
diff --git a/conf/locale/rtl/LC_MESSAGES/djangojs.mo b/conf/locale/rtl/LC_MESSAGES/djangojs.mo
index e3e7177ddcc3..aba1fafda640 100644
Binary files a/conf/locale/rtl/LC_MESSAGES/djangojs.mo and b/conf/locale/rtl/LC_MESSAGES/djangojs.mo differ
diff --git a/conf/locale/rtl/LC_MESSAGES/djangojs.po b/conf/locale/rtl/LC_MESSAGES/djangojs.po
index 8d4bfa87175d..cef3d5931fe4 100644
--- a/conf/locale/rtl/LC_MESSAGES/djangojs.po
+++ b/conf/locale/rtl/LC_MESSAGES/djangojs.po
@@ -32,8 +32,8 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.1a\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
-"POT-Creation-Date: 2024-01-14 20:35+0000\n"
-"PO-Revision-Date: 2024-01-14 20:36:07.075048\n"
+"POT-Creation-Date: 2024-01-21 20:36+0000\n"
+"PO-Revision-Date: 2024-01-21 20:36:14.438254\n"
"Last-Translator: \n"
"Language-Team: openedx-translation \n"
"Language: rtl\n"
diff --git a/conf/locale/ru/LC_MESSAGES/djangojs.po b/conf/locale/ru/LC_MESSAGES/djangojs.po
index a2496a7f58e3..c1c87ca1308a 100644
--- a/conf/locale/ru/LC_MESSAGES/djangojs.po
+++ b/conf/locale/ru/LC_MESSAGES/djangojs.po
@@ -1,6 +1,6 @@
# #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Russian (http://app.transifex.com/open-edx/edx-platform/language/ru/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
diff --git a/conf/locale/sk/LC_MESSAGES/django.po b/conf/locale/sk/LC_MESSAGES/django.po
index cf83fd38b2ae..925e2e732110 100644
--- a/conf/locale/sk/LC_MESSAGES/django.po
+++ b/conf/locale/sk/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@
# adb712fb58d87c74cf0f50ac3f74745f_5787dfc , 2014
# #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Slovak (http://app.transifex.com/open-edx/edx-platform/language/sk/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -17,7 +17,7 @@
# Vladimír Záhradník , 2015
# #-#-#-#-# mako.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Slovak (http://app.transifex.com/open-edx/edx-platform/language/sk/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -7552,6 +7552,13 @@ msgstr ""
msgid "Specialty"
msgstr ""
+#. Translators: This label appears above a dropdown menu to select
+#. the user's work experience
+#: openedx/core/djangoapps/user_api/accounts/settings_views.py
+#: openedx/core/djangoapps/user_authn/api/form_fields.py
+msgid "Work experience"
+msgstr ""
+
#: openedx/core/djangoapps/user_api/accounts/utils.py
#, python-brace-format
msgid ""
@@ -11753,6 +11760,10 @@ msgstr "Duplikát '{0}'"
msgid "Invalid prerequisite course key"
msgstr "Neplatný kľúč ku kurzu, ktorý je predpokladom pre kurz aktuálny"
+#: cms/djangoapps/contentstore/utils.py
+msgid "Set Date"
+msgstr ""
+
#. #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
#. Translators: This is the status of an active video upload
#: cms/djangoapps/contentstore/video_storage_handlers.py
@@ -11960,10 +11971,6 @@ msgstr ""
msgid "Course has been successfully reindexed."
msgstr "Kurz bol úspešne preindexovaný."
-#: cms/djangoapps/contentstore/views/course.py
-msgid "Set Date"
-msgstr ""
-
#: cms/djangoapps/contentstore/views/course.py
msgid ""
"Special characters not allowed in organization, course number, and course "
@@ -21542,6 +21549,10 @@ msgstr ""
msgid "Select this problem"
msgstr ""
+#: cms/templates/studio_xblock_wrapper.html
+msgid "Manage Tags"
+msgstr ""
+
#: cms/templates/studio_xblock_wrapper.html
msgid "Manage Access"
msgstr ""
@@ -21867,6 +21878,10 @@ msgstr ""
msgid "Outline"
msgstr ""
+#: cms/templates/widgets/header.html
+msgid "Videos"
+msgstr ""
+
#: cms/templates/widgets/header.html
msgid "Publisher"
msgstr ""
diff --git a/conf/locale/sk/LC_MESSAGES/djangojs.po b/conf/locale/sk/LC_MESSAGES/djangojs.po
index 500bf8dc899a..d696329967af 100644
--- a/conf/locale/sk/LC_MESSAGES/djangojs.po
+++ b/conf/locale/sk/LC_MESSAGES/djangojs.po
@@ -1,6 +1,6 @@
# #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Slovak (http://app.transifex.com/open-edx/edx-platform/language/sk/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
diff --git a/conf/locale/sw_KE/LC_MESSAGES/django.po b/conf/locale/sw_KE/LC_MESSAGES/django.po
index 02aeb4f8926f..89e2726e23cd 100644
--- a/conf/locale/sw_KE/LC_MESSAGES/django.po
+++ b/conf/locale/sw_KE/LC_MESSAGES/django.po
@@ -16,7 +16,7 @@
# YAHAYA MWAVURIZI , 2017
# #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Swahili (Kenya) (http://app.transifex.com/open-edx/edx-platform/language/sw_KE/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -30,7 +30,7 @@
# YAHAYA MWAVURIZI , 2017
# #-#-#-#-# mako.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Swahili (Kenya) (http://app.transifex.com/open-edx/edx-platform/language/sw_KE/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -7597,6 +7597,13 @@ msgstr ""
msgid "Specialty"
msgstr ""
+#. Translators: This label appears above a dropdown menu to select
+#. the user's work experience
+#: openedx/core/djangoapps/user_api/accounts/settings_views.py
+#: openedx/core/djangoapps/user_authn/api/form_fields.py
+msgid "Work experience"
+msgstr ""
+
#: openedx/core/djangoapps/user_api/accounts/utils.py
#, python-brace-format
msgid ""
@@ -11878,6 +11885,10 @@ msgstr "Nakala ya '{0}'"
msgid "Invalid prerequisite course key"
msgstr ""
+#: cms/djangoapps/contentstore/utils.py
+msgid "Set Date"
+msgstr ""
+
#. Translators: This is the status of an active video upload
#: cms/djangoapps/contentstore/video_storage_handlers.py
msgid "Uploading"
@@ -12083,10 +12094,6 @@ msgstr ""
msgid "Course has been successfully reindexed."
msgstr "Kozi imefaulu kupata namba nyingine."
-#: cms/djangoapps/contentstore/views/course.py
-msgid "Set Date"
-msgstr ""
-
#: cms/djangoapps/contentstore/views/course.py
msgid ""
"Special characters not allowed in organization, course number, and course "
@@ -22251,6 +22258,10 @@ msgstr ""
msgid "Select this problem"
msgstr ""
+#: cms/templates/studio_xblock_wrapper.html
+msgid "Manage Tags"
+msgstr ""
+
#: cms/templates/studio_xblock_wrapper.html
msgid "Manage Access"
msgstr ""
@@ -22593,6 +22604,10 @@ msgstr ""
msgid "Outline"
msgstr "Muongozo"
+#: cms/templates/widgets/header.html
+msgid "Videos"
+msgstr ""
+
#: cms/templates/widgets/header.html
msgid "Publisher"
msgstr ""
diff --git a/conf/locale/sw_KE/LC_MESSAGES/djangojs.po b/conf/locale/sw_KE/LC_MESSAGES/djangojs.po
index 27c09d86d923..d817b71cc507 100644
--- a/conf/locale/sw_KE/LC_MESSAGES/djangojs.po
+++ b/conf/locale/sw_KE/LC_MESSAGES/djangojs.po
@@ -1,6 +1,6 @@
# #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Swahili (Kenya) (http://app.transifex.com/open-edx/edx-platform/language/sw_KE/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
diff --git a/conf/locale/th/LC_MESSAGES/django.po b/conf/locale/th/LC_MESSAGES/django.po
index ab5fb2b58bfa..24829294ea89 100644
--- a/conf/locale/th/LC_MESSAGES/django.po
+++ b/conf/locale/th/LC_MESSAGES/django.po
@@ -25,7 +25,7 @@
# Theeranuch Sirikojakorn , 2015
# #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Thai (http://app.transifex.com/open-edx/edx-platform/language/th/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -42,7 +42,7 @@
# Sitdhibong Laokok , 2015
# #-#-#-#-# mako.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Thai (http://app.transifex.com/open-edx/edx-platform/language/th/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -7392,6 +7392,13 @@ msgstr ""
msgid "Specialty"
msgstr ""
+#. Translators: This label appears above a dropdown menu to select
+#. the user's work experience
+#: openedx/core/djangoapps/user_api/accounts/settings_views.py
+#: openedx/core/djangoapps/user_authn/api/form_fields.py
+msgid "Work experience"
+msgstr ""
+
#: openedx/core/djangoapps/user_api/accounts/utils.py
#, python-brace-format
msgid ""
@@ -11535,6 +11542,10 @@ msgstr "ค่าซ้ำกันของ '{0}'"
msgid "Invalid prerequisite course key"
msgstr "หลักสูตรพื้นฐานไม่ถูกต้อง"
+#: cms/djangoapps/contentstore/utils.py
+msgid "Set Date"
+msgstr ""
+
#. #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
#. Translators: This is the status of an active video upload
#: cms/djangoapps/contentstore/video_storage_handlers.py
@@ -11742,10 +11753,6 @@ msgstr ""
msgid "Course has been successfully reindexed."
msgstr "หลักสูตรได้รับการจัดเรียงเรียบร้อย"
-#: cms/djangoapps/contentstore/views/course.py
-msgid "Set Date"
-msgstr ""
-
#: cms/djangoapps/contentstore/views/course.py
msgid ""
"Special characters not allowed in organization, course number, and course "
@@ -21747,6 +21754,10 @@ msgstr "ขยายเพิ่มหรือยุบทิ้ง"
msgid "Select this problem"
msgstr ""
+#: cms/templates/studio_xblock_wrapper.html
+msgid "Manage Tags"
+msgstr ""
+
#: cms/templates/studio_xblock_wrapper.html
msgid "Manage Access"
msgstr ""
@@ -22084,6 +22095,10 @@ msgstr "แนะนำหลักสูตร"
msgid "Outline"
msgstr "เค้าโครงหลักสูตร"
+#: cms/templates/widgets/header.html
+msgid "Videos"
+msgstr ""
+
#: cms/templates/widgets/header.html
msgid "Publisher"
msgstr ""
diff --git a/conf/locale/th/LC_MESSAGES/djangojs.po b/conf/locale/th/LC_MESSAGES/djangojs.po
index 02e7fcaa4578..b5d94c2b5991 100644
--- a/conf/locale/th/LC_MESSAGES/djangojs.po
+++ b/conf/locale/th/LC_MESSAGES/djangojs.po
@@ -1,6 +1,6 @@
# #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Thai (http://app.transifex.com/open-edx/edx-platform/language/th/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
diff --git a/conf/locale/tr_TR/LC_MESSAGES/django.po b/conf/locale/tr_TR/LC_MESSAGES/django.po
index 5a7a199d008b..ed22d43b8795 100644
--- a/conf/locale/tr_TR/LC_MESSAGES/django.po
+++ b/conf/locale/tr_TR/LC_MESSAGES/django.po
@@ -28,7 +28,7 @@
# ca47f5bf05c27c3888896d9870e257ad_00aad6f <5addf4166015f6e11583e89fe2c53975_164880>, 2014
# #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Turkish (Turkey) (http://app.transifex.com/open-edx/edx-platform/language/tr_TR/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -49,7 +49,7 @@
# Mustafa Tat, 2015
# #-#-#-#-# mako.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Turkish (Turkey) (http://app.transifex.com/open-edx/edx-platform/language/tr_TR/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -121,9 +121,9 @@
# a56fc07028489bb2b53400de33ba6a83, 2014
# #-#-#-#-# edx_proctoring_proctortrack.po (0.1a) #-#-#-#-#
# edX community translations have been downloaded from Turkish (Turkey) (https://app.transifex.com/open-edx/teams/6205/tr_TR/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
-# EdX Team , 2023.
+# EdX Team , 2024.
#
# Translators:
# Ali Işıngör , 2021
@@ -132,7 +132,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.1a\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
-"POT-Creation-Date: 2023-12-24 20:43+0000\n"
+"POT-Creation-Date: 2024-01-14 20:43+0000\n"
"PO-Revision-Date: 2019-01-20 20:43+0000\n"
"Last-Translator: Ali Işıngör , 2021\n"
"Language-Team: Turkish (Turkey) (https://app.transifex.com/open-edx/teams/6205/tr_TR/)\n"
@@ -8427,6 +8427,13 @@ msgstr "Meslek"
msgid "Specialty"
msgstr "Uzmanlık"
+#. Translators: This label appears above a dropdown menu to select
+#. the user's work experience
+#: openedx/core/djangoapps/user_api/accounts/settings_views.py
+#: openedx/core/djangoapps/user_authn/api/form_fields.py
+msgid "Work experience"
+msgstr ""
+
#: openedx/core/djangoapps/user_api/accounts/utils.py
#, python-brace-format
msgid ""
@@ -13237,6 +13244,10 @@ msgstr "'{0}'ın tekrarı"
msgid "Invalid prerequisite course key"
msgstr "Geçersiz ders anahtar koşulu."
+#: cms/djangoapps/contentstore/utils.py
+msgid "Set Date"
+msgstr "Tarihi Belirle"
+
#. #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
#. Translators: This is the status of an active video upload
#: cms/djangoapps/contentstore/video_storage_handlers.py
@@ -13454,10 +13465,6 @@ msgstr "Sadece Akran Değerlendirmesi"
msgid "Course has been successfully reindexed."
msgstr "Dersin tekrar indekslenme işlemi başarılı."
-#: cms/djangoapps/contentstore/views/course.py
-msgid "Set Date"
-msgstr "Tarihi Belirle"
-
#: cms/djangoapps/contentstore/views/course.py
msgid ""
"Special characters not allowed in organization, course number, and course "
@@ -24334,6 +24341,10 @@ msgstr "Genişlet veya Daralt"
msgid "Select this problem"
msgstr ""
+#: cms/templates/studio_xblock_wrapper.html
+msgid "Manage Tags"
+msgstr ""
+
#: cms/templates/studio_xblock_wrapper.html
msgid "Manage Access"
msgstr "Erişimi Yönet"
@@ -24705,6 +24716,10 @@ msgstr "Ders Navigasyonu"
msgid "Outline"
msgstr "Taslak"
+#: cms/templates/widgets/header.html
+msgid "Videos"
+msgstr ""
+
#: cms/templates/widgets/header.html
msgid "Publisher"
msgstr "Yayımcı"
diff --git a/conf/locale/tr_TR/LC_MESSAGES/djangojs.po b/conf/locale/tr_TR/LC_MESSAGES/djangojs.po
index 38a434471eac..12124f2c5bb0 100644
--- a/conf/locale/tr_TR/LC_MESSAGES/djangojs.po
+++ b/conf/locale/tr_TR/LC_MESSAGES/djangojs.po
@@ -1,6 +1,6 @@
# #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Turkish (Turkey) (http://app.transifex.com/open-edx/edx-platform/language/tr_TR/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -32,7 +32,7 @@
# ElektrikAkar , 2014
# #-#-#-#-# djangojs-studio.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Turkish (Turkey) (http://app.transifex.com/open-edx/edx-platform/language/tr_TR/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -69,7 +69,7 @@
#
# #-#-#-#-# underscore.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Turkish (Turkey) (http://app.transifex.com/open-edx/edx-platform/language/tr_TR/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -88,7 +88,7 @@
# sevde , 2015
# #-#-#-#-# underscore-studio.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Turkish (Turkey) (http://app.transifex.com/open-edx/edx-platform/language/tr_TR/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -110,7 +110,7 @@ msgid ""
msgstr ""
"Project-Id-Version: edx-platform\n"
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
-"POT-Creation-Date: 2023-12-24 20:43+0000\n"
+"POT-Creation-Date: 2024-01-14 20:43+0000\n"
"PO-Revision-Date: 2014-06-11 15:18+0000\n"
"Last-Translator: Ali Işıngör , 2018,2020-2021,2023\n"
"Language-Team: Turkish (Turkey) (http://app.transifex.com/open-edx/edx-platform/language/tr_TR/)\n"
diff --git a/conf/locale/uk/LC_MESSAGES/django.po b/conf/locale/uk/LC_MESSAGES/django.po
index e19d8f1b6a33..6efc858e4d88 100644
--- a/conf/locale/uk/LC_MESSAGES/django.po
+++ b/conf/locale/uk/LC_MESSAGES/django.po
@@ -34,7 +34,7 @@
# Валентина Пицик , 2019
# #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Ukrainian (http://app.transifex.com/open-edx/edx-platform/language/uk/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -50,7 +50,7 @@
# Валентина Пицик , 2019
# #-#-#-#-# mako.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Ukrainian (http://app.transifex.com/open-edx/edx-platform/language/uk/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -8076,6 +8076,13 @@ msgstr "Професія"
msgid "Specialty"
msgstr "Спеціальність"
+#. Translators: This label appears above a dropdown menu to select
+#. the user's work experience
+#: openedx/core/djangoapps/user_api/accounts/settings_views.py
+#: openedx/core/djangoapps/user_authn/api/form_fields.py
+msgid "Work experience"
+msgstr ""
+
#: openedx/core/djangoapps/user_api/accounts/utils.py
#, python-brace-format
msgid ""
@@ -12742,6 +12749,10 @@ msgstr "Копіювання '{0}'"
msgid "Invalid prerequisite course key"
msgstr "Невірний ключ передумовного курсу"
+#: cms/djangoapps/contentstore/utils.py
+msgid "Set Date"
+msgstr "Встановити Дату"
+
#. Translators: This is the status of an active video upload
#: cms/djangoapps/contentstore/video_storage_handlers.py
msgid "Uploading"
@@ -12957,10 +12968,6 @@ msgstr ""
msgid "Course has been successfully reindexed."
msgstr "Пошуковий індекс курсу успішно оновлено."
-#: cms/djangoapps/contentstore/views/course.py
-msgid "Set Date"
-msgstr "Встановити Дату"
-
#: cms/djangoapps/contentstore/views/course.py
msgid ""
"Special characters not allowed in organization, course number, and course "
@@ -22796,6 +22803,10 @@ msgstr ""
msgid "Select this problem"
msgstr ""
+#: cms/templates/studio_xblock_wrapper.html
+msgid "Manage Tags"
+msgstr ""
+
#: cms/templates/studio_xblock_wrapper.html
msgid "Manage Access"
msgstr ""
@@ -23125,6 +23136,10 @@ msgstr ""
msgid "Outline"
msgstr "Структура курсу"
+#: cms/templates/widgets/header.html
+msgid "Videos"
+msgstr ""
+
#: cms/templates/widgets/header.html
msgid "Publisher"
msgstr ""
diff --git a/conf/locale/uk/LC_MESSAGES/djangojs.po b/conf/locale/uk/LC_MESSAGES/djangojs.po
index f24f64597136..75eab73030dd 100644
--- a/conf/locale/uk/LC_MESSAGES/djangojs.po
+++ b/conf/locale/uk/LC_MESSAGES/djangojs.po
@@ -1,6 +1,6 @@
# #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Ukrainian (http://app.transifex.com/open-edx/edx-platform/language/uk/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
diff --git a/conf/locale/vi/LC_MESSAGES/django.po b/conf/locale/vi/LC_MESSAGES/django.po
index 3cbf399171ff..65e6e1d2c4fa 100644
--- a/conf/locale/vi/LC_MESSAGES/django.po
+++ b/conf/locale/vi/LC_MESSAGES/django.po
@@ -49,7 +49,7 @@
# Vu Bach, 2019
# #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Vietnamese (http://app.transifex.com/open-edx/edx-platform/language/vi/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -74,7 +74,7 @@
# Trung V. Nguyen , 2015
# #-#-#-#-# mako.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Vietnamese (http://app.transifex.com/open-edx/edx-platform/language/vi/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -7469,6 +7469,13 @@ msgstr ""
msgid "Specialty"
msgstr ""
+#. Translators: This label appears above a dropdown menu to select
+#. the user's work experience
+#: openedx/core/djangoapps/user_api/accounts/settings_views.py
+#: openedx/core/djangoapps/user_authn/api/form_fields.py
+msgid "Work experience"
+msgstr ""
+
#: openedx/core/djangoapps/user_api/accounts/utils.py
#, python-brace-format
msgid ""
@@ -11614,6 +11621,10 @@ msgstr "Sao chép của '{0}'"
msgid "Invalid prerequisite course key"
msgstr "Khóa điều kiện bắt buộc không hợp lệ"
+#: cms/djangoapps/contentstore/utils.py
+msgid "Set Date"
+msgstr ""
+
#. #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
#. Translators: This is the status of an active video upload
#: cms/djangoapps/contentstore/video_storage_handlers.py
@@ -11830,10 +11841,6 @@ msgstr ""
msgid "Course has been successfully reindexed."
msgstr "Khóa học đã được lập chỉ mục lại."
-#: cms/djangoapps/contentstore/views/course.py
-msgid "Set Date"
-msgstr ""
-
#: cms/djangoapps/contentstore/views/course.py
msgid ""
"Special characters not allowed in organization, course number, and course "
@@ -22367,6 +22374,10 @@ msgstr "Mở rộng hoặc Thu gọn"
msgid "Select this problem"
msgstr ""
+#: cms/templates/studio_xblock_wrapper.html
+msgid "Manage Tags"
+msgstr ""
+
#: cms/templates/studio_xblock_wrapper.html
msgid "Manage Access"
msgstr ""
@@ -22734,6 +22745,10 @@ msgstr "Danh Mục Khóa Học"
msgid "Outline"
msgstr "Phác Thảo"
+#: cms/templates/widgets/header.html
+msgid "Videos"
+msgstr ""
+
#: cms/templates/widgets/header.html
msgid "Publisher"
msgstr ""
diff --git a/conf/locale/vi/LC_MESSAGES/djangojs.po b/conf/locale/vi/LC_MESSAGES/djangojs.po
index 85682ee6c057..05d6164f9307 100644
--- a/conf/locale/vi/LC_MESSAGES/djangojs.po
+++ b/conf/locale/vi/LC_MESSAGES/djangojs.po
@@ -1,6 +1,6 @@
# #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Vietnamese (http://app.transifex.com/open-edx/edx-platform/language/vi/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
diff --git a/conf/locale/zh_CN/LC_MESSAGES/django.po b/conf/locale/zh_CN/LC_MESSAGES/django.po
index c0795eb20dab..3d2a2963c80c 100644
--- a/conf/locale/zh_CN/LC_MESSAGES/django.po
+++ b/conf/locale/zh_CN/LC_MESSAGES/django.po
@@ -100,7 +100,7 @@
# 赵宏鑫 , 2015
# #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Chinese (China) (http://app.transifex.com/open-edx/edx-platform/language/zh_CN/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -7954,6 +7954,13 @@ msgstr "从事职业"
msgid "Specialty"
msgstr "专业技能"
+#. Translators: This label appears above a dropdown menu to select
+#. the user's work experience
+#: openedx/core/djangoapps/user_api/accounts/settings_views.py
+#: openedx/core/djangoapps/user_authn/api/form_fields.py
+msgid "Work experience"
+msgstr ""
+
#: openedx/core/djangoapps/user_api/accounts/utils.py
#, python-brace-format
msgid ""
@@ -12226,6 +12233,10 @@ msgstr "“{0}”的副本"
msgid "Invalid prerequisite course key"
msgstr "先修课程标识无效"
+#: cms/djangoapps/contentstore/utils.py
+msgid "Set Date"
+msgstr "设置日期"
+
#. #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
#. Translators: This is the status of an active video upload
#: cms/djangoapps/contentstore/video_storage_handlers.py
@@ -12434,10 +12445,6 @@ msgstr "仅限同行评估"
msgid "Course has been successfully reindexed."
msgstr "课程重新索引成功。"
-#: cms/djangoapps/contentstore/views/course.py
-msgid "Set Date"
-msgstr "设置日期"
-
#: cms/djangoapps/contentstore/views/course.py
msgid ""
"Special characters not allowed in organization, course number, and course "
@@ -22168,6 +22175,10 @@ msgstr "展开或折叠"
msgid "Select this problem"
msgstr ""
+#: cms/templates/studio_xblock_wrapper.html
+msgid "Manage Tags"
+msgstr ""
+
#: cms/templates/studio_xblock_wrapper.html
msgid "Manage Access"
msgstr ""
@@ -22497,6 +22508,10 @@ msgstr "课程导航"
msgid "Outline"
msgstr "大纲"
+#: cms/templates/widgets/header.html
+msgid "Videos"
+msgstr ""
+
#: cms/templates/widgets/header.html
msgid "Publisher"
msgstr ""
diff --git a/conf/locale/zh_CN/LC_MESSAGES/djangojs.po b/conf/locale/zh_CN/LC_MESSAGES/djangojs.po
index 82f342d05f75..b081196244d8 100644
--- a/conf/locale/zh_CN/LC_MESSAGES/djangojs.po
+++ b/conf/locale/zh_CN/LC_MESSAGES/djangojs.po
@@ -1,6 +1,6 @@
# #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Chinese (China) (http://app.transifex.com/open-edx/edx-platform/language/zh_CN/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
diff --git a/conf/locale/zh_HANS/LC_MESSAGES/django.po b/conf/locale/zh_HANS/LC_MESSAGES/django.po
index c0795eb20dab..3d2a2963c80c 100644
--- a/conf/locale/zh_HANS/LC_MESSAGES/django.po
+++ b/conf/locale/zh_HANS/LC_MESSAGES/django.po
@@ -100,7 +100,7 @@
# 赵宏鑫 , 2015
# #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Chinese (China) (http://app.transifex.com/open-edx/edx-platform/language/zh_CN/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -7954,6 +7954,13 @@ msgstr "从事职业"
msgid "Specialty"
msgstr "专业技能"
+#. Translators: This label appears above a dropdown menu to select
+#. the user's work experience
+#: openedx/core/djangoapps/user_api/accounts/settings_views.py
+#: openedx/core/djangoapps/user_authn/api/form_fields.py
+msgid "Work experience"
+msgstr ""
+
#: openedx/core/djangoapps/user_api/accounts/utils.py
#, python-brace-format
msgid ""
@@ -12226,6 +12233,10 @@ msgstr "“{0}”的副本"
msgid "Invalid prerequisite course key"
msgstr "先修课程标识无效"
+#: cms/djangoapps/contentstore/utils.py
+msgid "Set Date"
+msgstr "设置日期"
+
#. #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
#. Translators: This is the status of an active video upload
#: cms/djangoapps/contentstore/video_storage_handlers.py
@@ -12434,10 +12445,6 @@ msgstr "仅限同行评估"
msgid "Course has been successfully reindexed."
msgstr "课程重新索引成功。"
-#: cms/djangoapps/contentstore/views/course.py
-msgid "Set Date"
-msgstr "设置日期"
-
#: cms/djangoapps/contentstore/views/course.py
msgid ""
"Special characters not allowed in organization, course number, and course "
@@ -22168,6 +22175,10 @@ msgstr "展开或折叠"
msgid "Select this problem"
msgstr ""
+#: cms/templates/studio_xblock_wrapper.html
+msgid "Manage Tags"
+msgstr ""
+
#: cms/templates/studio_xblock_wrapper.html
msgid "Manage Access"
msgstr ""
@@ -22497,6 +22508,10 @@ msgstr "课程导航"
msgid "Outline"
msgstr "大纲"
+#: cms/templates/widgets/header.html
+msgid "Videos"
+msgstr ""
+
#: cms/templates/widgets/header.html
msgid "Publisher"
msgstr ""
diff --git a/conf/locale/zh_HANS/LC_MESSAGES/djangojs.po b/conf/locale/zh_HANS/LC_MESSAGES/djangojs.po
index 82f342d05f75..b081196244d8 100644
--- a/conf/locale/zh_HANS/LC_MESSAGES/djangojs.po
+++ b/conf/locale/zh_HANS/LC_MESSAGES/djangojs.po
@@ -1,6 +1,6 @@
# #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Chinese (China) (http://app.transifex.com/open-edx/edx-platform/language/zh_CN/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
diff --git a/conf/locale/zh_TW/LC_MESSAGES/django.po b/conf/locale/zh_TW/LC_MESSAGES/django.po
index 07a4d86c7f2d..a95a94acfc20 100644
--- a/conf/locale/zh_TW/LC_MESSAGES/django.po
+++ b/conf/locale/zh_TW/LC_MESSAGES/django.po
@@ -44,7 +44,7 @@
# 陳子琦 , 2014
# #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Chinese (Taiwan) (http://app.transifex.com/open-edx/edx-platform/language/zh_TW/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -72,7 +72,7 @@
# Zhen-Rong Chen , 2014-2015
# #-#-#-#-# mako.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Chinese (Taiwan) (http://app.transifex.com/open-edx/edx-platform/language/zh_TW/)
-# Copyright (C) 2023 edX
+# Copyright (C) 2024 edX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
@@ -7567,6 +7567,13 @@ msgstr ""
msgid "Specialty"
msgstr ""
+#. Translators: This label appears above a dropdown menu to select
+#. the user's work experience
+#: openedx/core/djangoapps/user_api/accounts/settings_views.py
+#: openedx/core/djangoapps/user_authn/api/form_fields.py
+msgid "Work experience"
+msgstr ""
+
#: openedx/core/djangoapps/user_api/accounts/utils.py
#, python-brace-format
msgid ""
@@ -11770,6 +11777,10 @@ msgstr "與'{0}'重複"
msgid "Invalid prerequisite course key"
msgstr "無效的預備課程key"
+#: cms/djangoapps/contentstore/utils.py
+msgid "Set Date"
+msgstr ""
+
#. #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-#
#. Translators: This is the status of an active video upload
#: cms/djangoapps/contentstore/video_storage_handlers.py
@@ -11977,10 +11988,6 @@ msgstr ""
msgid "Course has been successfully reindexed."
msgstr "課程已經成功重新索引。"
-#: cms/djangoapps/contentstore/views/course.py
-msgid "Set Date"
-msgstr ""
-
#: cms/djangoapps/contentstore/views/course.py
msgid ""
"Special characters not allowed in organization, course number, and course "
@@ -21562,6 +21569,10 @@ msgstr ""
msgid "Select this problem"
msgstr ""
+#: cms/templates/studio_xblock_wrapper.html
+msgid "Manage Tags"
+msgstr ""
+
#: cms/templates/studio_xblock_wrapper.html
msgid "Manage Access"
msgstr ""
@@ -21885,6 +21896,10 @@ msgstr ""
msgid "Outline"
msgstr "課程大綱"
+#: cms/templates/widgets/header.html
+msgid "Videos"
+msgstr ""
+
#: cms/templates/widgets/header.html
msgid "Publisher"
msgstr ""
diff --git a/conf/locale/zh_TW/LC_MESSAGES/djangojs.po b/conf/locale/zh_TW/LC_MESSAGES/djangojs.po
index 88242ee6fccd..7423aa7b0468 100644
--- a/conf/locale/zh_TW/LC_MESSAGES/djangojs.po
+++ b/conf/locale/zh_TW/LC_MESSAGES/djangojs.po
@@ -1,6 +1,6 @@
# #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-#
# edX community translations have been downloaded from Chinese (Taiwan) (http://app.transifex.com/open-edx/edx-platform/language/zh_TW/).
-# Copyright (C) 2023 EdX
+# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
#
# Translators:
diff --git a/lms/djangoapps/certificates/admin.py b/lms/djangoapps/certificates/admin.py
index 8b98a2c97151..3facf6f6b530 100644
--- a/lms/djangoapps/certificates/admin.py
+++ b/lms/djangoapps/certificates/admin.py
@@ -20,7 +20,8 @@
CertificateHtmlViewConfiguration,
CertificateTemplate,
CertificateTemplateAsset,
- GeneratedCertificate
+ GeneratedCertificate,
+ ModifiedCertificateTemplateCommandConfiguration,
)
@@ -92,6 +93,11 @@ class CertificateGenerationCourseSettingAdmin(admin.ModelAdmin):
show_full_result_count = False
+@admin.register(ModifiedCertificateTemplateCommandConfiguration)
+class ModifiedCertificateTemplateCommandConfigurationAdmin(ConfigurationModelAdmin):
+ pass
+
+
@admin.register(CertificateGenerationCommandConfiguration)
class CertificateGenerationCommandConfigurationAdmin(ConfigurationModelAdmin):
pass
diff --git a/lms/djangoapps/certificates/management/commands/modify_cert_template.py b/lms/djangoapps/certificates/management/commands/modify_cert_template.py
new file mode 100644
index 000000000000..f4ae5f64d2b6
--- /dev/null
+++ b/lms/djangoapps/certificates/management/commands/modify_cert_template.py
@@ -0,0 +1,91 @@
+"""Management command to modify certificate templates."""
+import logging
+import shlex
+from argparse import RawDescriptionHelpFormatter
+
+from django.core.management.base import BaseCommand, CommandError
+
+from lms.djangoapps.certificates.models import (
+ ModifiedCertificateTemplateCommandConfiguration,
+)
+from lms.djangoapps.certificates.tasks import handle_modify_cert_template
+
+log = logging.getLogger(__name__)
+
+
+class Command(BaseCommand):
+ """Management command to modify certificate templates.
+ Example usage:
+ ./manage.py lms modify_cert_template --old-text "" --new text "boo!
" --templates 867 3509
+ """
+
+ help = """Modify one or more certificate templates.
+ This is DANGEROUS.
+ * This uses string replacement to modify HTML-like templates, because the presence of
+ Django Templating makes it impossible to do true parsing.
+ * This isn't parameterizing the replacement text, for the same reason. It has
+ no way of knowing what is template language and what is HTML.
+ Do not trust that this will get the conversion right without verification,
+ and absolutely do not accepted untrusted user input for the replacement text. This is
+ to be run by trusted users only.
+ Always run this with dry-run or in a reliable test environment.
+ """
+
+ def add_arguments(self, parser):
+ parser.formatter_class = RawDescriptionHelpFormatter
+ parser.add_argument(
+ "--dry-run",
+ action="store_true",
+ help="Just show a preview of what would happen.",
+ )
+ parser.add_argument(
+ "--old-text",
+ help="Text to replace in the template.",
+ )
+ parser.add_argument(
+ "--new-text",
+ help="Replacement text for the template.",
+ )
+ parser.add_argument(
+ "--templates",
+ nargs="+",
+ help="Certificate templates to modify.",
+ )
+ parser.add_argument(
+ "--args-from-database",
+ action="store_true",
+ help="Use arguments from the ModifyCertificateTemplateConfiguration model instead of the command line.",
+ )
+
+ def get_args_from_database(self):
+ """
+ Returns an options dictionary from the current ModifiedCertificateTemplateCommandConfiguration instance.
+ """
+ config = ModifiedCertificateTemplateCommandConfiguration.current()
+ if not config.enabled:
+ raise CommandError(
+ "ModifyCertificateTemplateCommandConfiguration is disabled, but --args-from-database was requested"
+ )
+ args = shlex.split(config.arguments)
+ parser = self.create_parser("manage.py", "modify_cert_template")
+ return vars(parser.parse_args(args))
+
+ def handle(self, *args, **options):
+ # database args will override cmd line args
+ if options["args_from_database"]:
+ options = self.get_args_from_database()
+ # Check required arguments here. We can't rely on marking args "required" because they might come from django
+ if not (options["old_text"] and options["new_text"] and options["templates"]):
+ raise CommandError(
+ "The following arguments are required: --old-text, --new-text, --templates"
+ )
+ log.info(
+ "modify_cert_template starting, dry-run={dry_run}, templates={templates}, "
+ "old-text={old}, new-text={new}".format(
+ dry_run=options["dry_run"],
+ templates=options["templates"],
+ old=options["old_text"],
+ new=options["new_text"],
+ )
+ )
+ handle_modify_cert_template.delay(options)
diff --git a/lms/djangoapps/certificates/management/commands/tests/test_modify_certs_template.py b/lms/djangoapps/certificates/management/commands/tests/test_modify_certs_template.py
new file mode 100644
index 000000000000..03d9b05d5413
--- /dev/null
+++ b/lms/djangoapps/certificates/management/commands/tests/test_modify_certs_template.py
@@ -0,0 +1,41 @@
+"""
+Tests for the modify_cert_template command
+"""
+
+import pytest
+from django.core.management import CommandError, call_command
+from django.test import TestCase
+
+
+class ModifyCertTemplateTests(TestCase):
+ """Tests for the modify_cert_template management command"""
+
+ def test_command_with_missing_param_old_text(self):
+ """Verify command with a missing param --old-text."""
+ with pytest.raises(
+ CommandError,
+ match="The following arguments are required: --old-text, --new-text, --templates",
+ ):
+ call_command(
+ "modify_cert_template", "--new-text", "blah", "--templates", "1 2 3"
+ )
+
+ def test_command_with_missing_param_new_text(self):
+ """Verify command with a missing param --new-text."""
+ with pytest.raises(
+ CommandError,
+ match="The following arguments are required: --old-text, --new-text, --templates",
+ ):
+ call_command(
+ "modify_cert_template", "--old-text", "blah", "--templates", "1 2 3"
+ )
+
+ def test_command_with_missing_param_templates(self):
+ """Verify command with a missing param --templates."""
+ with pytest.raises(
+ CommandError,
+ match="The following arguments are required: --old-text, --new-text, --templates",
+ ):
+ call_command(
+ "modify_cert_template", "--new-text", "blah", "--old-text", "xyzzy"
+ )
diff --git a/lms/djangoapps/certificates/migrations/0036_modifiedcertificatetemplatecommandconfiguration.py b/lms/djangoapps/certificates/migrations/0036_modifiedcertificatetemplatecommandconfiguration.py
new file mode 100644
index 000000000000..ebc6cfd95b9a
--- /dev/null
+++ b/lms/djangoapps/certificates/migrations/0036_modifiedcertificatetemplatecommandconfiguration.py
@@ -0,0 +1,29 @@
+# Generated by Django 3.2.23 on 2024-01-16 18:57
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ('certificates', '0035_auto_20230808_0944'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='ModifiedCertificateTemplateCommandConfiguration',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')),
+ ('enabled', models.BooleanField(default=False, verbose_name='Enabled')),
+ ('arguments', models.TextField(blank=True, default='', help_text='Arguments for the \'modify_cert_template\' management command. Specify like \'--old-text "foo" --new-text "bar" --template_ids \'')),
+ ('changed_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='Changed by')),
+ ],
+ options={
+ 'verbose_name': 'modify_cert_template argument',
+ },
+ ),
+ ]
diff --git a/lms/djangoapps/certificates/models.py b/lms/djangoapps/certificates/models.py
index fa16112f3add..9c58327b99aa 100644
--- a/lms/djangoapps/certificates/models.py
+++ b/lms/djangoapps/certificates/models.py
@@ -2,11 +2,11 @@
Course certificates are created for a student and an offering of a course (a course run).
"""
-from datetime import timezone
import json
import logging
import os
import uuid
+from datetime import timezone
from config_models.models import ConfigurationModel
from django.apps import apps
@@ -16,7 +16,6 @@
from django.db import models, transaction
from django.db.models import Count
from django.dispatch import receiver
-
from django.utils.translation import gettext_lazy as _
from model_utils import Choices
from model_utils.models import TimeStampedModel
@@ -1243,6 +1242,30 @@ class Meta:
app_label = "certificates"
+class ModifiedCertificateTemplateCommandConfiguration(ConfigurationModel):
+ """
+ Manages configuration for a run of the modify_cert_template management command.
+
+ .. no_pii:
+ """
+
+ class Meta:
+ app_label = "certificates"
+ verbose_name = "modify_cert_template argument"
+
+ arguments = models.TextField(
+ blank=True,
+ help_text=(
+ "Arguments for the 'modify_cert_template' management command. Specify like '--old-text \"foo\" "
+ "--new-text \"bar\" --template_ids '"
+ ),
+ default="",
+ )
+
+ def __str__(self):
+ return str(self.arguments)
+
+
class CertificateGenerationCommandConfiguration(ConfigurationModel):
"""
Manages configuration for a run of the cert_generation management command.
diff --git a/lms/djangoapps/certificates/tasks.py b/lms/djangoapps/certificates/tasks.py
index 6d524352c378..8229cef3948c 100644
--- a/lms/djangoapps/certificates/tasks.py
+++ b/lms/djangoapps/certificates/tasks.py
@@ -1,17 +1,20 @@
"""
-Tasks that generate a course certificate for a user
+Tasks that operate on course certificates for a user
"""
+from difflib import unified_diff
from logging import getLogger
+from typing import Any, Dict, List
from celery import shared_task
-from celery_utils.persist_on_failure import LoggedPersistOnFailureTask
+from celery_utils.persist_on_failure import LoggedPersistOnFailureTask, LoggedTask
from django.contrib.auth import get_user_model
from edx_django_utils.monitoring import set_code_owner_attribute
from opaque_keys.edx.keys import CourseKey
from lms.djangoapps.certificates.data import CertificateStatuses
from lms.djangoapps.certificates.generation import generate_course_certificate
+from lms.djangoapps.certificates.models import CertificateTemplate
log = getLogger(__name__)
User = get_user_model()
@@ -21,7 +24,9 @@
CERTIFICATE_DELAY_SECONDS = 2
-@shared_task(base=LoggedPersistOnFailureTask, bind=True, default_retry_delay=30, max_retries=2)
+@shared_task(
+ base=LoggedPersistOnFailureTask, bind=True, default_retry_delay=30, max_retries=2
+)
@set_code_owner_attribute
def generate_certificate(self, **kwargs): # pylint: disable=unused-argument
"""
@@ -37,12 +42,125 @@ def generate_certificate(self, **kwargs): # pylint: disable=unused-argument
- generation_mode: Used when emitting an event. Options are "self" (implying the user generated the cert
themself) and "batch" for everything else. Defaults to 'batch'.
"""
- student = User.objects.get(id=kwargs.pop('student'))
- course_key = CourseKey.from_string(kwargs.pop('course_key'))
- status = kwargs.pop('status', CertificateStatuses.downloadable)
- enrollment_mode = kwargs.pop('enrollment_mode')
- course_grade = kwargs.pop('course_grade', '')
- generation_mode = kwargs.pop('generation_mode', 'batch')
-
- generate_course_certificate(user=student, course_key=course_key, status=status, enrollment_mode=enrollment_mode,
- course_grade=course_grade, generation_mode=generation_mode)
+ student = User.objects.get(id=kwargs.pop("student"))
+ course_key = CourseKey.from_string(kwargs.pop("course_key"))
+ status = kwargs.pop("status", CertificateStatuses.downloadable)
+ enrollment_mode = kwargs.pop("enrollment_mode")
+ course_grade = kwargs.pop("course_grade", "")
+ generation_mode = kwargs.pop("generation_mode", "batch")
+
+ generate_course_certificate(
+ user=student,
+ course_key=course_key,
+ status=status,
+ enrollment_mode=enrollment_mode,
+ course_grade=course_grade,
+ generation_mode=generation_mode,
+ )
+
+
+@shared_task(base=LoggedTask, ignore_result=True)
+@set_code_owner_attribute
+def handle_modify_cert_template(options: Dict[str, Any]) -> None:
+ """
+ Celery task to handle the modify_cert_template management command.
+
+ Args:
+ old_text (string): Text in the template of which the first instance should be changed
+ new_text (string): Replacement text for old_text
+ template_ids (list[string]): List of template IDs for this run.
+ dry_run (boolean): Don't do the work, just report the changes that would happen
+ """
+
+ template_ids = options["templates"]
+ if not template_ids:
+ template_ids = []
+
+ log.info(
+ "[modify_cert_template] Attempting to modify {num} templates".format(
+ num=len(template_ids)
+ )
+ )
+
+ templates_changed = get_changed_cert_templates(options)
+ for template in templates_changed:
+ template.save()
+
+
+def get_changed_cert_templates(options: Dict[str, Any]) -> List[CertificateTemplate]:
+ """
+ Loop through the templates and return instances with changed template text.
+
+ Args:
+ old_text (string): Text in the template of which the first instance should be changed
+ new_text (string): Replacement text for old_text
+ template_ids (list[string]): List of template IDs for this run.
+ dry_run (boolean): Don't do the work, just report the changes that would happen
+ """
+ template_ids = options["templates"]
+ if not template_ids:
+ template_ids = []
+
+ log.info(
+ "[modify_cert_template] Attempting to modify {num} templates".format(
+ num=len(template_ids)
+ )
+ )
+ dry_run = options.get("dry_run", None)
+ templates_changed = []
+
+ for template_id in template_ids:
+ template = None
+ try:
+ template = CertificateTemplate.objects.get(id=template_id)
+ except CertificateTemplate.DoesNotExist:
+ log.warning(f"Template {template_id} could not be found")
+ if template is not None:
+ log.info(
+ "[modify_cert_template] Calling for template {template_id} : {name}".format(
+ template_id=template_id, name=template.description
+ )
+ )
+ new_template = template.template.replace(
+ options["old_text"], options["new_text"], 1
+ )
+ if template.template == new_template:
+ log.info(
+ "[modify_cert_template] No changes to {template_id}".format(
+ template_id=template_id
+ )
+ )
+ else:
+ if not dry_run:
+ log.info(
+ "[modify_cert_template] Modifying template {template} ({description})".format(
+ template=template_id,
+ description=template.description,
+ )
+ )
+ template.template = new_template
+ templates_changed.append(template)
+ else:
+ log.info(
+ "DRY-RUN: Not making the following template change to {id}.".format(
+ id=template_id
+ )
+ )
+ log.info(
+ "\n".join(
+ unified_diff(
+ template.template.splitlines(),
+ new_template.splitlines(),
+ lineterm="",
+ fromfile="old_template",
+ tofile="new_template",
+ )
+ ),
+ )
+ log.info(
+ "[modify_cert_template] Modified {num} templates".format(
+ num=len(templates_changed)
+ )
+ )
+
+ return templates_changed
diff --git a/lms/djangoapps/certificates/tests/factories.py b/lms/djangoapps/certificates/tests/factories.py
index 15d5386aa445..ad7727876076 100644
--- a/lms/djangoapps/certificates/tests/factories.py
+++ b/lms/djangoapps/certificates/tests/factories.py
@@ -6,6 +6,7 @@
import datetime
from uuid import uuid4
+from factory import Sequence
from factory.django import DjangoModelFactory
from common.djangoapps.student.models import LinkedInAddToProfileConfiguration
@@ -15,7 +16,8 @@
CertificateHtmlViewConfiguration,
CertificateInvalidation,
CertificateStatuses,
- GeneratedCertificate
+ CertificateTemplate,
+ GeneratedCertificate,
)
@@ -23,15 +25,16 @@ class GeneratedCertificateFactory(DjangoModelFactory):
"""
GeneratedCertificate factory
"""
+
class Meta:
model = GeneratedCertificate
course_id = None
status = CertificateStatuses.unavailable
mode = GeneratedCertificate.MODES.honor
- name = ''
+ name = ""
verify_uuid = uuid4().hex
- grade = ''
+ grade = ""
class CertificateAllowlistFactory(DjangoModelFactory):
@@ -44,7 +47,7 @@ class Meta:
course_id = None
allowlist = True
- notes = 'Test Notes'
+ notes = "Test Notes"
class CertificateInvalidationFactory(DjangoModelFactory):
@@ -55,7 +58,7 @@ class CertificateInvalidationFactory(DjangoModelFactory):
class Meta:
model = CertificateInvalidation
- notes = 'Test Notes'
+ notes = "Test Notes"
active = True
@@ -112,8 +115,21 @@ class CertificateDateOverrideFactory(DjangoModelFactory):
"""
CertificateDateOverride factory
"""
+
class Meta:
model = CertificateDateOverride
date = datetime.datetime(2021, 5, 11, 0, 0, tzinfo=datetime.timezone.utc)
reason = "Learner really wanted this on their birthday"
+
+
+class CertificateTemplateFactory(DjangoModelFactory):
+ """CertificateTemplate factory"""
+
+ class Meta:
+ model = CertificateTemplate
+
+ name = Sequence("template{}".format)
+ description = Sequence("description for template{}".format)
+ template = ""
+ is_active = True
diff --git a/lms/djangoapps/certificates/tests/test_tasks.py b/lms/djangoapps/certificates/tests/test_tasks.py
index c2c73f053cdd..2e6c84464936 100644
--- a/lms/djangoapps/certificates/tests/test_tasks.py
+++ b/lms/djangoapps/certificates/tests/test_tasks.py
@@ -3,6 +3,7 @@
"""
+from textwrap import dedent
from unittest import mock
from unittest.mock import patch
@@ -13,7 +14,11 @@
from common.djangoapps.course_modes.models import CourseMode
from common.djangoapps.student.tests.factories import UserFactory
from lms.djangoapps.certificates.data import CertificateStatuses
-from lms.djangoapps.certificates.tasks import generate_certificate
+from lms.djangoapps.certificates.tasks import (
+ generate_certificate,
+ get_changed_cert_templates,
+)
+from lms.djangoapps.certificates.tests.factories import CertificateTemplateFactory
@ddt.ddt
@@ -21,23 +26,24 @@ class GenerateUserCertificateTest(TestCase):
"""
Tests for course certificate tasks
"""
+
def setUp(self):
super().setUp()
self.user = UserFactory()
- self.course_key = 'course-v1:edX+DemoX+Demo_Course'
+ self.course_key = "course-v1:edX+DemoX+Demo_Course"
- @ddt.data('student', 'course_key', 'enrollment_mode')
+ @ddt.data("student", "course_key", "enrollment_mode")
def test_missing_args(self, missing_arg):
kwargs = {
- 'student': self.user.id,
- 'course_key': self.course_key,
- 'other_arg': 'shiny',
- 'enrollment_mode': CourseMode.MASTERS
+ "student": self.user.id,
+ "course_key": self.course_key,
+ "other_arg": "shiny",
+ "enrollment_mode": CourseMode.MASTERS,
}
del kwargs[missing_arg]
- with patch('lms.djangoapps.certificates.tasks.User.objects.get'):
+ with patch("lms.djangoapps.certificates.tasks.User.objects.get"):
with self.assertRaisesRegex(KeyError, missing_arg):
generate_certificate.apply_async(kwargs=kwargs).get()
@@ -48,13 +54,13 @@ def test_generation(self):
enrollment_mode = CourseMode.VERIFIED
with mock.patch(
- 'lms.djangoapps.certificates.tasks.generate_course_certificate',
- return_value=None
+ "lms.djangoapps.certificates.tasks.generate_course_certificate",
+ return_value=None,
) as mock_generate_cert:
kwargs = {
- 'student': self.user.id,
- 'course_key': self.course_key,
- 'enrollment_mode': enrollment_mode
+ "student": self.user.id,
+ "course_key": self.course_key,
+ "enrollment_mode": enrollment_mode,
}
generate_certificate.apply_async(kwargs=kwargs)
@@ -63,31 +69,31 @@ def test_generation(self):
course_key=CourseKey.from_string(self.course_key),
status=CertificateStatuses.downloadable,
enrollment_mode=enrollment_mode,
- course_grade='',
- generation_mode='batch'
+ course_grade="",
+ generation_mode="batch",
)
def test_generation_custom(self):
"""
Verify the task handles certificate generation custom params
"""
- gen_mode = 'self'
+ gen_mode = "self"
status = CertificateStatuses.notpassing
enrollment_mode = CourseMode.AUDIT
- course_grade = '0.89'
+ course_grade = "0.89"
with mock.patch(
- 'lms.djangoapps.certificates.tasks.generate_course_certificate',
- return_value=None
+ "lms.djangoapps.certificates.tasks.generate_course_certificate",
+ return_value=None,
) as mock_generate_cert:
kwargs = {
- 'status': status,
- 'student': self.user.id,
- 'course_key': self.course_key,
- 'course_grade': course_grade,
- 'enrollment_mode': enrollment_mode,
- 'generation_mode': gen_mode,
- 'what_about': 'dinosaurs'
+ "status": status,
+ "student": self.user.id,
+ "course_key": self.course_key,
+ "course_grade": course_grade,
+ "enrollment_mode": enrollment_mode,
+ "generation_mode": gen_mode,
+ "what_about": "dinosaurs",
}
generate_certificate.apply_async(kwargs=kwargs)
@@ -97,5 +103,74 @@ def test_generation_custom(self):
status=status,
enrollment_mode=enrollment_mode,
course_grade=course_grade,
- generation_mode=gen_mode
+ generation_mode=gen_mode,
)
+
+
+class ModifyCertTemplateTests(TestCase):
+ """Tests for get_changed_cert_templates"""
+
+ def test_command_changes_called_templates(self):
+ """Verify command changes for all and only those templates for which it is called."""
+ template1 = CertificateTemplateFactory.create(
+ template="fiddledee-doo fiddledee-dah"
+ )
+ template2 = CertificateTemplateFactory.create(
+ template="violadee-doo violadee-dah"
+ )
+ template3 = CertificateTemplateFactory.create(
+ template="fiddledee-doo fiddledee-dah"
+ )
+ template1.save()
+ template2.save()
+ template3.save()
+ expected1 = "fiddleeep-doo fiddledee-dah"
+ expected2 = "violaeep-doo violadee-dah"
+ options = {
+ "old_text": "dee",
+ "new_text": "eep",
+ "templates": [1, 2],
+ }
+ new_templates = get_changed_cert_templates(options)
+ assert len(new_templates) == 2
+ assert new_templates[0].template == expected1
+ assert new_templates[1].template == expected2
+
+ def test_dry_run(self):
+ """Verify command doesn't change anything on dry-run."""
+ template1 = CertificateTemplateFactory.create(
+ template="fiddledee-doo fiddledee-dah"
+ )
+ template2 = CertificateTemplateFactory.create(
+ template="violadee-doo violadee-dah"
+ )
+ template1.save()
+ template2.save()
+ options = {
+ "old_text": "dee",
+ "new_text": "eep",
+ "templates": [1, 2],
+ "dry_run": True,
+ }
+ new_templates = get_changed_cert_templates(options)
+ assert not new_templates
+
+ def test_multiline_change(self):
+ """Verify template change works with a multiline change string."""
+ template1 = CertificateTemplateFactory.create(
+ template="fiddledee-doo fiddledee-dah"
+ )
+ template1.save()
+ new_text = """
+ there's something happening here
+ what it is ain't exactly clear
+ """
+ expected = f"fiddle{dedent(new_text)}-doo fiddledee-dah"
+ options = {
+ "old_text": "dee",
+ "new_text": dedent(new_text),
+ "templates": [1],
+ }
+ new_templates = get_changed_cert_templates(options)
+ assert len(new_templates) == 1
+ assert new_templates[0].template == expected
diff --git a/lms/djangoapps/instructor/tests/test_api.py b/lms/djangoapps/instructor/tests/test_api.py
index bb534d9b026a..0874d6954def 100644
--- a/lms/djangoapps/instructor/tests/test_api.py
+++ b/lms/djangoapps/instructor/tests/test_api.py
@@ -1228,14 +1228,17 @@ def test_enroll_with_email(self, protocol):
assert text_body.startswith('Dear NotEnrolled Student\n\n')
for body in [text_body, html_body]:
- assert f'You have been enrolled in {self.course.display_name} at edx.org by a member of the course staff.'\
- in body
-
- assert 'This course will now appear on your edx.org dashboard.' in body
+ assert f'You have been enrolled in {self.course.display_name} at ' in body
+ assert self.site_name in body
+ assert ' by a member of the course staff.' in body
+ assert 'This course will now appear on your ' in body
assert f'{protocol}://{self.site_name}{self.course_path}' in body
assert 'To start accessing course materials, please visit' in text_body
- assert 'This email was automatically sent from edx.org to NotEnrolled Student\n\n' in text_body
+ assert (
+ f'This email was automatically sent from {self.site_name} to {self.notenrolled_student.first_name} '
+ f'{self.notenrolled_student.last_name}\n\n'
+ ) in text_body
@ddt.data('http', 'https')
def test_enroll_with_email_not_registered(self, protocol):
@@ -1264,22 +1267,21 @@ def test_enroll_with_email_not_registered(self, protocol):
assert register_url in html_body
for body in [text_body, html_body]:
- assert 'You have been invited to join {course} at edx.org by a member of the course staff.'.format(
+ assert 'You have been invited to join {course} at '.format(
course=self.course.display_name
) in body
-
- assert ('fill out the registration form making sure to use '
- 'robot-not-an-email-yet@robot.org in the Email field') in body
-
+ assert self.site_name in body
+ assert ' by a member of the course staff.' in body
+ assert 'fill out the registration form making sure to use ' in body
+ assert self.notregistered_email in body
+ assert ' in the Email field' in body
assert 'Once you have registered and activated your account,' in body
-
assert '{proto}://{site}{about_path}'.format(
proto=protocol,
site=self.site_name,
about_path=self.about_path
) in body
-
- assert 'This email was automatically sent from edx.org to robot-not-an-email-yet@robot.org' in body
+ assert 'This email was automatically sent from ' in body
@ddt.data('http', 'https')
@patch.dict(settings.FEATURES, {'ENABLE_MKTG_SITE': True})
@@ -1302,23 +1304,22 @@ def test_enroll_email_not_registered_mktgsite(self, protocol):
assert 'Please finish your registration and fill' in html_body
for body in [text_body, html_body]:
- assert 'You have been invited to join {display_name} at edx.org by a member of the course staff.'.format(
+ assert 'You have been invited to join {display_name} at '.format(
display_name=self.course.display_name
) in body
-
+ assert self.site_name in body
+ assert 'by a member of the course staff.' in body
assert '{proto}://{site}/register'.format(
proto=protocol,
site=self.site_name
) in body
-
- assert ('fill out the registration form making sure to use '
- 'robot-not-an-email-yet@robot.org in the Email field') in body
-
+ assert 'fill out the registration form making sure to use ' in body
+ assert self.notregistered_email in body
+ assert ' in the Email field' in body
assert 'You can then enroll in {display_name}.'.format(
display_name=self.course.display_name
) in body
-
- assert 'This email was automatically sent from edx.org to robot-not-an-email-yet@robot.org' in body
+ assert 'This email was automatically sent from ' in body
@ddt.data('http', 'https')
def test_enroll_with_email_not_registered_autoenroll(self, protocol):
@@ -1353,20 +1354,19 @@ def test_enroll_with_email_not_registered_autoenroll(self, protocol):
assert register_url in html_body
for body in [text_body, html_body]:
- assert 'You have been invited to join {display_name} at edx.org by a member of the course staff.'.format(
+ assert 'You have been invited to join {display_name} at '.format(
display_name=self.course.display_name
) in body
-
- assert (' and fill '
- 'out the registration form making sure to use robot-not-an-email-yet@robot.org '
- 'in the Email field') in body
-
+ assert self.site_name in body
+ assert 'by a member of the course staff.' in body
+ assert ' and fill out the registration form making sure to use ' in body
+ assert self.notregistered_email in body
+ assert 'in the Email field' in body
assert ('Once you have registered and activated your account, '
'you will see {display_name} listed on your dashboard.').format(
display_name=self.course.display_name
) in body
-
- assert 'This email was automatically sent from edx.org to robot-not-an-email-yet@robot.org' in body
+ assert 'This email was automatically sent from ' in body
def test_unenroll_without_email(self):
url = reverse('students_update_enrollment', kwargs={'course_id': str(self.course.id)})
@@ -1461,13 +1461,15 @@ def test_unenroll_with_email(self):
assert text_body.startswith('Dear Enrolled Student')
for body in [text_body, html_body]:
- assert 'You have been unenrolled from {display_name} at edx.org by a member of the course staff.'.format(
+ assert 'You have been unenrolled from {display_name} at '.format(
display_name=self.course.display_name,
) in body
-
- assert 'This course will no longer appear on your edx.org dashboard.' in body
+ assert self.site_name in body
+ assert ' by a member of the course staff.' in body
+ assert 'This course will no longer appear on your ' in body
assert 'Your other courses have not been affected.' in body
- assert 'This email was automatically sent from edx.org to Enrolled Student' in body
+ assert 'This email was automatically sent from ' in body
+ assert f'to {self.enrolled_student.first_name} {self.enrolled_student.last_name}' in body
def test_unenroll_with_email_allowed_student(self):
url = reverse('students_update_enrollment', kwargs={'course_id': str(self.course.id)})
@@ -1519,7 +1521,9 @@ def test_unenroll_with_email_allowed_student(self):
) in body
assert 'Please disregard the invitation previously sent.' in body
- assert 'This email was automatically sent from edx.org to robot-allowed@robot.org' in body
+ assert 'This email was automatically sent from ' in body
+ assert self.site_name in body
+ assert self.allowed_email in body
@ddt.data('http', 'https')
@patch('lms.djangoapps.instructor.enrollment.uses_shib')
@@ -1551,11 +1555,13 @@ def test_enroll_with_email_not_registered_with_shib(self, protocol, mock_uses_sh
assert course_url in html_body
for body in [text_body, html_body]:
- assert 'You have been invited to join {display_name} at edx.org by a member of the course staff.'.format(
+ assert 'You have been invited to join {display_name} at '.format(
display_name=self.course.display_name,
) in body
-
- assert 'This email was automatically sent from edx.org to robot-not-an-email-yet@robot.org' in body
+ assert self.site_name in body
+ assert ' by a member of the course staff.' in body
+ assert 'This email was automatically sent from ' in body
+ assert self.notregistered_email in body
@patch('lms.djangoapps.instructor.enrollment.uses_shib')
@patch.dict(settings.FEATURES, {'ENABLE_MKTG_SITE': True})
@@ -1576,11 +1582,13 @@ def test_enroll_email_not_registered_shib_mktgsite(self, mock_uses_shib):
assert text_body.startswith('Dear student,')
for body in [text_body, html_body]:
- assert 'You have been invited to join {display_name} at edx.org by a member of the course staff.'.format(
+ assert 'You have been invited to join {display_name} at '.format(
display_name=self.course.display_name,
) in body
-
- assert 'This email was automatically sent from edx.org to robot-not-an-email-yet@robot.org' in body
+ assert self.site_name in body
+ assert ' by a member of the course staff.' in body
+ assert 'This email was automatically sent from ' in body
+ assert self.notregistered_email in body
@ddt.data('http', 'https')
@patch('lms.djangoapps.instructor.enrollment.uses_shib')
@@ -1611,11 +1619,13 @@ def test_enroll_with_email_not_registered_with_shib_autoenroll(self, protocol, m
assert 'To access this course click on the button below and login:' in html_body
for body in [text_body, html_body]:
- assert 'You have been invited to join {display_name} at edx.org by a member of the course staff.'.format(
+ assert 'You have been invited to join {display_name} at '.format(
display_name=self.course.display_name,
) in body
-
- assert 'This email was automatically sent from edx.org to robot-not-an-email-yet@robot.org' in body
+ assert ' by a member of the course staff.' in body
+ assert 'This email was automatically sent from ' in body
+ assert self.site_name in body
+ assert self.notregistered_email in body
def test_enroll_already_enrolled_student(self):
"""
@@ -1998,22 +2008,19 @@ def test_add_notenrolled_with_email(self, protocol):
assert f'Visit {self.course.display_name}' in html_body
for body in [text_body, html_body]:
- assert 'You have been invited to be a beta tester for {display_name} at edx.org'.format(
+ assert 'You have been invited to be a beta tester for {display_name} at '.format(
display_name=self.course.display_name,
) in body
-
+ assert self.site_name in body
assert 'by a member of the course staff.' in body
assert 'enroll in this course and begin the beta test' in body
-
assert '{proto}://{site}{about_path}'.format(
proto=protocol,
site=self.site_name,
about_path=self.about_path,
) in body
-
- assert 'This email was automatically sent from edx.org to {student_email}'.format(
- student_email=self.notenrolled_student.email,
- ) in body
+ assert 'This email was automatically sent from ' in body
+ assert self.notenrolled_student.email in body
@ddt.data('http', 'https')
def test_add_notenrolled_with_email_autoenroll(self, protocol):
@@ -2050,22 +2057,19 @@ def test_add_notenrolled_with_email_autoenroll(self, protocol):
assert text_body.startswith(f'Dear {student_name}')
for body in [text_body, html_body]:
- assert 'You have been invited to be a beta tester for {display_name} at edx.org'.format(
+ assert 'You have been invited to be a beta tester for {display_name} at '.format(
display_name=self.course.display_name,
) in body
-
+ assert self.site_name in body
assert 'by a member of the course staff' in body
-
assert 'To start accessing course materials, please visit' in body
assert '{proto}://{site}{course_path}'.format(
proto=protocol,
site=self.site_name,
course_path=self.course_path
)
-
- assert 'This email was automatically sent from edx.org to {student_email}'.format(
- student_email=self.notenrolled_student.email,
- ) in body
+ assert 'This email was automatically sent from ' in body
+ assert self.notenrolled_student.email in body
@patch.dict(settings.FEATURES, {'ENABLE_MKTG_SITE': True})
def test_add_notenrolled_email_mktgsite(self):
@@ -2081,16 +2085,14 @@ def test_add_notenrolled_email_mktgsite(self):
assert text_body.startswith(f'Dear {student_name}')
for body in [text_body, html_body]:
- assert 'You have been invited to be a beta tester for {display_name} at edx.org'.format(
+ assert 'You have been invited to be a beta tester for {display_name} at '.format(
display_name=self.course.display_name,
) in body
-
+ assert self.site_name in body
assert 'by a member of the course staff.' in body
- assert 'Visit edx.org' in body
assert 'enroll in this course and begin the beta test' in body
- assert 'This email was automatically sent from edx.org to {student_email}'.format(
- student_email=self.notenrolled_student.email,
- ) in body
+ assert 'This email was automatically sent from ' in body
+ assert self.notenrolled_student.email in body
def test_enroll_with_email_not_registered(self):
# User doesn't exist
@@ -2184,18 +2186,15 @@ def test_remove_with_email(self):
assert text_body.startswith(f'Dear {self.beta_tester.profile.name}')
for body in [text_body, html_body]:
- assert 'You have been removed as a beta tester for {display_name} at edx.org'.format(
+ assert 'You have been removed as a beta tester for {display_name} at '.format(
display_name=self.course.display_name,
) in body
-
+ assert self.site_name in body
assert ('This course will remain on your dashboard, but you will no longer be '
'part of the beta testing group.') in body
-
assert 'Your other courses have not been affected.' in body
-
- assert 'This email was automatically sent from edx.org to {email_address}'.format(
- email_address=self.beta_tester.email,
- ) in body
+ assert 'This email was automatically sent from ' in body
+ assert self.beta_tester.email in body
class TestInstructorAPILevelsAccess(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
diff --git a/lms/templates/instructor/edx_ace/addbetatester/email/body.html b/lms/templates/instructor/edx_ace/addbetatester/email/body.html
index 39389f39ac0c..2b454d8583f1 100644
--- a/lms/templates/instructor/edx_ace/addbetatester/email/body.html
+++ b/lms/templates/instructor/edx_ace/addbetatester/email/body.html
@@ -3,6 +3,7 @@
{% load i18n %}
{% load static %}
{% block content %}
+{% with site_name=''|safe|add:site_name|add:''|safe email_address=''|safe|add:email_address|add:''|safe %}
+{% endwith %}
{% endblock %}
diff --git a/lms/templates/instructor/edx_ace/allowedenroll/email/body.html b/lms/templates/instructor/edx_ace/allowedenroll/email/body.html
index 37aef5de4a1f..c70d3c16d518 100644
--- a/lms/templates/instructor/edx_ace/allowedenroll/email/body.html
+++ b/lms/templates/instructor/edx_ace/allowedenroll/email/body.html
@@ -3,6 +3,7 @@
{% load i18n %}
{% load static %}
{% block content %}
+{% with site_name=''|safe|add:site_name|add:''|safe email_address=''|safe|add:email_address|add:''|safe %}
+{% endwith %}
{% endblock %}
diff --git a/lms/templates/instructor/edx_ace/allowedunenroll/email/body.html b/lms/templates/instructor/edx_ace/allowedunenroll/email/body.html
index d3f40738e3b0..06b53856dcd5 100644
--- a/lms/templates/instructor/edx_ace/allowedunenroll/email/body.html
+++ b/lms/templates/instructor/edx_ace/allowedunenroll/email/body.html
@@ -3,6 +3,7 @@
{% load i18n %}
{% load static %}
{% block content %}
+{% with site_name=''|safe|add:site_name|add:''|safe email_address=''|safe|add:email_address|add:''|safe %}
+{% endwith %}
{% endblock %}
diff --git a/lms/templates/instructor/edx_ace/enrolledunenroll/email/body.html b/lms/templates/instructor/edx_ace/enrolledunenroll/email/body.html
index 33524c068927..686797dc2a95 100644
--- a/lms/templates/instructor/edx_ace/enrolledunenroll/email/body.html
+++ b/lms/templates/instructor/edx_ace/enrolledunenroll/email/body.html
@@ -3,6 +3,7 @@
{% load i18n %}
{% load static %}
{% block content %}
+{% with site_name=''|safe|add:site_name|add:''|safe %}
+{% endwith %}
{% endblock %}
diff --git a/lms/templates/instructor/edx_ace/enrollenrolled/email/body.html b/lms/templates/instructor/edx_ace/enrollenrolled/email/body.html
index e5a4735a62c0..8f14a6a0876a 100644
--- a/lms/templates/instructor/edx_ace/enrollenrolled/email/body.html
+++ b/lms/templates/instructor/edx_ace/enrollenrolled/email/body.html
@@ -3,6 +3,7 @@
{% load i18n %}
{% load static %}
{% block content %}
+{% with site_name=''|safe|add:site_name|add:''|safe %}
+{% endwith %}
{% endblock %}
diff --git a/lms/templates/instructor/edx_ace/removebetatester/email/body.html b/lms/templates/instructor/edx_ace/removebetatester/email/body.html
index bb5677b40f61..72b0607ecd38 100644
--- a/lms/templates/instructor/edx_ace/removebetatester/email/body.html
+++ b/lms/templates/instructor/edx_ace/removebetatester/email/body.html
@@ -3,6 +3,7 @@
{% load i18n %}
{% load static %}
{% block content %}
+{% with site_name=''|safe|add:site_name|add:''|safe email_address=''|safe|add:email_address|add:''|safe %}
+{% endwith %}
{% endblock %}
diff --git a/lms/templates/verify_student/edx_ace/verificationsubmitted/email/body.html b/lms/templates/verify_student/edx_ace/verificationsubmitted/email/body.html
index c23fbdfca5ea..9e68d5cb30e4 100644
--- a/lms/templates/verify_student/edx_ace/verificationsubmitted/email/body.html
+++ b/lms/templates/verify_student/edx_ace/verificationsubmitted/email/body.html
@@ -3,6 +3,7 @@
{% load i18n %}
{% load static %}
{% block content %}
+{% with dashboard_link=''|add:dashboard_link|add:''|safe %}
+{% endwith %}
{% endblock %}
diff --git a/openedx/core/djangoapps/ace_common/templates/ace_common/edx_ace/common/base_body.html b/openedx/core/djangoapps/ace_common/templates/ace_common/edx_ace/common/base_body.html
index c04873ffdd44..3c0c3fa6839c 100644
--- a/openedx/core/djangoapps/ace_common/templates/ace_common/edx_ace/common/base_body.html
+++ b/openedx/core/djangoapps/ace_common/templates/ace_common/edx_ace/common/base_body.html
@@ -29,6 +29,7 @@
{% google_analytics_tracking_pixel %}
+{% with brand_color="#005686" logo_max_height="65px" %}
- 
+

@@ -218,8 +219,8 @@
{% get_action_links channel omit_unsubscribe_link=omit_unsubscribe_link as action_links %}
{% for action_link_url, action_link_text in action_links %}
-
- {{ action_link_text }}
+
+ {{ action_link_text }}
{% endfor %}
@@ -253,6 +254,7 @@
+{% endwith %}
{# Debug info that is not user-visible #}
{{ message.log_id }}
diff --git a/openedx/core/djangoapps/ace_common/templates/ace_common/edx_ace/common/return_to_course_cta.html b/openedx/core/djangoapps/ace_common/templates/ace_common/edx_ace/common/return_to_course_cta.html
index 72806a7c5c60..722cb54b18de 100644
--- a/openedx/core/djangoapps/ace_common/templates/ace_common/edx_ace/common/return_to_course_cta.html
+++ b/openedx/core/djangoapps/ace_common/templates/ace_common/edx_ace/common/return_to_course_cta.html
@@ -21,11 +21,11 @@
border-radius: 4px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
- background-color: #005686;
- border-top: 12px solid #005686;
- border-bottom: 12px solid #005686;
- border-right: 50px solid #005686;
- border-left: 50px solid #005686;
+ background-color: {{ brand_color }};
+ border-top: 12px solid {{ brand_color }};
+ border-bottom: 12px solid {{ brand_color }};
+ border-right: 50px solid {{ brand_color }};
+ border-left: 50px solid {{ brand_color }};
display: inline-block;
">
{# old email clients require the use of the font tag :( #}
diff --git a/openedx/core/djangoapps/credentials/tasks/v1/tasks.py b/openedx/core/djangoapps/credentials/tasks/v1/tasks.py
index dad4d3618a97..ee24289dad8c 100644
--- a/openedx/core/djangoapps/credentials/tasks/v1/tasks.py
+++ b/openedx/core/djangoapps/credentials/tasks/v1/tasks.py
@@ -6,7 +6,6 @@
from urllib.parse import urljoin
from celery import shared_task
-from celery.exceptions import MaxRetriesExceededError
from celery.utils.log import get_task_logger
from celery_utils.logged_task import LoggedTask
from django.conf import settings
@@ -43,12 +42,16 @@
CertificateStatuses.downloadable,
]
-# Maximum number of retries before giving up. For reference, 11 retries with exponential backoff yields a maximum
-# waiting time of 2047 seconds (about 30 minutes). Setting this to None could yield unwanted behavior: infinite retries.
-MAX_RETRIES = 11
-
-@shared_task(bind=True, ignore_result=True)
+@shared_task(
+ bind=True,
+ ignore_result=True,
+ autoretry_for=(Exception,),
+ max_retries=10,
+ retry_backoff=30,
+ retry_backoff_max=600,
+ retry_jitter=True,
+)
@set_code_owner_attribute
def send_grade_to_credentials(
self,
@@ -62,6 +65,10 @@ def send_grade_to_credentials(
"""
Celery task to notify the Credentials IDA of an "interesting" grade change via an API call.
+ If an exception occurs when trying to send data to the Credentials IDA, we will retry the task a maximum number of
+ 11 times (initial attempt + 10 retries). We are relying on built-in functionality of Celery to add a randomized
+ jitter to the retries so that the tasks don't retry exactly at the same time.
+
Args:
username (string): The username of the learner we are currently processing
course_run_key (string): String identifier of the course run associated with the grade update
@@ -70,35 +77,26 @@ def send_grade_to_credentials(
percent_grade (float): Number representing the learner's grade in this course run
grade_last_updated (string): String describing the last time this grade was modified in the LMS
"""
- logger.info(f"Running task send_grade_to_credentials for username {username} and course {course_run_key}")
+ data = {
+ 'username': username,
+ 'course_run': course_run_key,
+ 'letter_grade': letter_grade,
+ 'percent_grade': percent_grade,
+ 'verified': verified,
+ 'lms_last_updated_at': grade_last_updated
+ }
+ logger.info(f"Running task `send_grade_to_credentials` for username {username} with data: {data}")
- countdown = 2 ** self.request.retries
course_key = CourseKey.from_string(course_run_key)
+ credentials_client = get_credentials_api_client(User.objects.get(username=settings.CREDENTIALS_SERVICE_USERNAME))
+ api_url = urljoin(f"{get_credentials_api_base_url(org=course_key.org)}/", "grades/")
- try:
- credentials_client = get_credentials_api_client(
- User.objects.get(username=settings.CREDENTIALS_SERVICE_USERNAME)
- )
- api_url = urljoin(f"{get_credentials_api_base_url(org=course_key.org)}/", "grades/")
- response = credentials_client.post(
- api_url,
- data={
- 'username': username,
- 'course_run': course_run_key,
- 'letter_grade': letter_grade,
- 'percent_grade': percent_grade,
- 'verified': verified,
- 'lms_last_updated_at': grade_last_updated
- }
- )
- response.raise_for_status()
- logger.info(f"Sent grade for course {course_run_key} for user {username}")
- except Exception: # lint-amnesty, pylint: disable=W0703
- grade_str = f'(percent: {percent_grade} letter: {letter_grade})'
- error_msg = f'Failed to send grade {grade_str} for course {course_run_key} for user {username}.'
- logger.exception(error_msg)
- exception = MaxRetriesExceededError(f"Failed to send grade to credentials. Reason: {error_msg}")
- raise self.retry(exc=exception, countdown=countdown, max_retries=MAX_RETRIES) # pylint: disable=raise-missing-from
+ response = credentials_client.post(
+ api_url,
+ data=data,
+ )
+ response.raise_for_status()
+ logger.info(f"Sent grade for user {username} in course {course_run_key} to Credentials")
@shared_task(base=LoggedTask, ignore_result=True)
diff --git a/openedx/core/djangoapps/credentials/tests/test_tasks.py b/openedx/core/djangoapps/credentials/tests/test_tasks.py
index 64bde301f579..1ad372e4f8ad 100644
--- a/openedx/core/djangoapps/credentials/tests/test_tasks.py
+++ b/openedx/core/djangoapps/credentials/tests/test_tasks.py
@@ -82,14 +82,14 @@ def test_happy_path(self, mock_get_api_client):
def test_retry(self, mock_get_api_client):
"""
- Test that we retry when an exception occurs.
+ Test that we retry the appropriate number of times when an exception occurs.
"""
mock_get_api_client.side_effect = boom
task = tasks.send_grade_to_credentials.delay('user', 'course-v1:org+course+run', True, 'A', 1.0, None)
pytest.raises(Exception, task.get)
- assert mock_get_api_client.call_count == (tasks.MAX_RETRIES + 1)
+ assert mock_get_api_client.call_count == 11
@ddt.ddt
diff --git a/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/upgradereminder/email/body.html b/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/upgradereminder/email/body.html
index 03824fbea24f..cc3db8166e96 100644
--- a/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/upgradereminder/email/body.html
+++ b/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/upgradereminder/email/body.html
@@ -101,11 +101,11 @@ {% trans "Upgrade now" as tmsg %}{{ tmsg | force_escape }}
border-radius: 4px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
- background-color: #005686;
- border-top: 10px solid #005686;
- border-bottom: 10px solid #005686;
- border-right: 16px solid #005686;
- border-left: 16px solid #005686;
+ background-color: {{ brand_color }};
+ border-top: 10px solid {{ brand_color }};
+ border-bottom: 10px solid {{ brand_color }};
+ border-right: 16px solid {{ brand_color }};
+ border-left: 16px solid {{ brand_color }};
display: inline-block;
">
{# old email clients require the use of the font tag :( #}
diff --git a/openedx/core/djangoapps/user_api/templates/user_api/edx_ace/deletionnotificationmessage/email/body.html b/openedx/core/djangoapps/user_api/templates/user_api/edx_ace/deletionnotificationmessage/email/body.html
index 0e9ff89f9e06..3ca277e05907 100644
--- a/openedx/core/djangoapps/user_api/templates/user_api/edx_ace/deletionnotificationmessage/email/body.html
+++ b/openedx/core/djangoapps/user_api/templates/user_api/edx_ace/deletionnotificationmessage/email/body.html
@@ -2,6 +2,7 @@
{% load i18n %}
{% block content %}
+{% with contact_email=''|safe|add:contact_email|add:''|safe %}
+{% endwith %}
{% endblock %}
diff --git a/requirements/constraints.txt b/requirements/constraints.txt
index 2dca59048198..111ead0354a1 100644
--- a/requirements/constraints.txt
+++ b/requirements/constraints.txt
@@ -23,7 +23,7 @@ click>=8.0,<9.0
# The team that owns this package will manually bump this package rather than having it pulled in automatically.
# This is to allow them to better control its deployment and to do it in a process that works better
# for them.
-edx-enterprise==4.10.2
+edx-enterprise==4.10.6
# Stay on LTS version, remove once this is added to common constraint
Django<5.0
diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt
index 42768161612e..21dc8c3b2e62 100644
--- a/requirements/edx/base.txt
+++ b/requirements/edx/base.txt
@@ -476,7 +476,7 @@ edx-drf-extensions==9.1.2
# edx-when
# edxval
# openedx-learning
-edx-enterprise==4.10.2
+edx-enterprise==4.10.6
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/kernel.in
@@ -789,7 +789,7 @@ openedx-mongodbproxy==0.2.0
# via -r requirements/edx/kernel.in
optimizely-sdk==4.1.1
# via -r requirements/edx/bundled.in
-ora2==6.0.26
+ora2==6.0.28
# via -r requirements/edx/bundled.in
packaging==23.2
# via
diff --git a/requirements/edx/development.txt b/requirements/edx/development.txt
index d11b8e377650..9c0325ee5f84 100644
--- a/requirements/edx/development.txt
+++ b/requirements/edx/development.txt
@@ -757,7 +757,7 @@ edx-drf-extensions==9.1.2
# edx-when
# edxval
# openedx-learning
-edx-enterprise==4.10.2
+edx-enterprise==4.10.6
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/doc.txt
@@ -1326,7 +1326,7 @@ optimizely-sdk==4.1.1
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
-ora2==6.0.26
+ora2==6.0.28
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
diff --git a/requirements/edx/doc.txt b/requirements/edx/doc.txt
index f0213636caa7..36014f6b3749 100644
--- a/requirements/edx/doc.txt
+++ b/requirements/edx/doc.txt
@@ -554,7 +554,7 @@ edx-drf-extensions==9.1.2
# edx-when
# edxval
# openedx-learning
-edx-enterprise==4.10.2
+edx-enterprise==4.10.6
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/base.txt
@@ -931,7 +931,7 @@ openedx-mongodbproxy==0.2.0
# via -r requirements/edx/base.txt
optimizely-sdk==4.1.1
# via -r requirements/edx/base.txt
-ora2==6.0.26
+ora2==6.0.28
# via -r requirements/edx/base.txt
packaging==23.2
# via
diff --git a/requirements/edx/testing.txt b/requirements/edx/testing.txt
index 253a866c8efe..4b47f1324270 100644
--- a/requirements/edx/testing.txt
+++ b/requirements/edx/testing.txt
@@ -582,7 +582,7 @@ edx-drf-extensions==9.1.2
# edx-when
# edxval
# openedx-learning
-edx-enterprise==4.10.2
+edx-enterprise==4.10.6
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/base.txt
@@ -991,7 +991,7 @@ openedx-mongodbproxy==0.2.0
# via -r requirements/edx/base.txt
optimizely-sdk==4.1.1
# via -r requirements/edx/base.txt
-ora2==6.0.26
+ora2==6.0.28
# via -r requirements/edx/base.txt
packaging==23.2
# via