From 7c872f062169b1e8a1a1067d50393e00a06fc116 Mon Sep 17 00:00:00 2001 From: Yurii Horbatiuk Date: Wed, 29 Oct 2025 10:28:32 +0200 Subject: [PATCH 1/2] fix: [CHTC-121] fix course home page missing translations --- src/course-tabs/CourseTabsNavigation.jsx | 9 +++- src/instructor-toolbar/InstructorToolbar.jsx | 13 +++-- .../masquerade-widget/MasqueradeWidget.jsx | 51 ++++++++++++------- .../masquerade-widget/messages.js | 30 +++++++++++ 4 files changed, 80 insertions(+), 23 deletions(-) diff --git a/src/course-tabs/CourseTabsNavigation.jsx b/src/course-tabs/CourseTabsNavigation.jsx index 63640ebe41..623eefb040 100644 --- a/src/course-tabs/CourseTabsNavigation.jsx +++ b/src/course-tabs/CourseTabsNavigation.jsx @@ -26,7 +26,14 @@ const CourseTabsNavigation = ({ className={classNames('nav-item flex-shrink-0 nav-link', { active: slug === activeTabSlug })} href={url} > - {title} + {(() => { + switch (slug) { + case 'instructor_analytics': + return intl.formatMessage({ id: 'learn.tabs.instructorAnalytics', defaultMessage: 'Instructor analytics' }); + default: + return title; + } + })()} ))} diff --git a/src/instructor-toolbar/InstructorToolbar.jsx b/src/instructor-toolbar/InstructorToolbar.jsx index 71d968c869..c510689c35 100644 --- a/src/instructor-toolbar/InstructorToolbar.jsx +++ b/src/instructor-toolbar/InstructorToolbar.jsx @@ -2,6 +2,7 @@ import React, { useEffect, useState } from 'react'; import PropTypes from 'prop-types'; import { getConfig } from '@edx/frontend-platform'; +import { FormattedMessage } from '@edx/frontend-platform/i18n'; import { ALERT_TYPES, AlertList } from '../generic/user-messages'; import Alert from '../generic/user-messages/Alert'; import MasqueradeWidget from './masquerade-widget'; @@ -75,17 +76,23 @@ const InstructorToolbar = (props) => { {(urlStudio || urlInsights) && ( <>
- View course in: + + + )} {urlStudio && ( - Studio + + + )} {urlInsights && ( - Insights + + + )} diff --git a/src/instructor-toolbar/masquerade-widget/MasqueradeWidget.jsx b/src/instructor-toolbar/masquerade-widget/MasqueradeWidget.jsx index 554703fcfd..16c97154c1 100644 --- a/src/instructor-toolbar/masquerade-widget/MasqueradeWidget.jsx +++ b/src/instructor-toolbar/masquerade-widget/MasqueradeWidget.jsx @@ -21,7 +21,7 @@ class MasqueradeWidget extends Component { this.courseId = props.courseId; this.state = { autoFocus: false, - masquerade: 'Staff', + masquerade: this.props.intl.formatMessage(messages.staffLabel), options: [], shouldShowUserNameInput: false, masqueradeUsername: null, @@ -36,7 +36,7 @@ class MasqueradeWidget extends Component { // This was explicitly denied by the backend; // assume it's disabled/unavailable. // eslint-disable-next-line no-console - this.onError('Unable to get masquerade options'); + this.onError(this.props.intl.formatMessage(messages.optionsError)); } }).catch((response) => { // There's not much we can do to recover; @@ -71,7 +71,7 @@ class MasqueradeWidget extends Component { toggle(show) { this.setState(prevState => ({ autoFocus: true, - masquerade: 'Specific Student...', + masquerade: this.props.intl.formatMessage(messages.specificStudentLabel), shouldShowUserNameInput: show === undefined ? !prevState.shouldShowUserNameInput : show, })); } @@ -80,30 +80,42 @@ class MasqueradeWidget extends Component { const data = postData || {}; const active = data.active || {}; const available = data.available || []; - const options = available.map((group) => ( - this.toggle(...args)} - onSubmit={(payload) => this.onSubmit(payload)} - /> - )); + const options = available.map((group) => { + let localizedGroupName = group.name; + if (group.userName !== undefined) { + localizedGroupName = this.props.intl.formatMessage(messages.specificStudentLabel); + } else if (group.role === 'staff') { + localizedGroupName = this.props.intl.formatMessage(messages.staffLabel); + } else if (group.role === 'student' && !group.groupId) { + localizedGroupName = this.props.intl.formatMessage(messages.learnerLabel); + } else if (group.name === 'My certificate') { + localizedGroupName = this.props.intl.formatMessage(messages.myCertificateLabel); + } + return ( + this.toggle(...args)} + onSubmit={(payload) => this.onSubmit(payload)} + /> + ); + }); if (active.userName) { this.setState({ autoFocus: false, - masquerade: 'Specific Student...', + masquerade: this.props.intl.formatMessage(messages.specificStudentLabel), masqueradeUsername: active.userName, shouldShowUserNameInput: true, }); } else if (active.groupName) { this.setState({ masquerade: active.groupName }); } else if (active.role === 'student') { - this.setState({ masquerade: 'Learner' }); + this.setState({ masquerade: this.props.intl.formatMessage(messages.learnerLabel) }); } return options; } @@ -117,10 +129,11 @@ class MasqueradeWidget extends Component { masqueradeUsername, } = this.state; const specificLearnerInputText = this.props.intl.formatMessage(messages.placeholder); + const viewThisCourseAsText = this.props.intl.formatMessage(messages.viewThisCourseAsLabel); return (
- View this course as: + {viewThisCourseAsText} {masquerade} diff --git a/src/instructor-toolbar/masquerade-widget/messages.js b/src/instructor-toolbar/masquerade-widget/messages.js index 4621534c63..0a8948f9fe 100644 --- a/src/instructor-toolbar/masquerade-widget/messages.js +++ b/src/instructor-toolbar/masquerade-widget/messages.js @@ -16,6 +16,36 @@ const messages = defineMessages({ defaultMessage: 'Masquerade as this user', description: 'Label for the masquerade user input', }, + viewThisCourseAsLabel: { + id: 'masquerade-widget.viewThisCourseAs.label', + defaultMessage: 'View this course as:', + description: 'Label for masquerade dropdown in the instructor toolbar', + }, + staffLabel: { + id: 'masquerade-widget.role.staff', + defaultMessage: 'Staff', + description: 'Masquerade dropdown selected label for Staff role', + }, + learnerLabel: { + id: 'masquerade-widget.role.learner', + defaultMessage: 'Learner', + description: 'Masquerade dropdown selected label for Learner role', + }, + specificStudentLabel: { + id: 'masquerade-widget.role.specificStudent', + defaultMessage: 'Specific Student...', + description: 'Masquerade dropdown selected label when viewing specific student', + }, + myCertificateLabel: { + id: 'masquerade-widget.role.myCertificate', + defaultMessage: 'My certificate', + description: 'Masquerade dropdown label for the certificate view option', + }, + optionsError: { + id: 'masquerade-widget.options.error', + defaultMessage: 'Unable to get masquerade options', + description: 'Error shown when fetching masquerade options fails', + }, }); export default messages; From 653e74d2330057e3acdfeeb754793191528f7ed2 Mon Sep 17 00:00:00 2001 From: Yurii Horbatiuk Date: Wed, 5 Nov 2025 14:32:50 +0200 Subject: [PATCH 2/2] fix: [CHTC-121] correct the comments --- src/course-tabs/CourseTabsNavigation.jsx | 9 +---- .../masquerade-widget/MasqueradeWidget.jsx | 38 +++++++------------ 2 files changed, 14 insertions(+), 33 deletions(-) diff --git a/src/course-tabs/CourseTabsNavigation.jsx b/src/course-tabs/CourseTabsNavigation.jsx index 623eefb040..63640ebe41 100644 --- a/src/course-tabs/CourseTabsNavigation.jsx +++ b/src/course-tabs/CourseTabsNavigation.jsx @@ -26,14 +26,7 @@ const CourseTabsNavigation = ({ className={classNames('nav-item flex-shrink-0 nav-link', { active: slug === activeTabSlug })} href={url} > - {(() => { - switch (slug) { - case 'instructor_analytics': - return intl.formatMessage({ id: 'learn.tabs.instructorAnalytics', defaultMessage: 'Instructor analytics' }); - default: - return title; - } - })()} + {title} ))} diff --git a/src/instructor-toolbar/masquerade-widget/MasqueradeWidget.jsx b/src/instructor-toolbar/masquerade-widget/MasqueradeWidget.jsx index 16c97154c1..e33457cce5 100644 --- a/src/instructor-toolbar/masquerade-widget/MasqueradeWidget.jsx +++ b/src/instructor-toolbar/masquerade-widget/MasqueradeWidget.jsx @@ -80,31 +80,19 @@ class MasqueradeWidget extends Component { const data = postData || {}; const active = data.active || {}; const available = data.available || []; - const options = available.map((group) => { - let localizedGroupName = group.name; - if (group.userName !== undefined) { - localizedGroupName = this.props.intl.formatMessage(messages.specificStudentLabel); - } else if (group.role === 'staff') { - localizedGroupName = this.props.intl.formatMessage(messages.staffLabel); - } else if (group.role === 'student' && !group.groupId) { - localizedGroupName = this.props.intl.formatMessage(messages.learnerLabel); - } else if (group.name === 'My certificate') { - localizedGroupName = this.props.intl.formatMessage(messages.myCertificateLabel); - } - return ( - this.toggle(...args)} - onSubmit={(payload) => this.onSubmit(payload)} - /> - ); - }); + const options = available.map((group) => ( + this.toggle(...args)} + onSubmit={(payload) => this.onSubmit(payload)} + /> + )); if (active.userName) { this.setState({ autoFocus: false,