diff --git a/app/controllers/course/external_assessments_controller.rb b/app/controllers/course/external_assessments_controller.rb new file mode 100644 index 0000000000..91b04ece78 --- /dev/null +++ b/app/controllers/course/external_assessments_controller.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true +class Course::ExternalAssessmentsController < Course::ComponentController + before_action :load_external_assessment, only: [:grades] + + def grades + authorize! :grade, @external_assessment + # The gradebook keys students by user_id (see index/update_grade jbuilders), so the + # `studentId` param is a user_id, not a course_user PK. + course_user = current_course.course_users.find_by!(user_id: grade_params[:studentId]) + @grade = @external_assessment.external_assessment_grades. + find_or_initialize_by(course_user: course_user) + @grade.grade = normalized_grade(grade_params[:grade]) + @grade.save! + render 'update_grade' + rescue ActiveRecord::RecordNotUnique + retry + rescue ActiveRecord::RecordNotFound + head :not_found + rescue ActiveRecord::RecordInvalid => e + render json: { errors: { base: e.message } }, status: :unprocessable_entity + end + + private + + def component + current_component_host[:course_gradebook_component] + end + + def load_external_assessment + @external_assessment = Course::ExternalAssessment.for_course(current_course).find(params[:id]) + rescue ActiveRecord::RecordNotFound + head :not_found + end + + def grade_params + params.permit(:studentId, :grade) + end + + # Blank cell clears the grade to null (ungraded), never zero (decision #7). + def normalized_grade(value) + value.blank? ? nil : value + end +end diff --git a/app/models/course.rb b/app/models/course.rb index 7952e5a750..f52778fa95 100644 --- a/app/models/course.rb +++ b/app/models/course.rb @@ -55,6 +55,8 @@ class Course < ApplicationRecord has_many :assessments, through: :assessment_categories has_many :gradebook_contributions, class_name: 'Course::Gradebook::Contribution', dependent: :destroy, inverse_of: :course + has_many :external_assessments, class_name: 'Course::ExternalAssessment', + inverse_of: :course, dependent: :destroy has_many :assessment_skills, class_name: 'Course::Assessment::Skill', dependent: :destroy has_many :assessment_skill_branches, class_name: 'Course::Assessment::SkillBranch', diff --git a/app/models/course/external_assessment.rb b/app/models/course/external_assessment.rb new file mode 100644 index 0000000000..6f11f1ba8e --- /dev/null +++ b/app/models/course/external_assessment.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true +# A gradebook component graded outside Coursemology (e.g. a midterm or final). +# It is a first-class gradebook contributor, NOT a Course::Assessment: it never +# touches attempts, EXP, statistics, todos, or the lesson plan. Its weight lives on +# its course_gradebook_contributions row; its display grouping is synthesised by the +# gradebook serializer (no real tab/category exists). +class Course::ExternalAssessment < ApplicationRecord + # Sentinel id for the serializer's synthetic "External Assessments" category. + # Native categories are positive; externals and their synthetic grouping are negative. + SYNTHETIC_CATEGORY_ID = -1 + SYNTHETIC_CATEGORY_TITLE = 'External Assessments' + + validates :title, length: { maximum: 255 }, presence: true + validates :title, uniqueness: { scope: :course_id } + validates :maximum_grade, presence: true + validates :maximum_grade, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true + validates :creator, presence: true + validates :updater, presence: true + + belongs_to :course, inverse_of: :external_assessments + has_one :gradebook_contribution, class_name: 'Course::Gradebook::Contribution', + inverse_of: :external_assessment, dependent: :destroy + has_many :external_assessment_grades, class_name: 'Course::ExternalAssessmentGrade', + inverse_of: :external_assessment, dependent: :destroy + + scope :for_course, ->(course) { where(course_id: course.id) } + + # The negative serialized id used by the synthetic tab AND the leaf assessment. + def synthetic_tab_id + -id + end + + # Creates an external assessment and its gradebook contribution in one transaction. + # Raises ActiveRecord::RecordInvalid on a duplicate title within the course. + # rubocop:disable Metrics/ParameterLists -- factory mirrors the model's columns; named kwargs are clearer than a struct + def self.create_for_course!(course:, title:, maximum_grade:, weight: 0, + floor_at_zero: true, cap_at_maximum: true) + transaction do + external = course.external_assessments.create!( + title: title, maximum_grade: maximum_grade, + floor_at_zero: floor_at_zero, cap_at_maximum: cap_at_maximum + ) + Course::Gradebook::Contribution.create!(course: course, external_assessment: external, + weight: weight, weight_mode: 'equal', keep_highest: 0) + external + end + end + # rubocop:enable Metrics/ParameterLists +end diff --git a/app/models/course/external_assessment_grade.rb b/app/models/course/external_assessment_grade.rb new file mode 100644 index 0000000000..70518c79c9 --- /dev/null +++ b/app/models/course/external_assessment_grade.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true +# One external grade for a (external assessment, course_user). The binding key is +# course_user_id (the authoritative link to the person); imported_identifier is a +# non-authoritative snapshot of the email/Student ID used at import (audit + upsert +# mismatch detection), null for grades typed/edited inline. +class Course::ExternalAssessmentGrade < ApplicationRecord + validates :course_user, presence: true + validates :grade, numericality: true, allow_nil: true + validates :course_user_id, uniqueness: { scope: :external_assessment_id } + validates :creator, presence: true + validates :updater, presence: true + + belongs_to :external_assessment, class_name: 'Course::ExternalAssessment', + inverse_of: :external_assessment_grades + belongs_to :course_user, inverse_of: :external_assessment_grades +end diff --git a/app/models/course/gradebook/contribution.rb b/app/models/course/gradebook/contribution.rb index 734e8a6b00..fcad0bb792 100644 --- a/app/models/course/gradebook/contribution.rb +++ b/app/models/course/gradebook/contribution.rb @@ -8,13 +8,16 @@ class Course::Gradebook::Contribution < ApplicationRecord belongs_to :course, inverse_of: :gradebook_contributions belongs_to :tab, class_name: 'Course::Assessment::Tab', inverse_of: :gradebook_contribution, optional: true + belongs_to :external_assessment, class_name: 'Course::ExternalAssessment', + inverse_of: :gradebook_contribution, optional: true validates :creator, presence: true validates :updater, presence: true validates :weight, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 100 } validates :weight_mode, presence: true validates :keep_highest, numericality: { only_integer: true, greater_than_or_equal_to: 0 } - validates :tab_id, uniqueness: true + validates :tab_id, uniqueness: { allow_nil: true } + validates :external_assessment_id, uniqueness: { allow_nil: true } validate :exactly_one_contributor validate :course_matches_contributor # Bulk-upserts tab contributions and their per-assessment contributions for a course. @@ -27,13 +30,22 @@ class Course::Gradebook::Contribution < ApplicationRecord # @param updates [Array] each { tab_id:, weight:, weight_mode:, keep_highest:, # excluded_assessment_ids: [Integer], assessment_weights: [{ assessment_id:, weight: }] } def self.bulk_update(course:, updates:) + external_updates, tab_updates = updates.partition { |e| e[:tab_id].to_i < 0 } + course_tab_ids = course.assessment_tabs.pluck(:id).to_set - updates.each { |e| raise ActiveRecord::RecordNotFound unless course_tab_ids.include?(e[:tab_id]) } + tab_updates.each { |e| raise ActiveRecord::RecordNotFound unless course_tab_ids.include?(e[:tab_id]) } + + external_ids = external_updates.map { |e| -e[:tab_id] } + externals_by_id = course.external_assessments.where(id: external_ids).index_by(&:id) + external_updates.each { |e| raise ActiveRecord::RecordNotFound unless externals_by_id.key?(-e[:tab_id]) } - tabs_by_id = Course::Assessment::Tab.where(id: updates.map { |e| e[:tab_id] }). + tabs_by_id = Course::Assessment::Tab.where(id: tab_updates.map { |e| e[:tab_id] }). includes(:assessments).index_by(&:id) - transaction { updates.each { |entry| apply_entry(course, tabs_by_id, entry) } } + transaction do + tab_updates.each { |entry| apply_entry(course, tabs_by_id, entry) } + external_updates.each { |entry| apply_external_entry(course, externals_by_id[-entry[:tab_id]], entry) } + end end # @api private @@ -58,6 +70,16 @@ def self.apply_entry(course, tabs_by_id, entry) end private_class_method :apply_entry + # @api private + def self.apply_external_entry(course, external, entry) + contribution = find_or_initialize_by(external_assessment_id: external.id) + contribution.tab = nil + contribution.course = course + contribution.assign_attributes(weight: entry[:weight], weight_mode: 'equal', keep_highest: 0) + contribution.save! + end + private_class_method :apply_external_entry + # @api private def self.assessment_contribution_for(assessment) Course::Gradebook::AssessmentContribution.find_or_initialize_by(assessment_id: assessment.id) @@ -117,15 +139,19 @@ def self.validate_custom_assessment_weights_sum!(tab, entry, included_sum, inclu private - # Until the external-alignment design adds `external_assessment_id`, the only - # contributor is the tab, so "exactly one" reduces to "tab present". def exactly_one_contributor - errors.add(:tab, :blank) if tab_id.blank? + return if [tab_id, external_assessment_id].compact.size == 1 + + errors.add(:base, :exactly_one_contributor) end def course_matches_contributor - return if tab.nil? || course.nil? + return if course.nil? - errors.add(:course, :invalid) if tab.category.course_id != course_id + contributor_course_id = + if tab then tab.category.course_id + elsif external_assessment then external_assessment.course_id + end + errors.add(:course, :invalid) if contributor_course_id && contributor_course_id != course_id end end diff --git a/app/models/course_user.rb b/app/models/course_user.rb index 944fe25e09..6682fb1fac 100644 --- a/app/models/course_user.rb +++ b/app/models/course_user.rb @@ -50,6 +50,8 @@ class CourseUser < ApplicationRecord inverse_of: :course_user, dependent: :destroy has_many :groups, through: :group_users, class_name: 'Course::Group', source: :group has_many :personal_times, class_name: 'Course::PersonalTime', inverse_of: :course_user, dependent: :destroy + has_many :external_assessment_grades, class_name: 'Course::ExternalAssessmentGrade', + inverse_of: :course_user, dependent: :destroy belongs_to :reference_timeline, class_name: 'Course::ReferenceTimeline', inverse_of: :course_users, optional: true default_scope { where(deleted_at: nil) } diff --git a/app/views/course/external_assessments/update_grade.json.jbuilder b/app/views/course/external_assessments/update_grade.json.jbuilder new file mode 100644 index 0000000000..f997450dfc --- /dev/null +++ b/app/views/course/external_assessments/update_grade.json.jbuilder @@ -0,0 +1,4 @@ +# frozen_string_literal: true +json.studentId @grade.course_user.user_id +json.assessmentId(-@grade.external_assessment_id) +json.grade @grade.grade&.to_f diff --git a/app/views/course/gradebook/index.json.jbuilder b/app/views/course/gradebook/index.json.jbuilder index b3cc4ec4d0..8cab4699a0 100644 --- a/app/views/course/gradebook/index.json.jbuilder +++ b/app/views/course/gradebook/index.json.jbuilder @@ -2,31 +2,71 @@ json.weightedViewEnabled @weighted_view_enabled json.canManageWeights can?(:manage_gradebook_weights, current_course) -json.categories @categories do |cat| - json.id cat.id - json.title cat.title +json.categories do + json.array!(@categories) do |cat| + json.id cat.id + json.title cat.title + end + if @external_assessments.any? + json.child! do + json.id Course::ExternalAssessment::SYNTHETIC_CATEGORY_ID + json.title Course::ExternalAssessment::SYNTHETIC_CATEGORY_TITLE + end + end end -json.tabs @tabs do |tab| - json.id tab.id - json.title tab.title - json.categoryId tab.category_id - if @weighted_view_enabled - contribution = @tab_contributions[tab.id] - json.gradebookWeight (contribution&.weight || 0).to_f - json.weightMode(contribution&.weight_mode || 'equal') +json.tabs do + json.array!(@tabs) do |tab| + json.id tab.id + json.title tab.title + json.categoryId tab.category_id + if @weighted_view_enabled + contribution = @tab_contributions[tab.id] + json.gradebookWeight (contribution&.weight || 0).to_f + json.weightMode(contribution&.weight_mode || 'equal') + end + end + @external_assessments.each do |external| + json.child! do + json.id external.synthetic_tab_id + json.title external.title + json.categoryId Course::ExternalAssessment::SYNTHETIC_CATEGORY_ID + if @weighted_view_enabled + contribution = @external_contributions[external.id] + json.gradebookWeight (contribution&.weight || 0).to_f + json.weightMode 'equal' + end + end end end -json.assessments @published_assessments do |assessment| - json.id assessment.id - json.title assessment.title - json.tabId assessment.tab_id - json.maxGrade @assessment_max_grades[assessment.id] || 0 - if @weighted_view_enabled - contribution = @assessment_contributions[assessment.id] - json.gradebookWeight contribution&.weight&.to_f - json.gradebookExcluded(contribution&.excluded || false) +json.assessments do + json.array!(@published_assessments) do |assessment| + json.id assessment.id + json.title assessment.title + json.tabId assessment.tab_id + json.maxGrade @assessment_max_grades[assessment.id] || 0 + if @weighted_view_enabled + contribution = @assessment_contributions[assessment.id] + json.gradebookWeight contribution&.weight&.to_f + json.gradebookExcluded(contribution&.excluded || false) + end + end + @external_assessments.each do |external| + json.child! do + json.id(-external.id) + json.title external.title + json.tabId external.synthetic_tab_id + json.maxGrade external.maximum_grade.to_f + json.external true + json.floorAtZero external.floor_at_zero + json.capAtMaximum external.cap_at_maximum + if @weighted_view_enabled + contribution = @external_contributions[external.id] + json.gradebookWeight contribution&.weight&.to_f + json.gradebookExcluded false + end + end end end @@ -39,11 +79,21 @@ json.students @students do |course_user| json.totalXp course_user.experience_points end -json.submissions @submissions do |sub| - json.submissionId sub.submission_id - json.studentId sub.student_id - json.assessmentId sub.assessment_id - json.grade sub.grade&.to_f +json.submissions do + json.array!(@submissions) do |sub| + json.submissionId sub.submission_id + json.studentId sub.student_id + json.assessmentId sub.assessment_id + json.grade sub.grade&.to_f + end + @external_grades.each do |grade| + json.child! do + json.studentId grade.course_user.user_id + json.assessmentId(-grade.external_assessment_id) + json.grade grade.grade&.to_f + end + end end json.gamificationEnabled current_course.gamified? +json.userId current_user&.id diff --git a/client/app/api/course/Gradebook.ts b/client/app/api/course/Gradebook.ts index 7603f1f2a1..4fe79086b9 100644 --- a/client/app/api/course/Gradebook.ts +++ b/client/app/api/course/Gradebook.ts @@ -1,4 +1,8 @@ -import { GradebookData, UpdateWeightsPayload } from 'types/course/gradebook'; +import { + ExternalGradePayload, + GradebookData, + UpdateWeightsPayload, +} from 'types/course/gradebook'; import { APIResponse } from 'api/types'; @@ -18,4 +22,14 @@ export default class GradebookAPI extends BaseCourseAPI { ): APIResponse { return this.client.patch(`${this.#urlPrefix}/weights`, payload); } + + setExternalGrade( + id: number, + payload: { studentId: number; grade: number | null }, + ): APIResponse { + return this.client.put( + `${this.#urlPrefix}/external_assessments/${id}/grades`, + payload, + ); + } } diff --git a/client/app/bundles/course/gradebook/__tests__/buildAssessmentColumnIds.test.ts b/client/app/bundles/course/gradebook/__tests__/buildAssessmentColumnIds.test.ts new file mode 100644 index 0000000000..d231ce6559 --- /dev/null +++ b/client/app/bundles/course/gradebook/__tests__/buildAssessmentColumnIds.test.ts @@ -0,0 +1,31 @@ +import { + buildAssessmentColumnId, + parseAssessmentColumnId, +} from '../components/buildAssessmentColumnIds'; + +describe('assessment column ids', () => { + it('round-trips a positive (regular) assessment id', () => { + expect(parseAssessmentColumnId(buildAssessmentColumnId(100))).toBe(100); + }); + + it('round-trips a negative (external) assessment id', () => { + expect(parseAssessmentColumnId(buildAssessmentColumnId(-5))).toBe(-5); + }); + + it('returns null for a non-assessment column id', () => { + expect(parseAssessmentColumnId('name')).toBeNull(); + expect(parseAssessmentColumnId('totalXp')).toBeNull(); + }); + + it('round-trips a zero id (falsy but valid)', () => { + expect(parseAssessmentColumnId(buildAssessmentColumnId(0))).toBe(0); + }); + + it('returns null for a malformed or unanchored asn- column id', () => { + expect(parseAssessmentColumnId('asn-')).toBeNull(); + expect(parseAssessmentColumnId('asn-abc')).toBeNull(); + expect(parseAssessmentColumnId('asn-1.5')).toBeNull(); + expect(parseAssessmentColumnId('asn-12x')).toBeNull(); + expect(parseAssessmentColumnId('xasn-12')).toBeNull(); + }); +}); diff --git a/client/app/bundles/course/gradebook/__tests__/store.test.ts b/client/app/bundles/course/gradebook/__tests__/store.test.ts index 97143ade93..d56d6d1ff3 100644 --- a/client/app/bundles/course/gradebook/__tests__/store.test.ts +++ b/client/app/bundles/course/gradebook/__tests__/store.test.ts @@ -151,3 +151,55 @@ describe('UPDATE_TAB_WEIGHTS reducer', () => { ); }); }); + +describe('external assessment reducers', () => { + const state = { + categories: [{ id: 1, title: 'Cat A' }], + tabs: [{ id: 10, title: 'Tab 1', categoryId: 1 }], + assessments: [{ id: 100, title: 'Quiz 1', tabId: 10, maxGrade: 10 }], + students: [], + submissions: [{ studentId: 1, assessmentId: 100, grade: 8 }], + gamificationEnabled: false, + userId: 0, + weightedViewEnabled: false, + canManageWeights: true, + }; + + it('setExternalGrade upserts a submission row by (studentId, assessmentId)', () => { + const inserted = reducer( + state, + actions.setExternalGrade({ studentId: 1, assessmentId: -5, grade: 42 }), + ); + expect( + inserted.submissions.find( + (s) => s.studentId === 1 && s.assessmentId === -5, + )?.grade, + ).toBe(42); + + const updated = reducer( + inserted, + actions.setExternalGrade({ studentId: 1, assessmentId: -5, grade: 17 }), + ); + expect( + updated.submissions.filter( + (s) => s.studentId === 1 && s.assessmentId === -5, + ), + ).toHaveLength(1); + expect( + updated.submissions.find( + (s) => s.studentId === 1 && s.assessmentId === -5, + )?.grade, + ).toBe(17); + }); + + it('setExternalGrade can clear a grade to null', () => { + const next = reducer( + state, + actions.setExternalGrade({ studentId: 1, assessmentId: -5, grade: null }), + ); + expect( + next.submissions.find((s) => s.studentId === 1 && s.assessmentId === -5) + ?.grade, + ).toBeNull(); + }); +}); diff --git a/client/app/bundles/course/gradebook/components/GradebookTable.tsx b/client/app/bundles/course/gradebook/components/GradebookTable.tsx index eac4f66507..3060a783bc 100644 --- a/client/app/bundles/course/gradebook/components/GradebookTable.tsx +++ b/client/app/bundles/course/gradebook/components/GradebookTable.tsx @@ -9,6 +9,7 @@ import { import { defineMessages } from 'react-intl'; import { Checkbox, + Chip, Paper, type SxProps, Table, @@ -18,6 +19,7 @@ import { TableHead, TableRow, TableSortLabel, + TextField, type Theme, Tooltip, } from '@mui/material'; @@ -36,10 +38,13 @@ import { DEFAULT_TABLE_ROWS_PER_PAGE, } from 'lib/constants/sharedConstants'; import { getEditSubmissionURL } from 'lib/helpers/url-builders'; +import { useAppDispatch } from 'lib/hooks/store'; +import toast from 'lib/hooks/toast'; import useTranslation from 'lib/hooks/useTranslation'; import tableTranslations from 'lib/translations/table'; import { GAMIFICATION_COL_IDS } from '../constants'; +import { setExternalGrade } from '../operations'; import type { AssessmentData, CategoryData, @@ -110,6 +115,18 @@ const translations = defineMessages({ defaultMessage: 'No grade or gamification columns selected - export will include student info only.', }, + externalBadge: { + id: 'course.gradebook.GradebookTable.externalBadge', + defaultMessage: 'External', + }, + externalGradeAria: { + id: 'course.gradebook.GradebookTable.externalGradeAria', + defaultMessage: '{title} grade for {name}', + }, + gradeSaveError: { + id: 'course.gradebook.GradebookTable.gradeSaveError', + defaultMessage: 'Could not save the grade. Please try again.', + }, }); const HeaderLabel = forwardRef< @@ -177,6 +194,82 @@ const HeaderLabel = forwardRef< }); HeaderLabel.displayName = 'HeaderLabel'; +const ExternalGradeCell = ({ + assessmentId, + studentId, + studentName, + title, + value, +}: { + assessmentId: number; + studentId: number; + studentName: string; + title: string; + value: number | null | undefined; +}): JSX.Element => { + const { t } = useTranslation(); + const dispatch = useAppDispatch(); + const [editing, setEditing] = useState(false); + const [text, setText] = useState(''); + const [localValue, setLocalValue] = useState( + value, + ); + + const commit = async (): Promise => { + setEditing(false); + const trimmed = text.trim(); + const next = trimmed === '' ? null : Number(trimmed); + if (trimmed !== '' && Number.isNaN(next)) return; + if (next === (localValue ?? null)) return; + const prev = localValue; + setLocalValue(next); + try { + await dispatch(setExternalGrade(assessmentId, studentId, next)); + } catch { + setLocalValue(prev); + toast.error(t(translations.gradeSaveError)); + } + }; + + if (editing) { + return ( + setText(e.target.value)} + onKeyDown={(e) => { + if (e.key === 'Enter') commit(); + if (e.key === 'Escape') setEditing(false); + }} + size="small" + value={text} + variant="standard" + /> + ); + } + + return ( + { + setText(localValue == null ? '' : String(localValue)); + setEditing(true); + }} + role="button" + style={{ cursor: 'pointer', display: 'inline-block', minWidth: 24 }} + tabIndex={0} + > + {localValue == null ? '—' : localValue} + + ); +}; + interface GradebookRow { studentId: number; name: string; @@ -212,14 +305,14 @@ const GradebookTable = ({ const { t } = useTranslation(); const submissionsByStudent = useMemo(() => { - const map = new Map>(); + const map = new Map(); submissions.forEach((s) => { - let byAssessment = map.get(s.studentId); - if (!byAssessment) { - byAssessment = new Map(); - map.set(s.studentId, byAssessment); + const existing = map.get(s.studentId); + if (existing) { + existing.push(s); + } else { + map.set(s.studentId, [s]); } - byAssessment.set(s.assessmentId, s); }); return map; }, [submissions]); @@ -227,11 +320,11 @@ const GradebookTable = ({ const rows = useMemo( () => students.map((student) => { - const subs = submissionsByStudent.get(student.id); + const subs = submissionsByStudent.get(student.id) ?? []; const grades: Partial> = {}; const submissionIds: Partial> = {}; assessments.forEach((a) => { - const sub = subs?.get(a.id); + const sub = subs.find((s) => s.assessmentId === a.id); if (sub != null) { grades[a.id] = sub.grade; submissionIds[a.id] = sub.submissionId; @@ -329,6 +422,17 @@ const GradebookTable = ({ }, }, cell: (row) => { + if (asn.external) { + return ( + + ); + } const grade = row.grades[asn.id]; if (grade === undefined) return '—'; if (grade === null) return ''; @@ -597,6 +701,11 @@ const GradebookTable = ({ const isLeft = isLeftAligned(id); const fits = headerFits[id] ?? false; const sort = sortByColId.get(id); + const asnId = parseAssessmentColumnId(id); + const isExternalCol = + asnId !== null && + assessments.find((a) => a.id === asnId)?.external === + true; const labelNode = ( @@ -607,6 +716,17 @@ const GradebookTable = ({ ); + const sortedLabel = sort ? ( + + {labelNode} + + ) : ( + labelNode + ); return ( - {sort ? ( - - {labelNode} - + {sortedLabel} + + ) : ( - labelNode + sortedLabel )} ); @@ -675,11 +801,11 @@ const GradebookTable = ({ {visibleCols.map((c) => { const id = c.id ?? (c.of as string); const asnId = parseAssessmentColumnId(id); - let cellContent: string = ''; - if (id === 'name') cellContent = t(translations.maxMarks); + let cellNode: React.ReactNode = ''; + if (id === 'name') cellNode = t(translations.maxMarks); else if (asnId !== null) { const maxGrade = assessmentMaxGrades.get(asnId); - cellContent = maxGrade != null ? `/${maxGrade}` : ''; + cellNode = maxGrade != null ? `/${maxGrade}` : ''; } return ( - {cellContent} + {cellNode} ); })} diff --git a/client/app/bundles/course/gradebook/components/buildAssessmentColumnIds.ts b/client/app/bundles/course/gradebook/components/buildAssessmentColumnIds.ts index d12a4bd26a..13f84cf48a 100644 --- a/client/app/bundles/course/gradebook/components/buildAssessmentColumnIds.ts +++ b/client/app/bundles/course/gradebook/components/buildAssessmentColumnIds.ts @@ -2,6 +2,6 @@ export const buildAssessmentColumnId = (asnId: number): string => `asn-${asnId}`; export const parseAssessmentColumnId = (colId: string): number | null => { - const match = colId.match(/^asn-(\d+)$/); + const match = colId.match(/^asn-(-?\d+)$/); return match ? Number(match[1]) : null; }; diff --git a/client/app/bundles/course/gradebook/computeWeighted.ts b/client/app/bundles/course/gradebook/computeWeighted.ts index d4bb0424f7..e8f90afb6d 100644 --- a/client/app/bundles/course/gradebook/computeWeighted.ts +++ b/client/app/bundles/course/gradebook/computeWeighted.ts @@ -40,6 +40,19 @@ type GradeLookup = Map; const gradeKey = (studentId: number, assessmentId: number): string => `${studentId}:${assessmentId}`; +// Per-assessment grade bounding (external assessments only). Applied at READ time +// so the toggles stay reversible and the stored grade is never mutated. Native +// assessments leave both flags undefined → passthrough (unchanged behaviour). +export const effectiveGrade = ( + grade: number, + a: Pick, +): number => { + let g = grade; + if (a.floorAtZero && g < 0) g = 0; + if (a.capAtMaximum && g > a.maxGrade) g = a.maxGrade; + return g; +}; + // Index submissions by (student, assessment) once: O(submissions). const buildGradeLookup = (submissions: GradeEntry[]): GradeLookup => { const lookup: GradeLookup = new Map(); @@ -75,7 +88,7 @@ const equalSubtotal = ( if (included.length === 0) return null; const ratios = included.map((a) => { const grade = gradeLookup.get(gradeKey(studentId, a.id)); - return grade != null ? grade / a.maxGrade : 0; + return grade != null ? effectiveGrade(grade, a) / a.maxGrade : 0; }); return ratios.reduce((acc, r) => acc + r, 0) / ratios.length; }; @@ -97,7 +110,8 @@ const customSubtotal = ( if (a.gradebookExcluded) return; const grade = gradeLookup.get(gradeKey(studentId, a.id)); const assessmentWeight = a.gradebookWeight ?? 0; - if (grade != null) numerator += (grade / a.maxGrade) * assessmentWeight; + if (grade != null) + numerator += (effectiveGrade(grade, a) / a.maxGrade) * assessmentWeight; hasContributing = true; }); return hasContributing ? numerator / tabWeight : null; @@ -194,7 +208,7 @@ export const computeStudentBreakdown = ({ const contributions = list.map((a) => { const excluded = !!a.gradebookExcluded; const grade = gradeLookup.get(gradeKey(studentId, a.id)) ?? null; - const ratio = grade != null ? grade / a.maxGrade : 0; + const ratio = grade != null ? effectiveGrade(grade, a) / a.maxGrade : 0; let points: number; let effectiveWeight: number; if (excluded) { diff --git a/client/app/bundles/course/gradebook/operations.ts b/client/app/bundles/course/gradebook/operations.ts index ae2f962fbb..d47b3aa43e 100644 --- a/client/app/bundles/course/gradebook/operations.ts +++ b/client/app/bundles/course/gradebook/operations.ts @@ -17,4 +17,31 @@ export const updateGradebookWeights = dispatch(actions.updateTabWeights(response.data)); }; +// Optimistic: apply the new grade immediately, then reconcile with the server. +// On failure, restore the previous value and rethrow so the caller can toast. +export const setExternalGrade = + (assessmentId: number, studentId: number, grade: number | null): Operation => + async (dispatch, getState) => { + const prev = + getState().gradebook.submissions.find( + (s) => s.studentId === studentId && s.assessmentId === assessmentId, + )?.grade ?? null; + dispatch(actions.setExternalGrade({ studentId, assessmentId, grade })); + try { + const response = await CourseAPI.gradebook.setExternalGrade( + -assessmentId, + { + studentId, + grade, + }, + ); + dispatch(actions.setExternalGrade(response.data)); + } catch (error) { + dispatch( + actions.setExternalGrade({ studentId, assessmentId, grade: prev }), + ); + throw error; + } + }; + export default fetchGradebook; diff --git a/client/app/bundles/course/gradebook/selectors.ts b/client/app/bundles/course/gradebook/selectors.ts index 0fb7d1398d..2776f91211 100644 --- a/client/app/bundles/course/gradebook/selectors.ts +++ b/client/app/bundles/course/gradebook/selectors.ts @@ -26,3 +26,7 @@ export const getWeightedViewEnabled = (state: AppState): boolean => getLocalState(state).weightedViewEnabled; export const getCanManageWeights = (state: AppState): boolean => getLocalState(state).canManageWeights; +export const getExternalAssessments = ( + state: AppState, +): GradebookState['assessments'] => + getLocalState(state).assessments.filter((a) => a.external); diff --git a/client/app/bundles/course/gradebook/store.ts b/client/app/bundles/course/gradebook/store.ts index 4777e16b3b..75f9072a51 100644 --- a/client/app/bundles/course/gradebook/store.ts +++ b/client/app/bundles/course/gradebook/store.ts @@ -1,5 +1,6 @@ import { produce } from 'immer'; import type { + ExternalGradePayload, GradebookData, UpdateWeightsPayload, } from 'types/course/gradebook'; @@ -14,6 +15,7 @@ import type { const SAVE_GRADEBOOK = 'course/gradebook/SAVE_GRADEBOOK'; const UPDATE_TAB_WEIGHTS = 'course/gradebook/UPDATE_TAB_WEIGHTS'; +const SET_EXTERNAL_GRADE = 'course/gradebook/SET_EXTERNAL_GRADE'; interface GradebookState { categories: CategoryData[]; @@ -36,6 +38,11 @@ interface UpdateTabWeightsAction { payload: UpdateWeightsPayload; } +interface SetExternalGradeAction { + type: typeof SET_EXTERNAL_GRADE; + payload: ExternalGradePayload; +} + const initialState: GradebookState = { categories: [], tabs: [], @@ -50,7 +57,10 @@ const initialState: GradebookState = { const reducer = produce( ( draft: GradebookState, - action: SaveGradebookAction | UpdateTabWeightsAction, + action: + | SaveGradebookAction + | UpdateTabWeightsAction + | SetExternalGradeAction, ) => { switch (action.type) { case SAVE_GRADEBOOK: { @@ -99,6 +109,15 @@ const reducer = produce( ); break; } + case SET_EXTERNAL_GRADE: { + const { studentId, assessmentId, grade } = action.payload; + const existing = draft.submissions.find( + (s) => s.studentId === studentId && s.assessmentId === assessmentId, + ); + if (existing) existing.grade = grade; + else draft.submissions.push({ studentId, assessmentId, grade }); + break; + } default: break; } @@ -117,6 +136,9 @@ export const actions = { type: UPDATE_TAB_WEIGHTS, payload, }), + setExternalGrade: ( + payload: ExternalGradePayload, + ): SetExternalGradeAction => ({ type: SET_EXTERNAL_GRADE, payload }), }; export default reducer; diff --git a/client/app/bundles/course/statistics/pages/StatisticsIndex/index.tsx b/client/app/bundles/course/statistics/pages/StatisticsIndex/index.tsx index d1dd39720a..c1e230f896 100644 --- a/client/app/bundles/course/statistics/pages/StatisticsIndex/index.tsx +++ b/client/app/bundles/course/statistics/pages/StatisticsIndex/index.tsx @@ -115,7 +115,10 @@ const StatisticsIndex: FC = () => { return ( - + { diff --git a/client/app/lib/components/table/TanStackTableBuilder/columnsBuilder.ts b/client/app/lib/components/table/TanStackTableBuilder/columnsBuilder.ts index 8ebb312766..2b1a825b0e 100644 --- a/client/app/lib/components/table/TanStackTableBuilder/columnsBuilder.ts +++ b/client/app/lib/components/table/TanStackTableBuilder/columnsBuilder.ts @@ -61,6 +61,9 @@ const buildTanStackColumns = ( column.sortProps!.sort!(rowA.original, rowB.original) : 'alphanumeric', sortUndefined: column.sortProps?.undefinedPriority ?? false, + ...(column.sortProps?.descFirst !== undefined && { + sortDescFirst: column.sortProps.descFirst, + }), filterFn: column.filterProps?.shouldInclude && Object.assign( diff --git a/client/app/lib/components/table/builder/ColumnTemplate.ts b/client/app/lib/components/table/builder/ColumnTemplate.ts index cbfe6132ac..265e16f7f8 100644 --- a/client/app/lib/components/table/builder/ColumnTemplate.ts +++ b/client/app/lib/components/table/builder/ColumnTemplate.ts @@ -17,6 +17,7 @@ interface SearchingProps { interface SortingProps { sort?: (datumA: D, datumB: D) => number; undefinedPriority?: false | 'first' | 'last'; + descFirst?: boolean; } interface ColumnTemplate { diff --git a/client/app/lib/components/table/utils.ts b/client/app/lib/components/table/utils.ts index 6b84e7a373..916dfdba69 100644 --- a/client/app/lib/components/table/utils.ts +++ b/client/app/lib/components/table/utils.ts @@ -2,10 +2,13 @@ import { downloadFile } from 'utilities/downloadFile'; const DEFAULT_CSV_FILENAME = 'data' as const; +// Prepend UTF-8 BOM so Excel on macOS/Windows detects UTF-8 encoding instead +// of falling back to a legacy code page (Mac Roman / Windows-1252), which +// misreads multibyte characters like em dash (U+2014) as mojibake (e.g. "‚Äî"). export const downloadCsv = (csvData: string, filename?: string): void => { downloadFile( 'text/csv;charset=utf-8', - csvData, + `\uFEFF${csvData}`, `${filename ?? DEFAULT_CSV_FILENAME}.csv`, ); }; diff --git a/client/app/types/course/gradebook.ts b/client/app/types/course/gradebook.ts index c9009afbfe..a87156279e 100644 --- a/client/app/types/course/gradebook.ts +++ b/client/app/types/course/gradebook.ts @@ -18,6 +18,9 @@ export interface AssessmentData { maxGrade: number; gradebookWeight?: number | null; gradebookExcluded?: boolean; + external?: boolean; + floorAtZero?: boolean; + capAtMaximum?: boolean; } export interface StudentData { @@ -32,7 +35,7 @@ export interface StudentData { export interface SubmissionData { studentId: number; assessmentId: number; - submissionId: number; + submissionId?: number; grade: number | null; } @@ -56,3 +59,9 @@ export interface UpdateWeightsPayload { assessmentWeights?: { assessmentId: number; weight: number }[]; }[]; } + +export interface ExternalGradePayload { + studentId: number; + assessmentId: number; + grade: number | null; +} diff --git a/client/locales/en.json b/client/locales/en.json index 1d9bf1cce6..e11d8ffd46 100644 --- a/client/locales/en.json +++ b/client/locales/en.json @@ -29,6 +29,9 @@ "app.DashboardPage.yourCourses": { "defaultMessage": "Your Courses" }, + "app.ErrorPage.courseSuspended": { + "defaultMessage": "This course is suspended." + }, "app.ErrorPage.error": { "defaultMessage": "KABOOM, a meteor has just crashed." }, @@ -59,14 +62,11 @@ "app.ErrorPage.notFoundSubtitle": { "defaultMessage": "Check if you've typed the correct address, try again later, or go back home." }, - "app.ErrorPage.userSuspended": { - "defaultMessage": "Your access to this course has been suspended." - }, "app.ErrorPage.suspendedSubtitle": { "defaultMessage": "Please contact your instructors or the course staff." }, - "app.ErrorPage.courseSuspended": { - "defaultMessage": "This course is suspended." + "app.ErrorPage.userSuspended": { + "defaultMessage": "Your access to this course has been suspended." }, "app.Footer.contactUs": { "defaultMessage": "Contact Us" @@ -80,12 +80,12 @@ "app.Footer.instructorsGuide": { "defaultMessage": "Instructors' Guide" }, - "app.Footer.reportIssue": { - "defaultMessage": "Report an Issue" - }, "app.Footer.privacyPolicy": { "defaultMessage": "Privacy Policy" }, + "app.Footer.reportIssue": { + "defaultMessage": "Report an Issue" + }, "app.Footer.termsOfService": { "defaultMessage": "Terms of Service" }, @@ -263,23 +263,23 @@ "course.achievement.AchievementAward.AchievementAwardManager.saveChanges": { "defaultMessage": "Save Changes" }, + "course.achievement.AchievementAward.AchievementAwardSummary.awardedStudents": { + "defaultMessage": "Awarded Students" + }, "course.achievement.AchievementAward.AchievementAwardSummary.name": { "defaultMessage": "Name" }, - "course.achievement.AchievementAward.AchievementAwardSummary.userType": { - "defaultMessage": "User Type" + "course.achievement.AchievementAward.AchievementAwardSummary.normalStudent": { + "defaultMessage": "Normal Student" }, - "course.achievement.AchievementAward.AchievementAwardSummary.awardedStudents": { - "defaultMessage": "Awarded Students" + "course.achievement.AchievementAward.AchievementAwardSummary.phantomStudent": { + "defaultMessage": "Phantom Student" }, "course.achievement.AchievementAward.AchievementAwardSummary.revokedStudents": { "defaultMessage": "Revoked Students" }, - "course.achievement.AchievementAward.AchievementAwardSummary.phantomStudent": { - "defaultMessage": "Phantom Student" - }, - "course.achievement.AchievementAward.AchievementAwardSummary.normalStudent": { - "defaultMessage": "Normal Student" + "course.achievement.AchievementAward.AchievementAwardSummary.userType": { + "defaultMessage": "User Type" }, "course.achievement.AchievementAward.awardAchievement": { "defaultMessage": "Award Achievement" @@ -353,26 +353,26 @@ "course.achievement.AchievementShow.studentsWithAchievement": { "defaultMessage": "Students with this achievement" }, - "course.achievement.AchievementTable.noAchievement": { - "defaultMessage": "No achievement" + "course.achievement.AchievementTable.actions": { + "defaultMessage": "Actions" }, "course.achievement.AchievementTable.badge": { "defaultMessage": "Badge" }, - "course.achievement.AchievementTable.title": { - "defaultMessage": "Title" - }, "course.achievement.AchievementTable.description": { "defaultMessage": "Description" }, - "course.achievement.AchievementTable.requirements": { - "defaultMessage": "Requirements" + "course.achievement.AchievementTable.noAchievement": { + "defaultMessage": "No achievement" }, "course.achievement.AchievementTable.published": { "defaultMessage": "Published" }, - "course.achievement.AchievementTable.actions": { - "defaultMessage": "Actions" + "course.achievement.AchievementTable.requirements": { + "defaultMessage": "Requirements" + }, + "course.achievement.AchievementTable.title": { + "defaultMessage": "Title" }, "course.achievement.AchievementsIndex.achievements": { "defaultMessage": "Achievements" @@ -515,45 +515,6 @@ "course.admin.AssessmentSettings.toTab": { "defaultMessage": "to {tab}" }, - "course.admin.CodaveriSettings.codaveriModel": { - "defaultMessage": "Model" - }, - "course.admin.CodaveriSettings.codaveriModelDescription": { - "defaultMessage": "The AI model used by Codaveri to generate help conversations with students for programming questions." - }, - "course.admin.CodaveriSettings.codaveriSystemPromptDescription": { - "defaultMessage": "You may customize the behavior of the Codaveri model by providing instructions here. {br} When assisting students, these instructions will be followed in addition to any you have set on the question itself.{br}To reference question-specific details, you may use the following variables within the prompt, writing them with brackets as shown below:" - }, - "course.admin.CodaveriSettings.codaveriSystemPromptProblemDescriptionLine": { - "defaultMessage": "{problemDescriptionVar} : The full description of the coding problem." - }, - "course.admin.CodaveriSettings.codaveriSystemPromptStudentFilePathsLine": { - "defaultMessage": "{studentFilePathsVar} : A comma-separated list of file paths the student is working on." - }, - "course.admin.CodaveriSettings.codaveriSettings": { - "defaultMessage": "Codaveri settings" - }, - "course.admin.CodaveriSettings.codaveriSettingsSubtitle": { - "defaultMessage": "This is currently an experimental feature. Codaveri provides code evaluation and automated code feedback services for students' codes." - }, - "course.admin.CodaveriSettings.feedbackWorkflow": { - "defaultMessage": "Automatic Post-Submission Comments" - }, - "course.admin.CodaveriSettings.feedbackWorkflowDescription": { - "defaultMessage": "When a submission with programming question is finalised," - }, - "course.admin.CodaveriSettings.feedbackWorkflowNone": { - "defaultMessage": "Generate no feedback" - }, - "course.admin.CodaveriSettings.feedbackWorkflowDraft": { - "defaultMessage": "Generate feedback as a draft requiring approval from staff" - }, - "course.admin.CodaveriSettings.feedbackWorkflowPublish": { - "defaultMessage": "Publish feedback directly to student" - }, - "course.admin.CodaveriSettings.error": { - "defaultMessage": "An error occurred while updating the codaveri setting." - }, "course.admin.CodaveriSettings.Some": { "defaultMessage": "Some" }, @@ -569,32 +530,80 @@ "course.admin.CodaveriSettings.codaveriEngineDescription": { "defaultMessage": "Type of codaveri engine used to generate programming code feedback" }, + "course.admin.CodaveriSettings.codaveriEvaluatorSettings": { + "defaultMessage": "Codaveri Evaluator" + }, + "course.admin.CodaveriSettings.codaveriModel": { + "defaultMessage": "Model" + }, + "course.admin.CodaveriSettings.codaveriModelDescription": { + "defaultMessage": "The AI model used by Codaveri to generate help conversations with students for programming questions." + }, "course.admin.CodaveriSettings.codaveriOverrideSystemPrompt": { "defaultMessage": "Use a custom system prompt" }, "course.admin.CodaveriSettings.codaveriOverrideSystemPromptDescription": { "defaultMessage": "When assisting students, these instructions will be followed in addition to any you have set on the question itself. To reference question-specific details, you may use these variables within the prompt, writing them with brackets as shown below:" }, + "course.admin.CodaveriSettings.codaveriSettings": { + "defaultMessage": "Codaveri settings" + }, + "course.admin.CodaveriSettings.codaveriSettingsSubtitle": { + "defaultMessage": "This is currently an experimental feature. Codaveri provides code evaluation and automated code feedback services for students' codes." + }, "course.admin.CodaveriSettings.codaveriSystemPrompt": { "defaultMessage": "System Prompt" }, + "course.admin.CodaveriSettings.codaveriSystemPromptDescription": { + "defaultMessage": "The Codaveri system prompt controls AI behavior when interacting with students." + }, + "course.admin.CodaveriSettings.codaveriSystemPromptProblemDescriptionLine": { + "defaultMessage": "{problemDescriptionVar} : The full description of the coding problem." + }, + "course.admin.CodaveriSettings.codaveriSystemPromptStudentFilePathsLine": { + "defaultMessage": "{studentFilePathsVar} : A comma-separated list of file paths the student is working on." + }, "course.admin.CodaveriSettings.codaveriUseDefaultSystemPrompt": { "defaultMessage": "Use the default system prompt" }, + "course.admin.CodaveriSettings.enableDisableButton": { + "defaultMessage": "{enabled, select, true {Enable} other {Disable}}" + }, + "course.admin.CodaveriSettings.enableDisableEvaluator": { + "defaultMessage": "{enabled, select, true {Enable } other {Disable }} Codaveri Evaluator for {questionCount} programming questions in {title}?" + }, + "course.admin.CodaveriSettings.enableDisableEvaluatorDescription": { + "defaultMessage": "{questionCount} programming questions in this {type} will use {enabled, select, true {Codaveri } other {Default }} evaluator" + }, + "course.admin.CodaveriSettings.enableDisableLiveFeedback": { + "defaultMessage": "{enabled, select, true {Enable } other {Disable }} Get Help for {questionCount} programming questions in {title}?" + }, + "course.admin.CodaveriSettings.errorOccurredWhenUpdatingCodaveriEvaluatorSettings": { + "defaultMessage": "An error occurred while updating the codaveri evaluator settings." + }, + "course.admin.CodaveriSettings.errorOccurredWhenUpdatingLiveFeedbackSettings": { + "defaultMessage": "An error occurred while updating the Get Help settings." + }, "course.admin.CodaveriSettings.evaluatorUpdateSuccess": { "defaultMessage": "{question} is now using {evaluator} evaluator" }, "course.admin.CodaveriSettings.expandAll": { "defaultMessage": "Expand All Questions" }, - "course.admin.CodaveriSettings.programmingQuestionSettings": { - "defaultMessage": "Programming Question Settings" + "course.admin.CodaveriSettings.feedbackWorkflow": { + "defaultMessage": "Automatic Post-Submission Comments" }, - "course.admin.CodaveriSettings.programmingQuestionSettingsSubtitle": { - "defaultMessage": "Enable/disable Codaveri as evaluator for programming questions in various assessments." + "course.admin.CodaveriSettings.feedbackWorkflowDescription": { + "defaultMessage": "When a submission with programming question is finalised," }, - "course.admin.CodaveriSettings.succesfulUpdateAllEvaluator": { - "defaultMessage": "Successfully updated all questions to use {evaluator} evaluator" + "course.admin.CodaveriSettings.feedbackWorkflowDraft": { + "defaultMessage": "Generate feedback as a draft requiring approval from staff" + }, + "course.admin.CodaveriSettings.feedbackWorkflowNone": { + "defaultMessage": "Generate no feedback" + }, + "course.admin.CodaveriSettings.feedbackWorkflowPublish": { + "defaultMessage": "Publish feedback directly to student" }, "course.admin.CodaveriSettings.getHelpUsageLimit": { "defaultMessage": "Limit Get Help messages per student" @@ -602,35 +611,23 @@ "course.admin.CodaveriSettings.getHelpUsageLimitDescription": { "defaultMessage": "If enabled, students will only be able to send a limited number of messages per question. Students will be able to see this limit and how many messages they have left." }, - "course.admin.CodaveriSettings.maxGetHelpUserMessages": { - "defaultMessage": "Maximum messages per question" - }, - "course.admin.CodaveriSettings.errorOccurredWhenUpdatingCodaveriEvaluatorSettings": { - "defaultMessage": "An error occurred while updating the codaveri evaluator settings." - }, - "course.admin.CodaveriSettings.codaveriEvaluatorSettings": { - "defaultMessage": "Codaveri Evaluator" + "course.admin.CodaveriSettings.liveFeedbackEnabledUpdateSuccess": { + "defaultMessage": "Get Help for {question} is now {liveFeedbackEnabled, select, true {enabled} other {disabled}}" }, "course.admin.CodaveriSettings.liveFeedbackSettings": { "defaultMessage": "Get Help" }, - "course.admin.CodaveriSettings.errorOccurredWhenUpdatingLiveFeedbackSettings": { - "defaultMessage": "An error occurred while updating the Get Help settings." - }, - "course.admin.CodaveriSettings.enableDisableButton": { - "defaultMessage": "{enabled, select, true {Enable} other {Disable}}" - }, - "course.admin.CodaveriSettings.enableDisableEvaluator": { - "defaultMessage": "{enabled, select, true {Enable } other {Disable }} Codaveri Evaluator for {questionCount} programming questions in {title}?" + "course.admin.CodaveriSettings.maxGetHelpUserMessages": { + "defaultMessage": "Maximum messages per question" }, - "course.admin.CodaveriSettings.enableDisableLiveFeedback": { - "defaultMessage": "{enabled, select, true {Enable } other {Disable }} Get Help for {questionCount} programming questions in {title}?" + "course.admin.CodaveriSettings.programmingQuestionSettings": { + "defaultMessage": "Programming Question Settings" }, - "course.admin.CodaveriSettings.enableDisableEvaluatorDescription": { - "defaultMessage": "{questionCount} programming questions in this {type} will use {enabled, select, true {Codaveri } other {Default }} evaluator" + "course.admin.CodaveriSettings.programmingQuestionSettingsSubtitle": { + "defaultMessage": "Enable/disable Codaveri as evaluator for programming questions in various assessments." }, - "course.admin.CodaveriSettings.liveFeedbackEnabledUpdateSuccess": { - "defaultMessage": "Get Help for {question} is now {liveFeedbackEnabled, select, true {enabled} other {disabled}}" + "course.admin.CodaveriSettings.succesfulUpdateAllEvaluator": { + "defaultMessage": "Successfully updated all questions to use {evaluator} evaluator" }, "course.admin.CodaveriSettings.successfulUpdateAllLiveFeedbackEnabled": { "defaultMessage": "Successfully {liveFeedbackEnabled, select, true {enabled} other {disabled}} Get Help for all questions" @@ -647,9 +644,15 @@ "course.admin.ComponentSettings.errorOccurredWhenUpdatingComponents": { "defaultMessage": "An error occurred while updating the component settings." }, + "course.admin.ComponentSettings.settingUpComponent": { + "defaultMessage": "Setting up component for this course" + }, "course.admin.CourseSettings.allowUsersToSendEnrolmentRequests": { "defaultMessage": "Allow users to send enrolment requests" }, + "course.admin.CourseSettings.autoApproveEnrolmentRequests": { + "defaultMessage": "Automatically approve enrolment requests" + }, "course.admin.CourseSettings.clearChanges": { "defaultMessage": "Clear changes" }, @@ -677,6 +680,12 @@ "course.admin.CourseSettings.courseSettings": { "defaultMessage": "Course settings" }, + "course.admin.CourseSettings.courseSuspensionMessage": { + "defaultMessage": "Course suspension message" + }, + "course.admin.CourseSettings.courseSuspensionMessageDescription": { + "defaultMessage": "This message will be shown to users while this course is suspended. Leave blank to show a default message." + }, "course.admin.CourseSettings.daysInAdvance": { "defaultMessage": "Days in advance" }, @@ -764,23 +773,14 @@ "course.admin.CourseSettings.stragglersDescription": { "defaultMessage": "Leave no one behind; subsequent closing reference timings will be pushed back if students complete their assessments late." }, - "course.admin.CourseSettings.suspension": { - "defaultMessage": "Access suspension" - }, "course.admin.CourseSettings.suspendCourse": { "defaultMessage": "Suspend course" }, "course.admin.CourseSettings.suspendCourseDescription": { "defaultMessage": "A suspended course is inaccessible to all students. Instructors can still access the course and all student data will be retained." }, - "course.admin.CourseSettings.unsuspendCourse": { - "defaultMessage": "Unsuspend course" - }, - "course.admin.CourseSettings.courseSuspensionMessage": { - "defaultMessage": "Course suspension message" - }, - "course.admin.CourseSettings.courseSuspensionMessageDescription": { - "defaultMessage": "This message will be shown to users while this course is suspended. Leave blank to show a default message." + "course.admin.CourseSettings.suspendCourseFailure": { + "defaultMessage": "An error occurred while suspending this course." }, "course.admin.CourseSettings.suspendCoursePromptText": { "defaultMessage": "Are you sure you want to suspend this course? All students will not be able to access it until it is unsuspended." @@ -788,20 +788,8 @@ "course.admin.CourseSettings.suspendCourseSuccess": { "defaultMessage": "This course has been suspended." }, - "course.admin.CourseSettings.suspendCourseFailure": { - "defaultMessage": "An error occurred while suspending this course." - }, - "course.admin.CourseSettings.unsuspendCourseSuccess": { - "defaultMessage": "This course has been unsuspended." - }, - "course.admin.CourseSettings.unsuspendCourseFailure": { - "defaultMessage": "An error occurred while unsuspending this course." - }, - "course.admin.CourseSettings.userSuspensionMessage": { - "defaultMessage": "User suspension message" - }, - "course.admin.CourseSettings.userSuspensionMessageDescription": { - "defaultMessage": "This message will be shown to individual users whose access to this course has been suspended. Leave blank to show a default message." + "course.admin.CourseSettings.suspension": { + "defaultMessage": "Access suspension" }, "course.admin.CourseSettings.timeSettings": { "defaultMessage": "Time settings" @@ -812,12 +800,27 @@ "course.admin.CourseSettings.titleRequired": { "defaultMessage": "Course name is required." }, + "course.admin.CourseSettings.unsuspendCourse": { + "defaultMessage": "Unsuspend course" + }, + "course.admin.CourseSettings.unsuspendCourseFailure": { + "defaultMessage": "An error occurred while unsuspending this course." + }, + "course.admin.CourseSettings.unsuspendCourseSuccess": { + "defaultMessage": "This course has been unsuspended." + }, "course.admin.CourseSettings.uploadANewImage": { "defaultMessage": "Choose a new image" }, "course.admin.CourseSettings.uploadingLogo": { "defaultMessage": "Uploading your new logo..." }, + "course.admin.CourseSettings.userSuspensionMessage": { + "defaultMessage": "User suspension message" + }, + "course.admin.CourseSettings.userSuspensionMessageDescription": { + "defaultMessage": "This message will be shown to individual users whose access to this course has been suspended. Leave blank to show a default message." + }, "course.admin.CourseSettingst.confirmDeletePlaceholder": { "defaultMessage": "This is your last chance to go back!" }, @@ -872,6 +875,15 @@ "course.admin.ForumsSettings.markPostAsAnswerSetting": { "defaultMessage": "User who can mark a post as answer" }, + "course.admin.GradebookSettings.gradebookSettings": { + "defaultMessage": "Gradebook settings" + }, + "course.admin.GradebookSettings.weightedViewEnabled": { + "defaultMessage": "Enable weighted grade view" + }, + "course.admin.GradebookSettings.weightedViewEnabledHint": { + "defaultMessage": "Enables a \"Weighted total\" view in the gradebook where staff can configure per-tab weights and see a weighted Total column." + }, "course.admin.LeaderboardSettings.displayUserCount": { "defaultMessage": "Display user count" }, @@ -924,7 +936,10 @@ "defaultMessage": "Component Item Settings" }, "course.admin.LessonPlanSettings.lessonPlanItemSettings": { - "defaultMessage": "Lesson Plan Item Settings" + "defaultMessage": "Item Settings" + }, + "course.admin.LessonPlanSettings.lessonPlanSettings": { + "defaultMessage": "Lesson Plan Settings" }, "course.admin.LessonPlanSettings.noLessonPlanItems": { "defaultMessage": "There are no lesson plan items to configure for lesson plan display." @@ -941,11 +956,14 @@ "course.admin.MaterialSettings.materialsSettings": { "defaultMessage": "Materials settings" }, + "course.admin.NotificationSettings.component": { + "defaultMessage": "Component" + }, "course.admin.NotificationSettings.description": { "defaultMessage": "Description" }, "course.admin.NotificationSettings.emailSettings": { - "defaultMessage": "Email Settings" + "defaultMessage": "Email settings" }, "course.admin.NotificationSettings.noEmailSettings": { "defaultMessage": "None of the enabled components have email settings." @@ -1058,23 +1076,143 @@ "course.admin.NotificationSettings.updateSuccess": { "defaultMessage": "The email setting \"{setting}\" for {user} users has been {action}." }, - "course.admin.SidebarSettings.errorOccurredWhenUpdatingSidebar": { - "defaultMessage": "An error occurred while updating the sidebar ordering." + "course.admin.RagWiseSettings.ForumKnowledgeBaseSwitch.addFailure": { + "defaultMessage": "{forum} could not be added to knowledge base." }, - "course.admin.SidebarSettings.sidebarSettings": { - "defaultMessage": "Student's sidebar ordering" + "course.admin.RagWiseSettings.ForumKnowledgeBaseSwitch.addSuccess": { + "defaultMessage": "{forum} {n, plural, one {has} other {have}} been added to knowledge base." }, - "course.admin.SidebarSettings.sidebarSettingsSubtitle": { - "defaultMessage": "Drag and drop the sidebar items to rearrange." + "course.admin.RagWiseSettings.ForumKnowledgeBaseSwitch.pendingImport": { + "defaultMessage": "Please wait as your request to import forums into knowledge base is being processed. You may close this window while importing is in progress." }, - "course.admin.SidebarSettings.sidebarSettingsUpdated": { - "defaultMessage": "The new sidebar ordering has been applied. Refresh to see the latest changes." + "course.admin.RagWiseSettings.ForumKnowledgeBaseSwitch.removeFailure": { + "defaultMessage": "{forum} could not be removed from knowledge base." }, - "course.admin.VideosSettings.addATab": { - "defaultMessage": "Add a tab" + "course.admin.RagWiseSettings.ForumKnowledgeBaseSwitch.removeSuccess": { + "defaultMessage": "{forum} {n, plural, one {has} other {have}} been removed from knowledge base." }, - "course.admin.VideosSettings.deleteTabPromptAction": { - "defaultMessage": "Delete {title} tab" + "course.admin.RagWiseSettings.KnowledgeBaseSwitch.addFailure": { + "defaultMessage": "{material} could not be added to knowledge base." + }, + "course.admin.RagWiseSettings.KnowledgeBaseSwitch.addSuccess": { + "defaultMessage": "{material} {n, plural, one {has} other {have}} been added to knowledge base." + }, + "course.admin.RagWiseSettings.KnowledgeBaseSwitch.pendingAdd": { + "defaultMessage": "Please wait as your request to add materials into knowledge base is being processed. You may close this window while adding is in progress." + }, + "course.admin.RagWiseSettings.KnowledgeBaseSwitch.removeFailure": { + "defaultMessage": "{material} could not be removed from knowledge base." + }, + "course.admin.RagWiseSettings.KnowledgeBaseSwitch.removeSuccess": { + "defaultMessage": "{material} {n, plural, one {has} other {have}} been removed from knowledge base." + }, + "course.admin.RagWiseSettings.expandAll": { + "defaultMessage": "Expand all {object}" + }, + "course.admin.RagWiseSettings.forumSectionSubtitle": { + "defaultMessage": "Manage the inclusion or exclusion of forum data from related courses in the knowledge base, allowing users to control its availability to the LLM for generating responses." + }, + "course.admin.RagWiseSettings.forumSectionTitle": { + "defaultMessage": "No related courses found." + }, + "course.admin.RagWiseSettings.knowledgeBaseStatusSettings": { + "defaultMessage": "Knowledge Base" + }, + "course.admin.RagWiseSettings.materialsSectionSubtitle": { + "defaultMessage": "Add/remove pdf/docx/ipynb/txt files in knowledge base, allowing users to control its availability to the LLM for generating responses." + }, + "course.admin.RagWiseSettings.materialsSectionTitle": { + "defaultMessage": "Materials" + }, + "course.admin.RagWiseSettings.ragWiseSettings": { + "defaultMessage": "RagWise settings" + }, + "course.admin.RagWiseSettings.ragWiseSettingsSubtitle": { + "defaultMessage": "This is currently an experimental feature. RagWise uses Retrieval-Augmented Generation to generate contextually aware responses to student's query on forum." + }, + "course.admin.RagWiseSettings.responseWorkflowAuto": { + "defaultMessage": "Automatically respond" + }, + "course.admin.RagWiseSettings.responseWorkflowDescription": { + "defaultMessage": "When students post a question on forum," + }, + "course.admin.RagWiseSettings.responseWorkflowDraft": { + "defaultMessage": "Always draft" + }, + "course.admin.RagWiseSettings.responseWorkflowDraftDescription": { + "defaultMessage": "Generated response will be drafted." + }, + "course.admin.RagWiseSettings.responseWorkflowHighTrust": { + "defaultMessage": "High trust" + }, + "course.admin.RagWiseSettings.responseWorkflowLowTrust": { + "defaultMessage": "Low trust" + }, + "course.admin.RagWiseSettings.responseWorkflowLowTrustDescription": { + "defaultMessage": "Generated response will be conditionally published with {trust}% trust." + }, + "course.admin.RagWiseSettings.responseWorkflowNoAuto": { + "defaultMessage": "Do not automatically respond" + }, + "course.admin.RagWiseSettings.responseWorkflowPublish": { + "defaultMessage": "Always publish" + }, + "course.admin.RagWiseSettings.responseWorkflowPublishDescription": { + "defaultMessage": "Generated response will be immediately published." + }, + "course.admin.RagWiseSettings.responseWorkflowTitle": { + "defaultMessage": "Automatic Forum Response" + }, + "course.admin.RagWiseSettings.roleplayCharacter": { + "defaultMessage": "Specified Character Prompt" + }, + "course.admin.RagWiseSettings.roleplayCharacterLabel": { + "defaultMessage": "Character prompt (Max 200 Characters)" + }, + "course.admin.RagWiseSettings.roleplayDeadpool": { + "defaultMessage": "You must always impersonate Deadpool character in all your responses." + }, + "course.admin.RagWiseSettings.roleplayDeadpoolLabel": { + "defaultMessage": "Deadpool" + }, + "course.admin.RagWiseSettings.roleplayDescription": { + "defaultMessage": "Customise character prompt to change how LLM response" + }, + "course.admin.RagWiseSettings.roleplayNormal": { + "defaultMessage": "" + }, + "course.admin.RagWiseSettings.roleplayNormalLabel": { + "defaultMessage": "No roleplay" + }, + "course.admin.RagWiseSettings.roleplaySubtitle": { + "defaultMessage": "Character that LLM will roleplay as in responses." + }, + "course.admin.RagWiseSettings.roleplayTitle": { + "defaultMessage": "Response Roleplay" + }, + "course.admin.RagWiseSettings.roleplayYoda": { + "defaultMessage": "You must always impersonate Master Yoda character in all your responses." + }, + "course.admin.RagWiseSettings.roleplayYodaLabel": { + "defaultMessage": "Master Yoda" + }, + "course.admin.SidebarSettings.errorOccurredWhenUpdatingSidebar": { + "defaultMessage": "An error occurred while updating the sidebar ordering." + }, + "course.admin.SidebarSettings.sidebarSettings": { + "defaultMessage": "Student's sidebar ordering" + }, + "course.admin.SidebarSettings.sidebarSettingsSubtitle": { + "defaultMessage": "Drag and drop the sidebar items to rearrange." + }, + "course.admin.SidebarSettings.sidebarSettingsUpdated": { + "defaultMessage": "The new sidebar ordering has been applied. Refresh to see the latest changes." + }, + "course.admin.VideosSettings.addATab": { + "defaultMessage": "Add a tab" + }, + "course.admin.VideosSettings.deleteTabPromptAction": { + "defaultMessage": "Delete {title} tab" }, "course.admin.VideosSettings.deleteTabPromptMessage": { "defaultMessage": "Deleting this tab will delete all its associated videos and statistics. This action is irreversible." @@ -1121,6 +1259,51 @@ "course.admin.courseSettings": { "defaultMessage": "Course Settings" }, + "course.admin.storiesSettings.autoCreateAccounts": { + "defaultMessage": "User accounts and chat rooms on Cikgo will automatically be created if they don't yet exist. Information shared with Cikgo is governed by our Privacy Policy and Cikgo's Privacy Policy." + }, + "course.admin.storiesSettings.integrationHint": { + "defaultMessage": "To integrate your course on Cikgo with this course, enter its integration key here. Here's what's going to happen once this course is integrated with Cikgo." + }, + "course.admin.storiesSettings.integrationSettings": { + "defaultMessage": "Integration settings" + }, + "course.admin.storiesSettings.learnTitle": { + "defaultMessage": "Learn page title" + }, + "course.admin.storiesSettings.leaveEmptyToUseDefaultTitle": { + "defaultMessage": "Leave empty to use the default \"Learn\" title." + }, + "course.admin.storiesSettings.onlyOwnersCanManage": { + "defaultMessage": "Only you, Owners, and Managers can configure the integration of this course with Cikgo." + }, + "course.admin.storiesSettings.pingError": { + "defaultMessage": "There was a problem connecting to Cikgo. You may try again at a later time." + }, + "course.admin.storiesSettings.publishTaskCompletions": { + "defaultMessage": "Student's submission statuses will be reflected in their chat rooms in Cikgo." + }, + "course.admin.storiesSettings.pushKey": { + "defaultMessage": "Integration key" + }, + "course.admin.storiesSettings.pushKeyError": { + "defaultMessage": "This integration key doesn't point to a valid course on Cikgo. Please check your settings on Cikgo and try again." + }, + "course.admin.storiesSettings.pushKeyHint": { + "defaultMessage": "Integration keys aren't strictly secretive, but should be handled in confidence." + }, + "course.admin.storiesSettings.pushKeyPointsToCourse": { + "defaultMessage": "This integration key points to {course} on Cikgo." + }, + "course.admin.storiesSettings.redirects": { + "defaultMessage": "When students access this course's root URL, they'll be redirected to the Learn page. The home page is still accessible from the sidebar." + }, + "course.admin.storiesSettings.storiesSettings": { + "defaultMessage": "Stories settings" + }, + "course.admin.storiesSettings.syncs": { + "defaultMessage": "Published assessments, videos, and surveys in this course will be available in and kept in sync with Cikgo as resources." + }, "course.announcement.AnnouncementsDisplay.searchBarPlaceholder": { "defaultMessage": "Search by title or content" }, @@ -1232,6 +1415,12 @@ "course.assessment.AssessmentForm.blockStudentViewingAfterSubmittedHint": { "defaultMessage": "Students will only be able to view their submissions after their grades have been published." }, + "course.assessment.AssessmentForm.blocksAccessesFromInvalidSUS": { + "defaultMessage": "Block accesses from browsers with invalid UA" + }, + "course.assessment.AssessmentForm.blocksAccessesFromInvalidSUSHint": { + "defaultMessage": "If enabled, examinees using browsers with invalid UA (does not contain the specified SUS below) will be blocked from accessing this assessment. Instructors can override access with the session unlock password. Heartbeats from an overridden browser session will be flagged as valid in the PulseGrid." + }, "course.assessment.AssessmentForm.bonusEndAt": { "defaultMessage": "Bonus ends at" }, @@ -1244,9 +1433,6 @@ "course.assessment.AssessmentForm.delayedGradePublicationHint": { "defaultMessage": "If enabled, gradings will not be immediately shown to students. To publish all gradings, you may click Publish Grades in the Submissions page." }, - "course.assessment.AssessmentForm.canEnableCodaveriInComponents": { - "defaultMessage": "Contact the course manager or owner to enable this feature in Components in the Course Settings." - }, "course.assessment.AssessmentForm.description": { "defaultMessage": "Description" }, @@ -1301,12 +1487,24 @@ "course.assessment.AssessmentForm.hasPersonalTimesHint": { "defaultMessage": "Timings for this item will be automatically adjusted for users based on learning rate." }, + "course.assessment.AssessmentForm.hasTimeLimit": { + "defaultMessage": "Automatically submit when timer ends" + }, + "course.assessment.AssessmentForm.hasTimeLimitHint": { + "defaultMessage": "When enabled, each submission will have its own timer and will automatically be finalised when its timer ends." + }, "course.assessment.AssessmentForm.hasToBeMoreThanMinInterval": { "defaultMessage": "Has to be greater than the minimum value." }, "course.assessment.AssessmentForm.hasToBeMoreThanValueMs": { "defaultMessage": "Has to be at least 3000 ms." }, + "course.assessment.AssessmentForm.hasToBeNumber": { + "defaultMessage": "Has to be valid number." + }, + "course.assessment.AssessmentForm.hasToBePositive": { + "defaultMessage": "Has to be positive." + }, "course.assessment.AssessmentForm.hasToBePositiveInteger": { "defaultMessage": "Has to be a positive integer less than 86,400,000 ms" }, @@ -1319,6 +1517,12 @@ "course.assessment.AssessmentForm.intervalHint": { "defaultMessage": "Controls how frequent heartbeats are sent from the students' browsers. Intervals are randomised between these two ranges." }, + "course.assessment.AssessmentForm.koditsuDisabledInCourse": { + "defaultMessage": "Please contact the Course Administrator to enable Koditsu Exam in Course Settings." + }, + "course.assessment.AssessmentForm.liveFeedback": { + "defaultMessage": "Get Help" + }, "course.assessment.AssessmentForm.maxInterval": { "defaultMessage": "Max interval" }, @@ -1328,9 +1532,18 @@ "course.assessment.AssessmentForm.minInterval": { "defaultMessage": "Min interval" }, + "course.assessment.AssessmentForm.minutes": { + "defaultMessage": "minute(s)" + }, "course.assessment.AssessmentForm.modeSwitchingHint": { "defaultMessage": "You can no longer change the grading mode because there are already submissions for this assessment." }, + "course.assessment.AssessmentForm.needSUSAndSessionUnlockPassword": { + "defaultMessage": "You need to specify a SUS and session unlock password to enable this." + }, + "course.assessment.AssessmentForm.noProgrammingQuestion": { + "defaultMessage": "You need to add at least one programming question that can be supported by Codaveri to allow enabling Get Help for this Assessment" + }, "course.assessment.AssessmentForm.noTestCaseChosenError": { "defaultMessage": "Select at least one type of test case" }, @@ -1355,29 +1568,32 @@ "course.assessment.AssessmentForm.personalisedTimelines": { "defaultMessage": "Personalised timelines" }, + "course.assessment.AssessmentForm.proctorWithKoditsu": { + "defaultMessage": "Proctor Exam using Koditsu" + }, "course.assessment.AssessmentForm.published": { "defaultMessage": "Published" }, "course.assessment.AssessmentForm.publishedHint": { "defaultMessage": "Everyone can see this assessment." }, + "course.assessment.AssessmentForm.questionsIncompatibleWithKoditsu": { + "defaultMessage": "Please make sure that all questions in this assessment is compatible with Koditsu before activating proctoring in Koditsu" + }, "course.assessment.AssessmentForm.secret": { "defaultMessage": "Secret UA Substring (SUS)" }, "course.assessment.AssessmentForm.secretHint": { - "defaultMessage": "If provided, Coursemology can automatically flag a connection as valid in PulseGrid if the examinee's User Agent (UA) contains this secret. Otherwise, connections will be flagged only by heartbeat intervals." + "defaultMessage": "If provided, the PulseGrid automatically checks if the examinee's browser's User Agent (UA) contains this secret, and marks connections that do not as invalid. This string is case-sensitive." }, "course.assessment.AssessmentForm.sessionPassword": { "defaultMessage": "Session unlock password" }, - "course.assessment.AssessmentForm.sessionPasswordHint": { - "defaultMessage": "Ideally, do NOT give this password to students." - }, "course.assessment.AssessmentForm.sessionProtection": { "defaultMessage": "Enable session protection" }, "course.assessment.AssessmentForm.sessionProtectionHint": { - "defaultMessage": "If enabled, students can only access their attempt once. Further access will require the session unlock password." + "defaultMessage": "If enabled, students can only access their attempt once. Further access will require the session unlock password. Ideally, do NOT give this password to students." }, "course.assessment.AssessmentForm.showEvaluation": { "defaultMessage": "Show evaluation test cases" @@ -1391,12 +1607,12 @@ "course.assessment.AssessmentForm.showMcqMrqSolution": { "defaultMessage": "Show MCQ/MRQ solution(s)" }, - "course.assessment.AssessmentForm.showRubricToStudents": { - "defaultMessage": "Show rubric breakdown to students" - }, "course.assessment.AssessmentForm.showPrivate": { "defaultMessage": "Show private test cases" }, + "course.assessment.AssessmentForm.showRubricToStudents": { + "defaultMessage": "Show rubric breakdown to students" + }, "course.assessment.AssessmentForm.singlePage": { "defaultMessage": "Single Page" }, @@ -1421,9 +1637,15 @@ "course.assessment.AssessmentForm.timeBonusExp": { "defaultMessage": "Time Bonus EXP" }, + "course.assessment.AssessmentForm.timeLimit": { + "defaultMessage": "Time Limit" + }, "course.assessment.AssessmentForm.title": { "defaultMessage": "Title" }, + "course.assessment.AssessmentForm.toggleLiveFeedbackDescription": { + "defaultMessage": "Enable Get Help feature for all programming questions" + }, "course.assessment.AssessmentForm.unavailableInAutograded": { "defaultMessage": "Unavailable in autograded assessments." }, @@ -1454,12 +1676,6 @@ "course.assessment.AssessmentForm.visibility": { "defaultMessage": "Visibility" }, - "course.assessment.AssessmentForm.toggleLiveFeedbackDescription": { - "defaultMessage": "{enabled, select, true {Enable} other {Disable}} Get Help feature for all programming questions" - }, - "course.assessment.AssessmentForm.noProgrammingQuestion": { - "defaultMessage": "You need to add at least one programming question that can be supported by Codaveri to allow enabling Get Help for this Assessment" - }, "course.assessment.FileManager.addFiles": { "defaultMessage": "Add Files" }, @@ -1505,9 +1721,24 @@ "course.assessment.edit.update": { "defaultMessage": "Save" }, + "course.assessment.generation.allFieldsLocked": { + "defaultMessage": "All fields are locked, so nothing can be generated." + }, "course.assessment.generation.confirmDeleteConversation": { "defaultMessage": "Are you sure you want to delete \"{title}\" and all its history items? THIS ACTION IS IRREVERSIBLE!" }, + "course.assessment.generation.createMode": { + "defaultMessage": "Create New" + }, + "course.assessment.generation.createModeTooltip": { + "defaultMessage": "Generate fresh questions from scratch" + }, + "course.assessment.generation.enhanceMode": { + "defaultMessage": "Enhance" + }, + "course.assessment.generation.enhanceModeTooltip": { + "defaultMessage": "Build upon your current question" + }, "course.assessment.generation.exportAction": { "defaultMessage": "Export" }, @@ -1517,140 +1748,212 @@ "course.assessment.generation.exportError": { "defaultMessage": "An error occurred in exporting this question: {error}" }, - "course.assessment.generation.lockTooltip": { - "defaultMessage": "Lock to prevent changes to this section" - }, - "course.assessment.generation.newTab": { - "defaultMessage": "New" - }, - "course.assessment.generation.openExportDialog": { - "defaultMessage": "Export" + "course.assessment.generation.generateError": { + "defaultMessage": "An error occurred generating question \"{title}\"." }, - "course.assessment.generation.resetConversation": { - "defaultMessage": "Reset" + "course.assessment.generation.generateMcqPage": { + "defaultMessage": "Generate Multiple Choice Question" }, - "course.assessment.generation.unlockTooltip": { - "defaultMessage": "Unlock to continue editing this section" + "course.assessment.generation.generateMrqPage": { + "defaultMessage": "Generate Multiple Response Question" }, - "course.assessment.generation.mrq.numberOfQuestionsField": { - "defaultMessage": "Number of Questions" + "course.assessment.generation.generateMultipleSuccess": { + "defaultMessage": "Successfully generated {count} questions!" }, - "course.assessment.generation.promptPlaceholder": { - "defaultMessage": "Type something here..." + "course.assessment.generation.generatePage": { + "defaultMessage": "Generate Programming Question" }, "course.assessment.generation.generateQuestion": { "defaultMessage": "Generate" }, - "course.assessment.generation.showInactive": { - "defaultMessage": "Show inactive items" - }, - "course.assessment.generation.mrq.numberOfQuestionsRange": { - "defaultMessage": "Please enter a number from {min} to {max}" + "course.assessment.generation.generateSuccess": { + "defaultMessage": "Generation for \"{title}\" successful." }, - "course.assessment.generation.enhanceMode": { - "defaultMessage": "Enhance" + "course.assessment.generation.languageField": { + "defaultMessage": "Language" }, - "course.assessment.generation.createMode": { - "defaultMessage": "Create New" + "course.assessment.generation.loadingSourceError": { + "defaultMessage": "Unable to load source question data." }, - "course.assessment.generation.enhanceModeTooltip": { - "defaultMessage": "Build upon your current question" + "course.assessment.generation.lockTooltip": { + "defaultMessage": "Lock to prevent changes to this section" }, - "course.assessment.generation.createModeTooltip": { - "defaultMessage": "Generate fresh questions from scratch" + "course.assessment.generation.mrq.exportAction": { + "defaultMessage": "Export" }, "course.assessment.generation.mrq.exportDialogHeader": { "defaultMessage": "Export Questions ({exportCount} selected)" }, - "course.assessment.generation.requireNonEmptyOptionError": { - "defaultMessage": "Question must have at least one non-empty option" + "course.assessment.generation.mrq.numberOfQuestionsField": { + "defaultMessage": "Number of Questions" }, - "course.assessment.generation.untitledQuestion": { - "defaultMessage": "Untitled Question" + "course.assessment.generation.mrq.numberOfQuestionsRange": { + "defaultMessage": "Please enter a number from {min} to {max}" }, - "course.assessment.question.multipleResponses.showOptions": { - "defaultMessage": "Show Options" + "course.assessment.generation.newTab": { + "defaultMessage": "New" }, - "course.assessment.question.multipleResponses.hideOptions": { - "defaultMessage": "Hide Options" + "course.assessment.generation.openExportDialog": { + "defaultMessage": "Export" }, - "course.assessment.question.multipleResponses.noOptions": { - "defaultMessage": "No options" + "course.assessment.generation.promptPlaceholder": { + "defaultMessage": "Type something here..." }, - "course.assessment.question.multipleResponses.title": { - "defaultMessage": "Title" + "course.assessment.generation.requireNonEmptyOptionError": { + "defaultMessage": "Question must have at least one non-empty option" }, - "course.assessment.generation.generateMrqPage": { - "defaultMessage": "Generate Multiple Response Question" + "course.assessment.generation.resetConversation": { + "defaultMessage": "Reset" }, - "course.assessment.generation.generateMcqPage": { - "defaultMessage": "Generate Multiple Choice Question" + "course.assessment.generation.showInactive": { + "defaultMessage": "Show inactive items" }, - "course.assessment.generation.generateMultipleSuccess": { - "defaultMessage": "Successfully generated {count} questions!" + "course.assessment.generation.sourceLanguageNotSupported": { + "defaultMessage": "Source question language not supported by the generation tool." }, - "course.assessment.generation.generateSuccess": { - "defaultMessage": "Generation for {title} successful." + "course.assessment.generation.unlockTooltip": { + "defaultMessage": "Unlock to continue editing this section" }, - "course.assessment.generation.generateError": { - "defaultMessage": "An error occurred generating question {title}." + "course.assessment.generation.untitledQuestion": { + "defaultMessage": "Untitled Question" }, - "course.assessment.generation.loadingSourceError": { - "defaultMessage": "Unable to load source question data." + "course.assessment.liveFeedback.comments": { + "defaultMessage": "Comments" }, - "course.assessment.generation.allFieldsLocked": { - "defaultMessage": "All fields are locked, so nothing can be generated." + "course.assessment.liveFeedback.lineHeader": { + "defaultMessage": "Line {lineNumber}" + }, + "course.assessment.liveFeedback.messageTimingTitle": { + "defaultMessage": "Generated at: {usedAt}" + }, + "course.assessment.liveFeedback.questionTitle": { + "defaultMessage": "Question {index}" + }, + "course.assessment.monitoring.accessGrantedForThisSessionOnly": { + "defaultMessage": "Access will be granted only for this browser session." }, "course.assessment.monitoring.alivePresenceHint": { "defaultMessage": "Last heartbeat was received in time." }, "course.assessment.monitoring.alivePresenceHintSUSMatches": { - "defaultMessage": "Last heartbeat was received in time and the SUS matches." + "defaultMessage": "Last heartbeat was received in time and came from an authorised browser, if browser authorisation is enabled." }, "course.assessment.monitoring.blankField": { "defaultMessage": "(blank)" }, + "course.assessment.monitoring.blocksAccessesFromInvalidSUS": { + "defaultMessage": "Block accesses from unauthorised browsers" + }, + "course.assessment.monitoring.blocksAccessesFromInvalidSUSHint": { + "defaultMessage": "If enabled, examinees using unauthorised browsers can't access this assessment. Instructors can override access with the session unlock password. Heartbeats from overridden browser sessions will always be valid (green) in the PulseGrid." + }, + "course.assessment.monitoring.browserAuthorizationMethod": { + "defaultMessage": "Browser authorisation method" + }, + "course.assessment.monitoring.browserAuthorizationMethodHint": { + "defaultMessage": "Choose how sessions are authorised as valid or invalid. Changes apply to all sessions and heartbeats immediately and updates live in PulseGrid." + }, "course.assessment.monitoring.cannotConnectToLiveMonitoringChannel": { "defaultMessage": "Oops, an error occurred when connecting to the live monitoring channel." }, "course.assessment.monitoring.connected": { "defaultMessage": "Connected" }, - "course.assessment.monitoring.connectedToLiveMonitoringChannel": { - "defaultMessage": "Connected to the live monitoring channel" + "course.assessment.monitoring.connecting": { + "defaultMessage": "Connecting" + }, + "course.assessment.monitoring.deltaFromPreviousHeartbeat": { + "defaultMessage": "{ms} ms from previous heartbeat" }, "course.assessment.monitoring.detailsOfNHeartbeats": { - "defaultMessage": "Details of the last {n} heartbeats" + "defaultMessage": "Last {n} heartbeats" }, "course.assessment.monitoring.disconnected": { "defaultMessage": "Disconnected" }, - "course.assessment.monitoring.disconnectedFromLiveMonitoringChannel": { - "defaultMessage": "Disconnected from the live monitoring channel" + "course.assessment.monitoring.enableBrowserAuthorization": { + "defaultMessage": "Authorise browsers that access this assessment" + }, + "course.assessment.monitoring.enableBrowserAuthorizationHint": { + "defaultMessage": "If enabled, PulseGrid will additionally check if an examinee is accessing this assessment from an authorised browser, based on the authorisation method you choose." + }, + "course.assessment.monitoring.examMonitoring": { + "defaultMessage": "Enable exam monitoring" + }, + "course.assessment.monitoring.examMonitoringHint": { + "defaultMessage": "If enabled, examinees' sessions will be monitored in real time from when they attempt the exam until they finalise it or the first 24 hours since their attempt, whichever is earlier. Instructors can monitor these sessions in PulseGrid." + }, + "course.assessment.monitoring.expiredSession": { + "defaultMessage": "Expired session. It has been at least 24 hours since the submission was made." }, "course.assessment.monitoring.filterByGroup": { "defaultMessage": "Filter by Group" }, + "course.assessment.monitoring.firstReceivedHeartbeat": { + "defaultMessage": "First received heartbeat" + }, "course.assessment.monitoring.generatedAt": { "defaultMessage": "Generated at" }, + "course.assessment.monitoring.intervalHint": { + "defaultMessage": "Controls how frequent heartbeats are sent from the examinees' browsers. Intervals are randomised between these two ranges." + }, + "course.assessment.monitoring.invalidBrowser": { + "defaultMessage": "Invalid browser configuration" + }, + "course.assessment.monitoring.invalidBrowserSubtitle": { + "defaultMessage": "Access to this assessment is not allowed with your current browser and/or its configuration. Contact your instructor for assistance." + }, + "course.assessment.monitoring.invalidHeartbeat": { + "defaultMessage": "Invalid" + }, "course.assessment.monitoring.ipAddress": { "defaultMessage": "IP Address" }, - "course.assessment.monitoring.lastHeartbeat": { - "defaultMessage": "Last heartbeat" - }, "course.assessment.monitoring.latePresenceHint": { "defaultMessage": "Next heartbeat hasn't been received in time, but still within the configured inter-heartbeats interval." }, "course.assessment.monitoring.live": { "defaultMessage": "Live" }, + "course.assessment.monitoring.liveHint": { + "defaultMessage": "This heartbeat was immediately received by the server." + }, + "course.assessment.monitoring.liveness": { + "defaultMessage": "Liveness" + }, + "course.assessment.monitoring.loadAllHeartbeats": { + "defaultMessage": "Load all" + }, + "course.assessment.monitoring.maxInterval": { + "defaultMessage": "Max interval" + }, + "course.assessment.monitoring.milliseconds": { + "defaultMessage": "ms" + }, + "course.assessment.monitoring.minInterval": { + "defaultMessage": "Min interval" + }, "course.assessment.monitoring.missingPresenceHint": { - "defaultMessage": "Next heartbeat hasn't been received in time." + "defaultMessage": "Next heartbeat hasn't been received in time, or the last heartbeat came from an unauthorised browser, if browser authorisation is enabled." + }, + "course.assessment.monitoring.needSUSAndSessionUnlockPassword": { + "defaultMessage": "You must enable browser authorisation and set a session unlock password to enable this." }, "course.assessment.monitoring.noActiveSessions": { - "defaultMessage": "No active sessions." + "defaultMessage": "No active sessions. No attempts have been made." + }, + "course.assessment.monitoring.offset": { + "defaultMessage": "Inter-heartbeat offset" + }, + "course.assessment.monitoring.offsetHint": { + "defaultMessage": "Controls how long PulseGrid should wait after the frequency interval before flagging a session as late." + }, + "course.assessment.monitoring.openSubmissionInNewTab": { + "defaultMessage": "Open submission in new tab" + }, + "course.assessment.monitoring.overrideAccess": { + "defaultMessage": "Override access" }, "course.assessment.monitoring.pulsegrid": { "defaultMessage": "PulseGrid" @@ -1661,27 +1964,120 @@ "course.assessment.monitoring.recentActivitiesHint": { "defaultMessage": "These logs will disappear if you close this tab!" }, - "course.assessment.monitoring.stale": { - "defaultMessage": "Stale" + "course.assessment.monitoring.resetZoom": { + "defaultMessage": "Reset zoom" }, - "course.assessment.monitoring.summaryCorrectAsAt": { - "defaultMessage": "Summary correct as at {time}" + "course.assessment.monitoring.sebConfigKey": { + "defaultMessage": "Safe Exam Browser (SEB) Config Key" }, - "course.assessment.monitoring.type": { - "defaultMessage": "Type" + "course.assessment.monitoring.sebConfigKeyFieldHint": { + "defaultMessage": "Your SEB Config Key, not the Browser Exam Key, is generated from your specific SEB configuration. It stays the same across operating systems and SEB versions. Ensure this field is updated if you change your SEB configuration." }, - "course.assessment.monitoring.userAgent": { - "defaultMessage": "User Agent" + "course.assessment.monitoring.sebConfigKeyFieldLabel": { + "defaultMessage": "SEB Config Key" }, - "course.assessment.monitoring.userHeartbeatContinuedStreaming": { + "course.assessment.monitoring.sebConfigKeyHint": { + "defaultMessage": "Flags a session as valid if the examinee is using Safe Exam Browser (SEB) with a valid configuration. SEB generates a unique Config Key for a specific configuration. This method requires SEB 3.4 for Windows and SEB 3.0 for iOS and macOS, or later." + }, + "course.assessment.monitoring.sebPayload": { + "defaultMessage": "Safe Exam Browser (SEB) Config Key Hash & URL" + }, + "course.assessment.monitoring.secret": { + "defaultMessage": "Secret UA Substring (SUS)" + }, + "course.assessment.monitoring.secretHint": { + "defaultMessage": "If an examinee's browser's User Agent (UA) contains this case-sensitive secret, PulseGrid will flag that session as valid, and invalid otherwise. If you leave this blank, all sessions will be flagged as valid." + }, + "course.assessment.monitoring.sessionUnlockPassword": { + "defaultMessage": "Session unlock password" + }, + "course.assessment.monitoring.stale": { + "defaultMessage": "Stale" + }, + "course.assessment.monitoring.staleHint": { + "defaultMessage": "This heartbeat wasn't immediately received by the server because the examinee's browser was temporarily unreachable. It was cached in the browser, and sent to the server when the browser was reachable again." + }, + "course.assessment.monitoring.stoppedSession": { + "defaultMessage": "Stopped session. Student may have finalised their submission." + }, + "course.assessment.monitoring.summaryCorrectAsAt": { + "defaultMessage": "Summary correct as at {time}" + }, + "course.assessment.monitoring.type": { + "defaultMessage": "Type" + }, + "course.assessment.monitoring.userAgent": { + "defaultMessage": "User Agent (UA)" + }, + "course.assessment.monitoring.userAgentHint": { + "defaultMessage": "Flags a session as valid if the examinee's browser's User Agent (UA) contains a secret substring." + }, + "course.assessment.monitoring.userHeartbeatContinuedStreaming": { "defaultMessage": "{name}'s heartbeat just continued streaming." }, "course.assessment.monitoring.userHeartbeatNotReceivedInTime": { "defaultMessage": "{name}'s heartbeat wasn't received in time." }, + "course.assessment.monitoring.validHeartbeat": { + "defaultMessage": "Valid" + }, + "course.assessment.monitoring.zoomPanHint": { + "defaultMessage": "Pinch or scroll to zoom. Drag to pan." + }, "course.assessment.newAssessment": { "defaultMessage": "New Assessment" }, + "course.assessment.plagiarism.actions": { + "defaultMessage": "Actions" + }, + "course.assessment.plagiarism.baseSubmission": { + "defaultMessage": "Base Submission" + }, + "course.assessment.plagiarism.cannotManageSubmission": { + "defaultMessage": "You do not have permission to manage this submission." + }, + "course.assessment.plagiarism.comparedSubmission": { + "defaultMessage": "Compared Submission" + }, + "course.assessment.plagiarism.confirmStartMessage": { + "defaultMessage": "Running a new plagiarism check will remove the previous results." + }, + "course.assessment.plagiarism.confirmStartTitle": { + "defaultMessage": "Confirm Plagiarism Check?" + }, + "course.assessment.plagiarism.downloadPdf": { + "defaultMessage": "Download PDF" + }, + "course.assessment.plagiarism.lastRunTime": { + "defaultMessage": "Last run at: {date}" + }, + "course.assessment.plagiarism.notStarted": { + "defaultMessage": "No plagiarism check has been run" + }, + "course.assessment.plagiarism.plagiarism": { + "defaultMessage": "Plagiarism Results" + }, + "course.assessment.plagiarism.results": { + "defaultMessage": "Plagiarism Results (similarity between submissions)" + }, + "course.assessment.plagiarism.searchByStudentName": { + "defaultMessage": "Search by Student Name" + }, + "course.assessment.plagiarism.showSelfPlagiarism": { + "defaultMessage": "Include self-plagiarism comparisons (same student, different courses)" + }, + "course.assessment.plagiarism.similarityScore": { + "defaultMessage": "Similarity Score" + }, + "course.assessment.plagiarism.start": { + "defaultMessage": "New Plagiarism Check" + }, + "course.assessment.plagiarism.status": { + "defaultMessage": "Plagiarism Check Status" + }, + "course.assessment.plagiarism.viewReport": { + "defaultMessage": "View Report" + }, "course.assessment.question.forumPostResponses.enableTextResponse": { "defaultMessage": "Include a text field for students to provide further inputs" }, @@ -1754,6 +2150,9 @@ "course.assessment.question.multipleResponses.grading": { "defaultMessage": "Grading" }, + "course.assessment.question.multipleResponses.hideOptions": { + "defaultMessage": "Hide Options" + }, "course.assessment.question.multipleResponses.ignoresRandomization": { "defaultMessage": "Ignores randomization" }, @@ -1766,18 +2165,39 @@ "course.assessment.question.multipleResponses.maximumGrade": { "defaultMessage": "Maximum grade" }, + "course.assessment.question.multipleResponses.mustBeLessThanMaxAttachmentSize": { + "defaultMessage": "Must be at most {defaultMax}MB." + }, + "course.assessment.question.multipleResponses.mustBeLessThanMaxAttachments": { + "defaultMessage": "Must be at most {defaultMax}." + }, "course.assessment.question.multipleResponses.mustBeLessThanMaxMaximumGrade": { "defaultMessage": "Must be less than 1000." }, + "course.assessment.question.multipleResponses.mustHaveAtLeastOneResponse": { + "defaultMessage": "You must specify at least one response." + }, "course.assessment.question.multipleResponses.mustSpecifyAtLeastOneCorrectChoice": { "defaultMessage": "You must specify at least one correct choice." }, "course.assessment.question.multipleResponses.mustSpecifyChoice": { "defaultMessage": "You must specify a valid choice title." }, + "course.assessment.question.multipleResponses.mustSpecifyMaxAttachment": { + "defaultMessage": "You must specify a valid, positive maximum attachment number." + }, + "course.assessment.question.multipleResponses.mustSpecifyMaxAttachmentSize": { + "defaultMessage": "You must specify a valid, positive maximum attachment size." + }, "course.assessment.question.multipleResponses.mustSpecifyMaximumGrade": { "defaultMessage": "You must specify a valid, non-negative maximum grade to award." }, + "course.assessment.question.multipleResponses.mustSpecifyPositiveMaxAttachment": { + "defaultMessage": "Max Number of Attachments has to be at least 2." + }, + "course.assessment.question.multipleResponses.mustSpecifyPositiveMaxAttachmentSize": { + "defaultMessage": "Max Size has to be positive." + }, "course.assessment.question.multipleResponses.mustSpecifyPositiveMaximumGrade": { "defaultMessage": "Maximum grade has to be non-negative." }, @@ -1790,6 +2210,9 @@ "course.assessment.question.multipleResponses.newResponseCannotUndo": { "defaultMessage": "This is a new response. It will immediately disappear if you delete before saving it." }, + "course.assessment.question.multipleResponses.noOptions": { + "defaultMessage": "No options" + }, "course.assessment.question.multipleResponses.noSkillsCanCreateSkills": { "defaultMessage": "There are no skills in this course yet. You can create new skills at the Skills page." }, @@ -1826,6 +2249,9 @@ "course.assessment.question.multipleResponses.saveChangesFirstBeforeConvertingMcqMrq": { "defaultMessage": "Please save your changes before attempting to convert this question." }, + "course.assessment.question.multipleResponses.showOptions": { + "defaultMessage": "Show Options" + }, "course.assessment.question.multipleResponses.skills": { "defaultMessage": "Skills" }, @@ -1838,6 +2264,9 @@ "course.assessment.question.multipleResponses.staffOnlyCommentsHint": { "defaultMessage": "Useful for internal notes or documentations. Students will never see this." }, + "course.assessment.question.multipleResponses.title": { + "defaultMessage": "Title" + }, "course.assessment.question.multipleResponses.undoDeleteChoice": { "defaultMessage": "Undo delete choice" }, @@ -1892,6 +2321,9 @@ "course.assessment.question.programming.codaveriEvaluatorHint": { "defaultMessage": "On top of the default evaluation, this evaluator will provide automated code feedback powered by Codaveri when the submission is finalised. They will appear as draft comments for the instructors to review, edit, and publish." }, + "course.assessment.question.programming.codaveriEvaluatorNotSupported": { + "defaultMessage": "{languageName} is not supported by the Codaveri evaluator." + }, "course.assessment.question.programming.codeInserts": { "defaultMessage": "Code inserts" }, @@ -1913,15 +2345,18 @@ "course.assessment.question.programming.defaultEvaluator": { "defaultMessage": "Default" }, - "course.assessment.question.programming.defaultEvaluatorDependencyTitle": { - "defaultMessage": "{name}: Installed Dependencies" - }, "course.assessment.question.programming.defaultEvaluatorDependencyDescription": { "defaultMessage": "Submitted code is run in a containerized environment with the following dependencies installed locally.{br}If your programming question requires a dependency not listed below, contact us and we will consider adding it." }, + "course.assessment.question.programming.defaultEvaluatorDependencyTitle": { + "defaultMessage": "{name}: Installed Dependencies" + }, "course.assessment.question.programming.defaultEvaluatorHint": { "defaultMessage": "No fuss; just run the code according to the evaluation package below and report the test results." }, + "course.assessment.question.programming.defaultEvaluatorNotSupported": { + "defaultMessage": "{languageName} is not supported by the default evaluator." + }, "course.assessment.question.programming.dependencySearchText": { "defaultMessage": "Search dependencies by name" }, @@ -1953,7 +2388,7 @@ "defaultMessage": "Hold tight, evaluating all submissions with the new package..." }, "course.assessment.question.programming.evaluationLimits": { - "defaultMessage": "Evaluationlimits" + "defaultMessage": "Evaluation limits" }, "course.assessment.question.programming.evaluationTestCases": { "defaultMessage": "Evaluation test cases" @@ -1970,6 +2405,9 @@ "course.assessment.question.programming.expected": { "defaultMessage": "Expected" }, + "course.assessment.question.programming.expectedOutput": { + "defaultMessage": "Expected Output" + }, "course.assessment.question.programming.expression": { "defaultMessage": "Expression" }, @@ -2000,6 +2438,9 @@ "course.assessment.question.programming.inlineCode": { "defaultMessage": "Inline code" }, + "course.assessment.question.programming.input": { + "defaultMessage": "Input" + }, "course.assessment.question.programming.javaTestCasesHint": { "defaultMessage": "Expressions will be evaluated in the context of the submitted code. Their return values will be compared against the Expected expectations using the expectEquals(expression, expected) void. Its simplified definition is as follows, where Object has been overloaded for all Java primitives." }, @@ -2015,6 +2456,9 @@ "course.assessment.question.programming.languageAndEvaluation": { "defaultMessage": "Language and evaluation" }, + "course.assessment.question.programming.languageDeprecatedWarning": { + "defaultMessage": "Your selected language is deprecated. Please change it to another language." + }, "course.assessment.question.programming.lastUpdated": { "defaultMessage": "Last updated by {by} on {on}." }, @@ -2024,6 +2468,9 @@ "course.assessment.question.programming.liveFeedbackCustomPromptDescription": { "defaultMessage": "Add instructions to guide the generation of Get Help feedback here. If unsure, just leave this blank." }, + "course.assessment.question.programming.liveFeedbackNotSupported": { + "defaultMessage": "Get Help is not supported for {languageName}." + }, "course.assessment.question.programming.lowestGradingPriority": { "defaultMessage": "Lowest grading priority" }, @@ -2051,24 +2498,24 @@ "course.assessment.question.programming.packageCreationModeHint": { "defaultMessage": "You cannot change this mode once this question is successfully created. Choose wisely!" }, - "course.assessment.question.programming.packageImportSuccess": { - "defaultMessage": "The package was successfully imported." + "course.assessment.question.programming.packageImportEvaluationError": { + "defaultMessage": "An error occurred evaluating your solution against its test cases. Please double-check them and try again." + }, + "course.assessment.question.programming.packageImportEvaluationTimeout": { + "defaultMessage": "No response was received from an evaluator within the required time. This may indicate all our evaluators are busy right now, please try again later." + }, + "course.assessment.question.programming.packageImportGenericError": { + "defaultMessage": "The package could not be imported: {error}" }, "course.assessment.question.programming.packageImportInvalidPackage": { "defaultMessage": "The package could not be imported: the uploaded package does not have a valid structure." }, - "course.assessment.question.programming.packageImportEvaluationTimeout": { - "defaultMessage": "No response was received from an evaluator within the required time. This may indicate all our evaluators are busy right now, please try again later." + "course.assessment.question.programming.packageImportSuccess": { + "defaultMessage": "The package was successfully imported." }, "course.assessment.question.programming.packageImportTimeLimitExceeded": { "defaultMessage": "The solution did not finish evaluating the test cases in the specified time limit." }, - "course.assessment.question.programming.packageImportEvaluationError": { - "defaultMessage": "An error occurred evaluating your solution against its test cases. Please double-check them and try again." - }, - "course.assessment.question.programming.packageImportGenericError": { - "defaultMessage": "The package could not be imported: {error}" - }, "course.assessment.question.programming.packageInfoOnline": { "defaultMessage": "Generated evaluation package" }, @@ -2129,6 +2576,9 @@ "course.assessment.question.programming.standardError": { "defaultMessage": "Standard error" }, + "course.assessment.question.programming.standardInputOutputTestCasesHint": { + "defaultMessage": "Each test case launches a separate {language} console environment and provides input via standard input. The environment will combine the Prepend, student submission, and Append scripts into a single program and run it. The standard output of the program will be compared (as a string) to the expected output of the test case. We recommend handling input parsing and function calls in one of these scripts." + }, "course.assessment.question.programming.standardOutput": { "defaultMessage": "Standard output" }, @@ -2156,6 +2606,9 @@ "course.assessment.question.programming.timeLimit": { "defaultMessage": "Time limit" }, + "course.assessment.question.programming.timeLimitDetail": { + "defaultMessage": "{timeLimit, plural, one {# minute} other {# minutes}}" + }, "course.assessment.question.programming.uploadNewPackage": { "defaultMessage": "Upload a new package" }, @@ -2171,164 +2624,242 @@ "course.assessment.question.programminquestion.questionSavedRedirecting": { "defaultMessage": "Question saved." }, - "course.assessment.question.scribing.ScribingQuestionForm.cannotBeBlankValidationError": { - "defaultMessage": "Cannot be blank." - }, - "course.assessment.question.scribing.ScribingQuestionForm.chooseFileButton": { - "defaultMessage": "Choose File", - "description": "Button for adding an image attachment." + "course.assessment.question.rubricBasedResponses.addNewCategory": { + "defaultMessage": "Add new category" }, - "course.assessment.question.scribing.ScribingQuestionForm.descriptionFieldLabel": { - "defaultMessage": "Description", - "description": "Label for the description input field." + "course.assessment.question.rubricBasedResponses.addNewLevel": { + "defaultMessage": "Add new grade" }, - "course.assessment.question.scribing.ScribingQuestionForm.fetchFailureMessage": { - "defaultMessage": "An error occurred, please try again." + "course.assessment.question.rubricBasedResponses.aiGrading": { + "defaultMessage": "AI Grading" }, - "course.assessment.question.scribing.ScribingQuestionForm.fileAttachmentRequired": { - "defaultMessage": "File attachment required." + "course.assessment.question.rubricBasedResponses.aiGradingCustomPrompt": { + "defaultMessage": "Custom Prompt" }, - "course.assessment.question.scribing.ScribingQuestionForm.fileUploaded": { - "defaultMessage": "File uploaded:" + "course.assessment.question.rubricBasedResponses.aiGradingCustomPromptDescription": { + "defaultMessage": "Add grading instructions (e.g. question context, model answer, feedback tone). Leave blank if unsure." }, - "course.assessment.question.scribing.ScribingQuestionForm.lessThanEqualZeroValidationError": { - "defaultMessage": "Value must be greater than 0." + "course.assessment.question.rubricBasedResponses.aiGradingModelAnswer": { + "defaultMessage": "Model Answer" }, - "course.assessment.question.scribing.ScribingQuestionForm.maximumGradeFieldLabel": { - "defaultMessage": "Maximum Grade", - "description": "Label for the maximum grade input field." + "course.assessment.question.rubricBasedResponses.aiGradingModelAnswerDescription": { + "defaultMessage": "Add an example answer that would get the maximum grades in each rubric category. Leave blank if unsure." }, - "course.assessment.question.scribing.ScribingQuestionForm.noFileChosenMessage": { - "defaultMessage": "No file chosen", - "description": "Message to be displayed when no file is chosen for a file input." + "course.assessment.question.rubricBasedResponses.bonusReservedNames": { + "defaultMessage": "After finalization, a special category named 'Moderation' will be added automatically. It allows graders to award bonus or penalty points at their discretion." }, - "course.assessment.question.scribing.ScribingQuestionForm.positiveNumberValidationError": { - "defaultMessage": "Value must be positive." + "course.assessment.question.rubricBasedResponses.categoryGrade": { + "defaultMessage": "Grade" }, - "course.assessment.question.scribing.ScribingQuestionForm.resolveErrorsMessage": { - "defaultMessage": "This form has errors, please resolve before submitting." + "course.assessment.question.rubricBasedResponses.categoryGradeExplanation": { + "defaultMessage": "Explanation" }, - "course.assessment.question.scribing.ScribingQuestionForm.scribingQuestionWarning": { - "defaultMessage": "NOTE: Each page of a PDF file will be created as a single Scribing question with every question taking on the same question details. You can choose to leave the optional inputs blank and return to edit the questions again after creation." + "course.assessment.question.rubricBasedResponses.categoryMaximumGrade": { + "defaultMessage": "Max" }, - "course.assessment.question.scribing.ScribingQuestionForm.skillsFieldLabel": { - "defaultMessage": "Skills", - "description": "Label for the skills input field." + "course.assessment.question.rubricBasedResponses.categoryName": { + "defaultMessage": "Category Name" }, - "course.assessment.question.scribing.ScribingQuestionForm.staffOnlyCommentsFieldLabel": { - "defaultMessage": "Staff only comments", - "description": "Label for the staff only comments input field." + "course.assessment.question.rubricBasedResponses.enableAiGrading": { + "defaultMessage": "Enable AI to auto-grade submissions" }, - "course.assessment.question.scribing.ScribingQuestionForm.submitButton": { - "defaultMessage": "Submit", - "description": "Button for submitting the form." + "course.assessment.question.rubricBasedResponses.enableAiGradingDescription": { + "defaultMessage": "AI will assign rubric scores and draft feedback for you to review and publish." }, - "course.assessment.question.scribing.ScribingQuestionForm.submitFailureMessage": { - "defaultMessage": "An error occurred, please try again." + "course.assessment.question.rubricBasedResponses.rubric": { + "defaultMessage": "Rubric" }, - "course.assessment.question.scribing.ScribingQuestionForm.submittingMessage": { - "defaultMessage": "Submitting...", - "description": "Text to be displayed when waiting for server response after form submission." + "course.assessment.question.rubricBasedResponses.rubricHint": { + "defaultMessage": "Rubric is used to grade the student's submission." }, - "course.assessment.question.scribing.ScribingQuestionForm.titleFieldLabel": { - "defaultMessage": "Title", - "description": "Label for the title input field." + "course.assessment.question.rubricPlayground.addAnswersPromptAction": { + "defaultMessage": "Add" }, - "course.assessment.question.scribing.ScribingQuestionForm.valueMoreThan1000Error": { - "defaultMessage": "Value must be less than 1000." + "course.assessment.question.rubricPlayground.addAnswersTitle": { + "defaultMessage": "Add Sample Answers" }, - "course.assessment.question.textResponses.addSolution": { - "defaultMessage": "Add a new solution" + "course.assessment.question.rubricPlayground.addExistingAnswers": { + "defaultMessage": "Add existing answers" }, - "course.assessment.question.textResponses.allowFileUpload": { - "defaultMessage": "Allow file upload in the answer" + "course.assessment.question.rubricPlayground.addRandomStudentAnswers": { + "defaultMessage": "Add {inputComponent} random student answer(s)" }, - "course.assessment.question.textResponses.deleteSolution": { - "defaultMessage": "Delete solution" + "course.assessment.question.rubricPlayground.addSampleAnswers": { + "defaultMessage": "Add Sample Answers" }, - "course.assessment.question.textResponses.exactMatch": { - "defaultMessage": "Exact Match" + "course.assessment.question.rubricPlayground.answer": { + "defaultMessage": "Answer" }, - "course.assessment.question.textResponses.fileUploadNote": { - "defaultMessage": "Note: File upload question is not auto-gradable. The autograder will always award the maximum grade." + "course.assessment.question.rubricPlayground.apply": { + "defaultMessage": "Apply" }, - "course.assessment.question.textResponses.noSolutionsNote": { - "defaultMessage": "If no solutions are provided, the autograder will always award the maximum grade." + "course.assessment.question.rubricPlayground.applyFailure": { + "defaultMessage": "Failed to apply grading results" }, - "course.assessment.question.textResponses.atLeastOneSolutionNote": { - "defaultMessage": "If at least one solution is provided, students will only be able to input plain text." + "course.assessment.question.rubricPlayground.applySuccess": { + "defaultMessage": "Grading rubric, prompt, and results successfully applied." }, - "course.assessment.question.textResponses.exactMatchSolutionNote": { - "defaultMessage": "If Exact Match is selected, solutions with multiple lines must match student answers exactly for the answer to be graded as correct. If such a match is found, the autograder will award the specified grade without considering other solutions." + "course.assessment.question.rubricPlayground.applyWillGradeAllAnswers": { + "defaultMessage": "Applying this rubric will assign grades to all student answers, including the ones not yet evaluated on this page." }, - "course.assessment.question.textResponses.solutionGradesExceedMaximumGradeNote": { - "defaultMessage": "If the student answer satisfies multiple solutions, the autograder will award the sum of those solutions' grades, up to the question's maximum grade." + "course.assessment.question.rubricPlayground.applyingRubricGradingData": { + "defaultMessage": "Applying rubric grading data..." }, - "course.assessment.question.textResponses.grade": { - "defaultMessage": "Grade" + "course.assessment.question.rubricPlayground.categoryHeading": { + "defaultMessage": "C{index}" }, - "course.assessment.question.textResponses.keyword": { - "defaultMessage": "Keyword" + "course.assessment.question.rubricPlayground.compare": { + "defaultMessage": "Compare" }, - "course.assessment.question.textResponses.newSolutionCannotUndo": { - "defaultMessage": "This is a new solution. It will immediately disappear if you delete before saving it." + "course.assessment.question.rubricPlayground.comparingRevisions": { + "defaultMessage": "Comparing {count} revisions" }, - "course.assessment.question.textResponses.solution": { - "defaultMessage": "Solution" + "course.assessment.question.rubricPlayground.confirmAIGradingApplication": { + "defaultMessage": "Confirm AI Grading Application" }, - "course.assessment.question.textResponses.solutionType": { - "defaultMessage": "Type of Solution" + "course.assessment.question.rubricPlayground.confirmProceed": { + "defaultMessage": "Are you sure you wish to proceed?" }, - "course.assessment.question.textResponses.solutionWillBeDeleted": { - "defaultMessage": "This solution will be deleted once you save your changes." + "course.assessment.question.rubricPlayground.dismiss": { + "defaultMessage": "Dismiss" }, - "course.assessment.question.textResponses.solutions": { - "defaultMessage": "Solutions" + "course.assessment.question.rubricPlayground.evaluate": { + "defaultMessage": "Evaluate" }, - "course.assessment.question.textResponses.solutionsHint": { - "defaultMessage": "Adding solutions allows the answer to be autograded." + "course.assessment.question.rubricPlayground.evaluateAll": { + "defaultMessage": "Evaluate All ({count})" }, - "course.assessment.question.textResponses.undoDeleteSolution": { - "defaultMessage": "Undo delete solution" + "course.assessment.question.rubricPlayground.evaluateRemaining": { + "defaultMessage": "Evaluate Remaining ({count})" }, - "course.assessment.question.textResponses.zeroGrade": { - "defaultMessage": "0.0" + "course.assessment.question.rubricPlayground.evaluating": { + "defaultMessage": "Evaluating" }, - "course.assessment.question.textResponses.templateText": { - "defaultMessage": "Template" + "course.assessment.question.rubricPlayground.feedback": { + "defaultMessage": "Feedback" }, - "course.assessment.question.textResponses.templateTextDescription": { - "defaultMessage": "Text that appears in the answer area when students attempt this question for the first time." + "course.assessment.question.rubricPlayground.gradingCategories": { + "defaultMessage": "Grading Categories" }, - "course.assessment.question.textResponses.regex": { - "defaultMessage": "Regular Expression" + "course.assessment.question.rubricPlayground.gradingPrompt": { + "defaultMessage": "Grading Prompt" }, - "course.assessment.question.textResponses.invalidRegex": { - "defaultMessage": "Invalid regular expression" + "course.assessment.question.rubricPlayground.gradingPromptDescription": { + "defaultMessage": "Instructions to guide the AI in grading and giving feedback." }, - "course.assessment.question.textResponses.spreadsheetFormula": { - "defaultMessage": "Spreadsheet Formula" + "course.assessment.question.rubricPlayground.modelAnswer": { + "defaultMessage": "Model Answer" }, - "course.assessment.question.textResponses.testSpreadsheet": { - "defaultMessage": "Test spreadsheet" + "course.assessment.question.rubricPlayground.modelAnswerDescription": { + "defaultMessage": "An example that scores the maximum for each category." }, - "course.assessment.question.textResponses.testSpreadsheetDescription": { - "defaultMessage": "A test spreadsheet is required to auto grade the student answer." + "course.assessment.question.rubricPlayground.noAnswers": { + "defaultMessage": "No sample answers have been added. Add some to get started." }, - "course.assessment.question.textResponses.testSpreadsheetRequired": { - "defaultMessage": "Please upload a test spreadsheet file." + "course.assessment.question.rubricPlayground.notLatestRevisionWarning": { + "defaultMessage": "You have selected to apply a rubric which is not the latest revision saved on this page." }, - "course.assessment.question.textResponses.spreadsheetAdvancedOptions": { - "defaultMessage": "Advanced Options" + "course.assessment.question.rubricPlayground.questionGrade": { + "defaultMessage": "Grade" }, - "course.assessment.question.textResponses.spreadsheetRandomization": { - "defaultMessage": "Enable randomization" + "course.assessment.question.rubricPlayground.reevaluate": { + "defaultMessage": "Re-evaluate" }, - "course.assessment.question.textResponses.spreadsheetRandomizationDescription": { - "defaultMessage": "If enabled, some spreadsheet values will be randomly adjusted when autograding. This is useful to ensure the formula actually computes the right answer instead of a preset value." + "course.assessment.question.rubricPlayground.reevaluateAll": { + "defaultMessage": "Re-evaluate All ({count})" }, - "course.assessment.question.textResponses.numberOfRandomTests": { - "defaultMessage": "Number of random tests" + "course.assessment.question.rubricPlayground.rubricPlayground": { + "defaultMessage": "Rubric Playground" + }, + "course.assessment.question.rubricPlayground.sampleAnswerEvaluations": { + "defaultMessage": "Sample Answer Evaluations" + }, + "course.assessment.question.rubricPlayground.savedRubric": { + "defaultMessage": "Saved Rubric, {date}" + }, + "course.assessment.question.rubricPlayground.searchAnswersPlaceholder": { + "defaultMessage": "Search answers by student name or grade" + }, + "course.assessment.question.rubricPlayground.student": { + "defaultMessage": "Student" + }, + "course.assessment.question.rubricPlayground.totalGrade": { + "defaultMessage": "Total" + }, + "course.assessment.question.rubricPlayground.viewEditRubric": { + "defaultMessage": "View / Edit Rubric" + }, + "course.assessment.question.rubricPlayground.writeAnswerPlaceholder": { + "defaultMessage": "Write the answer here" + }, + "course.assessment.question.rubricPlayground.writeCustomAnswer": { + "defaultMessage": "Write a custom answer" + }, + "course.assessment.question.scribing.ScribingQuestionForm.cannotBeBlankValidationError": { + "defaultMessage": "Cannot be blank." + }, + "course.assessment.question.scribing.ScribingQuestionForm.chooseFileButton": { + "defaultMessage": "Choose File", + "description": "Button for adding an image attachment." + }, + "course.assessment.question.scribing.ScribingQuestionForm.descriptionFieldLabel": { + "defaultMessage": "Description", + "description": "Label for the description input field." + }, + "course.assessment.question.scribing.ScribingQuestionForm.fetchFailureMessage": { + "defaultMessage": "An error occurred, please try again." + }, + "course.assessment.question.scribing.ScribingQuestionForm.fileAttachmentRequired": { + "defaultMessage": "File attachment required." + }, + "course.assessment.question.scribing.ScribingQuestionForm.fileUploaded": { + "defaultMessage": "File uploaded:" + }, + "course.assessment.question.scribing.ScribingQuestionForm.lessThanEqualZeroValidationError": { + "defaultMessage": "Value must be greater than 0." + }, + "course.assessment.question.scribing.ScribingQuestionForm.maximumGradeFieldLabel": { + "defaultMessage": "Maximum Grade", + "description": "Label for the maximum grade input field." + }, + "course.assessment.question.scribing.ScribingQuestionForm.noFileChosenMessage": { + "defaultMessage": "No file chosen", + "description": "Message to be displayed when no file is chosen for a file input." + }, + "course.assessment.question.scribing.ScribingQuestionForm.positiveNumberValidationError": { + "defaultMessage": "Value must be positive." + }, + "course.assessment.question.scribing.ScribingQuestionForm.resolveErrorsMessage": { + "defaultMessage": "This form has errors, please resolve before submitting." + }, + "course.assessment.question.scribing.ScribingQuestionForm.scribingQuestionWarning": { + "defaultMessage": "NOTE: Each page of a PDF file will be created as a single Scribing question with every question taking on the same question details. You can choose to leave the optional inputs blank and return to edit the questions again after creation." + }, + "course.assessment.question.scribing.ScribingQuestionForm.skillsFieldLabel": { + "defaultMessage": "Skills", + "description": "Label for the skills input field." + }, + "course.assessment.question.scribing.ScribingQuestionForm.staffOnlyCommentsFieldLabel": { + "defaultMessage": "Staff only comments", + "description": "Label for the staff only comments input field." + }, + "course.assessment.question.scribing.ScribingQuestionForm.submitButton": { + "defaultMessage": "Submit", + "description": "Button for submitting the form." + }, + "course.assessment.question.scribing.ScribingQuestionForm.submitFailureMessage": { + "defaultMessage": "An error occurred, please try again." + }, + "course.assessment.question.scribing.ScribingQuestionForm.submittingMessage": { + "defaultMessage": "Submitting...", + "description": "Text to be displayed when waiting for server response after form submission." + }, + "course.assessment.question.scribing.ScribingQuestionForm.titleFieldLabel": { + "defaultMessage": "Title", + "description": "Label for the title input field." + }, + "course.assessment.question.scribing.ScribingQuestionForm.valueMoreThan1000Error": { + "defaultMessage": "Value must be less than 1000." }, "course.assessment.question.textResponses.SpreadsheetManager.fixedRandomSeed": { "defaultMessage": "Fixed random seed" @@ -2342,24 +2873,81 @@ "course.assessment.question.textResponses.SpreadsheetManager.fixedTimestampDescription": { "defaultMessage": "If checked, formulas that use the current date/time (NOW, TODAY, etc.) will use this specific date/time instead." }, - "course.assessment.question.textResponses.randomizationMode": { - "defaultMessage": "Autograding Value Configuration" + "course.assessment.question.textResponses.addSolution": { + "defaultMessage": "Add a new solution" }, - "course.assessment.question.textResponses.randomizationModeDescription": { - "defaultMessage": "Click on any cell to configure how its value should be replaced/randomized during autograding." + "course.assessment.question.textResponses.atLeastOneSolutionNote": { + "defaultMessage": "If at least one solution is provided, students will only be able to input plain text." }, - "course.assessment.question.textResponses.randomizationModeClearAll": { - "defaultMessage": "Clear All" + "course.assessment.question.textResponses.attachmentSettingRequired": { + "defaultMessage": "Attachment Setting should be defined in this question" }, - "course.assessment.question.textResponses.randomizationModeRestoreDefaults": { - "defaultMessage": "Restore Defaults" + "course.assessment.question.textResponses.attachmentSettings": { + "defaultMessage": "Attachment Settings" }, - "course.assessment.question.textResponses.randomizationModePopoverTitle": { - "defaultMessage": "During autograding..." + "course.assessment.question.textResponses.attachmentSettingsDescription": { + "defaultMessage": "When students are attempting this question," + }, + "course.assessment.question.textResponses.dateRandomizationMode": { + "defaultMessage": "Use random date value" + }, + "course.assessment.question.textResponses.deleteSolution": { + "defaultMessage": "Delete solution" + }, + "course.assessment.question.textResponses.exactMatch": { + "defaultMessage": "Exact Match" + }, + "course.assessment.question.textResponses.exactMatchSolutionNote": { + "defaultMessage": "If Exact Match is selected, solutions with multiple lines must match student answers exactly for the answer to be graded as correct. If such a match is found, the autograder will award the specified grade without considering other solutions." + }, + "course.assessment.question.textResponses.fileUploadNote": { + "defaultMessage": "Note: File upload question is not auto-gradable. The autograder will always award the maximum grade." + }, + "course.assessment.question.textResponses.grade": { + "defaultMessage": "Grade" + }, + "course.assessment.question.textResponses.invalidRegex": { + "defaultMessage": "Invalid regular expression" + }, + "course.assessment.question.textResponses.isAttachmentRequired": { + "defaultMessage": "Require file upload for this question" + }, + "course.assessment.question.textResponses.keyword": { + "defaultMessage": "Keyword" + }, + "course.assessment.question.textResponses.maxAttachmentSize": { + "defaultMessage": "Max Size per Attachment" + }, + "course.assessment.question.textResponses.maxAttachments": { + "defaultMessage": "Max Number of Attachments" + }, + "course.assessment.question.textResponses.multipleAttachments": { + "defaultMessage": "Multiple Attachments" + }, + "course.assessment.question.textResponses.multipleFileAttachmentDescription": { + "defaultMessage": "They can upload several attachments." + }, + "course.assessment.question.textResponses.newSolutionCannotUndo": { + "defaultMessage": "This is a new solution. It will immediately disappear if you delete before saving it." + }, + "course.assessment.question.textResponses.noAttachment": { + "defaultMessage": "No Attachment" + }, + "course.assessment.question.textResponses.noAttachmentDescription": { + "defaultMessage": "They will not be able to upload any attachment." }, "course.assessment.question.textResponses.noRandomizationMode": { "defaultMessage": "Keep original value" }, + "course.assessment.question.textResponses.noSolutionsNote": { + "defaultMessage": "If no solutions are provided, the autograder will always award the maximum grade." + }, + "course.assessment.question.textResponses.numberOfRandomTests": { + "defaultMessage": "Number of random tests" + }, + "course.assessment.question.textResponses.numericRandomizationMode": { + "defaultMessage": "Use random numeric value" + }, "course.assessment.question.textResponses.overrideRandomizationMode": { "defaultMessage": "Override with specified value" }, @@ -2369,17 +2957,20 @@ "course.assessment.question.textResponses.overrideValue": { "defaultMessage": "Value" }, - "course.assessment.question.textResponses.numericRandomizationMode": { - "defaultMessage": "Use random numeric value" + "course.assessment.question.textResponses.randomizationMode": { + "defaultMessage": "Autograding Value Configuration" }, - "course.assessment.question.textResponses.roundToInteger": { - "defaultMessage": "Round down to nearest integer" + "course.assessment.question.textResponses.randomizationModeClearAll": { + "defaultMessage": "Clear All" }, - "course.assessment.question.textResponses.stringRandomizationMode": { - "defaultMessage": "Randomize characters in value" + "course.assessment.question.textResponses.randomizationModeDescription": { + "defaultMessage": "Click on any cell to configure how its value should be replaced/randomized during autograding." }, - "course.assessment.question.textResponses.stringRandomizationModeDescription": { - "defaultMessage": "Each character class to be randomized may be replaced with different character(s) from the same class." + "course.assessment.question.textResponses.randomizationModePopoverTitle": { + "defaultMessage": "During autograding..." + }, + "course.assessment.question.textResponses.randomizationModeRestoreDefaults": { + "defaultMessage": "Restore Defaults" }, "course.assessment.question.textResponses.randomizeDigits": { "defaultMessage": "Randomize digits (0-9)" @@ -2387,152 +2978,86 @@ "course.assessment.question.textResponses.randomizeLetters": { "defaultMessage": "Randomize letters (a-z)" }, - "course.assessment.question.textResponses.dateRandomizationMode": { - "defaultMessage": "Use random date value" + "course.assessment.question.textResponses.regex": { + "defaultMessage": "Regular Expression" }, "course.assessment.question.textResponses.roundToDay": { "defaultMessage": "Round down to day start (00:00)" }, + "course.assessment.question.textResponses.roundToInteger": { + "defaultMessage": "Round down to nearest integer" + }, "course.assessment.question.textResponses.shuffleRandomizationMode": { "defaultMessage": "Shuffle value with other cells" }, "course.assessment.question.textResponses.shuffleRandomizationModeDescription": { "defaultMessage": "The values of each cell marked \"Shuffle\" will be randomly rearranged. The overall distribution remains the same, but each value may end up in a different cell." }, - "course.assessment.question.rubricPlayground.rubricPlayground": { - "defaultMessage": "Rubric Playground" - }, - "course.assessment.question.rubricPlayground.savedRubric": { - "defaultMessage": "Saved Rubric, {date}" + "course.assessment.question.textResponses.singleFileAttachment": { + "defaultMessage": "Single Attachment" }, - "course.assessment.question.rubricPlayground.viewEditRubric": { - "defaultMessage": "View / Edit Rubric" + "course.assessment.question.textResponses.singleFileAttachmentDescription": { + "defaultMessage": "They can only upload one attachment." }, - "course.assessment.question.rubricPlayground.evaluate": { - "defaultMessage": "Evaluate" + "course.assessment.question.textResponses.solution": { + "defaultMessage": "Solution" }, - "course.assessment.question.rubricPlayground.compare": { - "defaultMessage": "Compare" + "course.assessment.question.textResponses.solutionGradesExceedMaximumGradeNote": { + "defaultMessage": "If the student answer satisfies multiple solutions, the autograder will award the sum of those solutions' grades, up to the question's maximum grade." }, - "course.assessment.question.rubricPlayground.apply": { - "defaultMessage": "Apply" + "course.assessment.question.textResponses.solutionType": { + "defaultMessage": "Type of Solution" }, - "course.assessment.question.rubricPlayground.confirmAIGradingApplication": { - "defaultMessage": "Confirm AI Grading Application" + "course.assessment.question.textResponses.solutionWillBeDeleted": { + "defaultMessage": "This solution will be deleted once you save your changes." }, - "course.assessment.question.rubricPlayground.applyingRubricGradingData": { - "defaultMessage": "Applying rubric grading data..." + "course.assessment.question.textResponses.solutions": { + "defaultMessage": "Solutions" }, - "course.assessment.question.rubricPlayground.applySuccess": { - "defaultMessage": "Grading rubric, prompt, and results successfully applied." + "course.assessment.question.textResponses.solutionsHint": { + "defaultMessage": "Adding solutions allows the answer to be autograded." }, - "course.assessment.question.rubricPlayground.applyFailure": { - "defaultMessage": "Failed to apply grading results" + "course.assessment.question.textResponses.spreadsheetAdvancedOptions": { + "defaultMessage": "Advanced Options" }, - "course.assessment.question.rubricPlayground.notLatestRevisionWarning": { - "defaultMessage": "You have selected to apply a rubric which is not the latest revision saved on this page." - }, - "course.assessment.question.rubricPlayground.applyWillGradeAllAnswers": { - "defaultMessage": "Applying this rubric will assign grades to all student answers, including the ones not yet evaluated on this page." - }, - "course.assessment.question.rubricPlayground.confirmProceed": { - "defaultMessage": "Are you sure you wish to proceed?" - }, - "course.assessment.question.rubricPlayground.sampleAnswerEvaluations": { - "defaultMessage": "Sample Answer Evaluations" - }, - "course.assessment.question.rubricPlayground.addSampleAnswers": { - "defaultMessage": "Add Sample Answers" - }, - "course.assessment.question.rubricPlayground.evaluateAll": { - "defaultMessage": "Evaluate All ({count})" - }, - "course.assessment.question.rubricPlayground.reevaluateAll": { - "defaultMessage": "Re-evaluate All ({count})" - }, - "course.assessment.question.rubricPlayground.evaluateRemaining": { - "defaultMessage": "Evaluate Remaining ({count})" - }, - "course.assessment.question.rubricPlayground.comparingRevisions": { - "defaultMessage": "Comparing {count} revisions" - }, - "course.assessment.question.rubricPlayground.addSampleAnswersTitle": { - "defaultMessage": "Add Sample Answers" - }, - "course.assessment.question.rubricPlayground.add": { - "defaultMessage": "Add" - }, - "course.assessment.question.rubricPlayground.addExistingAnswers": { - "defaultMessage": "Add existing answers" - }, - "course.assessment.question.rubricPlayground.student": { - "defaultMessage": "Student" - }, - "course.assessment.question.rubricPlayground.questionGrade": { - "defaultMessage": "Grade" - }, - "course.assessment.question.rubricPlayground.categoryHeading": { - "defaultMessage": "C{index}" - }, - "course.assessment.question.rubricPlayground.answer": { - "defaultMessage": "Answer" - }, - "course.assessment.question.rubricPlayground.searchAnswersPlaceholder": { - "defaultMessage": "Search answers by student name or grade" - }, - "course.assessment.question.rubricPlayground.addRandomStudentAnswers": { - "defaultMessage": "Add {inputComponent} random student answer(s)" - }, - "course.assessment.question.rubricPlayground.writeCustomAnswer": { - "defaultMessage": "Write a custom answer" - }, - "course.assessment.question.rubricPlayground.writeAnswerPlaceholder": { - "defaultMessage": "Write the answer here" - }, - "course.assessment.question.rubricPlayground.dismiss": { - "defaultMessage": "Dismiss" - }, - "course.assessment.question.rubricPlayground.noAnswers": { - "defaultMessage": "No sample answers have been added. Add some to get started." - }, - "course.assessment.question.rubricPlayground.reevaluate": { - "defaultMessage": "Re-evaluate" + "course.assessment.question.textResponses.spreadsheetFormula": { + "defaultMessage": "Spreadsheet Formula" }, - "course.assessment.question.rubricPlayground.totalGrade": { - "defaultMessage": "Total" + "course.assessment.question.textResponses.spreadsheetRandomization": { + "defaultMessage": "Enable randomization" }, - "course.assessment.question.rubricPlayground.feedback": { - "defaultMessage": "Feedback" + "course.assessment.question.textResponses.spreadsheetRandomizationDescription": { + "defaultMessage": "If enabled, some spreadsheet values will be randomly adjusted when autograding. This is useful to ensure the formula actually computes the right answer instead of a preset value." }, - "course.assessment.question.rubricPlayground.evaluating": { - "defaultMessage": "Evaluating" + "course.assessment.question.textResponses.stringRandomizationMode": { + "defaultMessage": "Randomize characters in value" }, - "course.assessment.question.rubricPlayground.gradingPrompt": { - "defaultMessage": "Grading Prompt" + "course.assessment.question.textResponses.stringRandomizationModeDescription": { + "defaultMessage": "Each character class to be randomized may be replaced with different character(s) from the same class." }, - "course.assessment.question.rubricPlayground.gradingPromptDescription": { - "defaultMessage": "Instructions to guide the AI in grading and giving feedback." + "course.assessment.question.textResponses.templateText": { + "defaultMessage": "Template" }, - "course.assessment.question.rubricPlayground.modelAnswer": { - "defaultMessage": "Model Answer" + "course.assessment.question.textResponses.templateTextDescription": { + "defaultMessage": "Text that appears in the answer area when students attempt this question for the first time." }, - "course.assessment.question.rubricPlayground.modelAnswerDescription": { - "defaultMessage": "An example that scores the maximum for each category." + "course.assessment.question.textResponses.testSpreadsheet": { + "defaultMessage": "Test spreadsheet" }, - "course.assessment.question.rubricPlayground.gradingCategories": { - "defaultMessage": "Grading Categories" + "course.assessment.question.textResponses.testSpreadsheetDescription": { + "defaultMessage": "A test spreadsheet is required to auto grade the student answer." }, - "course.assessment.question.rubricPlayground.addNewCategory": { - "defaultMessage": "Add New Category" + "course.assessment.question.textResponses.testSpreadsheetRequired": { + "defaultMessage": "Please upload a test spreadsheet file." }, - "course.assessment.question.rubricPlayground.categoryName": { - "defaultMessage": "Category Name" + "course.assessment.question.textResponses.undoDeleteSolution": { + "defaultMessage": "Undo delete solution" }, - "course.assessment.question.rubricPlayground.max": { - "defaultMessage": "Max" + "course.assessment.question.textResponses.validAttachmentSettingValues": { + "defaultMessage": "Attachment Settings should be either no attachment, single file attachment, or multiple file attachment" }, - "course.assessment.question.rubricPlayground.addNewGrade": { - "defaultMessage": "Add New Grade" + "course.assessment.question.textResponses.zeroGrade": { + "defaultMessage": "0.0" }, "course.assessment.session.assessmentNotStarted": { "defaultMessage": "The assessment has not started yet. Please come back after {startDate}." @@ -2558,9 +3083,6 @@ "course.assessment.show.assessmentOnlyAvailableFrom": { "defaultMessage": "This assessment will only be available from" }, - "course.assessment.show.audioResponse": { - "defaultMessage": "Audio Response" - }, "course.assessment.show.baseExp": { "defaultMessage": "Base EXP" }, @@ -2594,6 +3116,9 @@ "course.assessment.show.chooseAssessmentToDuplicateInto": { "defaultMessage": "Choose an assessment to duplicate into" }, + "course.assessment.show.comprehension": { + "defaultMessage": "Comprehension" + }, "course.assessment.show.delete": { "defaultMessage": "Delete" }, @@ -2651,9 +3176,15 @@ "course.assessment.show.errorMovingQuestion": { "defaultMessage": "An error occurred while moving the question." }, + "course.assessment.show.failedSyncingWithKoditsu": { + "defaultMessage": "Not Synced with Koditsu" + }, "course.assessment.show.fileUpload": { "defaultMessage": "File Upload" }, + "course.assessment.show.fileUploadDescription": { + "defaultMessage": "Settings for the number of attachments allowed (none, one, or multiple)" + }, "course.assessment.show.files": { "defaultMessage": "Files" }, @@ -2666,20 +3197,20 @@ "course.assessment.show.forumPostResponse": { "defaultMessage": "Forum Post Response" }, - "course.assessment.show.gradedTestCases": { - "defaultMessage": "Graded test cases" - }, "course.assessment.show.generate": { "defaultMessage": "Generate Questions" }, - "course.assessment.show.generateTooltip": { - "defaultMessage": "Collaborate with Codaveri AI to create questions" + "course.assessment.show.generateFromProgrammingQuestion": { + "defaultMessage": "Generate a similar question with Codaveri AI" }, "course.assessment.show.generateFromQuestion": { "defaultMessage": "Generate a similar question with AI" }, - "course.assessment.show.generateFromProgrammingQuestion": { - "defaultMessage": "Generate a similar question with Codaveri AI" + "course.assessment.show.generateTooltip": { + "defaultMessage": "Collaborate with Codaveri AI to create questions" + }, + "course.assessment.show.gradedTestCases": { + "defaultMessage": "Graded test cases" }, "course.assessment.show.gradingMode": { "defaultMessage": "Grading mode" @@ -2696,6 +3227,9 @@ "course.assessment.show.hideOptions": { "defaultMessage": "Hide options" }, + "course.assessment.show.koditsuMode": { + "defaultMessage": "Koditsu" + }, "course.assessment.show.manageComponents": { "defaultMessage": "Manage Components in Course Settings" }, @@ -2744,6 +3278,9 @@ "course.assessment.show.newQuestion": { "defaultMessage": "New Question" }, + "course.assessment.show.newRubricBasedResponse": { + "defaultMessage": "New Rubric Based Response Question" + }, "course.assessment.show.newScribing": { "defaultMessage": "New Scribing Question" }, @@ -2801,6 +3338,9 @@ "course.assessment.show.requirementsHint": { "defaultMessage": "The following items must be fulfilled to unlock this assessment." }, + "course.assessment.show.rubricBasedResponse": { + "defaultMessage": "Rubric-Based Response" + }, "course.assessment.show.scribing": { "defaultMessage": "Scribing" }, @@ -2810,15 +3350,15 @@ "course.assessment.show.showMcqMrqSolution": { "defaultMessage": "Show MCQ/MRQ solutions" }, - "course.assessment.show.showRubricToStudents": { - "defaultMessage": "Show rubric breakdown to students" - }, "course.assessment.show.showMcqSubmitResult": { "defaultMessage": "Show MCQ submit result" }, "course.assessment.show.showOptions": { "defaultMessage": "Show options" }, + "course.assessment.show.showRubricToStudents": { + "defaultMessage": "Show rubric breakdown to students" + }, "course.assessment.show.sureChangingQuestionType": { "defaultMessage": "Sure you're changing this question type?" }, @@ -2828,6 +3368,12 @@ "course.assessment.show.sureDeletingQuestion": { "defaultMessage": "Sure you're deleting this question?" }, + "course.assessment.show.syncedWithKoditsu": { + "defaultMessage": "Synced with Koditsu" + }, + "course.assessment.show.syncingWithKoditsu": { + "defaultMessage": "Syncing with Koditsu" + }, "course.assessment.show.textResponse": { "defaultMessage": "Text Response" }, @@ -2843,6 +3389,9 @@ "course.assessment.show.unsubmittingAndChangingQuestionType": { "defaultMessage": "Unsubmitting submissions and changing your question type..." }, + "course.assessment.show.voiceResponse": { + "defaultMessage": "Audio Response" + }, "course.assessment.show.whileHoldingToCancelMoving": { "defaultMessage": "while holding to cancel moving." }, @@ -2945,119 +3494,113 @@ "course.assessment.skills.SkillsTable.uncategorised": { "defaultMessage": "Uncategorised Skills" }, - "course.assessment.liveFeedback.questionTitle": { - "defaultMessage": "Question {index}" + "course.assessment.statistics.ancestorFail": { + "defaultMessage": "Failed to fetch past iterations of this assessment." }, - "course.assessment.liveFeedback.messageTimingTitle": { - "defaultMessage": "Generated at: {usedAt}" + "course.assessment.statistics.ancestorSelect.current": { + "defaultMessage": "Current" }, - "course.assessment.liveFeedback.liveFeedbackName": { - "defaultMessage": "Get Help" + "course.assessment.statistics.ancestorSelect.fromCourse": { + "defaultMessage": "From {courseTitle}" }, - "course.assessment.liveFeedback.comments": { - "defaultMessage": "Comments" + "course.assessment.statistics.ancestorSelect.subtitle": { + "defaultMessage": "Compare against past versions of this assessment:" }, - "course.assessment.liveFeedback.lineHeader": { - "defaultMessage": "Line {lineNumber}" + "course.assessment.statistics.ancestorSelect.title": { + "defaultMessage": "Duplication History" }, - "course.assessment.submission.GetHelpChatPage.chatInputText": { - "defaultMessage": "How can we help you?" + "course.assessment.statistics.ancestorStatisticsFail": { + "defaultMessage": "Failed to fetch ancestor's statistics." }, - "course.assessment.submission.GetHelpChatPage.chatMessagesRemaining": { - "defaultMessage": "{numMessages} / {maxMessages} {numMessages, plural, one {message} other {messages}} remaining" + "course.assessment.statistics.answers": { + "defaultMessage": "Answers" }, - "course.assessment.submission.GetHelpChatPage.noChatMessagesRemaining": { - "defaultMessage": "You have reached the message limit for this question." + "course.assessment.statistics.attemptCount": { + "defaultMessage": "Attempt Count" }, - "course.assessment.submission.GetHelpChatPage.codeUpdated": { - "defaultMessage": "Code Updated" + "course.assessment.statistics.attempts.filename": { + "defaultMessage": "Question-level Attempt Statistics for {assessment}" }, - "course.assessment.submission.GetHelpChatPage.ConversationArea.lineNumber": { - "defaultMessage": "Line {lineNumber}" + "course.assessment.statistics.attempts.greenCellLegend": { + "defaultMessage": "Correct" }, - "course.assessment.submission.GetHelpChatPage.ConversationArea.fileNameAndLineNumber": { - "defaultMessage": "{filename}:{lineNumber}" + "course.assessment.statistics.attempts.redCellLegend": { + "defaultMessage": "Incorrect" }, - "course.assessment.submission.GetHelpChatPage.ConversationArea.threadExpired": { - "defaultMessage": "The chat above has ended. Start a new chat?" + "course.assessment.statistics.closePrompt": { + "defaultMessage": "Close" }, - "course.assessment.plagiarism.plagiarism": { - "defaultMessage": "Plagiarism Results" + "course.assessment.statistics.comments": { + "defaultMessage": "Comments" }, - "course.assessment.plagiarism.status": { - "defaultMessage": "Plagiarism Check Status" + "course.assessment.statistics.duplicationHistory": { + "defaultMessage": "Duplication History" }, - "course.assessment.plagiarism.lastRunTime": { - "defaultMessage": "Last run at: {date}" + "course.assessment.statistics.email": { + "defaultMessage": "Email" }, - "course.assessment.plagiarism.start": { - "defaultMessage": "New Plagiarism Check" + "course.assessment.statistics.fail": { + "defaultMessage": "Failed to fetch statistics." }, - "course.assessment.plagiarism.notStarted": { - "defaultMessage": "No plagiarism check has been run" + "course.assessment.statistics.gradeDisplay": { + "defaultMessage": "Grade: {grade} / {maxGrade}" }, - "course.assessment.plagiarism.confirmStartTitle": { - "defaultMessage": "Confirm Plagiarism Check?" + "course.assessment.statistics.gradeDistribution": { + "defaultMessage": "Grade Distribution" }, - "course.assessment.plagiarism.confirmStartMessage": { - "defaultMessage": "Running a new plagiarism check will remove the previous results." + "course.assessment.statistics.gradeDistribution.datasetLabel": { + "defaultMessage": "Distribution" }, - "course.assessment.plagiarism.results": { - "defaultMessage": "Plagiarism Results (similarity between submissions)" + "course.assessment.statistics.gradeDistribution.xAxisLabel": { + "defaultMessage": "Grades" }, - "course.assessment.plagiarism.baseSubmission": { - "defaultMessage": "Base Submission" + "course.assessment.statistics.gradeDistribution.yAxisLabel": { + "defaultMessage": "Submissions" }, - "course.assessment.plagiarism.comparedSubmission": { - "defaultMessage": "Compared Submission" + "course.assessment.statistics.grader": { + "defaultMessage": "Grader" }, - "course.assessment.plagiarism.similarityScore": { - "defaultMessage": "Similarity Score" + "course.assessment.statistics.gradesPerQuestion": { + "defaultMessage": "Grades Per Question" }, - "course.assessment.plagiarism.actions": { - "defaultMessage": "Actions" + "course.assessment.statistics.grayCellLegend": { + "defaultMessage": "Undecided (question is Non-autogradable)" }, - "course.assessment.plagiarism.viewReport": { - "defaultMessage": "View Report" + "course.assessment.statistics.group": { + "defaultMessage": "Group" }, - "course.assessment.plagiarism.downloadPdf": { - "defaultMessage": "Download PDF" + "course.assessment.statistics.header": { + "defaultMessage": "Statistics for {title}" }, - "course.assessment.plagiarism.searchByStudentName": { - "defaultMessage": "Search by Student Name" + "course.assessment.statistics.includePhantom": { + "defaultMessage": "Include Phantom Student" }, - "course.assessment.plagiarism.showSelfPlagiarism": { - "defaultMessage": "Include self-plagiarism comparisons (same student, different courses)" + "course.assessment.statistics.legendHigherLabelGrade": { + "defaultMessage": "Higher Grade" }, - "course.assessment.statistics.answers": { - "defaultMessage": "Answers" + "course.assessment.statistics.legendHigherLabelGradeDiff": { + "defaultMessage": "More Improvement" }, - "course.assessment.statistics.attempts.filename": { - "defaultMessage": "Question-level Attempt Statistics for {assessment}" + "course.assessment.statistics.legendLowerLabelGrade": { + "defaultMessage": "Lower Grade" }, - "course.assessment.statistics.attempts.greenCellLegend": { - "defaultMessage": "Correct" + "course.assessment.statistics.legendLowerLabelGradeDiff": { + "defaultMessage": "Less Improvement" }, - "course.assessment.statistics.attempts.redCellLegend": { - "defaultMessage": "Incorrect" + "course.assessment.statistics.legendLowerLabelMessagesSent": { + "defaultMessage": "Lower Usage" }, - "course.assessment.statistics.closePrompt": { - "defaultMessage": "Close" + "course.assessment.statistics.legendLowerLabelWordCount": { + "defaultMessage": "Lower Word Count" }, - "course.assessment.statistics.grader": { - "defaultMessage": "Grader" + "course.assessment.statistics.legendUpperLabelMessagesSent": { + "defaultMessage": "Higher Usage" }, - "course.assessment.statistics.grayCellLegend": { - "defaultMessage": "Undecided (question is Non-autogradable)" - }, - "course.assessment.statistics.group": { - "defaultMessage": "Group" - }, - "course.assessment.statistics.legendHigherusage": { - "defaultMessage": "Higher Usage" + "course.assessment.statistics.legendUpperLabelWordCount": { + "defaultMessage": "Higher Word Count" }, - "course.assessment.statistics.legendLowerUsage": { - "defaultMessage": "Lower Usage" + "course.assessment.statistics.liveFeedback": { + "defaultMessage": "Get Help" }, "course.assessment.statistics.liveFeedback.filename": { "defaultMessage": "Question-level Get Help Statistics for {assessment}" @@ -3083,78 +3626,30 @@ "course.assessment.statistics.nameGroupsSearchText": { "defaultMessage": "Search by Name or Groups" }, + "course.assessment.statistics.noIncludePhantom": { + "defaultMessage": "*All statistics in this duplicated assessments does not include Phantom Students" + }, "course.assessment.statistics.noSubmission": { "defaultMessage": "No submission yet" }, "course.assessment.statistics.onlyForAutogradableAssessment": { "defaultMessage": "This table is only displayed for Assessment with at least one Autograded Questions" }, + "course.assessment.statistics.pastAnswerTitle": { + "defaultMessage": "Submitted At: {submittedAt}" + }, "course.assessment.statistics.questionDisplayTitle": { "defaultMessage": "Q{index} for {student}" }, "course.assessment.statistics.questionIndex": { "defaultMessage": "Q{index}" }, - "course.assessment.statistics.total": { - "defaultMessage": "Total" - }, - "course.assessment.statistics.workflowState": { - "defaultMessage": "Status" - }, - "course.assessment.statistics.ancestorFail": { - "defaultMessage": "Failed to fetch past iterations of this assessment." - }, - "course.assessment.statistics.ancestorStatisticsFail": { - "defaultMessage": "Failed to fetch ancestor's statistics." - }, - "course.assessment.statistics.fail": { - "defaultMessage": "Failed to fetch statistics." - }, - "course.assessment.statistics.gradeDistribution": { - "defaultMessage": "Grade Distribution" - }, - "course.assessment.statistics.gradeViolin.datasetLabel": { - "defaultMessage": "Distribution" - }, - "course.assessment.statistics.gradeViolin.xAxisLabel": { - "defaultMessage": "Grades" - }, - "course.assessment.statistics.gradeViolin.yAxisLabel": { - "defaultMessage": "Submissions" - }, - "course.assessment.statistics.ancestorSelect.current": { - "defaultMessage": "Current" - }, - "course.assessment.statistics.ancestorSelect.fromCourse": { - "defaultMessage": "From {courseTitle}" - }, - "course.assessment.statistics.ancestorSelect.subtitle": { - "defaultMessage": "Compare against past versions of this assessment:" - }, - "course.assessment.statistics.ancestorSelect.title": { - "defaultMessage": "Duplication History" - }, - "course.assessment.statistics.attemptCount": { - "defaultMessage": "Attempt Count" - }, - "course.assessment.statistics.duplicationHistory": { - "defaultMessage": "Duplication History" - }, - "course.assessment.statistics.gradesPerQuestion": { - "defaultMessage": "Grades Per Question" - }, - "course.assessment.statistics.includePhantom": { - "defaultMessage": "Include Phantom Student" - }, - "course.assessment.statistics.liveFeedback": { - "defaultMessage": "Get Help" - }, - "course.assessment.statistics.header": { - "defaultMessage": "Statistics for {title}" - }, "course.assessment.statistics.statistics": { "defaultMessage": "Statistics" }, + "course.assessment.statistics.submissionPage": { + "defaultMessage": "Go to Answer Page" + }, "course.assessment.statistics.submissionStatuses": { "defaultMessage": "Submission Statuses" }, @@ -3173,9 +3668,18 @@ "course.assessment.statistics.submissionTimeGradeChart.xAxisLabel.withoutDeadline": { "defaultMessage": "Submission Date" }, + "course.assessment.statistics.total": { + "defaultMessage": "Total" + }, + "course.assessment.statistics.workflowState": { + "defaultMessage": "Status" + }, "course.assessment.submission.Annotations.comment": { "defaultMessage": "Add Comment" }, + "course.assessment.submission.Answer.rendererNotImplemented": { + "defaultMessage": "The display for this question type has not been implemented yet." + }, "course.assessment.submission.CodaveriFeedbackStatus.codaveriFeedbackStatus": { "defaultMessage": "Codaveri Feedback Status" }, @@ -3194,14 +3698,77 @@ "course.assessment.submission.EvaluatorErrorPanel.emailSubject": { "defaultMessage": "[Bug Report] Evaluator Error" }, + "course.assessment.submission.FileInput.exactlyOneFileUploadAllowed": { + "defaultMessage": "*You must upload EXACTLY 1 file for this question" + }, + "course.assessment.submission.FileInput.fileName": { + "defaultMessage": "{index}. {name}" + }, + "course.assessment.submission.FileInput.fileTooLargeErrorMessage": { + "defaultMessage": "The following files have size larger than allowed ({maxAttachmentSize} MB)" + }, + "course.assessment.submission.FileInput.fileUploadErrorTitle": { + "defaultMessage": "Error in Uploading Files" + }, + "course.assessment.submission.FileInput.onlyOneFileUploadAllowed": { + "defaultMessage": "*You can only upload AT MOST {maxAttachments} file for this question" + }, + "course.assessment.submission.FileInput.requiredUploadLimitedNumberOfFiles": { + "defaultMessage": "*You can upload AT LEAST 1 and AT MOST {maxAttachments} files for this question" + }, + "course.assessment.submission.FileInput.tooManyFilesErrorMessage": { + "defaultMessage": "You have attempted to upload {numFiles} files, but ONLY {maxAttachmentsAllowed} {maxAttachmentsAllowed, plural, one {file} other {files}} can be uploaded {numAttachments, plural, =0 {} one {since 1 file has been uploaded before} other {since {numAttachments} files has been uploaded before}}" + }, "course.assessment.submission.FileInput.uploadDisabled": { "defaultMessage": "File upload disabled" }, "course.assessment.submission.FileInput.uploadLabel": { "defaultMessage": "Drag and drop or click to upload files" }, + "course.assessment.submission.GetHelpChatPage": { + "defaultMessage": "Get Help" + }, + "course.assessment.submission.GetHelpChatPage.ConversationArea.fileNameAndLineNumber": { + "defaultMessage": "{filename}:{lineNumber}" + }, + "course.assessment.submission.GetHelpChatPage.ConversationArea.lineNumber": { + "defaultMessage": "Line {lineNumber}" + }, + "course.assessment.submission.GetHelpChatPage.ConversationArea.threadExpired": { + "defaultMessage": "The chat above has ended. Start a new chat?" + }, + "course.assessment.submission.GetHelpChatPage.chatInputText": { + "defaultMessage": "How can we help you?" + }, + "course.assessment.submission.GetHelpChatPage.chatMessagesRemaining": { + "defaultMessage": "{numMessages} / {maxMessages} {numMessages, plural, one {message} other {messages}} remaining" + }, + "course.assessment.submission.GetHelpChatPage.codeUpdated": { + "defaultMessage": "Code Updated" + }, + "course.assessment.submission.GetHelpChatPage.endOfConversation": { + "defaultMessage": "View code after conversation" + }, + "course.assessment.submission.GetHelpChatPage.failedSyncingWithCodaveri": { + "defaultMessage": "Unavailable" + }, + "course.assessment.submission.GetHelpChatPage.noChatMessagesRemaining": { + "defaultMessage": "You have reached the message limit for this question." + }, + "course.assessment.submission.GetHelpChatPage.syncedWithCodaveri": { + "defaultMessage": "Ready" + }, + "course.assessment.submission.GetHelpChatPage.syncingWithCodaveri": { + "defaultMessage": "Preparing" + }, + "course.assessment.submission.ImportedFileView.delete": { + "defaultMessage": "Delete" + }, "course.assessment.submission.ImportedFileView.deleteConfirmation": { - "defaultMessage": "Are you sure you want to delete this file?" + "defaultMessage": "Are you sure you want to delete \"{fileName}\"?" + }, + "course.assessment.submission.ImportedFileView.deleteTitle": { + "defaultMessage": "Delete File" }, "course.assessment.submission.ImportedFileView.noFiles": { "defaultMessage": "No files uploaded." @@ -3209,17 +3776,44 @@ "course.assessment.submission.ImportedFileView.uploadedFiles": { "defaultMessage": "Uploaded Files:" }, - "course.assessment.submission.Answer.missingAnswer": { - "defaultMessage": "There is no answer submitted for this question - this might be caused by the addition of this question after the submission is submitted." + "course.assessment.submission.ResultView.expected": { + "defaultMessage": "Expected" }, - "course.assessment.submission.answers.AnswerHeader.noPastAnswers": { - "defaultMessage": "No past answers." + "course.assessment.submission.ResultView.output": { + "defaultMessage": "Output" }, - "course.assessment.submission.Answer.rendererNotImplemented": { - "defaultMessage": "The display for this question type has not been implemented yet." + "course.assessment.submission.ResultView.solution": { + "defaultMessage": "Solution" }, - "course.assessment.submission.SubmissionAnswer.viewPastAnswers": { - "defaultMessage": "Past Answers" + "course.assessment.submission.ResultView.solutionHeaders.exactMatch": { + "defaultMessage": "Answer matches exactly {solution}" + }, + "course.assessment.submission.ResultView.solutionHeaders.keyword": { + "defaultMessage": "Answer contains keyword {solution}" + }, + "course.assessment.submission.ResultView.solutionHeaders.regex": { + "defaultMessage": "Answer matches regular expression {solution}" + }, + "course.assessment.submission.ResultView.solutionHeaders.spreadsheetFormula": { + "defaultMessage": "Answer formula equivalent to {solution}" + }, + "course.assessment.submission.ResultView.solutionInvertedHeaders.exactMatch": { + "defaultMessage": "Answer is not exactly {solution}" + }, + "course.assessment.submission.ResultView.solutionInvertedHeaders.keyword": { + "defaultMessage": "Answer does not contain keyword {solution}" + }, + "course.assessment.submission.ResultView.solutionInvertedHeaders.regex": { + "defaultMessage": "Answer does not match regular expression {solution}" + }, + "course.assessment.submission.ResultView.solutionInvertedHeaders.spreadsheetFormula": { + "defaultMessage": "Answer formula not equivalent to {solution}" + }, + "course.assessment.submission.SubmissionEditIndex.TimeLimitBanner.hoursMinutesSeconds": { + "defaultMessage": "{hrs, plural, one {# hour} other {# hours}} {mins, plural, =0 {} one {# minute} other {# minutes}} {secs, plural, =0 {} one {# second} other {# seconds}}" + }, + "course.assessment.submission.SubmissionEditIndex.TimeLimitBanner.minutesSeconds": { + "defaultMessage": "{secs, plural, one {# second} other {# seconds}}" }, "course.assessment.submission.SubmissionsIndex.accessLogs": { "defaultMessage": "Access Logs" @@ -3254,6 +3848,9 @@ "course.assessment.submission.SubmissionsIndex.experiencePoints": { "defaultMessage": "EXP Awarded" }, + "course.assessment.submission.SubmissionsIndex.fetchFromKoditsu": { + "defaultMessage": "Fetch Submissions from Koditsu" + }, "course.assessment.submission.SubmissionsIndex.forceSubmit": { "defaultMessage": "Force Submit Remaining" }, @@ -3266,12 +3863,12 @@ "course.assessment.submission.SubmissionsIndex.includePhantoms": { "defaultMessage": "Include phantom users" }, - "lib.translations.myStudents": { - "defaultMessage": "My Students" - }, "course.assessment.submission.SubmissionsIndex.phantom": { "defaultMessage": "Phantom User" }, + "course.assessment.submission.SubmissionsIndex.publishAutoFeedback": { + "defaultMessage": "Publish Automated Programming Feedback ({count})" + }, "course.assessment.submission.SubmissionsIndex.publishGrades": { "defaultMessage": "Publish Grades" }, @@ -3281,21 +3878,6 @@ "course.assessment.submission.SubmissionsIndex.remind": { "defaultMessage": "Send Reminder Emails" }, - "lib.translations.staff": { - "defaultMessage": "Staff" - }, - "lib.translations.students": { - "defaultMessage": "Students" - }, - "lib.translations.myStudentsIncludingPhantoms": { - "defaultMessage": "My Students (Including Phantoms)" - }, - "lib.translations.studentsIncludingPhantoms": { - "defaultMessage": "Students (Including Phantoms)" - }, - "lib.translations.staffIncludingPhantoms": { - "defaultMessage": "Staff (Including Phantoms)" - }, "course.assessment.submission.SubmissionsIndex.submissionStatus": { "defaultMessage": "Status" }, @@ -3311,6 +3893,9 @@ "course.assessment.submission.SubmissionsIndex.userName": { "defaultMessage": "Name" }, + "course.assessment.submission.TestCaseView.allFailed": { + "defaultMessage": "All failed" + }, "course.assessment.submission.TestCaseView.allPassed": { "defaultMessage": "All passed" }, @@ -3350,8 +3935,17 @@ "course.assessment.submission.TestCaseView.standardOutput": { "defaultMessage": "Standard Output" }, + "course.assessment.submission.TestCaseView.testCasesPassed": { + "defaultMessage": "{numPassed}/{numTestCases} passed" + }, "course.assessment.submission.UploadedFileView.deleteConfirmation": { - "defaultMessage": "Are you sure you want to delete this attachment?" + "defaultMessage": "Are you sure you want to delete {fileName}?" + }, + "course.assessment.submission.UploadedFileView.deleteTitle": { + "defaultMessage": "Delete File" + }, + "course.assessment.submission.UploadedFileView.deleting": { + "defaultMessage": "Delete" }, "course.assessment.submission.UploadedFileView.noFiles": { "defaultMessage": "No files uploaded." @@ -3360,7 +3954,7 @@ "defaultMessage": "Uploaded Files" }, "course.assessment.submission.VoiceResponseAnswer.chooseVoiceFileExplain": { - "defaultMessage": "Drag your audio file here, or click to select an audio file. Only wav and mp3 formats are supported. Alternatively, you may use the recorder below to record your response" + "defaultMessage": "Drag and drop or click to upload your WAV / MP3 files. Alternatively, use the recorder below to record your response" }, "course.assessment.submission.VoiceResponseAnswer.pleaseRecordYourVoice": { "defaultMessage": "Please record your voice" @@ -3485,6 +4079,24 @@ "course.assessment.submission.answerSubmitted": { "defaultMessage": "Answer Submitted" }, + "course.assessment.submission.answerTooLarge": { + "defaultMessage": "Answer Too Large" + }, + "course.assessment.submission.answerTooLargeError": { + "defaultMessage": "Your answer must be less than 2 MB." + }, + "course.assessment.submission.answers.AnswerHeader.noPastAnswers": { + "defaultMessage": "No past answers." + }, + "course.assessment.submission.answers.AnswerHeader.viewAllAnswers": { + "defaultMessage": "All Answers ({count})" + }, + "course.assessment.submission.answers.AnswerHeader.viewGetHelpHistory": { + "defaultMessage": "Get Help History ({count})" + }, + "course.assessment.submission.answers.AnswerHeader.viewPastAnswers": { + "defaultMessage": "Past Answers ({count})" + }, "course.assessment.submission.answers.ForumPostResponse.ForumCard.forumCardTitleTypeNoneSelected": { "defaultMessage": "Forum" }, @@ -3557,17 +4169,11 @@ "course.assessment.submission.answers.ForumPostResponse.TopicCard.viewTopicInNewTab": { "defaultMessage": "View Topic" }, - "course.assessment.submission.answers.Programming.ProgrammingFile.downloadFile": { - "defaultMessage": "Download File" - }, "course.assessment.submission.answers.Programming.ProgrammingFile.sizeTooBig": { "defaultMessage": "The file is too big and cannot be displayed." }, - "course.assessment.submission.answerTooLarge": { - "defaultMessage": "Answer Too Large" - }, - "course.assessment.submission.answerTooLargeError": { - "defaultMessage": "Your answer must be less than 2 MB." + "course.assessment.submission.attachmentRequired": { + "defaultMessage": "*please upload AT LEAST 1 file for this question" }, "course.assessment.submission.attemptedAt": { "defaultMessage": "Attempted At" @@ -3590,14 +4196,17 @@ "course.assessment.submission.bonusEndAt": { "defaultMessage": "Bonus End At" }, - "course.assessment.submission.codaveriAutogradeFailure": { - "defaultMessage": "There is an error while evaluating your code in Codaveri. Try submitting your code again in a couple of minutes or check the error message in the network response." + "course.assessment.submission.category": { + "defaultMessage": "Category" }, - "course.assessment.submission.liveFeedbackNoneGenerated": { - "defaultMessage": "Question {questionIndex}: No feedback generated." + "course.assessment.submission.checkAnswer": { + "defaultMessage": "Check Answer" + }, + "course.assessment.submission.checkAnswerWithLimit": { + "defaultMessage": "Check Answer ({attemptsLeft, plural, one {# attempt} other {# attempts}} left)" }, - "course.assessment.submission.liveFeedbackSuccess": { - "defaultMessage": "Question {questionIndex}: Feedback successfully generated." + "course.assessment.submission.codaveriAutogradeFailure": { + "defaultMessage": "There is an error while evaluating your code in Codaveri. Try submitting your code again in a couple of minutes or check the error message in the network response." }, "course.assessment.submission.comment.CodaveriCommentCard.finalise": { "defaultMessage": "Finalise and Post Feedback" @@ -3623,14 +4232,14 @@ "course.assessment.submission.comment.CommentCard.deleteConfirmation": { "defaultMessage": "Are you sure you want to delete this comment?" }, - "course.assessment.submission.comment.CommentCard.save": { - "defaultMessage": "Save" + "course.assessment.submission.comment.CommentCard.isAiGenerated": { + "defaultMessage": "AI Generated Comment" }, "course.assessment.submission.comment.CommentCard.publish": { "defaultMessage": "Publish" }, - "course.assessment.submission.comment.CommentCard.isAiGenerated": { - "defaultMessage": "AI Generated Comment" + "course.assessment.submission.comment.CommentCard.save": { + "defaultMessage": "Save" }, "course.assessment.submission.comment.CommentField.comment": { "defaultMessage": "Comment" @@ -3647,18 +4256,6 @@ "course.assessment.submission.comments": { "defaultMessage": "Comments" }, - "course.assessment.submission.answers.Programming.ProgrammingFiles.liveFeedbackItemDelete": { - "defaultMessage": "Dismiss" - }, - "course.assessment.submission.answers.Programming.ProgrammingFiles.liveFeedbackItemDislike": { - "defaultMessage": "Dislike" - }, - "course.assessment.submission.answers.Programming.ProgrammingFiles.liveFeedbackItemLike": { - "defaultMessage": "Like" - }, - "course.assessment.submission.answers.Programming.ProgrammingFiles.liveFeedbackItemLineHeading": { - "defaultMessage": "Line {linenum}" - }, "course.assessment.submission.continue": { "defaultMessage": "Continue" }, @@ -3704,6 +4301,9 @@ "course.assessment.submission.emptyAssessment": { "defaultMessage": "This assessment currently has no questions." }, + "course.assessment.submission.errorUnknown": { + "defaultMessage": "Error is Unknown" + }, "course.assessment.submission.examDialogMessage": { "defaultMessage": "Please do not sign out or close the browser, otherwise you may have trouble continuing the exam." }, @@ -3713,6 +4313,18 @@ "course.assessment.submission.expAwarded": { "defaultMessage": "EXP Awarded" }, + "course.assessment.submission.explanation": { + "defaultMessage": "Explanation" + }, + "course.assessment.submission.fetchSubmissionsFromKoditsuConfirmation": { + "defaultMessage": "Are you sure you want to fetch all submissions from Koditsu? all the existing answers here will be overwritten by the newer one. NOTE THAT THIS ACTION IS IRREVERSIBLE!" + }, + "course.assessment.submission.fetchSubmissionsFromKoditsuPending": { + "defaultMessage": "Please wait as the submissions are currently being fetched from Koditsu." + }, + "course.assessment.submission.fetchSubmissionsFromKoditsuSuccess": { + "defaultMessage": "All submissions have been fetched successfully from Koditsu" + }, "course.assessment.submission.finalise": { "defaultMessage": "Finalise all answers" }, @@ -3743,6 +4355,9 @@ "course.assessment.submission.grade": { "defaultMessage": "Grade" }, + "course.assessment.submission.gradeDisplay": { + "defaultMessage": "Grade: {grade}" + }, "course.assessment.submission.gradePrefilled": { "defaultMessage": "Pre-filled" }, @@ -3755,9 +4370,6 @@ "course.assessment.submission.gradeSummary": { "defaultMessage": "Grade Summary" }, - "course.assessment.submission.gradeUnsaved": { - "defaultMessage": "Unsaved" - }, "course.assessment.submission.gradeUnsavedHint": { "defaultMessage": "This grade is not yet saved. Click Save Grade at the end of the page to save all grade changes." }, @@ -3773,6 +4385,12 @@ "course.assessment.submission.group": { "defaultMessage": "Group" }, + "course.assessment.submission.history.questionTitle": { + "defaultMessage": "Question Details" + }, + "course.assessment.submission.history.title": { + "defaultMessage": "Submission by {studentName}, Question {number}" + }, "course.assessment.submission.importFilesFailure": { "defaultMessage": "File uploads failed: {errors}" }, @@ -3782,9 +4400,24 @@ "course.assessment.submission.invalidFileUpload": { "defaultMessage": "File uploads failed: Only java files can be uploaded" }, + "course.assessment.submission.isSaved": { + "defaultMessage": "Saved" + }, + "course.assessment.submission.isSaving": { + "defaultMessage": "Saving" + }, + "course.assessment.submission.isUnsaved": { + "defaultMessage": "Unsaved" + }, "course.assessment.submission.lateSubmission": { "defaultMessage": "This submission is LATE! You may want to penalize the student for late submission." }, + "course.assessment.submission.liveFeedbackHistory.codeHistory": { + "defaultMessage": "Code History" + }, + "course.assessment.submission.liveFeedbackNoneGenerated": { + "defaultMessage": "No feedback generated." + }, "course.assessment.submission.loadingComment": { "defaultMessage": "Loading comment field..." }, @@ -3821,6 +4454,9 @@ "course.assessment.submission.mark": { "defaultMessage": "Submit for Publishing" }, + "course.assessment.submission.max": { + "defaultMessage": "Max" + }, "course.assessment.submission.maximumGroupGrade": { "defaultMessage": "Maximum Grade for this Group" }, @@ -3833,6 +4469,9 @@ "course.assessment.submission.ok": { "defaultMessage": "OK" }, + "course.assessment.submission.onlyOneAttachmentAllowed": { + "defaultMessage": "*ONLY 1 file is allowed for this question" + }, "course.assessment.submission.pastAnswers": { "defaultMessage": "Past Answers" }, @@ -3875,14 +4514,20 @@ "course.assessment.submission.question": { "defaultMessage": "Question" }, - "course.assessment.submission.questionNumber": { - "defaultMessage": "Q{number}" + "course.assessment.submission.questionAnswer": { + "defaultMessage": "Answer" }, "course.assessment.submission.questionDescription": { "defaultMessage": "Description" }, - "course.assessment.submission.questionAnswer": { - "defaultMessage": "Answer" + "course.assessment.submission.questionHeading": { + "defaultMessage": "Question {number}" + }, + "course.assessment.submission.questionHeadingWithTitle": { + "defaultMessage": "Question {number}: {title}" + }, + "course.assessment.submission.questionNumber": { + "defaultMessage": "Q{number}" }, "course.assessment.submission.readOnlyEditor.expandComments": { "defaultMessage": "Expand all comments" @@ -3893,6 +4538,12 @@ "course.assessment.submission.reevaluate": { "defaultMessage": "Re-evaluate Answer" }, + "course.assessment.submission.remainingBufferTime": { + "defaultMessage": "Finalising in: {timeLimit}" + }, + "course.assessment.submission.remainingTime": { + "defaultMessage": "Time Remaining: {timeLimit}" + }, "course.assessment.submission.rendererNotImplemented": { "defaultMessage": "The display for this question type has not been implemented yet." }, @@ -3905,14 +4556,8 @@ "course.assessment.submission.resetConfirmation": { "defaultMessage": "Are you sure you want to reset your answer? This action is irreversible and you will lose all your current work for this question." }, - "course.assessment.submission.checkAnswer": { - "defaultMessage": "Check Answer" - }, - "course.assessment.submission.checkAnswerWithLimit": { - "defaultMessage": "Check Answer ({attemptsLeft, plural, one {# attempt} other {# attempts}} left)" - }, - "course.assessment.submission.submitWithLimit": { - "defaultMessage": "Submit ({attemptsLeft, plural, one {# attempt} other {# attempts}} left)" + "course.assessment.submission.rubricScores": { + "defaultMessage": "Rubric Grades" }, "course.assessment.submission.saveDraft": { "defaultMessage": "Save Draft" @@ -3920,6 +4565,15 @@ "course.assessment.submission.saveGrade": { "defaultMessage": "Save Grade" }, + "course.assessment.submission.saved": { + "defaultMessage": "Saved" + }, + "course.assessment.submission.saving": { + "defaultMessage": "Saving" + }, + "course.assessment.submission.savingFailed": { + "defaultMessage": "Saving Failed" + }, "course.assessment.submission.sendReminderEmailConfirmation": { "defaultMessage": "Send reminder emails to {unattempted} unattempted and {attempting} attempting user(s) ({selectedUsers}) who have not completed the assessment?" }, @@ -3956,6 +4610,9 @@ "course.assessment.submission.submissionBy": { "defaultMessage": "Submission by {name}" }, + "course.assessment.submission.submissionError": { + "defaultMessage": "There is a problem in submitting question for {questions}" + }, "course.assessment.submission.submissionsHeader": { "defaultMessage": "Submissions: {assessment}" }, @@ -3968,22 +4625,58 @@ "course.assessment.submission.submitShortcut": { "defaultMessage": "(Ctrl+Enter) or (⌘+Enter)" }, + "course.assessment.submission.submitWithLimit": { + "defaultMessage": "Submit ({attemptsLeft, plural, one {# attempt} other {# attempts}} left)" + }, "course.assessment.submission.submitted": { "defaultMessage": "Submitted" }, "course.assessment.submission.submittedAt": { "defaultMessage": "Submitted At" }, - "course.assessment.submission.unknown": { - "defaultMessage": "Unknown status, please contact administrator" + "course.assessment.submission.suggestions.howDoIFixThis": { + "defaultMessage": "How do I fix this?" }, - "course.assessment.submission.totalGrade": { - "defaultMessage": "Total Grade" + "course.assessment.submission.suggestions.iAmStuck": { + "defaultMessage": "I am stuck" }, - "course.assessment.submission.type": { - "defaultMessage": "Type" + "course.assessment.submission.suggestions.looksWrong": { + "defaultMessage": "This looks wrong" }, - "course.assessment.submission.unmark": { + "course.assessment.submission.suggestions.optimizeThisCode": { + "defaultMessage": "Review my code" + }, + "course.assessment.submission.suggestions.questionUnclear": { + "defaultMessage": "Explain the question" + }, + "course.assessment.submission.suggestions.whereAmIWrong": { + "defaultMessage": "Where am I wrong?" + }, + "course.assessment.submission.timeIsUp": { + "defaultMessage": "Time is Up!" + }, + "course.assessment.submission.timedAssessmentDialogMessage": { + "defaultMessage": "{stillSomeTimeRemaining, select, true {Once the time is up, the assessment will be automatically finalised.} other {Finalising the submission now!}}" + }, + "course.assessment.submission.timedAssessmentDialogTitle": { + "defaultMessage": "{stillSomeTimeRemaining, select, true {{remainingTime} {isNewSubmission, select, true {} other {remaining}} to complete this assessment.} other {The assessment has ended!}}" + }, + "course.assessment.submission.timedExamDialogMessage": { + "defaultMessage": "{stillSomeTimeRemaining, select, true {Please do not sign out or close the browser while attempting this exam. Once the time is up, the assessment will be automatically finalised.} other {Finalising the submission now!}}" + }, + "course.assessment.submission.timedExamDialogTitle": { + "defaultMessage": "{stillSomeTimeRemaining, select, true {{remainingTime} {isNewSubmission, select, true {} other {remaining}} to complete this exam.} other {The exam has ended!}}" + }, + "course.assessment.submission.totalGrade": { + "defaultMessage": "Total Grade" + }, + "course.assessment.submission.type": { + "defaultMessage": "Type" + }, + "course.assessment.submission.unknown": { + "defaultMessage": "Unknown status, please contact administrator" + }, + "course.assessment.submission.unmark": { "defaultMessage": "Revert to Submitted" }, "course.assessment.submission.unpublishedGrades": { @@ -3996,7 +4689,7 @@ "defaultMessage": "Unsubmit Submission" }, "course.assessment.submission.unsubmitAllConfirmation": { - "defaultMessage": "Are you sure you want to UNSUBMIT the submissions for all {users}? All submissions will be unsubmitted and this will reset the submission time and permit the users to change their answers. NOTE THAT THIS ACTION IS IRREVERSIBLE" + "defaultMessage": "Are you sure you want to UNSUBMIT the submissions for all {users}? All submissions will be unsubmitted and this will reset the submission time and permit the users to change their submissions. NOTE THAT THIS ACTION IS IRREVERSIBLE" }, "course.assessment.submission.unsubmitAllSubmissionsJobPending": { "defaultMessage": "Please wait as the submissions are currently being unsubmitted." @@ -4013,6 +4706,9 @@ "course.assessment.submission.updateFailure": { "defaultMessage": "Submission update failed: {errors}" }, + "course.assessment.submission.updateIndividualSuccess": { + "defaultMessage": "Submission for {errors} updated successfully" + }, "course.assessment.submission.updateSuccess": { "defaultMessage": "Submission updated successfully." }, @@ -4049,9 +4745,6 @@ "course.assessment.submissions.SubmissionsIndex.header": { "defaultMessage": "Submissions" }, - "course.assessment.submission.SubmissionsIndex.publishAutoFeedback": { - "defaultMessage": "Publish Automated Programming Feedback ({count})" - }, "course.assessment.submissions.SubmissionsTable.gradeTooltip": { "defaultMessage": "These grades can't be seen by the student until they are published" }, @@ -4074,7 +4767,7 @@ "defaultMessage": "Submitted At" }, "course.assessment.submissions.SubmissionsTable.tableHeaderTitle": { - "defaultMessage": "Assessment" + "defaultMessage": "Title" }, "course.assessment.submissions.SubmissionsTable.tableHeaderTotalGrade": { "defaultMessage": "Grade" @@ -4133,6 +4826,18 @@ "course.assessments.index.hasTodo": { "defaultMessage": "Has TODO" }, + "course.assessments.index.inviteToKoditsu": { + "defaultMessage": "Invite users to Koditsu Exam" + }, + "course.assessments.index.invitingUserToKoditsu": { + "defaultMessage": "Inviting users to Koditsu Exam" + }, + "course.assessments.index.invitingUserToKoditsuFailure": { + "defaultMessage": "There is a problem in inviting users to Koditsu. Please try again later" + }, + "course.assessments.index.invitingUserToKoditsuSuccess": { + "defaultMessage": "Successful in inviting users to Koditsu Exam" + }, "course.assessments.index.neededFor": { "defaultMessage": "Needed for" }, @@ -4163,6 +4868,9 @@ "course.assessments.index.submittedCount": { "defaultMessage": "Submissions" }, + "course.assessments.index.timeLimitIcon": { + "defaultMessage": "Time Limit: {timeLimit, plural, one {# minute} other {# minutes}}" + }, "course.assessments.index.title": { "defaultMessage": "Title" }, @@ -4181,9 +4889,6 @@ "course.asssessment.submission.submitNoQuestionExplain": { "defaultMessage": "Mark as completed?" }, - "course.admin.NotificationSettings.component": { - "defaultMessage": "Component" - }, "course.componentTitles.course_achievements_component": { "defaultMessage": "Achievements" }, @@ -4268,15 +4973,6 @@ "course.courses.CourseAnnouncements.announcementHeader": { "defaultMessage": "Latest announcements" }, - "course.courses.CourseSuspendedAlert.header": { - "defaultMessage": "This course is suspended. Instructors can still access it, but students cannot." - }, - "course.courses.CourseSuspendedAlert.canSuspendMessage": { - "defaultMessage": "You can unsuspend it from the {link} page." - }, - "course.courses.CourseSuspendedAlert.cannotSuspendMessage": { - "defaultMessage": "If you believe this is a mistake, contact a course manager or owner to have them unsuspend the course." - }, "course.courses.CourseDisplay.noCourse": { "defaultMessage": "There is no course yet..." }, @@ -4322,6 +5018,15 @@ "course.courses.CourseShow.instructorsHeader": { "defaultMessage": "Instructors" }, + "course.courses.CourseSuspendedAlert.canSuspendMessage": { + "defaultMessage": "You can unsuspend it from the {link} page." + }, + "course.courses.CourseSuspendedAlert.cannotSuspendMessage": { + "defaultMessage": "If you believe this is a mistake, contact a course manager or owner to have them unsuspend the course." + }, + "course.courses.CourseSuspendedAlert.header": { + "defaultMessage": "This course is suspended. Instructors can still access it, but students cannot." + }, "course.courses.CourseUserItem.differentCourseNameHint": { "defaultMessage": "You're seeing a name different from your account name because this course's manager invited you with this name." }, @@ -4437,7 +5142,7 @@ "defaultMessage": "Starts at" }, "course.courses.PendingTodosTable.tableHeaderTitle": { - "defaultMessage": "Title" + "defaultMessage": "Assessment" }, "course.courses.PendingTodosTable.tableSeeMore": { "defaultMessage": "See {n} more" @@ -4445,6 +5150,9 @@ "course.courses.Sidebar.administration": { "defaultMessage": "Administration" }, + "course.courses.Sidebar.joinCoursemologyMessage": { + "defaultMessage": "Create a Coursemology account or sign up to join this course." + }, "course.courses.SidebarItem.admin.duplication": { "defaultMessage": "Duplicate Data" }, @@ -4490,15 +5198,15 @@ "course.courses.SidebarItem.home": { "defaultMessage": "Home" }, + "course.courses.SidebarItem.scholaistic.assessments": { + "defaultMessage": "Role-Playing Assessments" + }, "course.courses.SidebarItem.stories.learn": { "defaultMessage": "Learn" }, "course.courses.SidebarItem.stories.missionControl": { "defaultMessage": "Mission Control" }, - "course.courses.SidebarItem.scholaistic.assessments": { - "defaultMessage": "Role-Playing Assessments" - }, "course.courses.TodoIgnoreButton.ignore.ignoreButtonText": { "defaultMessage": "Ignore" }, @@ -4541,6 +5249,12 @@ "course.discussion.topics.CommentCard.deleteSuccess": { "defaultMessage": "Successfully deleted comment." }, + "course.discussion.topics.CommentCard.isAiGenerated": { + "defaultMessage": "AI Generated Comment" + }, + "course.discussion.topics.CommentCard.publish": { + "defaultMessage": "Publish" + }, "course.discussion.topics.CommentCard.publishFailure": { "defaultMessage": "Failed to publish feedback." }, @@ -4562,12 +5276,6 @@ "course.discussion.topics.CommentCard.updateSuccess": { "defaultMessage": "Successfully updated comment." }, - "course.discussion.topics.CommentCard.publish": { - "defaultMessage": "Publish" - }, - "course.discussion.topics.CommentCard.isAiGenerated": { - "defaultMessage": "AI Generated Comment" - }, "course.discussion.topics.CommentField.comment": { "defaultMessage": "Comment" }, @@ -4635,7 +5343,7 @@ "defaultMessage": "Select current instance" }, "course.duplication.Duplication.DestinationCourseSelector.InstanceDropdown.destinationInstance": { - "defaultMessage": "Destination Instance" + "defaultMessage": "Destination instance" }, "course.duplication.Duplication.DestinationCourseSelector.NewCourseForm.newStartAt": { "defaultMessage": "New Start Date *" @@ -4739,15 +5447,15 @@ "course.duplication.Duplication.duplicateData": { "defaultMessage": "Duplicate Data" }, - "course.duplication.Duplication.fromCourse": { - "defaultMessage": "Duplicate Data from {courseTitle}" - }, "course.duplication.Duplication.duplicationDisabled": { "defaultMessage": "Duplication is disabled for this course." }, "course.duplication.Duplication.existingCourse": { "defaultMessage": "Existing Course" }, + "course.duplication.Duplication.fromCourse": { + "defaultMessage": "Duplicate data from {courseTitle}" + }, "course.duplication.Duplication.items": { "defaultMessage": "Selected Items" }, @@ -4841,6 +5549,135 @@ "course.enrolRequests.UserRequests.rejected": { "defaultMessage": "Rejected Enrolment Requests" }, + "course.experiencePoints.disbursement.DisbursementForm.createDisbursementFailure": { + "defaultMessage": "Failed to award experience points." + }, + "course.experiencePoints.disbursement.DisbursementForm.createDisbursementSuccess": { + "defaultMessage": "Experience points disbursed to {recipientCount} recipients." + }, + "course.experiencePoints.disbursement.DisbursementForm.fetchDisbursementFailure": { + "defaultMessage": "Failed to retrieve data." + }, + "course.experiencePoints.disbursement.DisbursementForm.fetchFilterFailure": { + "defaultMessage": "Failed to retrieve filtered forum users." + }, + "course.experiencePoints.disbursement.DisbursementForm.fetchFilterNone": { + "defaultMessage": "No post made between these 2 dates." + }, + "course.experiencePoints.disbursement.DisbursementForm.filter": { + "defaultMessage": "Filter by group" + }, + "course.experiencePoints.disbursement.DisbursementForm.noDisbursement": { + "defaultMessage": "No points are disbursed to users." + }, + "course.experiencePoints.disbursement.DisbursementForm.notNumber": { + "defaultMessage": "Not a Number." + }, + "course.experiencePoints.disbursement.DisbursementForm.reason": { + "defaultMessage": "Reason For Disbursement" + }, + "course.experiencePoints.disbursement.DisbursementForm.submit": { + "defaultMessage": "Disburse Points" + }, + "course.experiencePoints.disbursement.DisbursementIndex.disbursements": { + "defaultMessage": "Experience Points" + }, + "course.experiencePoints.disbursement.DisbursementIndex.experienceTab": { + "defaultMessage": "History" + }, + "course.experiencePoints.disbursement.DisbursementIndex.fetchDisbursementFailure": { + "defaultMessage": "Failed to retrieve data." + }, + "course.experiencePoints.disbursement.DisbursementIndex.forumTab": { + "defaultMessage": "Forum Participation" + }, + "course.experiencePoints.disbursement.DisbursementIndex.generalTab": { + "defaultMessage": "General Disbursement" + }, + "course.experiencePoints.disbursement.DisbursementTable.copy": { + "defaultMessage": "Copy value for all students" + }, + "course.experiencePoints.disbursement.DisbursementTable.name": { + "defaultMessage": "Name" + }, + "course.experiencePoints.disbursement.DisbursementTable.pointsAwarded": { + "defaultMessage": "EXP Awarded" + }, + "course.experiencePoints.disbursement.DisbursementTable.remove": { + "defaultMessage": "Remove value for all students" + }, + "course.experiencePoints.disbursement.FilterForm.endTime": { + "defaultMessage": "End Date *" + }, + "course.experiencePoints.disbursement.FilterForm.startTime": { + "defaultMessage": "Start Date *" + }, + "course.experiencePoints.disbursement.FilterForm.submit": { + "defaultMessage": "Search" + }, + "course.experiencePoints.disbursement.FilterForm.weeklyCap": { + "defaultMessage": "Weekly Cap" + }, + "course.experiencePoints.disbursement.ForumDisbursement.fetchDisbursementFailure": { + "defaultMessage": "Failed to retrieve data." + }, + "course.experiencePoints.disbursement.ForumDisbursement.fetchForumPostsFailure": { + "defaultMessage": "Failed to fetch forum posts." + }, + "course.experiencePoints.disbursement.ForumDisbursement.postListDialogHeader": { + "defaultMessage": "Posts created between {startDate} and {endDate} by" + }, + "course.experiencePoints.disbursement.ForumDisbursementForm.createDisbursementFailure": { + "defaultMessage": "Failed to award experience points." + }, + "course.experiencePoints.disbursement.ForumDisbursementForm.createDisbursementSuccess": { + "defaultMessage": "Experience points disbursed to {recipientCount} recipients." + }, + "course.experiencePoints.disbursement.ForumDisbursementForm.fetchForumPostsFailure": { + "defaultMessage": "Failed to fetch forum posts." + }, + "course.experiencePoints.disbursement.ForumDisbursementForm.reason": { + "defaultMessage": "Reason For Disbursement" + }, + "course.experiencePoints.disbursement.ForumDisbursementForm.reasonFill": { + "defaultMessage": "Forum Participation" + }, + "course.experiencePoints.disbursement.ForumDisbursementForm.submit": { + "defaultMessage": "Disburse Points" + }, + "course.experiencePoints.disbursement.ForumDisbursementForm.viewPosts": { + "defaultMessage": "View Forum Posts" + }, + "course.experiencePoints.disbursement.ForumDisbursementTable.exp": { + "defaultMessage": "Experience Points" + }, + "course.experiencePoints.disbursement.ForumDisbursementTable.level": { + "defaultMessage": "Level" + }, + "course.experiencePoints.disbursement.ForumDisbursementTable.name": { + "defaultMessage": "Name" + }, + "course.experiencePoints.disbursement.ForumDisbursementTable.pointsAwarded": { + "defaultMessage": "EXP Awarded" + }, + "course.experiencePoints.disbursement.ForumDisbursementTable.postCount": { + "defaultMessage": "Post Count" + }, + "course.experiencePoints.disbursement.ForumDisbursementTable.voteTally": { + "defaultMessage": "Vote Tally" + }, + "course.experiencePoints.disbursement.ForumPostTable.datePosted": { + "defaultMessage": "Date Posted" + }, + "course.experiencePoints.disbursement.ForumPostTable.topicTitle": { + "defaultMessage": "Topic Title" + }, + "course.experiencePoints.disbursement.ForumPostTable.voteTally": { + "defaultMessage": "Vote Tally" + }, + "course.experiencePoints.disbursement.GeneralDisbursement.fetchDisbursementFailure": { + "defaultMessage": "Failed to retrieve data." + }, "course.experiencePoints.downloadCsvButton": { "defaultMessage": "Download CSV" }, @@ -4853,581 +5690,830 @@ "course.experiencePoints.downloadRequestSuccess": { "defaultMessage": "Your request to download is successful" }, + "course.experiencePoints.fetchRecordsFailure": { + "defaultMessage": "Failed to fetch records" + }, "course.experiencePoints.filterByNameButton": { "defaultMessage": "Filter by Name" }, - "course.experiencePoints.disbursement.DisbursementForm.createDisbursementFailure": { - "defaultMessage": "Failed to award experience points." + "course.forum.FormShow.fetchTopicsFailure": { + "defaultMessage": "Failed to retrieve forum topic data." }, - "course.experiencePoints.disbursement.DisbursementForm.createDisbursementSuccess": { - "defaultMessage": "Experience points disbursed to {recipientCount} recipients." + "course.forum.FormShow.header": { + "defaultMessage": "Forum Topics" }, - "course.experiencePoints.disbursement.DisbursementForm.fetchDisbursementFailure": { - "defaultMessage": "Failed to retrieve data." + "course.forum.FormShow.markAllAsReadSuccess": { + "defaultMessage": "All topics in this forum have been marked as read." }, - "course.experiencePoints.disbursement.DisbursementForm.fetchFilterFailure": { - "defaultMessage": "Failed to retrieve filtered forum users." + "course.forum.FormShow.newTopic": { + "defaultMessage": "New Topic" }, - "course.experiencePoints.disbursement.DisbursementForm.fetchFilterNone": { - "defaultMessage": "No post made between these 2 dates." + "course.forum.ForumEdit.editForum": { + "defaultMessage": "Edit Forum" }, - "course.experiencePoints.disbursement.DisbursementForm.filter": { - "defaultMessage": "Filter by group" + "course.forum.ForumEdit.updateFailure": { + "defaultMessage": "Failed to update the forum." }, - "course.experiencePoints.disbursement.DisbursementForm.noDisbursement": { - "defaultMessage": "No points are disbursed to users." + "course.forum.ForumEdit.updateSuccess": { + "defaultMessage": "Forum {title} has been updated." + }, + "course.forum.ForumForm.description": { + "defaultMessage": "Description" + }, + "course.forum.ForumForm.forumTopicsAutoSubscribe": { + "defaultMessage": "Enable auto-subscription to a forum topic when a user creates the topic, new posts or replies." + }, + "course.forum.ForumForm.name": { + "defaultMessage": "Name" + }, + "course.forum.ForumManagementButtons.deletionConfirm": { + "defaultMessage": "Are you sure you wish to delete this forum \"{title}\"?" + }, + "course.forum.ForumManagementButtons.deletionFailure": { + "defaultMessage": "Failed to delete forum - {error}" + }, + "course.forum.ForumManagementButtons.deletionSuccess": { + "defaultMessage": "Forum {title} was deleted." + }, + "course.forum.ForumNew.creationFailure": { + "defaultMessage": "Failed to create forum." + }, + "course.forum.ForumNew.creationSuccess": { + "defaultMessage": "Forum {title} has been created." + }, + "course.forum.ForumNew.newForum": { + "defaultMessage": "New Forum" + }, + "course.forum.ForumTable.autoSubscribe": { + "defaultMessage": "Users will be automatically subscribed to a topic in this forum when they create a post in the topic." + }, + "course.forum.ForumTable.forum": { + "defaultMessage": "Forum" + }, + "course.forum.ForumTable.hasUnresolved": { + "defaultMessage": "Has unresolved question(s)" + }, + "course.forum.ForumTable.isSubscribed": { + "defaultMessage": "Subscribed?" + }, + "course.forum.ForumTable.noForum": { + "defaultMessage": "No Forum" + }, + "course.forum.ForumTable.posts": { + "defaultMessage": "Posts" + }, + "course.forum.ForumTable.topics": { + "defaultMessage": "Topics" + }, + "course.forum.ForumTable.views": { + "defaultMessage": "Views" + }, + "course.forum.ForumTable.votes": { + "defaultMessage": "Votes" + }, + "course.forum.ForumTopicEdit.editForum": { + "defaultMessage": "Edit Topic" + }, + "course.forum.ForumTopicEdit.updateFailure": { + "defaultMessage": "Failed to update the topic." + }, + "course.forum.ForumTopicEdit.updateSuccess": { + "defaultMessage": "Topic {title} has been updated." + }, + "course.forum.ForumTopicForm.postAnonymously": { + "defaultMessage": "Anonymous post" + }, + "course.forum.ForumTopicForm.text": { + "defaultMessage": "Text" + }, + "course.forum.ForumTopicForm.title": { + "defaultMessage": "Title" + }, + "course.forum.ForumTopicForm.topicType": { + "defaultMessage": "Topic Type" + }, + "course.forum.ForumTopicForm.topicType.announcement": { + "defaultMessage": "Announcement" + }, + "course.forum.ForumTopicForm.topicType.normal": { + "defaultMessage": "Normal" + }, + "course.forum.ForumTopicForm.topicType.question": { + "defaultMessage": "Question" + }, + "course.forum.ForumTopicForm.topicType.sticky": { + "defaultMessage": "Sticky" + }, + "course.forum.ForumTopicManagementButtons.deletionConfirm": { + "defaultMessage": "Are you sure you wish to delete this topic \"{title}\"?" + }, + "course.forum.ForumTopicManagementButtons.deletionFailure": { + "defaultMessage": "Failed to delete topic - {error}" + }, + "course.forum.ForumTopicManagementButtons.deletionSuccess": { + "defaultMessage": "Topic {title} was deleted." + }, + "course.forum.ForumTopicNew.creationFailure": { + "defaultMessage": "Failed to create topic." + }, + "course.forum.ForumTopicNew.creationSuccess": { + "defaultMessage": "Topic {title} has been created." + }, + "course.forum.ForumTopicNew.newTopic": { + "defaultMessage": "New Topic" + }, + "course.forum.ForumTopicPostEditActionButtons.discardEditPostPromptAction": { + "defaultMessage": "Discard" + }, + "course.forum.ForumTopicPostEditActionButtons.discardEditPostPromptMessage": { + "defaultMessage": "You have edited this post and there are unsaved changes. Do you wish to proceed?" + }, + "course.forum.ForumTopicPostEditActionButtons.discardEditPostPromptTitle": { + "defaultMessage": "Discard unsaved changes?" + }, + "course.forum.ForumTopicPostEditActionButtons.emptyPost": { + "defaultMessage": "Post cannot be empty!" + }, + "course.forum.ForumTopicPostEditActionButtons.updateFailure": { + "defaultMessage": "Failed to update the post - {error}" + }, + "course.forum.ForumTopicPostEditActionButtons.updateSuccess": { + "defaultMessage": "The post has been updated." + }, + "course.forum.ForumTopicPostForm.postAnonymously": { + "defaultMessage": "Anonymous post" + }, + "course.forum.ForumTopicPostManagementButtons.deletionConfirm": { + "defaultMessage": "Are you sure you wish to delete this topic post?" + }, + "course.forum.ForumTopicPostManagementButtons.deletionFailure": { + "defaultMessage": "Failed to delete topic - {error}" + }, + "course.forum.ForumTopicPostManagementButtons.deletionSuccess": { + "defaultMessage": "The post has been deleted." + }, + "course.forum.ForumTopicPostNew.creationFailure": { + "defaultMessage": "Failed to create the post - {error}" + }, + "course.forum.ForumTopicPostNew.creationSuccess": { + "defaultMessage": "The post has been created." + }, + "course.forum.ForumTopicPostNew.newPost": { + "defaultMessage": "Create a New Post" + }, + "course.forum.ForumTopicShow.fetchPostsFailure": { + "defaultMessage": "Failed to retrieve forum topic data." + }, + "course.forum.ForumTopicShow.header": { + "defaultMessage": "Forum Topic Posts" + }, + "course.forum.ForumTopicShow.lockedNote": { + "defaultMessage": "You are unable to add new post as this topic has been locked by the teaching staff." + }, + "course.forum.ForumTopicShow.noPosts": { + "defaultMessage": "No Post" + }, + "course.forum.ForumTopicShow.topicResolved": { + "defaultMessage": "This question topic has been resolved." + }, + "course.forum.ForumTopicShow.topicUnresolved": { + "defaultMessage": "This question topic is unresolved." + }, + "course.forum.ForumTopicShow.topicUnresolvedNote": { + "defaultMessage": "Mark helpful post(s) as answer(s) to resolve this question." + }, + "course.forum.ForumTopicTable.hidden": { + "defaultMessage": "This topic is hidden for students." + }, + "course.forum.ForumTopicTable.isSubscribed": { + "defaultMessage": "Subscribed?" + }, + "course.forum.ForumTopicTable.lastPostedBy": { + "defaultMessage": "Last Posted By" + }, + "course.forum.ForumTopicTable.locked": { + "defaultMessage": "This topic is closed; it no longer accepts new replies." + }, + "course.forum.ForumTopicTable.noTopic": { + "defaultMessage": "No Topic" + }, + "course.forum.ForumTopicTable.posts": { + "defaultMessage": "Posts" + }, + "course.forum.ForumTopicTable.resolved": { + "defaultMessage": "Question (Resolved)" + }, + "course.forum.ForumTopicTable.startedBy": { + "defaultMessage": "Started By" + }, + "course.forum.ForumTopicTable.topics": { + "defaultMessage": "Topics" + }, + "course.forum.ForumTopicTable.unresolved": { + "defaultMessage": "Question (Unresolved)" + }, + "course.forum.ForumTopicTable.views": { + "defaultMessage": "Views" + }, + "course.forum.ForumTopicTable.votes": { + "defaultMessage": "Votes" + }, + "course.forum.ForumsIndex.fetchForumsFailure": { + "defaultMessage": "Failed to retrieve forum data." + }, + "course.forum.ForumsIndex.header": { + "defaultMessage": "Forums" + }, + "course.forum.ForumsIndex.markAllAsReadFailed": { + "defaultMessage": "Failed to mark all topics as read. Please try again later." + }, + "course.forum.ForumsIndex.markAllAsReadSuccess": { + "defaultMessage": "All topics have been marked as read." + }, + "course.forum.ForumsIndex.newForum": { + "defaultMessage": "New Forum" + }, + "course.forum.GenerateReplyButton.generateReply": { + "defaultMessage": "Generate reply" + }, + "course.forum.GenerateReplyButton.generateReplySuccess": { + "defaultMessage": "A reply has been successfully generated." + }, + "course.forum.GenerateReplyButton.generatingReply": { + "defaultMessage": "Generating reply" + }, + "course.forum.HideButton.hide": { + "defaultMessage": "Hide" + }, + "course.forum.HideButton.hideFailure": { + "defaultMessage": "Failed to hide the topic \"{title}\" - {error}" + }, + "course.forum.HideButton.hideSuccess": { + "defaultMessage": "The topic \"{title}\" has successfully been hidden." + }, + "course.forum.HideButton.hideTooltip": { + "defaultMessage": "Hide topic from students" + }, + "course.forum.HideButton.unhide": { + "defaultMessage": "Unhide" }, - "course.experiencePoints.disbursement.DisbursementForm.notNumber": { - "defaultMessage": "Not a Number." + "course.forum.HideButton.unhideFailure": { + "defaultMessage": "Failed to unhide the topic \"{title}\" - {error}" }, - "course.experiencePoints.disbursement.DisbursementForm.reason": { - "defaultMessage": "Reason For Disbursement" + "course.forum.HideButton.unhideSuccess": { + "defaultMessage": "The topic \"{title}\" has successfully been unhidden." }, - "course.experiencePoints.disbursement.DisbursementForm.submit": { - "defaultMessage": "Disburse Points" + "course.forum.HideButton.unhideTooltip": { + "defaultMessage": "Show topic to students" }, - "course.experiencePoints.disbursement.DisbursementIndex.disbursements": { - "defaultMessage": "Disbursed Experience Points" + "course.forum.LockButton.lockTooltip": { + "defaultMessage": "Lock to stop students from posting in this topic" }, - "course.experiencePoints.disbursement.DisbursementIndex.experienceTab": { - "defaultMessage": "History" + "course.forum.LockButton.locked": { + "defaultMessage": "Lock" }, - "course.experiencePoints.disbursement.DisbursementIndex.fetchDisbursementFailure": { - "defaultMessage": "Failed to retrieve data." + "course.forum.LockButton.lockedFailure": { + "defaultMessage": "Failed to locked the topic \"{title}\" - {error}" }, - "course.experiencePoints.disbursement.DisbursementIndex.forumTab": { - "defaultMessage": "Forum Participation" + "course.forum.LockButton.lockedSuccess": { + "defaultMessage": "The topic \"{title}\" has successfully been locked." }, - "course.experiencePoints.disbursement.DisbursementIndex.generalTab": { - "defaultMessage": "General Disbursement" + "course.forum.LockButton.unlockTooltip": { + "defaultMessage": "Unlock to allow students to post within this topic" }, - "course.experiencePoints.disbursement.DisbursementTable.copy": { - "defaultMessage": "Copy value for all students" + "course.forum.LockButton.unlocked": { + "defaultMessage": "Unlock" }, - "course.experiencePoints.disbursement.DisbursementTable.name": { - "defaultMessage": "Name" + "course.forum.LockButton.unlockedFailure": { + "defaultMessage": "Failed to unlocked the topic \"{title}\" - {error}" }, - "course.experiencePoints.disbursement.DisbursementTable.pointsAwarded": { - "defaultMessage": "EXP Awarded" + "course.forum.LockButton.unlockedSuccess": { + "defaultMessage": "The topic \"{title}\" has successfully been unlocked." }, - "course.experiencePoints.disbursement.DisbursementTable.remove": { - "defaultMessage": "Remove value for all students" + "course.forum.MarkAllAsReadButton.AllReadTooltip": { + "defaultMessage": "Hooray! All topics have been read!" }, - "course.experiencePoints.disbursement.FilterForm.endTime": { - "defaultMessage": "End Date *" + "course.forum.MarkAllAsReadButton.markAllAsRead": { + "defaultMessage": "Mark all as read" }, - "course.experiencePoints.disbursement.FilterForm.startTime": { - "defaultMessage": "Start Date *" + "course.forum.MarkAllAsReadButton.markAllAsReadTooltip": { + "defaultMessage": "Mark all forum posts on the current page as read" }, - "course.experiencePoints.disbursement.FilterForm.submit": { - "defaultMessage": "Search" + "course.forum.MarkAnswerButton.markAsAnswer": { + "defaultMessage": "Mark as answer" }, - "course.experiencePoints.disbursement.FilterForm.weeklyCap": { - "defaultMessage": "Weekly Cap" + "course.forum.MarkAnswerButton.markAsAnswerAndPublish": { + "defaultMessage": "Mark as answer and publish" }, - "course.experiencePoints.disbursement.ForumDisbursementForm.createDisbursementFailure": { - "defaultMessage": "Failed to award experience points." + "course.forum.MarkAnswerButton.markAsAnswerAndPublishTooltip": { + "defaultMessage": "Mark as answer and publish for students to view" }, - "course.experiencePoints.disbursement.ForumDisbursementForm.createDisbursementSuccess": { - "defaultMessage": "Experience points disbursed to {recipientCount} recipients." + "course.forum.MarkAnswerButton.markedAsAnswer": { + "defaultMessage": "Marked as answer" }, - "course.experiencePoints.disbursement.ForumDisbursementForm.fetchForumPostsFailure": { - "defaultMessage": "Failed to fetch forum posts." + "course.forum.MarkAnswerButton.unmarkAsAnswer": { + "defaultMessage": "Unmark as answer" }, - "course.experiencePoints.disbursement.ForumDisbursementForm.postListDialogHeader": { - "defaultMessage": "Posts created between {startDate} and {endDate} by" + "course.forum.MarkAnswerButton.updateFailure": { + "defaultMessage": "Failed to update the post - {error}" }, - "course.experiencePoints.disbursement.ForumDisbursementForm.reason": { - "defaultMessage": "Reason For Disbursement" + "course.forum.NextUnreadButton.AllReadTooltip": { + "defaultMessage": "Hooray! All topics have been read!" }, - "course.experiencePoints.disbursement.ForumDisbursementForm.reasonFill": { - "defaultMessage": "Forum Participation" + "course.forum.NextUnreadButton.nextUnread": { + "defaultMessage": "Next Unread" }, - "course.experiencePoints.disbursement.ForumDisbursementForm.submit": { - "defaultMessage": "Disburse Points" + "course.forum.NextUnreadButton.nextUnreadTooltip": { + "defaultMessage": "Jump to next unread topic" }, - "course.experiencePoints.disbursement.ForumDisbursementForm.viewPosts": { - "defaultMessage": "View Forum Posts" + "course.forum.PostCreatorObject.anonymousUser": { + "defaultMessage": "Anonymous User" }, - "course.experiencePoints.disbursement.ForumDisbursementTable.exp": { - "defaultMessage": "Experience Points" + "course.forum.PostCreatorObject.maskUser": { + "defaultMessage": "Mask User" }, - "course.experiencePoints.disbursement.ForumDisbursementTable.level": { - "defaultMessage": "Level" + "course.forum.PostCreatorObject.postAnonymously": { + "defaultMessage": "Anonymous post" }, - "course.experiencePoints.disbursement.ForumDisbursementTable.name": { - "defaultMessage": "Name" + "course.forum.PostCreatorObject.unmaskUser": { + "defaultMessage": "Unmask User" }, - "course.experiencePoints.disbursement.ForumDisbursementTable.pointsAwarded": { - "defaultMessage": "EXP Awarded" + "course.forum.ReplyCard.emptyPost": { + "defaultMessage": "Post cannot be empty!" }, - "course.experiencePoints.disbursement.ForumDisbursementTable.postCount": { - "defaultMessage": "Post Count" + "course.forum.ReplyCard.postAnonymously": { + "defaultMessage": "Anonymous post" }, - "course.experiencePoints.disbursement.ForumDisbursementTable.voteTally": { - "defaultMessage": "Vote Tally" + "course.forum.ReplyCard.replyFailure": { + "defaultMessage": "Failed to submit the post - {error}" }, - "course.experiencePoints.disbursement.ForumPostTable.datePosted": { - "defaultMessage": "Date Posted" + "course.forum.ReplyCard.replySuccess": { + "defaultMessage": "The reply post has been created." }, - "course.experiencePoints.disbursement.ForumPostTable.topicTitle": { - "defaultMessage": "Topic Title" + "course.forum.ReplyCard.replyTo": { + "defaultMessage": "Reply to {user}" }, - "course.experiencePoints.disbursement.ForumPostTable.voteTally": { - "defaultMessage": "Vote Tally" + "course.forum.SubscribeButton.commonTranslations.manageMySubscription": { + "defaultMessage": "Manage My Subscriptions" }, - "course.forum.FormShow.fetchTopicsFailure": { - "defaultMessage": "Failed to retrieve forum topic data." + "course.forum.SubscribeButton.commonTranslations.subscribe": { + "defaultMessage": "Subscribe" }, - "course.forum.FormShow.header": { - "defaultMessage": "Forum Topics" + "course.forum.SubscribeButton.commonTranslations.unsubscribe": { + "defaultMessage": "Unsubscribe" }, - "course.forum.FormShow.markAllAsReadSuccess": { - "defaultMessage": "All topics in this forum have been marked as read." + "course.forum.SubscribeButton.commonTranslations.updateSubscriptionFailure": { + "defaultMessage": "Failed to update subscription - {error}" }, - "course.forum.FormShow.newTopic": { - "defaultMessage": "New Topic" + "course.forum.SubscribeButton.forumTopicTranslations.adminSettingSubscribed": { + "defaultMessage": "Subscription of forum topics is disabled by the course admin." }, - "course.forum.ForumEdit.editForum": { - "defaultMessage": "Edit Forum" + "course.forum.SubscribeButton.forumTopicTranslations.subscribeSuccess": { + "defaultMessage": "You have successfully been subscribed to the forum topic {title}." }, - "course.forum.ForumEdit.updateFailure": { - "defaultMessage": "Failed to update the forum." + "course.forum.SubscribeButton.forumTopicTranslations.subscribeTooltip": { + "defaultMessage": "Subscribe to receive email notifications when someone replies in this forum topic." }, - "course.forum.ForumEdit.updateSuccess": { - "defaultMessage": "Forum {title} has been updated." + "course.forum.SubscribeButton.forumTopicTranslations.unsubscribeSuccess": { + "defaultMessage": "You have successfully been unsubscribed from the forum topic {title}." }, - "course.forum.ForumForm.description": { - "defaultMessage": "Description" + "course.forum.SubscribeButton.forumTopicTranslations.unsubscribeTooltip": { + "defaultMessage": "Unsubscribe to stop receiving email notifications when someone replies in this forum topic." }, - "course.forum.ForumForm.forumTopicsAutoSubscribe": { - "defaultMessage": "Enable auto-subscription to a forum topic when a user creates the topic, new posts or replies." + "course.forum.SubscribeButton.forumTopicTranslations.userSettingSubscribed": { + "defaultMessage": "You have unsubscribed from \"New Post and Reply\" for forums in this course. Please go to {manageMySubscriptionLink} to enable it." }, - "course.forum.ForumForm.name": { - "defaultMessage": "Name" + "course.forum.SubscribeButton.forumTranslations.adminSettingSubscribed": { + "defaultMessage": "Subscription of new forum topic is disabled by the course admin." }, - "course.forum.ForumManagementButtons.deletionConfirm": { - "defaultMessage": "Are you sure you wish to delete this forum \"{title}\"?" + "course.forum.SubscribeButton.forumTranslations.subscribeSuccess": { + "defaultMessage": "You have successfully been subscribed to {title}." }, - "course.forum.ForumManagementButtons.deletionFailure": { - "defaultMessage": "Failed to delete forum - {error}" + "course.forum.SubscribeButton.forumTranslations.subscribeTooltip": { + "defaultMessage": "Subscribe to receive an email notification when a new topic is created." }, - "course.forum.ForumManagementButtons.deletionSuccess": { - "defaultMessage": "Forum {title} was deleted." + "course.forum.SubscribeButton.forumTranslations.unsubscribeSuccess": { + "defaultMessage": "You have successfully been unsubscribed from {title}." }, - "course.forum.ForumNew.creationFailure": { - "defaultMessage": "Failed to create forum." + "course.forum.SubscribeButton.forumTranslations.unsubscribeTooltip": { + "defaultMessage": "Unsubscribe to stop receiving email notifications when a new topic is created." }, - "course.forum.ForumNew.creationSuccess": { - "defaultMessage": "Forum {title} has been created." + "course.forum.SubscribeButton.forumTranslations.userSettingSubscribed": { + "defaultMessage": "You have unsubscribed from \"New Topic\" for forums in this course. Please go to {manageMySubscriptionLink} to enable it." }, - "course.forum.ForumNew.newForum": { - "defaultMessage": "New Forum" + "course.forum.VotePostButton.updateFailure": { + "defaultMessage": "Failed to update the vote number - {error}" }, - "course.forum.ForumTable.autoSubscribe": { - "defaultMessage": "Users will be automatically subscribed to a topic in this forum when they create a post in the topic." + "course.forum.forum.markAllAsReadFailed": { + "defaultMessage": "Failed to mark all topics in this forum as read. Please try again later." }, - "course.forum.ForumTable.forum": { - "defaultMessage": "Forum" + "course.forum.publishButton.generateReplyDisabledTooltip": { + "defaultMessage": "Disabled for generated reply" }, - "course.forum.ForumTable.hasUnresolved": { - "defaultMessage": "Has unresolved question(s)" + "course.forum.publishButton.generateReplySuccess": { + "defaultMessage": "Failed to generate a reply." }, - "course.forum.ForumTable.isSubscribed": { - "defaultMessage": "Subscribed?" + "course.forum.publishButton.generateReplyTooltip": { + "defaultMessage": "Generate a draft reply using AI" }, - "course.forum.ForumTable.noForum": { - "defaultMessage": "No Forum" + "course.forum.publishButton.publish": { + "defaultMessage": "Publish" }, - "course.forum.ForumTable.posts": { - "defaultMessage": "Posts" + "course.forum.publishButton.publishFailure": { + "defaultMessage": "Failed to publish the post." }, - "course.forum.ForumTable.topics": { - "defaultMessage": "Topics" + "course.forum.publishButton.publishSuccess": { + "defaultMessage": "The post has succesfully been published." }, - "course.forum.ForumTable.views": { - "defaultMessage": "Views" + "course.forum.publishButton.publishTooltip": { + "defaultMessage": "Pusblish post to students" }, - "course.forum.ForumTable.votes": { - "defaultMessage": "Votes" + "course.gradebook.AddExternalColumnPrompt.cancel": { + "defaultMessage": "Cancel" }, - "course.forum.ForumTopicEdit.editForum": { - "defaultMessage": "Edit Topic" + "course.gradebook.AddExternalColumnPrompt.create": { + "defaultMessage": "Create" }, - "course.forum.ForumTopicEdit.updateFailure": { - "defaultMessage": "Failed to update the topic." + "course.gradebook.AddExternalColumnPrompt.error": { + "defaultMessage": "Could not create the external assessment." }, - "course.forum.ForumTopicEdit.updateSuccess": { - "defaultMessage": "Topic {title} has been updated." + "course.gradebook.AddExternalColumnPrompt.maxLabel": { + "defaultMessage": "Max marks" }, - "course.forum.ForumTopicForm.postAnonymously": { - "defaultMessage": "Anonymous post" + "course.gradebook.AddExternalColumnPrompt.nameLabel": { + "defaultMessage": "Name" }, - "course.forum.ForumTopicForm.text": { - "defaultMessage": "Text" + "course.gradebook.AddExternalColumnPrompt.success": { + "defaultMessage": "External assessment created." }, - "course.forum.ForumTopicForm.title": { - "defaultMessage": "Title" + "course.gradebook.AddExternalColumnPrompt.title": { + "defaultMessage": "Add external assessment" }, - "course.forum.ForumTopicForm.topicType": { - "defaultMessage": "Topic Type" + "course.gradebook.ConfigureWeightsPrompt.allExcluded": { + "defaultMessage": "All assessments in \"{tab}\" are excluded — it contributes nothing to the total." }, - "course.forum.ForumTopicForm.topicType.announcement": { - "defaultMessage": "Announcement" + "course.gradebook.ConfigureWeightsPrompt.allExcludedCount": { + "defaultMessage": "All {n} excluded" }, - "course.forum.ForumTopicForm.topicType.normal": { - "defaultMessage": "Normal" + "course.gradebook.ConfigureWeightsPrompt.customMode": { + "defaultMessage": "Custom" }, - "course.forum.ForumTopicForm.topicType.question": { - "defaultMessage": "Question" + "course.gradebook.ConfigureWeightsPrompt.customSum": { + "defaultMessage": "Assessment weights: {sum} / {total}" }, - "course.forum.ForumTopicForm.topicType.sticky": { - "defaultMessage": "Sticky" + "course.gradebook.ConfigureWeightsPrompt.defaultsHint": { + "defaultMessage": "No weights set yet — these are suggested defaults with every tab counting equally. Save to confirm, or adjust below." }, - "course.forum.ForumTopicManagementButtons.deletionConfirm": { - "defaultMessage": "Are you sure you wish to delete this topic \"{title}\"?" + "course.gradebook.ConfigureWeightsPrompt.descriptionDrop": { + "defaultMessage": "In Equal mode, optionally drop each student's N lowest-scoring assessments before averaging." }, - "course.forum.ForumTopicManagementButtons.deletionFailure": { - "defaultMessage": "Failed to delete topic - {error}" + "course.gradebook.ConfigureWeightsPrompt.descriptionExclusion": { + "defaultMessage": "Expand a tab to include or exclude individual assessments from grading." + }, + "course.gradebook.ConfigureWeightsPrompt.descriptionIntro": { + "defaultMessage": "Control how tabs and assessments count toward each student's total grade." }, - "course.forum.ForumTopicManagementButtons.deletionSuccess": { - "defaultMessage": "Topic {title} was deleted." + "course.gradebook.ConfigureWeightsPrompt.descriptionModes": { + "defaultMessage": "Choose Equal (all assessments share the tab's weight) or Custom (set each assessment's share)." }, - "course.forum.ForumTopicNew.creationFailure": { - "defaultMessage": "Failed to create topic." + "course.gradebook.ConfigureWeightsPrompt.descriptionWeights": { + "defaultMessage": "Set each tab's weight — how much it contributes to the total (weights should sum to 100)." }, - "course.forum.ForumTopicNew.creationSuccess": { - "defaultMessage": "Topic {title} has been created." + "course.gradebook.ConfigureWeightsPrompt.equalMode": { + "defaultMessage": "Equal" }, - "course.forum.ForumTopicNew.newTopic": { - "defaultMessage": "New Topic" + "course.gradebook.ConfigureWeightsPrompt.excluded": { + "defaultMessage": "Excluded" }, - "course.forum.ForumTopicPostEditActionButtons.discardEditPostPromptAction": { - "defaultMessage": "Discard" + "course.gradebook.ConfigureWeightsPrompt.excludedCount": { + "defaultMessage": "{n} excluded" }, - "course.forum.ForumTopicPostEditActionButtons.discardEditPostPromptMessage": { - "defaultMessage": "You have edited this post and there are unsaved changes. Do you wish to proceed?" + "course.gradebook.ConfigureWeightsPrompt.includeAssessment": { + "defaultMessage": "Include {assessment} in grade" }, - "course.forum.ForumTopicPostEditActionButtons.discardEditPostPromptTitle": { - "defaultMessage": "Discard unsaved changes?" + "course.gradebook.ConfigureWeightsPrompt.modeAria": { + "defaultMessage": "{tab} weight mode" }, - "course.forum.ForumTopicPostEditActionButtons.emptyPost": { - "defaultMessage": "Post cannot be empty!" + "course.gradebook.ConfigureWeightsPrompt.ofGrade": { + "defaultMessage": "{pct}% of grade" }, - "course.forum.ForumTopicPostEditActionButtons.updateFailure": { - "defaultMessage": "Failed to update the post - {error}" + "course.gradebook.ConfigureWeightsPrompt.promptTitle": { + "defaultMessage": "Configure contributions" }, - "course.forum.ForumTopicPostEditActionButtons.updateSuccess": { - "defaultMessage": "The post has been updated." + "course.gradebook.ConfigureWeightsPrompt.saveError": { + "defaultMessage": "Failed to save weights. Please try again." }, - "course.forum.ForumTopicPostForm.postAnonymously": { - "defaultMessage": "Anonymous post" + "course.gradebook.ConfigureWeightsPrompt.total": { + "defaultMessage": "Total: {sum}%" }, - "course.forum.ForumTopicPostManagementButtons.deletionConfirm": { - "defaultMessage": "Are you sure you wish to delete this topic post?" + "course.gradebook.ConfigureWeightsPrompt.unbalanced": { + "defaultMessage": "Assessment weights for \"{tab}\" must sum to its tab total before saving." }, - "course.forum.ForumTopicPostManagementButtons.deletionFailure": { - "defaultMessage": "Failed to delete topic - {error}" + "course.gradebook.ConfigureWeightsPrompt.valueTooHigh": { + "defaultMessage": "Value must be at most 100" }, - "course.forum.ForumTopicPostManagementButtons.deletionSuccess": { - "defaultMessage": "The post has been deleted." + "course.gradebook.ConfigureWeightsPrompt.valueTooLow": { + "defaultMessage": "Value must be at least 0" }, - "course.forum.ForumTopicPostNew.creationFailure": { - "defaultMessage": "Failed to create the post - {error}" + "course.gradebook.ConfigureWeightsPrompt.weightsDoNotSum": { + "defaultMessage": "Weights do not sum to 100. Saving is allowed; Total may be inaccurate." }, - "course.forum.ForumTopicPostNew.creationSuccess": { - "defaultMessage": "The post has been created." + "course.gradebook.DeleteExternalColumnPrompt.body": { + "defaultMessage": "Delete \"{title}\"? This permanently removes the column and every student grade in it. This cannot be undone." }, - "course.forum.ForumTopicPostNew.newPost": { - "defaultMessage": "Create a New Post" + "course.gradebook.DeleteExternalColumnPrompt.cancel": { + "defaultMessage": "Cancel" }, - "course.forum.ForumTopicShow.fetchPostsFailure": { - "defaultMessage": "Failed to retrieve forum topic data." + "course.gradebook.DeleteExternalColumnPrompt.confirm": { + "defaultMessage": "Delete" }, - "course.forum.ForumTopicShow.header": { - "defaultMessage": "Forum Topic Posts" + "course.gradebook.DeleteExternalColumnPrompt.error": { + "defaultMessage": "Could not delete the external assessment." }, - "course.forum.ForumTopicShow.lockedNote": { - "defaultMessage": "You are unable to add new post as this topic has been locked by the teaching staff." + "course.gradebook.DeleteExternalColumnPrompt.title": { + "defaultMessage": "Delete external assessment" }, - "course.forum.ForumTopicShow.noPosts": { - "defaultMessage": "No Post" + "course.gradebook.ExternalGradeConflictPrompt.body": { + "defaultMessage": "These students already have a grade for these components. Keep their existing grades, or replace them with the values from your file? New students and blank cells are unaffected." }, - "course.forum.ForumTopicShow.topicResolved": { - "defaultMessage": "This question topic has been resolved." + "course.gradebook.ExternalGradeConflictPrompt.goBack": { + "defaultMessage": "Go Back" }, - "course.forum.ForumTopicShow.topicUnresolved": { - "defaultMessage": "This question topic is unresolved." + "course.gradebook.ExternalGradeConflictPrompt.keepExisting": { + "defaultMessage": "Keep Existing" }, - "course.forum.ForumTopicShow.topicUnresolvedNote": { - "defaultMessage": "Mark helpful post(s) as answer(s) to resolve this question." + "course.gradebook.ExternalGradeConflictPrompt.replace": { + "defaultMessage": "Replace" }, - "course.forum.ForumTopicTable.hidden": { - "defaultMessage": "This topic is hidden for students." + "course.gradebook.ExternalGradeConflictPrompt.title": { + "defaultMessage": "Resolve grade conflicts" }, - "course.forum.ForumTopicTable.isSubscribed": { - "defaultMessage": "Subscribed?" + "course.gradebook.ExternalGradeConflictTable.component": { + "defaultMessage": "Component" }, - "course.forum.ForumTopicTable.lastPostedBy": { - "defaultMessage": "Last Posted By" + "course.gradebook.ExternalGradeConflictTable.existing": { + "defaultMessage": "Existing grade" }, - "course.forum.ForumTopicTable.locked": { - "defaultMessage": "This topic is closed; it no longer accepts new replies." + "course.gradebook.ExternalGradeConflictTable.inFile": { + "defaultMessage": "In-file grade" }, - "course.forum.ForumTopicTable.noTopic": { - "defaultMessage": "No Topic" + "course.gradebook.ExternalGradeConflictTable.mismatch": { + "defaultMessage": "This identifier now resolves to a different student than the existing grade was imported under." }, - "course.forum.ForumTopicTable.posts": { - "defaultMessage": "Posts" + "course.gradebook.ExternalGradeConflictTable.student": { + "defaultMessage": "Student" }, - "course.forum.ForumTopicTable.resolved": { - "defaultMessage": "Question (Resolved)" + "course.gradebook.GradeLinkHint.hint": { + "defaultMessage": "Each grade is the total of the marks in a student's submission. Click any grade to open that submission and adjust the marks." }, - "course.forum.ForumTopicTable.startedBy": { - "defaultMessage": "Started By" + "course.gradebook.GradebookColumnTree.alwaysIncluded": { + "defaultMessage": "Always included" }, - "course.forum.ForumTopicTable.topics": { - "defaultMessage": "Topics" + "course.gradebook.GradebookColumnTree.gamification": { + "defaultMessage": "Gamification" }, - "course.forum.ForumTopicTable.unresolved": { - "defaultMessage": "Question (Unresolved)" + "course.gradebook.GradebookColumnTree.grades": { + "defaultMessage": "Grades" }, - "course.forum.ForumTopicTable.views": { - "defaultMessage": "Views" + "course.gradebook.GradebookColumnTree.studentInfo": { + "defaultMessage": "Student info" }, - "course.forum.ForumTopicTable.votes": { - "defaultMessage": "Votes" + "course.gradebook.GradebookIndex.addExternal": { + "defaultMessage": "Add external assessment" }, - "course.forum.ForumsIndex.fetchForumsFailure": { - "defaultMessage": "Failed to retrieve forum data." + "course.gradebook.GradebookIndex.allAssessments": { + "defaultMessage": "All assessments" }, - "course.forum.ForumsIndex.header": { - "defaultMessage": "Forums" + "course.gradebook.GradebookIndex.byWeight": { + "defaultMessage": "Weighted total" }, - "course.forum.ForumsIndex.markAllAsReadFailed": { - "defaultMessage": "Failed to mark all topics as read. Please try again later." + "course.gradebook.GradebookIndex.dialogTitle": { + "defaultMessage": "Select columns" }, - "course.forum.ForumsIndex.markAllAsReadSuccess": { - "defaultMessage": "All topics have been marked as read." + "course.gradebook.GradebookIndex.exportAllTooltip": { + "defaultMessage": "No rows selected - all rows will be exported." }, - "course.forum.ForumsIndex.newForum": { - "defaultMessage": "New Forum" + "course.gradebook.GradebookIndex.exportButton": { + "defaultMessage": "Export all rows" }, - "course.forum.HideButton.hide": { - "defaultMessage": "Hide" + "course.gradebook.GradebookIndex.exportRows": { + "defaultMessage": "Export {count, plural, one {# row} other {# rows}}" }, - "course.forum.HideButton.hideTooltip": { - "defaultMessage": "Hide topic from students" + "course.gradebook.GradebookIndex.fetchFailure": { + "defaultMessage": "Failed to retrieve Gradebook." }, - "course.forum.HideButton.hideFailure": { - "defaultMessage": "Failed to hide the topic \"{title}\" - {error}" + "course.gradebook.GradebookIndex.gradebook": { + "defaultMessage": "Gradebook" }, - "course.forum.HideButton.hideSuccess": { - "defaultMessage": "The topic \"{title}\" has successfully been hidden." + "course.gradebook.GradebookIndex.noStudents": { + "defaultMessage": "No students enrolled yet" }, - "course.forum.HideButton.unhide": { - "defaultMessage": "Unhide" + "course.gradebook.GradebookIndex.noStudentsHint": { + "defaultMessage": "Grades will appear here once students join the course." }, - "course.forum.HideButton.unhideTooltip": { - "defaultMessage": "Show topic to students" + "course.gradebook.GradebookIndex.searchStudents": { + "defaultMessage": "Search students" }, - "course.forum.HideButton.unhideFailure": { - "defaultMessage": "Failed to unhide the topic \"{title}\" - {error}" + "course.gradebook.GradebookIndex.selectColumns": { + "defaultMessage": "Select Columns" }, - "course.forum.HideButton.unhideSuccess": { - "defaultMessage": "The topic \"{title}\" has successfully been unhidden." + "course.gradebook.GradebookTable.delete": { + "defaultMessage": "Delete" }, - "course.forum.LockButton.locked": { - "defaultMessage": "Lock" + "course.gradebook.GradebookTable.externalBadge": { + "defaultMessage": "External" }, - "course.forum.LockButton.lockTooltip": { - "defaultMessage": "Lock to stop students from posting in this topic" + "course.gradebook.GradebookTable.externalGradeAria": { + "defaultMessage": "{title} grade for {name}" }, - "course.forum.LockButton.lockedFailure": { - "defaultMessage": "Failed to locked the topic \"{title}\" - {error}" + "course.gradebook.GradebookTable.externalMaxAria": { + "defaultMessage": "{title} max marks" }, - "course.forum.LockButton.lockedSuccess": { - "defaultMessage": "The topic \"{title}\" has successfully been locked." + "course.gradebook.GradebookTable.gradeSaveError": { + "defaultMessage": "Could not save the grade. Please try again." }, - "course.forum.LockButton.unlocked": { - "defaultMessage": "Unlock" + "course.gradebook.GradebookTable.manageAria": { + "defaultMessage": "manage {title}" }, - "course.forum.LockButton.unlockTooltip": { - "defaultMessage": "Unlock to allow students to post within this topic" + "course.gradebook.GradebookTable.maxMarks": { + "defaultMessage": "Max Marks" }, - "course.forum.LockButton.unlockedFailure": { - "defaultMessage": "Failed to unlocked the topic \"{title}\" - {error}" + "course.gradebook.GradebookTable.maxSaveError": { + "defaultMessage": "Could not save the max marks. Please try again." }, - "course.forum.LockButton.unlockedSuccess": { - "defaultMessage": "The topic \"{title}\" has successfully been unlocked." + "course.gradebook.GradebookTable.noDataColumnsHint": { + "defaultMessage": "No grade columns selected - export will include student info only." }, - "course.forum.MarkAllAsReadButton.AllReadTooltip": { - "defaultMessage": "Hooray! All topics have been read!" + "course.gradebook.GradebookTable.noDataColumnsHintWithGamification": { + "defaultMessage": "No grade or gamification columns selected - export will include student info only." }, - "course.forum.MarkAllAsReadButton.markAllAsRead": { - "defaultMessage": "Mark all as read" + "course.gradebook.GradebookTable.rename": { + "defaultMessage": "Rename" }, - "course.forum.MarkAllAsReadButton.markAllAsReadTooltip": { - "defaultMessage": "Mark all forum posts on the current page as read" + "course.gradebook.GradebookWeightedTable.collapseRow": { + "defaultMessage": "Collapse {name}" }, - "course.forum.MarkAnswerButton.markAsAnswer": { - "defaultMessage": "Mark as answer" + "course.gradebook.GradebookWeightedTable.configureWeights": { + "defaultMessage": "Configure Weights" }, - "course.forum.MarkAnswerButton.markedAsAnswer": { - "defaultMessage": "Marked as answer" + "course.gradebook.GradebookWeightedTable.defaultWeights": { + "defaultMessage": "Showing default weights — every tab counts equally. Click \"Configure Weights\" to set your own." }, - "course.forum.MarkAnswerButton.unmarkAsAnswer": { - "defaultMessage": "Unmark as answer" + "course.gradebook.GradebookWeightedTable.defaultWeightsNoAccess": { + "defaultMessage": "Showing default weights — every tab counts equally until weights are configured." }, - "course.forum.MarkAnswerButton.updateFailure": { - "defaultMessage": "Failed to update the post - {error}" + "course.gradebook.GradebookWeightedTable.displayMode": { + "defaultMessage": "Display mode" }, - "course.forum.NextUnreadButton.AllReadTooltip": { - "defaultMessage": "Hooray! All topics have been read!" + "course.gradebook.GradebookWeightedTable.displayPercent": { + "defaultMessage": "Percentage" }, - "course.forum.NextUnreadButton.nextUnread": { - "defaultMessage": "Next Unread" + "course.gradebook.GradebookWeightedTable.displayPercentTooltip": { + "defaultMessage": "What fraction of each tab the student earned. 100% on a tab worth 20% = the student earned all 20 grade points from that tab." }, - "course.forum.NextUnreadButton.nextUnreadTooltip": { - "defaultMessage": "Jump to next unread topic" + "course.gradebook.GradebookWeightedTable.displayPoints": { + "defaultMessage": "Points" }, - "course.forum.PostCreatorObject.anonymousUser": { - "defaultMessage": "Anonymous User" + "course.gradebook.GradebookWeightedTable.displayPointsTooltip": { + "defaultMessage": "How many grade points each tab contributes. Columns add up to the projected total." }, - "course.forum.PostCreatorObject.maskUser": { - "defaultMessage": "Mask User" + "course.gradebook.GradebookWeightedTable.downloadCsv": { + "defaultMessage": "Download as CSV" }, - "course.forum.PostCreatorObject.postAnonymously": { - "defaultMessage": "Anonymous post" + "course.gradebook.GradebookWeightedTable.excluded": { + "defaultMessage": "Excluded" }, - "course.forum.PostCreatorObject.unmaskUser": { - "defaultMessage": "Unmask User" + "course.gradebook.GradebookWeightedTable.expandRow": { + "defaultMessage": "Expand {name}" }, - "course.forum.ReplyCard.emptyPost": { - "defaultMessage": "Post cannot be empty!" + "course.gradebook.GradebookWeightedTable.noWeightsConfigured": { + "defaultMessage": "No weights configured — all tab weights are 0. Click \"Configure Weights\" to assign weights." }, - "course.forum.ReplyCard.postAnonymously": { - "defaultMessage": "Anonymous post" + "course.gradebook.GradebookWeightedTable.noWeightsNoAccess": { + "defaultMessage": "No tab weights have been configured yet." }, - "course.forum.ReplyCard.replyFailure": { - "defaultMessage": "Failed to submit the post - {error}" + "course.gradebook.GradebookWeightedTable.outOfWeight": { + "defaultMessage": "/{weight}" + }, + "course.gradebook.GradebookWeightedTable.percentOfGrade": { + "defaultMessage": "{weight}% of grade" }, - "course.forum.ReplyCard.replySuccess": { - "defaultMessage": "The reply post has been created." + "course.gradebook.GradebookWeightedTable.percentTotalExact": { + "defaultMessage": "100% total" }, - "course.forum.ReplyCard.replyTo": { - "defaultMessage": "Reply to {user}" + "course.gradebook.GradebookWeightedTable.percentTotalWarning": { + "defaultMessage": "{weight}% total" }, - "course.forum.SubscribeButton.commonTranslations.manageMySubscription": { - "defaultMessage": "Manage My Subscriptions" + "course.gradebook.GradebookWeightedTable.searchStudents": { + "defaultMessage": "Search students" }, - "course.forum.SubscribeButton.commonTranslations.subscribe": { - "defaultMessage": "Subscribe" + "course.gradebook.GradebookWeightedTable.total": { + "defaultMessage": "Total" }, - "course.forum.SubscribeButton.commonTranslations.unsubscribe": { - "defaultMessage": "Unsubscribe" + "course.gradebook.GradebookWeightedTable.weightsDoNotSum": { + "defaultMessage": "Weights do not sum to 100. Total may be inaccurate." }, - "course.forum.SubscribeButton.commonTranslations.updateSubscriptionFailure": { - "defaultMessage": "Failed to update subscription - {error}" + "course.gradebook.ImportExternalAssessmentsButton.label": { + "defaultMessage": "Import external assessments" }, - "course.forum.SubscribeButton.forumTopicTranslations.adminSettingSubscribed": { - "defaultMessage": "Subscription of forum topics is disabled by the course admin." + "course.gradebook.ImportWizard.addComponent": { + "defaultMessage": "Add component" }, - "course.forum.SubscribeButton.forumTopicTranslations.subscribeSuccess": { - "defaultMessage": "You have successfully been subscribed to the forum topic {title}." + "course.gradebook.ImportWizard.back": { + "defaultMessage": "Back" }, - "course.forum.SubscribeButton.forumTopicTranslations.subscribeTooltip": { - "defaultMessage": "Subscribe to receive email notifications when someone replies in this forum topic." + "course.gradebook.ImportWizard.cancel": { + "defaultMessage": "Cancel" }, - "course.forum.SubscribeButton.forumTopicTranslations.unsubscribeSuccess": { - "defaultMessage": "You have successfully been unsubscribed from the forum topic {title}." + "course.gradebook.ImportWizard.commitError": { + "defaultMessage": "Import failed. Nothing was saved." }, - "course.forum.SubscribeButton.forumTopicTranslations.unsubscribeTooltip": { - "defaultMessage": "Unsubscribe to stop receiving email notifications when someone replies in this forum topic." + "course.gradebook.ImportWizard.committed": { + "defaultMessage": "Import complete." }, - "course.forum.SubscribeButton.forumTopicTranslations.userSettingSubscribed": { - "defaultMessage": "You have unsubscribed from \"New Post and Reply\" for forums in this course. Please go to {manageMySubscriptionLink} to enable it." + "course.gradebook.ImportWizard.componentName": { + "defaultMessage": "Component name" }, - "course.forum.SubscribeButton.forumTranslations.adminSettingSubscribed": { - "defaultMessage": "Subscription of new forum topic is disabled by the course admin." + "course.gradebook.ImportWizard.continue": { + "defaultMessage": "Confirm import" }, - "course.forum.SubscribeButton.forumTranslations.subscribeSuccess": { - "defaultMessage": "You have successfully been subscribed to {title}." + "course.gradebook.ImportWizard.downloadTemplate": { + "defaultMessage": "Download template" }, - "course.forum.SubscribeButton.forumTranslations.subscribeTooltip": { - "defaultMessage": "Subscribe to receive an email notification when a new topic is created." + "course.gradebook.ImportWizard.email": { + "defaultMessage": "Email" }, - "course.forum.SubscribeButton.forumTranslations.unsubscribeSuccess": { - "defaultMessage": "You have successfully been unsubscribed from {title}." + "course.gradebook.ImportWizard.identifierMode": { + "defaultMessage": "Match students by" }, - "course.forum.SubscribeButton.forumTranslations.unsubscribeTooltip": { - "defaultMessage": "Unsubscribe to stop receiving email notifications when a new topic is created." + "course.gradebook.ImportWizard.malformed": { + "defaultMessage": "These cells are not valid numbers: {cells}" }, - "course.forum.SubscribeButton.forumTranslations.userSettingSubscribed": { - "defaultMessage": "You have unsubscribed from \"New Topic\" for forums in this course. Please go to {manageMySubscriptionLink} to enable it." + "course.gradebook.ImportWizard.maxMarks": { + "defaultMessage": "Max marks" }, - "course.forum.VotePostButton.updateFailure": { - "defaultMessage": "Failed to update the vote number - {error}" + "course.gradebook.ImportWizard.next": { + "defaultMessage": "Next" }, - "course.forum.forum.markAllAsReadFailed": { - "defaultMessage": "Failed to mark all topics in this forum as read. Please try again later." + "course.gradebook.ImportWizard.previewError": { + "defaultMessage": "Could not verify the file. Please try again." }, - "course.gradebook.GradebookColumnTree.grades": { - "defaultMessage": "Grades" + "course.gradebook.ImportWizard.stepDefine": { + "defaultMessage": "Define components" }, - "course.gradebook.GradebookColumnTree.alwaysIncluded": { - "defaultMessage": "Always included" + "course.gradebook.ImportWizard.stepUpload": { + "defaultMessage": "Template & upload" }, - "course.gradebook.GradebookColumnTree.studentInfo": { - "defaultMessage": "Student info" + "course.gradebook.ImportWizard.stepVerify": { + "defaultMessage": "Verify" }, - "course.gradebook.GradebookColumnTree.gamification": { - "defaultMessage": "Gamification" + "course.gradebook.ImportWizard.studentId": { + "defaultMessage": "Student ID" }, - "course.gradebook.GradebookIndex.dialogTitle": { - "defaultMessage": "Select columns" + "course.gradebook.ImportWizard.studentIdHint": { + "defaultMessage": "Matching uses each student's current Student ID. Keep Student IDs up to date in Manage Users." }, - "course.gradebook.GradebookIndex.exportAllTooltip": { - "defaultMessage": "No rows selected - all rows will be exported." + "course.gradebook.ImportWizard.title": { + "defaultMessage": "Import external assessments" }, - "course.gradebook.GradebookIndex.exportButton": { - "defaultMessage": "Export all rows" + "course.gradebook.ImportWizard.unresolved": { + "defaultMessage": "These identifiers were not found in the course: {ids}" }, - "course.gradebook.GradebookIndex.exportRows": { - "defaultMessage": "Export {count, plural, one {# row} other {# rows}}" + "course.gradebook.ImportWizard.updatesExisting": { + "defaultMessage": "Updates existing — managed in the gradebook" }, - "course.gradebook.GradebookIndex.selectColumns": { - "defaultMessage": "Select Columns" + "course.gradebook.ImportWizard.upload": { + "defaultMessage": "Upload filled CSV" }, - "course.gradebook.GradebookIndex.applyAndExport": { - "defaultMessage": "Apply and Export" + "course.gradebook.ImportWizard.verify": { + "defaultMessage": "Verify" }, - "course.gradebook.GradebookIndex.fetchFailure": { - "defaultMessage": "Failed to retrieve Gradebook." + "course.gradebook.ImportWizard.weightage": { + "defaultMessage": "Weightage" }, - "course.gradebook.GradebookIndex.gradebook": { - "defaultMessage": "Gradebook" + "course.gradebook.ProjectedTotalHint.policy": { + "defaultMessage": "Totals count ungraded assessments as 0." }, - "course.gradebook.GradebookIndex.searchStudents": { - "defaultMessage": "Search students" + "course.gradebook.RenameExternalColumnPrompt.cancel": { + "defaultMessage": "Cancel" }, - "course.gradebook.GradebookIndex.noStudents": { - "defaultMessage": "No students enrolled yet" + "course.gradebook.RenameExternalColumnPrompt.error": { + "defaultMessage": "Could not rename the external assessment." }, - "course.gradebook.GradebookIndex.noStudentsHint": { - "defaultMessage": "Grades will appear here once students join the course." + "course.gradebook.RenameExternalColumnPrompt.nameLabel": { + "defaultMessage": "Name" }, - "course.gradebook.GradebookTable.maxMarks": { - "defaultMessage": "Max Marks" + "course.gradebook.RenameExternalColumnPrompt.save": { + "defaultMessage": "Save" }, - "course.gradebook.GradebookTable.noDataColumnsHint": { - "defaultMessage": "No grade columns selected - export will include student info only." + "course.gradebook.RenameExternalColumnPrompt.title": { + "defaultMessage": "Rename external assessment" }, - "course.gradebook.GradebookTable.noDataColumnsHintWithGamification": { - "defaultMessage": "No grade or gamification columns selected - export will include student info only." + "course.gradebook.WeightedViewHint.hint": { + "defaultMessage": "Want a weighted total grade? You can set how much each tab counts toward each student’s overall grade and view the weighted total here. Turn it on in {link}." }, - "course.gradebook.GradeLinkHint.hint": { - "defaultMessage": "Each grade is the total of the marks in a student's submission. Click any grade to open that submission and adjust the marks." + "course.gradebook.WeightedViewHint.settingsLink": { + "defaultMessage": "Gradebook settings" }, "course.group.GroupCreationForm.description": { "defaultMessage": "Description (Optional)" @@ -5705,27 +6791,27 @@ "course.leaderboard.LeaderboardTable.average": { "defaultMessage": "Average" }, - "course.leaderboard.LeaderboardTable.experience": { - "defaultMessage": "Experience" + "course.leaderboard.LeaderboardTable.averageAchievements": { + "defaultMessage": "Average Achievements" }, - "course.leaderboard.LeaderboardTable.rank": { - "defaultMessage": "Rank" + "course.leaderboard.LeaderboardTable.averageExperience": { + "defaultMessage": "Average Experience" }, - "course.leaderboard.LeaderboardTable.name": { - "defaultMessage": "Name" + "course.leaderboard.LeaderboardTable.experience": { + "defaultMessage": "Experience" }, "course.leaderboard.LeaderboardTable.level": { "defaultMessage": "Level" }, - "course.leaderboard.LeaderboardTable.averageExperience": { - "defaultMessage": "Average Experience" - }, - "course.leaderboard.LeaderboardTable.averageAchievements": { - "defaultMessage": "Average Achievements" - }, "course.leaderboard.LeaderboardTable.members": { "defaultMessage": "Members" }, + "course.leaderboard.LeaderboardTable.name": { + "defaultMessage": "Name" + }, + "course.leaderboard.LeaderboardTable.rank": { + "defaultMessage": "Rank" + }, "course.leaderboard.LeaderboardTable.titleAchievements": { "defaultMessage": "By Achievements" }, @@ -5894,20 +6980,56 @@ "course.level.Level.levelHeader": { "defaultMessage": "Levels" }, - "course.level.Level.saveFailure": { - "defaultMessage": "Level saving failed, please try again." + "course.level.Level.orderedIncorrectly": { + "defaultMessage": "Levels will be sorted automatically when saved regardless of their order here." + }, + "course.level.Level.placeholder": { + "defaultMessage": "0" + }, + "course.level.Level.reset": { + "defaultMessage": "Reset" + }, + "course.level.Level.resetTooltip": { + "defaultMessage": "Reset changes" }, - "course.level.Level.saveLevels": { - "defaultMessage": "Save Levels" + "course.level.Level.saveChanges": { + "defaultMessage": "Save" + }, + "course.level.Level.saveFailure": { + "defaultMessage": "Failed to save levels" }, "course.level.Level.saveSuccess": { "defaultMessage": "Levels Saved" }, "course.level.Level.thresholdHeader": { - "defaultMessage": "Threshold" + "defaultMessage": "EXP Threshold" + }, + "course.level.Level.unsavedChanges": { + "defaultMessage": "You have unsaved changes" + }, + "course.material.files.DownloadingFilePage.clickToDownloadFile": { + "defaultMessage": "Download {name}" + }, + "course.material.files.DownloadingFilePage.clickToDownloadFileDescription": { + "defaultMessage": "Something happened when initiating an automatic download. Click the link below to immediately download the file." + }, + "course.material.files.DownloadingFilePage.downloading": { + "defaultMessage": "Downloading {name}" + }, + "course.material.files.DownloadingFilePage.downloadingDescription": { + "defaultMessage": "This file should start downloading automatically now. If it doesn't, you can try again by clicking the link below or refreshing this page." }, - "course.level.LevelRow.zeroThresholdError": { - "defaultMessage": "Experience points threshold cannot be 0" + "course.material.files.DownloadingFilePage.tryDownloadingAgain": { + "defaultMessage": "Try downloading again" + }, + "course.material.files.ErrorRetrievingFilePage.goToTheWorkbin": { + "defaultMessage": "Go to the Workbin" + }, + "course.material.files.ErrorRetrievingFilePage.problemRetrievingFile": { + "defaultMessage": "Problem retrieving file" + }, + "course.material.files.ErrorRetrievingFilePage.problemRetrievingFileDescription": { + "defaultMessage": "Either it no longer exists, you don't have the permission to access it, or something unexpected happened when we were trying to retrieve it." }, "course.material.folders.DownloadFolderButton.downloadFolderErrorMessage": { "defaultMessage": "Download has failed. Please try again later." @@ -5918,6 +7040,15 @@ "course.material.folders.DownloadFolderButton.downloading": { "defaultMessage": "Downloading..." }, + "course.material.folders.ErrorRetrievingFolderPage.goToMainFolder": { + "defaultMessage": "Go to the main folder" + }, + "course.material.folders.ErrorRetrievingFolderPage.problemRetrievingFolder": { + "defaultMessage": "Problem retrieving folder" + }, + "course.material.folders.ErrorRetrievingFolderPage.problemRetrievingFolderDescription": { + "defaultMessage": "Either it no longer exists, you don't have the permission to access it, or something unexpected happened when we were trying to retrieve it." + }, "course.material.folders.FolderEdit.editSubfolderTitle": { "defaultMessage": "Edit Folder" }, @@ -5957,6 +7088,12 @@ "course.material.folders.FolderShow.defaultHeader": { "defaultMessage": "Materials" }, + "course.material.folders.FolderShow.error": { + "defaultMessage": "(Error)" + }, + "course.material.folders.FolderShow.folderNotFound": { + "defaultMessage": "Folder not found" + }, "course.material.folders.MaterialEdit.editMaterialTitle": { "defaultMessage": "Edit Material" }, @@ -6002,41 +7139,71 @@ "course.material.folders.UploadFilesButton.uploadFilesTooltip": { "defaultMessage": "Upload" }, + "course.material.folders.WorkbinTable.lastModified": { + "defaultMessage": "Last Modified" + }, + "course.material.folders.WorkbinTable.name": { + "defaultMessage": "Name" + }, + "course.material.folders.WorkbinTable.startAt": { + "defaultMessage": "Start At" + }, "course.material.folders.WorkbinTableButtons.DeletionFailure": { "defaultMessage": "could not be deleted" }, + "course.material.folders.WorkbinTableButtons.addFailure": { + "defaultMessage": "{material} could not be added to knowledge base" + }, "course.material.folders.WorkbinTableButtons.deleteConfirmation": { "defaultMessage": "Are you sure you want to delete" }, "course.material.folders.WorkbinTableButtons.deletionSuccess": { "defaultMessage": "has been deleted" }, + "course.material.folders.WorkbinTableButtons.removeFailure": { + "defaultMessage": "{material} could not be removed from knowledge base" + }, + "course.material.folders.WorkbinTableButtons.removeSuccess": { + "defaultMessage": "{material} has been removed from knowledge base" + }, "course.material.folders.WorkbinTableButtons.tableButtonDeleteTooltip": { "defaultMessage": "Delete" }, - "course.material.folders.WorkbinTable.name": { - "defaultMessage": "Name" + "course.plagiarism.PlagiarismIndex.assessments.AssessmentLinkDialog.linkAssessments": { + "defaultMessage": "Link Assessments" }, - "course.material.folders.WorkbinTable.lastModified": { - "defaultMessage": "Last Modified" + "course.plagiarism.PlagiarismIndex.assessments.AssessmentLinkDialog.linkedAssessments": { + "defaultMessage": "Linked Assessments" }, - "course.material.folders.WorkbinTable.startAt": { - "defaultMessage": "Start At" + "course.plagiarism.PlagiarismIndex.assessments.AssessmentLinkDialog.searchPlaceholder": { + "defaultMessage": "Search by Assessment Title" }, - "course.plagiarism.PlagiarismIndex.header.plagiarism": { - "defaultMessage": "Plagiarism Check" + "course.plagiarism.PlagiarismIndex.assessments.AssessmentLinkDialog.unlinkedAssessments": { + "defaultMessage": "Available Assessments" }, - "course.plagiarism.PlagiarismIndex.assessments.assessment": { - "defaultMessage": "Assessments" + "course.plagiarism.PlagiarismIndex.assessments.AssessmentLinkDialog.updateLinksFailure": { + "defaultMessage": "Failed to update assessment links" }, - "course.plagiarism.PlagiarismIndex.assessments.numSubmitted": { - "defaultMessage": "# Submissions" + "course.plagiarism.PlagiarismIndex.assessments.AssessmentLinkDialog.updateLinksSuccess": { + "defaultMessage": "Assessment links updated successfully" }, - "course.plagiarism.PlagiarismIndex.assessments.numCheckableQuestions": { - "defaultMessage": "# Checkable Questions" + "course.plagiarism.PlagiarismIndex.assessments.AssessmentLinkList.cannotManage": { + "defaultMessage": "You do not have permission to manage this assessment." }, - "course.plagiarism.PlagiarismIndex.assessments.lastSubmittedAt": { - "defaultMessage": "Last Submission At" + "course.plagiarism.PlagiarismIndex.assessments.AssessmentLinkList.noAssessmentsFound": { + "defaultMessage": "No assessments found" + }, + "course.plagiarism.PlagiarismIndex.assessments.actions": { + "defaultMessage": "Actions" + }, + "course.plagiarism.PlagiarismIndex.assessments.assessment": { + "defaultMessage": "Assessment" + }, + "course.plagiarism.PlagiarismIndex.assessments.confirmRerunMessage": { + "defaultMessage": "Some of the selected assessments already have completed plagiarism checks. Running a new plagiarism check will remove the previous results." + }, + "course.plagiarism.PlagiarismIndex.assessments.confirmRerunTitle": { + "defaultMessage": "Confirm Plagiarism Check?" }, "course.plagiarism.PlagiarismIndex.assessments.lastRunStatus": { "defaultMessage": "Status" @@ -6044,17 +7211,17 @@ "course.plagiarism.PlagiarismIndex.assessments.lastRunTime": { "defaultMessage": "Last Run At" }, - "course.plagiarism.PlagiarismIndex.assessments.statusNotStarted": { - "defaultMessage": "Not Started" + "course.plagiarism.PlagiarismIndex.assessments.lastSubmittedAt": { + "defaultMessage": "Last Submission At" }, - "course.plagiarism.PlagiarismIndex.assessments.statusRunning": { - "defaultMessage": "Running" + "course.plagiarism.PlagiarismIndex.assessments.linkAssessments": { + "defaultMessage": "Link Assessments" }, - "course.plagiarism.PlagiarismIndex.assessments.statusCompleted": { - "defaultMessage": "Completed" + "course.plagiarism.PlagiarismIndex.assessments.newSubmissionsWarning": { + "defaultMessage": "New submissions detected since last plagiarism run" }, - "course.plagiarism.PlagiarismIndex.assessments.statusFailed": { - "defaultMessage": "Failed" + "course.plagiarism.PlagiarismIndex.assessments.noNewSubmissionsWarning": { + "defaultMessage": "No new submissions since last plagiarism run" }, "course.plagiarism.PlagiarismIndex.assessments.noPlagiarismCheckableQuestions": { "defaultMessage": "No checkable questions" @@ -6062,54 +7229,99 @@ "course.plagiarism.PlagiarismIndex.assessments.notEnoughSubmissions": { "defaultMessage": "Not enough submissions" }, + "course.plagiarism.PlagiarismIndex.assessments.numCheckableQuestions": { + "defaultMessage": "# Checkable Questions" + }, + "course.plagiarism.PlagiarismIndex.assessments.numSubmitted": { + "defaultMessage": "# Submissions" + }, "course.plagiarism.PlagiarismIndex.assessments.runAssessmentsPlagiarism": { "defaultMessage": "New Plagiarism Check ({count})" }, - "course.plagiarism.PlagiarismIndex.assessments.runPlagiarismCheckSuccess": { - "defaultMessage": "Started plagiarism check for {count, plural, =1 {# assessment} other {# assessments}}" + "course.plagiarism.PlagiarismIndex.assessments.runPlagiarismCheck": { + "defaultMessage": "Run Plagiarism Check" }, "course.plagiarism.PlagiarismIndex.assessments.runPlagiarismCheckError": { "defaultMessage": "Failed to start plagiarism checks for some assessments" }, + "course.plagiarism.PlagiarismIndex.assessments.runPlagiarismCheckSuccess": { + "defaultMessage": "Started plagiarism check for {count, plural, =1 {# assessment} other {# assessments}}" + }, "course.plagiarism.PlagiarismIndex.assessments.searchByAssessmentTitle": { "defaultMessage": "Search by Assessment Title" }, - "course.plagiarism.PlagiarismIndex.assessments.actions": { - "defaultMessage": "Actions" + "course.plagiarism.PlagiarismIndex.assessments.statusCompleted": { + "defaultMessage": "Completed" + }, + "course.plagiarism.PlagiarismIndex.assessments.statusFailed": { + "defaultMessage": "Failed" + }, + "course.plagiarism.PlagiarismIndex.assessments.statusNotStarted": { + "defaultMessage": "Not Started" + }, + "course.plagiarism.PlagiarismIndex.assessments.statusRunning": { + "defaultMessage": "Running" + }, + "course.plagiarism.PlagiarismIndex.assessments.statusStarting": { + "defaultMessage": "Starting" + }, + "course.plagiarism.PlagiarismIndex.assessments.viewResults": { + "defaultMessage": "View Results" + }, + "course.plagiarism.PlagiarismIndex.header.plagiarism": { + "defaultMessage": "Plagiarism Check" + }, + "course.statistics.StatisticsIndex.assessments.averageGrade": { + "defaultMessage": "Avg Grade" + }, + "course.statistics.StatisticsIndex.assessments.averageTimeTaken": { + "defaultMessage": "Avg Time" + }, + "course.statistics.StatisticsIndex.assessments.category": { + "defaultMessage": "Category" + }, + "course.statistics.StatisticsIndex.assessments.csvFileTitle": { + "defaultMessage": "Assessments Statistics" + }, + "course.statistics.StatisticsIndex.assessments.numLateStudents": { + "defaultMessage": "# Late" + }, + "course.statistics.StatisticsIndex.assessments.numSubmittedStudents": { + "defaultMessage": "# Attempted" + }, + "course.statistics.StatisticsIndex.assessments.searchBar": { + "defaultMessage": "Search by Assessment Title, Tab, or Category" + }, + "course.statistics.StatisticsIndex.assessments.startAt": { + "defaultMessage": "Starts At" }, - "course.plagiarism.PlagiarismIndex.assessments.runPlagiarismCheck": { - "defaultMessage": "Run Plagiarism Check" + "course.statistics.StatisticsIndex.assessments.stdevGrade": { + "defaultMessage": "Stdev Grade" }, - "course.plagiarism.PlagiarismIndex.assessments.viewResults": { - "defaultMessage": "View Results" + "course.statistics.StatisticsIndex.assessments.stdevTimeTaken": { + "defaultMessage": "Stdev Time" }, - "course.plagiarism.PlagiarismIndex.assessments.newSubmissionsWarning": { - "defaultMessage": "New submissions detected since last plagiarism run" + "course.statistics.StatisticsIndex.assessments.subtitle": { + "defaultMessage": "To view and export individual student grades, open Gradebook." }, - "course.plagiarism.PlagiarismIndex.assessments.noNewSubmissionsWarning": { - "defaultMessage": "No new submissions since last plagiarism run" + "course.statistics.StatisticsIndex.assessments.subtitleDisabled": { + "defaultMessage": "To view and export individual student grades, enable Gradebook." }, - "course.plagiarism.PlagiarismIndex.assessments.confirmRerunTitle": { - "defaultMessage": "Confirm Plagiarism Check?" + "course.statistics.StatisticsIndex.assessments.tab": { + "defaultMessage": "Tab" }, - "course.plagiarism.PlagiarismIndex.assessments.confirmRerunMessage": { - "defaultMessage": "Some of the selected assessments already have completed plagiarism checks. Running a new plagiarism check will remove the previous results." + "course.statistics.StatisticsIndex.assessments.tableTitle": { + "defaultMessage": "Assessments Statistics ({numStudents} students)" }, - "course.statistics.StatisticsIndex.course.StudentPerformanceTable.achievementCount": { - "defaultMessage": "No. of Achievements (Total: {courseAchievementCount})" + "course.statistics.StatisticsIndex.assessments.title": { + "defaultMessage": "Title" }, - "course.statistics.StatisticsIndex.course.StudentPerformanceTable.ascending": { - "defaultMessage": "Ascending" + "course.statistics.StatisticsIndex.course.StudentPerformanceTable.achievementCountDetails": { + "defaultMessage": "No. of Achievements (Total: {courseAchievementCount})" }, "course.statistics.StatisticsIndex.course.StudentPerformanceTable.correctness": { "defaultMessage": "Correctness" }, - "course.statistics.StatisticsIndex.course.StudentPerformanceTable.correctnessHint": { - "defaultMessage": "Correctness is the average grade percentage of all graded assessments by a student." - }, - "course.statistics.StatisticsIndex.course.StudentPerformanceTable.descending": { - "defaultMessage": "Descending" - }, "course.statistics.StatisticsIndex.course.StudentPerformanceTable.experiencePoints": { "defaultMessage": "Experience Points" }, @@ -6117,32 +7329,23 @@ "defaultMessage": "Tutors" }, "course.statistics.StatisticsIndex.course.StudentPerformanceTable.highlight": { - "defaultMessage": "Highlight top and bottom {percent}%" + "defaultMessage": "Highlight top and bottom {percent}% based on {criteria}" }, "course.statistics.StatisticsIndex.course.StudentPerformanceTable.learningRate": { "defaultMessage": "Learning Rate" }, - "course.statistics.StatisticsIndex.course.StudentPerformanceTable.learningRateHint": { - "defaultMessage": "A learning rate of 200% means that they can complete the course in half the time." - }, - "course.statistics.StatisticsIndex.course.StudentPerformanceTable.level": { + "course.statistics.StatisticsIndex.course.StudentPerformanceTable.levelInfo": { "defaultMessage": "Level (Max: {maxLevel})" }, - "course.statistics.StatisticsIndex.course.StudentPerformanceTable.levelFilter": { - "defaultMessage": "Level: {name}" - }, "course.statistics.StatisticsIndex.course.StudentPerformanceTable.name": { "defaultMessage": "Name" }, "course.statistics.StatisticsIndex.course.StudentPerformanceTable.noData": { "defaultMessage": "No Data" }, - "course.statistics.StatisticsIndex.course.StudentPerformanceTable.numSubmissions": { + "course.statistics.StatisticsIndex.course.StudentPerformanceTable.numSubmissionsDetails": { "defaultMessage": "No. of Submissions (Total: {courseAssessmentCount})" }, - "course.statistics.StatisticsIndex.course.StudentPerformanceTable.phantom": { - "defaultMessage": "Include phantom users" - }, "course.statistics.StatisticsIndex.course.StudentPerformanceTable.studentType": { "defaultMessage": "Student Type" }, @@ -6152,27 +7355,15 @@ "course.statistics.StatisticsIndex.course.StudentPerformanceTable.studentType.phantom": { "defaultMessage": "Phantom" }, - "course.statistics.StatisticsIndex.course.StudentPerformanceTable.tableTitle": { - "defaultMessage": "Students Sorted in {direction} {column}" - }, "course.statistics.StatisticsIndex.course.StudentPerformanceTable.title": { "defaultMessage": "Student Performance" }, - "course.statistics.StatisticsIndex.course.StudentPerformanceTable.tutorFilter": { - "defaultMessage": "Tutor: {name}" - }, - "course.statistics.StatisticsIndex.course.StudentPerformanceTable.videoPercentWatched": { - "defaultMessage": "Video % Count" - }, "course.statistics.StatisticsIndex.course.StudentPerformanceTable.videoPercentWatchedHeader": { "defaultMessage": "Average Video % Watched" }, "course.statistics.StatisticsIndex.course.StudentPerformanceTable.videoSubmissionCountHeader": { "defaultMessage": "Videos Watched (Total: {courseVideoCount})" }, - "course.statistics.StatisticsIndex.course.searchBar": { - "defaultMessage": "Search by Student Name" - }, "course.statistics.StatisticsIndex.course.StudentProgressionChart.deadlines": { "defaultMessage": "Deadlines" }, @@ -6203,14 +7394,11 @@ "course.statistics.StatisticsIndex.course.StudentProgressionChart.yAxisLabel": { "defaultMessage": "Assessment (Sorted by Deadline)" }, - "course.statistics.StatisticsIndex.course.error": { - "defaultMessage": "Something went wrong when fetching course statistics! Please refresh to try again." + "course.statistics.StatisticsIndex.course.csvFileTitle": { + "defaultMessage": "Student Performance Statistics" }, - "course.statistics.StatisticsIndex.course.performanceError": { - "defaultMessage": "Something went wrong when fetching course performance statistics! Please refresh to try again." - }, - "course.statistics.StatisticsIndex.course.progressionError": { - "defaultMessage": "Something went wrong when fetching course progression statistics! Please refresh to try again." + "course.statistics.StatisticsIndex.course.searchBar": { + "defaultMessage": "Search by Student Name" }, "course.statistics.StatisticsIndex.header.statistics": { "defaultMessage": "Statistics" @@ -6284,8 +7472,8 @@ "course.statistics.StatisticsIndex.staff.averageMarkingTime": { "defaultMessage": "Avg Time / Assessment" }, - "course.statistics.StatisticsIndex.staff.error": { - "defaultMessage": "Something went wrong when fetching staff statistics! Please refresh to try again." + "course.statistics.StatisticsIndex.staff.csvFileTitle": { + "defaultMessage": "Staff Statistics" }, "course.statistics.StatisticsIndex.staff.name": { "defaultMessage": "Name" @@ -6296,23 +7484,20 @@ "course.statistics.StatisticsIndex.staff.numStudents": { "defaultMessage": "# Students" }, + "course.statistics.StatisticsIndex.staff.searchBar": { + "defaultMessage": "Search by Staff Name" + }, "course.statistics.StatisticsIndex.staff.stddev": { - "defaultMessage": "Standard Deviation" + "defaultMessage": "Stdev Time / Assessment" }, "course.statistics.StatisticsIndex.staff.tableTitle": { "defaultMessage": "Staff Statistics" }, - "course.statistics.StatisticsIndex.staff.csvFileTitle": { - "defaultMessage": "Staff Statistics" - }, - "course.statistics.StatisticsIndex.staff.searchBar": { - "defaultMessage": "Search by Staff Name" - }, - "course.statistics.StatisticsIndex.staffFailure": { - "defaultMessage": "Failed to fetch staff data!" + "course.statistics.StatisticsIndex.students.csvFileTitle": { + "defaultMessage": "Student Statistics" }, - "course.statistics.StatisticsIndex.students.error": { - "defaultMessage": "Something went wrong when fetching student statistics! Please refresh to try again." + "course.statistics.StatisticsIndex.students.email": { + "defaultMessage": "Email" }, "course.statistics.StatisticsIndex.students.experiencePoints": { "defaultMessage": "Experience Points" @@ -6326,14 +7511,8 @@ "course.statistics.StatisticsIndex.students.name": { "defaultMessage": "Name" }, - "course.statistics.StatisticsIndex.students.email": { - "defaultMessage": "Email" - }, - "course.statistics.StatisticsIndex.students.noStudents": { - "defaultMessage": "There is no student in this course, yet..." - }, - "course.statistics.StatisticsIndex.students.showMyStudentsOnly": { - "defaultMessage": "Show My Students Only" + "course.statistics.StatisticsIndex.students.searchBar": { + "defaultMessage": "Search by Student Name, Student Type or External ID" }, "course.statistics.StatisticsIndex.students.studentsType": { "defaultMessage": "Student Type" @@ -6341,21 +7520,12 @@ "course.statistics.StatisticsIndex.students.tableTitle": { "defaultMessage": "Student Statistics ({numStudents} students, {numPhantom} phantom)" }, - "course.statistics.StatisticsIndex.students.tutorFilter": { - "defaultMessage": "Tutor: {name}" - }, "course.statistics.StatisticsIndex.students.videoPercentWatched": { "defaultMessage": "Average % Watched" }, "course.statistics.StatisticsIndex.students.videoSubmissionCount": { "defaultMessage": "Videos Watched (Total: {courseVideoCount})" }, - "course.statistics.StatisticsIndex.students.csvFileTitle": { - "defaultMessage": "Student Statistics" - }, - "course.statistics.StatisticsIndex.students.searchBar": { - "defaultMessage": "Search by Student Name, Student Type or External ID" - }, "course.statistics.StatisticsIndex.studentsFailure": { "defaultMessage": "Failed to fetch student data!" }, @@ -6380,12 +7550,6 @@ "course.statistics.course.studentProgressionChart.startAt": { "defaultMessage": "Starts at: {startAt}" }, - "course.statistics.failures.coursePerformance": { - "defaultMessage": "Failed to fetch course performance data!" - }, - "course.statistics.failures.courseProgression": { - "defaultMessage": "Failed to fetch course progression data!" - }, "course.statistics.tabs.course": { "defaultMessage": "Course" }, @@ -6395,6 +7559,15 @@ "course.statistics.tabs.courseProgression": { "defaultMessage": "Course Progression" }, + "course.stories.CikgoErrorPage.errorFetching": { + "defaultMessage": "Either it's supposed to be naught, or something went wrong." + }, + "course.stories.CikgoErrorPage.errorFetchingDescription": { + "defaultMessage": "Cikgo is our partner that powers this experience. They were contactable, but did not give us any resources for this request just now. Please try again later, and if this persists, contact us." + }, + "course.stories.pages.MissionControlPage": { + "defaultMessage": "Mission Control" + }, "course.survey.DeleteSectionButton.deleteSection": { "defaultMessage": "Delete Section" }, @@ -6882,7 +8055,7 @@ "defaultMessage": "Revert and delete timeline and its times" }, "course.timelines.defaultTimeline": { - "defaultMessage": "Default" + "defaultMessage": "Default Timeline" }, "course.timelines.deleteTime": { "defaultMessage": "Delete time" @@ -7040,6 +8213,30 @@ "course.userInvitation.InviteUsersRegistrationCode.registrationCodeNote": { "defaultMessage": "Users who have been invited and use this invitation code to register for the course would not have the proper status reflected in the Invitations page." }, + "course.userInvitations.ExternalIdConflictPrompt.body": { + "defaultMessage": "These users are already enrolled or have pending invitations. No new invitation emails will be sent to them. Would you like to keep their current External IDs, or replace them with the values from your file?" + }, + "course.userInvitations.ExternalIdConflictPrompt.goBack": { + "defaultMessage": "Go Back" + }, + "course.userInvitations.ExternalIdConflictPrompt.keepExisting": { + "defaultMessage": "Keep Existing" + }, + "course.userInvitations.ExternalIdConflictPrompt.pendingCourseUserUpdates": { + "defaultMessage": "Pending Course Member Updates ({count})" + }, + "course.userInvitations.ExternalIdConflictPrompt.pendingInvitationUpdates": { + "defaultMessage": "Pending Invitation Updates ({count})" + }, + "course.userInvitations.ExternalIdConflictPrompt.replace": { + "defaultMessage": "Replace" + }, + "course.userInvitations.ExternalIdConflictPrompt.title": { + "defaultMessage": "Confirm External ID Updates" + }, + "course.userInvitations.IndividualInvitations.addRowsByEmail": { + "defaultMessage": "Add Rows by Email" + }, "course.userInvitations.IndividualInvitations.appendNewRow": { "defaultMessage": "Add Row" }, @@ -7049,23 +8246,56 @@ "course.userInvitations.IndividualInvitations.invite": { "defaultMessage": "Invite All Users" }, + "course.userInvitations.IndividualInvitations.malformedEmail": { + "defaultMessage": "{n, plural, one {This email is } other {These emails are }} wrongly formatted: {emails}" + }, + "course.userInvitations.IndividualInvitations.nameEmailInput": { + "defaultMessage": "John Doe '; \"Doe, Jane\" '; ..." + }, "course.userInvitations.IndividualInvitations.namePlaceholder": { "defaultMessage": "Awesome User" }, "course.userInvitations.IndividualInvitations.removeInvitation": { "defaultMessage": "Remove Invitation" }, - "course.userInvitations.InvitationResultDialog.body": { - "defaultMessage": "{newInvitationsCount, plural, =0 {No new users were} one {# new user has been} other {# new users have been}} invited to Coursemology. {newCourseUsersCount, plural, =0 {No user with Coursemology account has been} one {# new user with existing Coursemology account has been} other {# new users with existing Coursemology accounts have been}} added to this course." + "course.userInvitations.IndividualInviteForm.failure": { + "defaultMessage": "Failed to invite users. {error}" }, - "course.userInvitations.InvitationResultDialog.close": { - "defaultMessage": "Close" + "course.userInvitations.IndividualInviteForm.failureGeneric": { + "defaultMessage": "Failed to invite users. You may reload and try again." + }, + "course.userInvitations.InvitationActionButtons.deletionConfirm": { + "defaultMessage": "Are you sure you wish to delete invitation to {name} ({email})?" + }, + "course.userInvitations.InvitationActionButtons.deletionFailure": { + "defaultMessage": "Failed to delete user - {error}" + }, + "course.userInvitations.InvitationActionButtons.deletionFailureGeneric": { + "defaultMessage": "Failed to delete user." + }, + "course.userInvitations.InvitationActionButtons.deletionSuccess": { + "defaultMessage": "Invitation for {name} was deleted." + }, + "course.userInvitations.InvitationActionButtons.deletionTooltip": { + "defaultMessage": "Delete Invitation" + }, + "course.userInvitations.InvitationActionButtons.resendFailure": { + "defaultMessage": "Failed to resend invitation." + }, + "course.userInvitations.InvitationActionButtons.resendSuccess": { + "defaultMessage": "Resent email invitation to {email}!" + }, + "course.userInvitations.InvitationActionButtons.resendTooltip": { + "defaultMessage": "Resend Invitation" }, - "course.userInvitations.InvitationResultDialog.duplicateInfo": { - "defaultMessage": "Duplicate users were found in the invitation. Only the first instance of each user will be invited." + "course.userInvitations.InvitationResultDialog.actionableTitle": { + "defaultMessage": "Failed ({count})" + }, + "course.userInvitations.InvitationResultDialog.blankHeaderWarning": { + "defaultMessage": "One or more columns had no header - their data was ignored." }, - "course.userInvitations.InvitationResultDialog.duplicateUsers": { - "defaultMessage": "Duplicate Users ({count})" + "course.userInvitations.InvitationResultDialog.close": { + "defaultMessage": "Close" }, "course.userInvitations.InvitationResultDialog.existingCourseUsers": { "defaultMessage": "Existing Course Users ({count})" @@ -7073,15 +8303,18 @@ "course.userInvitations.InvitationResultDialog.existingCourseUsersInfo": { "defaultMessage": "These users are already enrolled in this course. They were not re-enrolled." }, - "course.userInvitations.InvitationResultDialog.externalIdUpdatedInfo": { - "defaultMessage": "External IDs were updated where specified." - }, "course.userInvitations.InvitationResultDialog.existingInvitations": { "defaultMessage": "Existing Invitations ({count})" }, "course.userInvitations.InvitationResultDialog.existingInvitationsInfo": { "defaultMessage": "These users already have a pending invitation. They were not re-invited." }, + "course.userInvitations.InvitationResultDialog.externalIdUpdatedInfo": { + "defaultMessage": "External IDs were updated where specified." + }, + "course.userInvitations.InvitationResultDialog.failedRowsSubtitle": { + "defaultMessage": "{count} {count, plural, one {row} other {rows}} highlighted in red could not be sent" + }, "course.userInvitations.InvitationResultDialog.header": { "defaultMessage": "Invitation Summary" }, @@ -7091,29 +8324,17 @@ "course.userInvitations.InvitationResultDialog.newInvitations": { "defaultMessage": "New Invitations ({count})" }, - "course.userInvitations.InvitationResultDialog.actionableTitle": { - "defaultMessage": "Failed ({count})" - }, - "course.userInvitations.InvitationResultDialog.failedInvitations": { - "defaultMessage": "Failed to Send ({count})" - }, - "course.userInvitations.InvitationResultDialog.failedInvitationsInfo": { - "defaultMessage": "Error occurred when sending invitation email, please try again." - }, - "course.userInvitations.InvitationResultDialog.updatedSubtitle": { - "defaultMessage": "{count} updated · shown first" - }, - "course.userInvitations.InvitationResultDialog.blankHeaderWarning": { - "defaultMessage": "One or more columns had no header - their data was ignored." - }, "course.userInvitations.InvitationResultDialog.summary": { "defaultMessage": "{newInvitations} new {newInvitations, plural, one {invitation} other {invitations}} sent, {newEnrollments} directly enrolled, {alreadyInCourse} already in course." }, "course.userInvitations.InvitationResultDialog.summaryFailed": { "defaultMessage": "{count} failed." }, - "course.userInvitations.InvitationResultDialog.failedRowsSubtitle": { - "defaultMessage": "{count} {count, plural, one {row} other {rows}} highlighted in red could not be sent" + "course.userInvitations.InvitationResultDialog.updatedSubtitle": { + "defaultMessage": "{count} updated · shown first" + }, + "course.userInvitations.InvitationResultExistingTable.previouslyLabel": { + "defaultMessage": "Previously: {value}" }, "course.userInvitations.InvitationResultFailedTable.duplicateEmailInFile": { "defaultMessage": "Duplicate email in uploaded CSV" @@ -7130,21 +8351,6 @@ "course.userInvitations.InvitationResultFailedTable.missingEmail": { "defaultMessage": "Missing email" }, - "course.userInvitations.InvitationResultSkippedTable.no": { - "defaultMessage": "No" - }, - "course.userInvitations.InvitationResultSkippedTable.previouslyLabel": { - "defaultMessage": "Previously: {value}" - }, - "course.userInvitations.InvitationResultSkippedTable.yes": { - "defaultMessage": "Yes" - }, - "course.userInvitations.InvitationResultExistingTable.previouslyLabel": { - "defaultMessage": "Previously: {value}" - }, - "course.userInvitations.InvitationsBarChart.accepted": { - "defaultMessage": "Accepted Invitations" - }, "course.userInvitations.InvitationsIndex.failure": { "defaultMessage": "Failed to fetch all invitations" }, @@ -7175,14 +8381,17 @@ "course.userInvitations.InviteUsersFileUpload.failureGeneric": { "defaultMessage": "Failed to invite users. Please ensure your data is formatted correctly." }, + "course.userInvitations.InviteUsersFileUpload.fileRequired": { + "defaultMessage": "Please select a CSV file to upload." + }, "course.userInvitations.InviteUsersFileUpload.fileUploadExample": { "defaultMessage": "Name,Email,External ID,Role,Phantom{br}John,test1@example.com,A0123456,student,y{br}Mary,test2@example.com,A0123457,teaching_assistant,n" }, "course.userInvitations.InviteUsersFileUpload.fileUploadExamplePersonalTimeline": { "defaultMessage": "Name,Email,External ID,Role,Phantom,Personal Timeline{br}John,test1@example.com,A0123456,student,y,otot{br}Mary,test2@example.com,A0123457,teaching_assistant,n,fixed" }, - "course.userInvitations.InviteUsersFileUpload.fileUploadInfoRequired": { - "defaultMessage": "The CSV must include both a \"Name\" and \"Email\" column. All other columns are optional." + "course.userInvitations.InviteUsersFileUpload.fileUploadInfo": { + "defaultMessage": "Upload a .csv file with the following format:" }, "course.userInvitations.InviteUsersFileUpload.fileUploadInfoEmail": { "defaultMessage": "Each invitation must use a unique email address within the course. Duplicate emails will be skipped." @@ -7190,24 +8399,21 @@ "course.userInvitations.InviteUsersFileUpload.fileUploadInfoExternalId": { "defaultMessage": "If external IDs are provided, they must be unique within the course." }, - "course.userInvitations.InviteUsersFileUpload.fileUploadInfo": { - "defaultMessage": "Upload a .csv file with the following format:" - }, "course.userInvitations.InviteUsersFileUpload.fileUploadInfoPersonalTimeline": { "defaultMessage": "Personal Timelines can be [fixed, otot, stragglers, fomo], with course default: {defaultTimelineAlgorithm} if omitted." }, "course.userInvitations.InviteUsersFileUpload.fileUploadInfoPhantom": { "defaultMessage": "Phantom can be true/false with the following true values ['t', 'true', 'y', 'yes'] (case insenstitive), and defaults to false if omitted." }, + "course.userInvitations.InviteUsersFileUpload.fileUploadInfoRequired": { + "defaultMessage": "The CSV must include both a \"Name\" and \"Email\" column. All other columns are optional." + }, "course.userInvitations.InviteUsersFileUpload.fileUploadInfoRole": { "defaultMessage": "Roles can be [student, observer, teaching_assistant, manager, owner], and defaults to student if omitted. Teaching assistants can only invite users as students." }, "course.userInvitations.InviteUsersFileUpload.importInProgress": { "defaultMessage": "Importing users, please wait…" }, - "course.userInvitations.InviteUsersFileUpload.fileRequired": { - "defaultMessage": "Please select a CSV file to upload." - }, "course.userInvitations.InviteUsersFileUpload.template": { "defaultMessage": "(Template File)" }, @@ -7220,30 +8426,6 @@ "course.userInvitations.InviteUsersfileUploadForm.invite": { "defaultMessage": "Invite Users from File" }, - "course.userInvitations.InvitationActionButtons.deletionConfirm": { - "defaultMessage": "Are you sure you wish to delete invitation to {name} ({email})?" - }, - "course.userInvitations.InvitationActionButtons.deletionFailure": { - "defaultMessage": "Failed to delete user - {error}" - }, - "course.userInvitations.InvitationActionButtons.deletionFailureGeneric": { - "defaultMessage": "Failed to delete user." - }, - "course.userInvitations.InvitationActionButtons.deletionSuccess": { - "defaultMessage": "Invitation for {name} was deleted." - }, - "course.userInvitations.InvitationActionButtons.deletionTooltip": { - "defaultMessage": "Delete Invitation" - }, - "course.userInvitations.InvitationActionButtons.resendFailure": { - "defaultMessage": "Failed to resend invitation." - }, - "course.userInvitations.InvitationActionButtons.resendSuccess": { - "defaultMessage": "Resent email invitation to {email}!" - }, - "course.userInvitations.InvitationActionButtons.resendTooltip": { - "defaultMessage": "Resend Invitation" - }, "course.userInvitations.RegistrationCodeButton.registrationCode": { "defaultMessage": "Registration Code" }, @@ -7262,6 +8444,9 @@ "course.userInvitations.UserInvitationsTable.accepted": { "defaultMessage": "Accepted" }, + "course.userInvitations.UserInvitationsTable.confirmedTooltip": { + "defaultMessage": "Accepted {confirmedAt}" + }, "course.userInvitations.UserInvitationsTable.failed": { "defaultMessage": "Failed" }, @@ -7271,12 +8456,12 @@ "course.userInvitations.UserInvitationsTable.pending": { "defaultMessage": "Pending" }, + "course.userInvitations.UserInvitationsTable.searchText": { + "defaultMessage": "Search by name, email or external ID" + }, "course.userInvitations.UserInvitationsTable.sentTooltip": { "defaultMessage": "Sent {sentAt}" }, - "course.userInvitations.UserInvitationsTable.confirmedTooltip": { - "defaultMessage": "Accepted {confirmedAt}" - }, "course.userNotification.AchievementGainedPopup.unlocked": { "defaultMessage": "Achievement Unlocked!" }, @@ -7295,12 +8480,6 @@ "course.users.ExperiencePointsRecords.experiencePointsHistoryHeader": { "defaultMessage": "Experience Points History: {for}" }, - "course.users.ExperiencePointsRecords.fetchUsersFailure": { - "defaultMessage": "Failed to fetch records" - }, - "course.users.ExperiencePointsTable.fetchRecordsFailure": { - "defaultMessage": "Failed to fetch records" - }, "course.users.ManageStaff.noStaff": { "defaultMessage": "No staff in course." }, @@ -7313,6 +8492,12 @@ "course.users.ManageUsersTable.ManageUsersTable.searchText": { "defaultMessage": "Search by name, email or external ID" }, + "course.users.ManageUsersTable.addIdFailure": { + "defaultMessage": "Failed to set External ID to {newId}" + }, + "course.users.ManageUsersTable.addIdSuccess": { + "defaultMessage": "External ID set to {newId}" + }, "course.users.ManageUsersTable.assignToTimeline": { "defaultMessage": "Assign to timeline" }, @@ -7343,6 +8528,12 @@ "course.users.ManageUsersTable.changeAlgorithmSuccess": { "defaultMessage": "Updated {name}'s timeline algorithm to {timeline}." }, + "course.users.ManageUsersTable.changeIdFailure": { + "defaultMessage": "Failed to change ID from {oldId} to {newId}" + }, + "course.users.ManageUsersTable.changeIdSuccess": { + "defaultMessage": "ID was changed from {oldId} to {newId}" + }, "course.users.ManageUsersTable.changeRoleFailure": { "defaultMessage": "Failed to update {name}'s role to {role}." }, @@ -7358,29 +8549,26 @@ "course.users.ManageUsersTable.defaultTimeline": { "defaultMessage": "Default" }, - "course.users.ManageUsersTable.group": { - "defaultMessage": "Group: {name}" - }, - "course.users.ManageUsersTable.phantomSuccess": { - "defaultMessage": "{name} {isPhantom, select, true {is now a phantom user} other {is now a normal user} }." + "course.users.ManageUsersTable.deleteIdFailure": { + "defaultMessage": "Failed to delete External ID" }, - "course.users.ManageUsersTable.addIdFailure": { - "defaultMessage": "Failed to set External ID to {newId}" + "course.users.ManageUsersTable.deleteIdSuccess": { + "defaultMessage": "External ID deleted" }, - "course.users.ManageUsersTable.addIdSuccess": { - "defaultMessage": "External ID set to {newId}" + "course.users.ManageUsersTable.deletionConfirm": { + "defaultMessage": "Are you sure you wish to delete {role} {name} ({email})?" }, - "course.users.ManageUsersTable.changeIdFailure": { - "defaultMessage": "Failed to change ID from {oldId} to {newId}" + "course.users.ManageUsersTable.deletionFailure": { + "defaultMessage": "Failed to delete {role} {name} ({email})." }, - "course.users.ManageUsersTable.changeIdSuccess": { - "defaultMessage": "ID was changed from {oldId} to {newId}" + "course.users.ManageUsersTable.deletionScheduled": { + "defaultMessage": "{role} {name} ({email}) has been scheduled for deletion." }, - "course.users.ManageUsersTable.deleteIdFailure": { - "defaultMessage": "Failed to delete External ID" + "course.users.ManageUsersTable.group": { + "defaultMessage": "Group: {name}" }, - "course.users.ManageUsersTable.deleteIdSuccess": { - "defaultMessage": "External ID deleted" + "course.users.ManageUsersTable.phantomSuccess": { + "defaultMessage": "{name} {isPhantom, select, true {is now a phantom user} other {is now a normal user} }." }, "course.users.ManageUsersTable.renameFailure": { "defaultMessage": "Failed to rename {oldName} to {newName}" @@ -7391,6 +8579,24 @@ "course.users.ManageUsersTable.selectedNUsers": { "defaultMessage": "Selected {n, plural, =1 {# user} other {# users}}" }, + "course.users.ManageUsersTable.suspend": { + "defaultMessage": "Suspend" + }, + "course.users.ManageUsersTable.suspendFailure": { + "defaultMessage": "Failed to suspend {name}." + }, + "course.users.ManageUsersTable.suspendSuccess": { + "defaultMessage": "{name} is now suspended. They cannot access this course until they are unsuspended." + }, + "course.users.ManageUsersTable.unsuspend": { + "defaultMessage": "Unsuspend" + }, + "course.users.ManageUsersTable.unsuspendFailure": { + "defaultMessage": "Failed to unsuspend {name}." + }, + "course.users.ManageUsersTable.unsuspendSuccess": { + "defaultMessage": "{name} is no longer suspended. They can now access the course." + }, "course.users.ManageUsersTable.updateFailure": { "defaultMessage": "Failed to update user - {error}" }, @@ -7499,36 +8705,6 @@ "course.users.UpgradeToStaff.upgradeSuccess": { "defaultMessage": "{count, plural, =0 {No users were} one {# new user has} other {# new users have}} been upgraded to {role}" }, - "course.users.ManageUsersTable.deletionConfirm": { - "defaultMessage": "Are you sure you wish to delete {role} {name} ({email})?" - }, - "course.users.ManageUsersTable.deletionFailure": { - "defaultMessage": "Failed to delete user." - }, - "course.users.ManageUsersTable.deletionScheduled": { - "defaultMessage": "{role} {name} ({email}) has been scheduled for deletion." - }, - "course.users.ManageUsersTable.deletionSuccess": { - "defaultMessage": "User was deleted." - }, - "course.users.ManageUsersTable.suspend": { - "defaultMessage": "Suspend" - }, - "course.users.ManageUsersTable.suspendFailure": { - "defaultMessage": "Failed to suspend {name}." - }, - "course.users.ManageUsersTable.suspendSuccess": { - "defaultMessage": "{name} is now suspended. They cannot access this course until they are unsuspended." - }, - "course.users.ManageUsersTable.unsuspend": { - "defaultMessage": "Unsuspend" - }, - "course.users.ManageUsersTable.unsuspendFailure": { - "defaultMessage": "Failed to unsuspend {name}." - }, - "course.users.ManageUsersTable.unsuspendSuccess": { - "defaultMessage": "{name} is no longer suspended. They can now access the course." - }, "course.users.UserManagementTabs.enrolRequestsTitle": { "defaultMessage": "Enrol Requests" }, @@ -7667,27 +8843,27 @@ "course.video.VideoShow.videoTitle": { "defaultMessage": "Video - {title}" }, + "course.video.VideoTable.actions": { + "defaultMessage": "Actions" + }, + "course.video.VideoTable.averageWatched": { + "defaultMessage": "Average % Watched" + }, "course.video.VideoTable.noVideo": { "defaultMessage": "No Video" }, - "course.video.VideoTable.title": { - "defaultMessage": "Title" + "course.video.VideoTable.published": { + "defaultMessage": "Published" }, "course.video.VideoTable.startAt": { "defaultMessage": "Start At" }, + "course.video.VideoTable.title": { + "defaultMessage": "Title" + }, "course.video.VideoTable.watchCount": { "defaultMessage": "Watch Count" }, - "course.video.VideoTable.averageWatched": { - "defaultMessage": "Average % Watched" - }, - "course.video.VideoTable.published": { - "defaultMessage": "Published" - }, - "course.video.VideoTable.actions": { - "defaultMessage": "Actions" - }, "course.video.VideosIndex.fetchVideosFailure": { "defaultMessage": "Failed to retrieve videos." }, @@ -7835,9 +9011,33 @@ "course.videoSubmissions.UserVideoSubmissionsIndex.videoSubmissionsHeader": { "defaultMessage": "Video Watch History" }, + "d6avGo": { + "defaultMessage": "Submissions" + }, + "f9aTl7": { + "defaultMessage": "Role-Playing Assessments" + }, + "jvrMfo": { + "defaultMessage": "Assistants" + }, "landing_page.create_an_account": { "defaultMessage": "Create an account" }, + "landing_page.iconEngaging": { + "defaultMessage": "Engaging" + }, + "landing_page.iconEngagingSubtitle": { + "defaultMessage": "It is built for all teachers. You do not need to have any programming knowledge to master the platform. Coursemology is easy and intuitive to use for both teachers and students." + }, + "landing_page.iconGeneral": { + "defaultMessage": "General" + }, + "landing_page.iconGeneralSubtitle": { + "defaultMessage": "It is built for all subjects. The gamification system of Coursemology does not make any assumptions on the subject. Through Coursemology, any teacher who teaches any subject can turn his course exercises into an online game." + }, + "landing_page.iconSimple": { + "defaultMessage": "Simple" + }, "landing_page.new_to_coursemology": { "defaultMessage": "New to Coursemology?" }, @@ -7874,12 +9074,12 @@ "lib.components.core.Expandable.showMore": { "defaultMessage": "Show more" }, - "lib.components.core.Note.noteHeader": { - "defaultMessage": "Note" - }, "lib.components.core.Note.errorHeader": { "defaultMessage": "Error" }, + "lib.components.core.Note.noteHeader": { + "defaultMessage": "Note" + }, "lib.components.core.banners.ServerUnreachableBanner.refreshPage": { "defaultMessage": "Refresh page" }, @@ -8009,6 +9209,72 @@ "lib.components.form.fields.SingleFileInput.removeFile": { "defaultMessage": "Remove File" }, + "lib.components.getHelp.filter.filterAssessmentLabel": { + "defaultMessage": "Filter by Assessment" + }, + "lib.components.getHelp.filter.filterCourseLabel": { + "defaultMessage": "Filter by Course" + }, + "lib.components.getHelp.filter.filterEndDateLabel": { + "defaultMessage": "End Date" + }, + "lib.components.getHelp.filter.filterStartDateLabel": { + "defaultMessage": "Start Date" + }, + "lib.components.getHelp.filter.filterStudentLabel": { + "defaultMessage": "Filter by Student" + }, + "lib.components.getHelp.filter.lastFourteenDays": { + "defaultMessage": "Last 14 Days" + }, + "lib.components.getHelp.filter.lastSevenDays": { + "defaultMessage": "Last 7 Days" + }, + "lib.components.getHelp.filter.lastSixMonths": { + "defaultMessage": "Last 6 Months" + }, + "lib.components.getHelp.filter.lastThirtyDays": { + "defaultMessage": "Last 30 Days" + }, + "lib.components.getHelp.filter.lastTwelveMonths": { + "defaultMessage": "Last 12 Months" + }, + "lib.components.getHelp.header": { + "defaultMessage": "Recent Get Help Activity ({total, plural, one {# Conversation} other {# Conversations}})" + }, + "lib.components.getHelp.table.assessmentTitle": { + "defaultMessage": "Assessment" + }, + "lib.components.getHelp.table.courseTitle": { + "defaultMessage": "Course" + }, + "lib.components.getHelp.table.createdAt": { + "defaultMessage": "Last Message At" + }, + "lib.components.getHelp.table.instanceTitle": { + "defaultMessage": "Instance" + }, + "lib.components.getHelp.table.lastMessage": { + "defaultMessage": "Last Message" + }, + "lib.components.getHelp.table.messageCount": { + "defaultMessage": "# Msgs" + }, + "lib.components.getHelp.table.questionNumber": { + "defaultMessage": "Question" + }, + "lib.components.getHelp.table.studentName": { + "defaultMessage": "Name" + }, + "lib.components.getHelp.validation.endDateBeforeStartDate": { + "defaultMessage": "End date must be after or equal to Start date" + }, + "lib.components.getHelp.validation.exceedDateRange": { + "defaultMessage": "Date range cannot exceed 365 days" + }, + "lib.components.getHelp.validation.invalidDateSelection": { + "defaultMessage": "Invalid date" + }, "lib.components.navigation.AdminPopupMenuList.adminPanel": { "defaultMessage": "System Admin Panel" }, @@ -8045,6 +9311,21 @@ "lib.components.navigation.CourseSwitcherPopupMenu.thisCourse": { "defaultMessage": "This course" }, + "lib.components.table.MuiColumnPickerPrompt.apply": { + "defaultMessage": "Apply to view" + }, + "lib.components.table.MuiColumnPickerPrompt.cancel": { + "defaultMessage": "Cancel" + }, + "lib.components.table.MuiColumnPickerPrompt.defaultTitle": { + "defaultMessage": "Select columns" + }, + "lib.components.table.MuiTableToolbar.directExport": { + "defaultMessage": "Export" + }, + "lib.components.table.MuiTableToolbar.exportTrigger": { + "defaultMessage": "Export…" + }, "lib.hooks.router.usePrompt.sureYouWantToLeave": { "defaultMessage": "Are you sure you want to leave this page? You will lose unsaved changes." }, @@ -8162,21 +9443,21 @@ "lib.translations.course.users.manageUsersHeader": { "defaultMessage": "Manage Users" }, - "lib.translations.course.users.roles.student": { - "defaultMessage": "Student" - }, - "lib.translations.course.users.roles.teachingAssistant": { - "defaultMessage": "Teaching Assistant" + "lib.translations.course.users.roles.manager": { + "defaultMessage": "Manager" }, "lib.translations.course.users.roles.observer": { "defaultMessage": "Observer" }, - "lib.translations.course.users.roles.manager": { - "defaultMessage": "Manager" - }, "lib.translations.course.users.roles.owner": { "defaultMessage": "Owner" }, + "lib.translations.course.users.roles.student": { + "defaultMessage": "Student" + }, + "lib.translations.course.users.roles.teachingAssistant": { + "defaultMessage": "Teaching Assistant" + }, "lib.translations.experimental": { "defaultMessage": "Experimental" }, @@ -8237,6 +9518,9 @@ "lib.translations.form.endAt": { "defaultMessage": "End At" }, + "lib.translations.form.maximum": { + "defaultMessage": "Maximum" + }, "lib.translations.form.messages.areYouSure": { "defaultMessage": "Are you sure?" }, @@ -8252,6 +9536,9 @@ "lib.translations.form.messages.unsavedChanges": { "defaultMessage": "You have unsaved changes." }, + "lib.translations.form.minimum": { + "defaultMessage": "Minimum" + }, "lib.translations.form.startAt": { "defaultMessage": "Start At" }, @@ -8288,14 +9575,17 @@ "lib.translations.form.validation.startEndDateValidationError": { "defaultMessage": "Must be after Start Date" }, - "lib.translations.instance.users.roles.normal": { - "defaultMessage": "Normal" + "lib.translations.instance.users.roles.administrator": { + "defaultMessage": "Administrator" }, "lib.translations.instance.users.roles.instructor": { "defaultMessage": "Instructor" }, - "lib.translations.instance.users.roles.administrator": { - "defaultMessage": "Administrator" + "lib.translations.instance.users.roles.normal": { + "defaultMessage": "Normal" + }, + "lib.translations.messages.featureUnavailable": { + "defaultMessage": "This feature is currently unavailable." }, "lib.translations.messages.fetchingError": { "defaultMessage": "An error occurred when loading your data. Please reload and try again." @@ -8306,9 +9596,27 @@ "lib.translations.messages.loadImageError": { "defaultMessage": "An error occurred when loading your image. Please try selecting another one." }, + "lib.translations.myStudents": { + "defaultMessage": "My Students" + }, + "lib.translations.myStudentsIncludingPhantoms": { + "defaultMessage": "My Students (Including Phantoms)" + }, "lib.translations.no": { "defaultMessage": "No" }, + "lib.translations.staff": { + "defaultMessage": "Staff" + }, + "lib.translations.staffIncludingPhantoms": { + "defaultMessage": "Staff (Including Phantoms)" + }, + "lib.translations.students": { + "defaultMessage": "Students" + }, + "lib.translations.studentsIncludingPhantoms": { + "defaultMessage": "Students (Including Phantoms)" + }, "lib.translations.summary": { "defaultMessage": "Summary" }, @@ -8345,15 +9653,15 @@ "lib.translations.table.column.createdAt": { "defaultMessage": "Created At" }, + "lib.translations.table.column.currentExternalId": { + "defaultMessage": "Current External ID" + }, "lib.translations.table.column.designation": { "defaultMessage": "Designation" }, "lib.translations.table.column.email": { "defaultMessage": "Email" }, - "lib.translations.table.column.externalId": { - "defaultMessage": "External ID" - }, "lib.translations.table.column.endAt": { "defaultMessage": "End At" }, @@ -8363,6 +9671,9 @@ "lib.translations.table.column.experiencePointsAwarded": { "defaultMessage": "EXP Awarded" }, + "lib.translations.table.column.externalId": { + "defaultMessage": "External ID" + }, "lib.translations.table.column.groups": { "defaultMessage": "Group(s)" }, @@ -8405,6 +9716,9 @@ "lib.translations.table.column.name": { "defaultMessage": "Name" }, + "lib.translations.table.column.newExternalId": { + "defaultMessage": "New External ID" + }, "lib.translations.table.column.optional": { "defaultMessage": "Optional" }, @@ -8474,35 +9788,14 @@ "lib.translations.table.column.updater": { "defaultMessage": "Updater" }, - "lib.translations.table.column.videoName": { - "defaultMessage": "Video Name" - }, - "lib.translations.table.column.watchedAt": { - "defaultMessage": "Watched At" - }, - "lib.translations.yes": { - "defaultMessage": "Yes" - }, - "material.attemptLoader.errorAccessingMaterial": { - "defaultMessage": "An error occurred while accessing this material. Try again later." - }, - "system.admin.instance.instance.InstanceAdminNavigator.announcements": { - "defaultMessage": "Announcements" - }, - "system.admin.instance.instance.InstanceAdminNavigator.components": { - "defaultMessage": "Components" - }, - "system.admin.instance.instance.InstanceAdminNavigator.courses": { - "defaultMessage": "Courses" - }, - "system.admin.instance.instance.InstanceAdminNavigator.roleRequests": { - "defaultMessage": "Role Requests" + "lib.translations.table.column.videoName": { + "defaultMessage": "Video Name" }, - "system.admin.instance.instance.InstanceAdminNavigator.users": { - "defaultMessage": "Users" + "lib.translations.table.column.watchedAt": { + "defaultMessage": "Watched At" }, - "system.admin.instance.instance.InstanceAdminNavigator.getHelp": { - "defaultMessage": "Get Help" + "lib.translations.yes": { + "defaultMessage": "Yes" }, "system.admin.admin.AdminNavigator.announcements": { "defaultMessage": "System Announcements" @@ -8510,6 +9803,9 @@ "system.admin.admin.AdminNavigator.courses": { "defaultMessage": "Courses" }, + "system.admin.admin.AdminNavigator.getHelp": { + "defaultMessage": "Get Help" + }, "system.admin.admin.AdminNavigator.instances": { "defaultMessage": "Instances" }, @@ -8519,9 +9815,6 @@ "system.admin.admin.AdminNavigator.users": { "defaultMessage": "Users" }, - "system.admin.admin.AdminNavigator.getHelp": { - "defaultMessage": "Get Help" - }, "system.admin.admin.AnnouncementsIndex.fetchAnnouncementsFailure": { "defaultMessage": "Unable to fetch announcements" }, @@ -8606,21 +9899,24 @@ "system.admin.admin.InstancesTable.updateSuccess": { "defaultMessage": "Renamed {field} from {prevValue} to {newValue}" }, + "system.admin.admin.UsersButton.associatedCourses": { + "defaultMessage": "{courseName} ({instanceName})" + }, "system.admin.admin.UsersButton.deleteTooltip": { "defaultMessage": "Delete User" }, "system.admin.admin.UsersButton.deletionConfirm": { - "defaultMessage": "Are you sure you wish to delete {role} {name} ({email})?" + "defaultMessage": "Are you sure you wish to proceed?" }, "system.admin.admin.UsersButton.deletionConfirmTitle": { "defaultMessage": "Deleting {role} User {name} ({email})" }, - "system.admin.admin.UsersButton.deletionPromptContent": { - "defaultMessage": "Deleting this user will PERMANENTLY delete associated data in the following {count, plural, one {course} other {courses}}:" - }, "system.admin.admin.UsersButton.deletionFailure": { "defaultMessage": "Failed to delete user - {error}" }, + "system.admin.admin.UsersButton.deletionPromptContent": { + "defaultMessage": "Deleting this user will PERMANENTLY delete associated data in the following {count, plural, one {course} other {courses}}:" + }, "system.admin.admin.UsersButton.deletionSuccess": { "defaultMessage": "User was deleted." }, @@ -8666,6 +9962,24 @@ "system.admin.instance.instance.IndividualInvitations.invite": { "defaultMessage": "Invite All Users" }, + "system.admin.instance.instance.InstanceAdminNavigator.announcements": { + "defaultMessage": "Announcements" + }, + "system.admin.instance.instance.InstanceAdminNavigator.components": { + "defaultMessage": "Components" + }, + "system.admin.instance.instance.InstanceAdminNavigator.courses": { + "defaultMessage": "Courses" + }, + "system.admin.instance.instance.InstanceAdminNavigator.getHelp": { + "defaultMessage": "Get Help" + }, + "system.admin.instance.instance.InstanceAdminNavigator.roleRequests": { + "defaultMessage": "Role Requests" + }, + "system.admin.instance.instance.InstanceAdminNavigator.users": { + "defaultMessage": "Users" + }, "system.admin.instance.instance.InstanceAnnouncementsIndex.fetchAnnouncementsFailure": { "defaultMessage": "Unable to fetch announcements" }, @@ -8759,21 +10073,12 @@ "system.admin.instance.instance.InstanceUsersIndex.totalUsers": { "defaultMessage": "Total Users: {allCount} ({adminCount} Administrators, {instructorCount} Instructors, {normalCount} Normal)" }, - "system.admin.instance.instance.InstanceUsersInvitations.accepted": { - "defaultMessage": "Accepted Invitations" - }, - "system.admin.instance.instance.InstanceUsersInvitations.failed": { - "defaultMessage": "Failed Invitations" - }, "system.admin.instance.instance.InstanceUsersInvitations.fetch.failure": { "defaultMessage": "Failed to fetch invitations." }, "system.admin.instance.instance.InstanceUsersInvitations.header": { "defaultMessage": "Invitations" }, - "system.admin.instance.instance.InstanceUsersInvitations.pending": { - "defaultMessage": "Pending Invitations" - }, "system.admin.instance.instance.InstanceUsersInvitations.title": { "defaultMessage": "Users" }, @@ -8786,6 +10091,27 @@ "system.admin.instance.instance.InstanceUsersTabs.usersTab": { "defaultMessage": "Users" }, + "system.admin.instance.instance.InvitationActionButtons.deletionConfirm": { + "defaultMessage": "Are you sure you wish to delete invitation to {name} ({email})?" + }, + "system.admin.instance.instance.InvitationActionButtons.deletionFailure": { + "defaultMessage": "Failed to delete user - {error}" + }, + "system.admin.instance.instance.InvitationActionButtons.deletionSuccess": { + "defaultMessage": "Invitation for {name} was deleted." + }, + "system.admin.instance.instance.InvitationActionButtons.deletionTooltip": { + "defaultMessage": "Delete Invitation" + }, + "system.admin.instance.instance.InvitationActionButtons.resendFailure": { + "defaultMessage": "Failed to resend invitation - {error}" + }, + "system.admin.instance.instance.InvitationActionButtons.resendSuccess": { + "defaultMessage": "Resent email invitation to {email}!" + }, + "system.admin.instance.instance.InvitationActionButtons.resendTooltip": { + "defaultMessage": "Resend Invitation" + }, "system.admin.instance.instance.InvitationResultDialog.close": { "defaultMessage": "Close" }, @@ -8816,27 +10142,6 @@ "system.admin.instance.instance.InvitationResultDialog.newInvitations": { "defaultMessage": "New Invitations ({count})" }, - "system.admin.instance.instance.InvitationActionButtons.deletionConfirm": { - "defaultMessage": "Are you sure you wish to delete invitation to {name} ({email})?" - }, - "system.admin.instance.instance.InvitationActionButtons.deletionFailure": { - "defaultMessage": "Failed to delete user - {error}" - }, - "system.admin.instance.instance.InvitationActionButtons.deletionSuccess": { - "defaultMessage": "Invitation for {name} was deleted." - }, - "system.admin.instance.instance.InvitationActionButtons.deletionTooltip": { - "defaultMessage": "Delete Invitation" - }, - "system.admin.instance.instance.InvitationActionButtons.resendFailure": { - "defaultMessage": "Failed to resend invitation - {error}" - }, - "system.admin.instance.instance.InvitationActionButtons.resendSuccess": { - "defaultMessage": "Resent email invitation to {email}!" - }, - "system.admin.instance.instance.InvitationActionButtons.resendTooltip": { - "defaultMessage": "Resend Invitation" - }, "system.admin.instance.instance.PendingRoleRequestsButton.approveFailure": { "defaultMessage": "Failed to approve role request - {error}" }, @@ -8882,6 +10187,9 @@ "system.admin.instance.instance.UserInvitationsTable.accepted": { "defaultMessage": "Accepted" }, + "system.admin.instance.instance.UserInvitationsTable.confirmedTooltip": { + "defaultMessage": "Accepted {confirmedAt}" + }, "system.admin.instance.instance.UserInvitationsTable.failed": { "defaultMessage": "Failed" }, @@ -8894,9 +10202,6 @@ "system.admin.instance.instance.UserInvitationsTable.sentTooltip": { "defaultMessage": "Sent {sentAt}" }, - "system.admin.instance.instance.UserInvitationsTable.confirmedTooltip": { - "defaultMessage": "Accepted {confirmedAt}" - }, "system.admin.instance.instance.UsersButton.deleteTooltip": { "defaultMessage": "Remove User" }, @@ -8906,12 +10211,12 @@ "system.admin.instance.instance.UsersButton.deletionConfirmTitle": { "defaultMessage": "Removing {role} User {name} ({email})" }, - "system.admin.instance.instance.UsersButton.deletionPromptContent": { - "defaultMessage": "Removing this user may cause errors in the following {count, plural, one {course} other {courses}}:" - }, "system.admin.instance.instance.UsersButton.deletionFailure": { "defaultMessage": "Failed to remove user - {error}" }, + "system.admin.instance.instance.UsersButton.deletionPromptContent": { + "defaultMessage": "Removing this user may cause errors in the following {count, plural, one {course} other {courses}}:" + }, "system.admin.instance.instance.UsersButton.deletionSuccess": { "defaultMessage": "User was removed from this instance." }, @@ -9268,164 +10573,5 @@ }, "lib.translations.table.column.newExternalId": { "defaultMessage": "New External ID" - }, - "course.admin.GradebookSettings.gradebookSettings": { - "defaultMessage": "Gradebook settings" - }, - "course.admin.GradebookSettings.weightedViewEnabled": { - "defaultMessage": "Enable weighted grade view" - }, - "course.admin.GradebookSettings.weightedViewEnabledHint": { - "defaultMessage": "Enables a \"Weighted total\" view in the gradebook where staff can configure per-tab weights and see a weighted Total column." - }, - "course.gradebook.ConfigureWeightsPrompt.allExcluded": { - "defaultMessage": "All assessments in \"{tab}\" are excluded — it contributes nothing to the total." - }, - "course.gradebook.ConfigureWeightsPrompt.allExcludedCount": { - "defaultMessage": "All {n} excluded" - }, - "course.gradebook.ConfigureWeightsPrompt.customMode": { - "defaultMessage": "Custom" - }, - "course.gradebook.ConfigureWeightsPrompt.customSum": { - "defaultMessage": "Assessment weights: {sum} / {total}" - }, - "course.gradebook.ConfigureWeightsPrompt.defaultsHint": { - "defaultMessage": "No weights set yet — these are suggested defaults with every tab counting equally. Save to confirm, or adjust below." - }, - "course.gradebook.ConfigureWeightsPrompt.descriptionDrop": { - "defaultMessage": "In Equal mode, optionally drop each student's N lowest-scoring assessments before averaging." - }, - "course.gradebook.ConfigureWeightsPrompt.descriptionExclusion": { - "defaultMessage": "Expand a tab to include or exclude individual assessments from grading." - }, - "course.gradebook.ConfigureWeightsPrompt.descriptionIntro": { - "defaultMessage": "Control how tabs and assessments count toward each student's total grade." - }, - "course.gradebook.ConfigureWeightsPrompt.descriptionModes": { - "defaultMessage": "Choose Equal (all assessments share the tab's weight) or Custom (set each assessment's share)." - }, - "course.gradebook.ConfigureWeightsPrompt.descriptionWeights": { - "defaultMessage": "Set each tab's weight — how much it contributes to the total (weights should sum to 100)." - }, - "course.gradebook.ConfigureWeightsPrompt.equalMode": { - "defaultMessage": "Equal" - }, - "course.gradebook.ConfigureWeightsPrompt.excluded": { - "defaultMessage": "Excluded" - }, - "course.gradebook.ConfigureWeightsPrompt.excludedCount": { - "defaultMessage": "{n} excluded" - }, - "course.gradebook.ConfigureWeightsPrompt.includeAssessment": { - "defaultMessage": "Include {assessment} in grade" - }, - "course.gradebook.ConfigureWeightsPrompt.modeAria": { - "defaultMessage": "{tab} weight mode" - }, - "course.gradebook.ConfigureWeightsPrompt.ofGrade": { - "defaultMessage": "{pct}% of grade" - }, - "course.gradebook.ConfigureWeightsPrompt.promptTitle": { - "defaultMessage": "Configure contributions" - }, - "course.gradebook.ConfigureWeightsPrompt.saveError": { - "defaultMessage": "Failed to save weights. Please try again." - }, - "course.gradebook.ConfigureWeightsPrompt.total": { - "defaultMessage": "Total: {sum}%" - }, - "course.gradebook.ConfigureWeightsPrompt.unbalanced": { - "defaultMessage": "Assessment weights for \"{tab}\" must sum to its tab total before saving." - }, - "course.gradebook.ConfigureWeightsPrompt.valueTooHigh": { - "defaultMessage": "Value must be at most 100" - }, - "course.gradebook.ConfigureWeightsPrompt.valueTooLow": { - "defaultMessage": "Value must be at least 0" - }, - "course.gradebook.ConfigureWeightsPrompt.weightsDoNotSum": { - "defaultMessage": "Weights do not sum to 100. Saving is allowed; Total may be inaccurate." - }, - "course.gradebook.GradebookIndex.allAssessments": { - "defaultMessage": "All assessments" - }, - "course.gradebook.GradebookIndex.byWeight": { - "defaultMessage": "Weighted total" - }, - "course.gradebook.GradebookWeightedTable.collapseRow": { - "defaultMessage": "Collapse {name}" - }, - "course.gradebook.GradebookWeightedTable.configureWeights": { - "defaultMessage": "Configure Weights" - }, - "course.gradebook.GradebookWeightedTable.defaultWeights": { - "defaultMessage": "Showing default weights — every tab counts equally. Click \"Configure Weights\" to set your own." - }, - "course.gradebook.GradebookWeightedTable.defaultWeightsNoAccess": { - "defaultMessage": "Showing default weights — every tab counts equally until weights are configured." - }, - "course.gradebook.GradebookWeightedTable.displayPercent": { - "defaultMessage": "Percentage" - }, - "course.gradebook.GradebookWeightedTable.displayPercentTooltip": { - "defaultMessage": "What fraction of each tab the student earned. 100% on a tab worth 20% = the student earned all 20 grade points from that tab." - }, - "course.gradebook.GradebookWeightedTable.displayPoints": { - "defaultMessage": "Points" - }, - "course.gradebook.GradebookWeightedTable.displayPointsTooltip": { - "defaultMessage": "How many grade points each tab contributes. Columns add up to the projected total." - }, - "course.gradebook.GradebookWeightedTable.downloadCsv": { - "defaultMessage": "Download as CSV" - }, - "course.gradebook.GradebookWeightedTable.email": { - "defaultMessage": "Email" - }, - "course.gradebook.GradebookWeightedTable.excluded": { - "defaultMessage": "Excluded" - }, - "course.gradebook.GradebookWeightedTable.expandRow": { - "defaultMessage": "Expand {name}" - }, - "course.gradebook.GradebookWeightedTable.name": { - "defaultMessage": "Name" - }, - "course.gradebook.GradebookWeightedTable.noWeightsConfigured": { - "defaultMessage": "No weights configured — all tab weights are 0. Click \"Configure Weights\" to assign weights." - }, - "course.gradebook.GradebookWeightedTable.noWeightsNoAccess": { - "defaultMessage": "No tab weights have been configured yet." - }, - "course.gradebook.GradebookWeightedTable.outOfWeight": { - "defaultMessage": "/{weight}" - }, - "course.gradebook.GradebookWeightedTable.percentOfGrade": { - "defaultMessage": "{weight}% of grade" - }, - "course.gradebook.GradebookWeightedTable.percentTotalExact": { - "defaultMessage": "100% total" - }, - "course.gradebook.GradebookWeightedTable.percentTotalWarning": { - "defaultMessage": "{weight}% total" - }, - "course.gradebook.GradebookWeightedTable.total": { - "defaultMessage": "Total" - }, - "course.gradebook.GradebookWeightedTable.searchStudents": { - "defaultMessage": "Search students" - }, - "course.gradebook.GradebookWeightedTable.weightsDoNotSum": { - "defaultMessage": "Weights do not sum to 100. Total may be inaccurate." - }, - "course.gradebook.TotalHint.policy": { - "defaultMessage": "Totals count ungraded assessments as 0." - }, - "course.gradebook.WeightedViewHint.hint": { - "defaultMessage": "Want a weighted total grade? You can set how much each tab counts toward each student’s overall grade and view the weighted total here. Turn it on in {link}." - }, - "course.gradebook.WeightedViewHint.settingsLink": { - "defaultMessage": "Gradebook settings" } -} \ No newline at end of file +} diff --git a/client/locales/ko.json b/client/locales/ko.json index 9f9c0c593c..8fd74f5a60 100644 --- a/client/locales/ko.json +++ b/client/locales/ko.json @@ -29,6 +29,9 @@ "app.DashboardPage.yourCourses": { "defaultMessage": "내 강좌" }, + "app.ErrorPage.courseSuspended": { + "defaultMessage": "이 과정은 현재 정지되어 있습니다." + }, "app.ErrorPage.error": { "defaultMessage": "쾅, 운석이 떨어졌습니다." }, @@ -59,14 +62,11 @@ "app.ErrorPage.notFoundSubtitle": { "defaultMessage": "주소를 올바르게 입력했는지 확인하고, 나중에 다시 시도하거나, 홈으로 돌아가기를 클릭하세요." }, - "app.ErrorPage.userSuspended": { - "defaultMessage": "이 과정에 대한 접근이 정지되었습니다." - }, "app.ErrorPage.suspendedSubtitle": { "defaultMessage": "강사 또는 과정 담당자에게 문의하세요." }, - "app.ErrorPage.courseSuspended": { - "defaultMessage": "이 과정은 현재 정지되어 있습니다." + "app.ErrorPage.userSuspended": { + "defaultMessage": "이 과정에 대한 접근이 정지되었습니다." }, "app.Footer.contactUs": { "defaultMessage": "문의하기" @@ -80,12 +80,12 @@ "app.Footer.instructorsGuide": { "defaultMessage": "교사 안내서" }, - "app.Footer.reportIssue": { - "defaultMessage": "문제 신고" - }, "app.Footer.privacyPolicy": { "defaultMessage": "개인정보 보호정책" }, + "app.Footer.reportIssue": { + "defaultMessage": "문제 신고" + }, "app.Footer.termsOfService": { "defaultMessage": "서비스 약관" }, @@ -263,23 +263,23 @@ "course.achievement.AchievementAward.AchievementAwardManager.saveChanges": { "defaultMessage": "변경 사항 저장" }, + "course.achievement.AchievementAward.AchievementAwardSummary.awardedStudents": { + "defaultMessage": "부여된 학생" + }, "course.achievement.AchievementAward.AchievementAwardSummary.name": { "defaultMessage": "이름" }, - "course.achievement.AchievementAward.AchievementAwardSummary.userType": { - "defaultMessage": "사용자 유형" + "course.achievement.AchievementAward.AchievementAwardSummary.normalStudent": { + "defaultMessage": "일반 학생" }, - "course.achievement.AchievementAward.AchievementAwardSummary.awardedStudents": { - "defaultMessage": "부여된 학생" + "course.achievement.AchievementAward.AchievementAwardSummary.phantomStudent": { + "defaultMessage": "팬텀 학생" }, "course.achievement.AchievementAward.AchievementAwardSummary.revokedStudents": { "defaultMessage": "철회된 학생" }, - "course.achievement.AchievementAward.AchievementAwardSummary.phantomStudent": { - "defaultMessage": "팬텀 학생" - }, - "course.achievement.AchievementAward.AchievementAwardSummary.normalStudent": { - "defaultMessage": "일반 학생" + "course.achievement.AchievementAward.AchievementAwardSummary.userType": { + "defaultMessage": "사용자 유형" }, "course.achievement.AchievementAward.awardAchievement": { "defaultMessage": "성과 부여" @@ -353,26 +353,26 @@ "course.achievement.AchievementShow.studentsWithAchievement": { "defaultMessage": "이 성과를 가진 학생들" }, - "course.achievement.AchievementTable.noAchievement": { - "defaultMessage": "성과 없음" + "course.achievement.AchievementTable.actions": { + "defaultMessage": "작업" }, "course.achievement.AchievementTable.badge": { "defaultMessage": "배지" }, - "course.achievement.AchievementTable.title": { - "defaultMessage": "제목" - }, "course.achievement.AchievementTable.description": { "defaultMessage": "설명" }, - "course.achievement.AchievementTable.requirements": { - "defaultMessage": "요구 사항" + "course.achievement.AchievementTable.noAchievement": { + "defaultMessage": "성과 없음" }, "course.achievement.AchievementTable.published": { "defaultMessage": "게시됨" }, - "course.achievement.AchievementTable.actions": { - "defaultMessage": "작업" + "course.achievement.AchievementTable.requirements": { + "defaultMessage": "요구 사항" + }, + "course.achievement.AchievementTable.title": { + "defaultMessage": "제목" }, "course.achievement.AchievementsIndex.achievements": { "defaultMessage": "성과" @@ -530,47 +530,29 @@ "course.admin.CodaveriSettings.codaveriEngineDescription": { "defaultMessage": "프로그래밍 코드 피드백을 생성하는 데 사용되는 코다베리 엔진 유형" }, + "course.admin.CodaveriSettings.codaveriEvaluatorSettings": { + "defaultMessage": "코다베리 평가자" + }, + "course.admin.CodaveriSettings.codaveriModel": { + "defaultMessage": "모델" + }, + "course.admin.CodaveriSettings.codaveriModelDescription": { + "defaultMessage": "Codaveri가 프로그래밍 문제에 대한 학생 도움 대화를 생성하는 데 사용하는 AI 모델입니다." + }, "course.admin.CodaveriSettings.codaveriOverrideSystemPrompt": { "defaultMessage": "사용자 정의 시스템 프롬프트 사용" }, "course.admin.CodaveriSettings.codaveriOverrideSystemPromptDescription": { "defaultMessage": "학생을 도울 때, 이 지침은 문제 자체에 설정한 지침에 추가로 따르게 됩니다. 문제별 세부 사항을 참조하려면 프롬프트 내에서 다음 변수를 사용할 수 있으며, 아래와 같이 대괄호로 작성합니다:" }, - "course.admin.CodaveriSettings.codaveriSystemPrompt": { - "defaultMessage": "시스템 프롬프트" - }, - "course.admin.CodaveriSettings.codaveriUseDefaultSystemPrompt": { - "defaultMessage": "기본 시스템 프롬프트 사용" - }, - "course.admin.CodaveriSettings.evaluatorUpdateSuccess": { - "defaultMessage": "{question}이(가) 이제 {evaluator} 평가자를 사용합니다" - }, - "course.admin.CodaveriSettings.expandAll": { - "defaultMessage": "모든 질문 펼치기" - }, - "course.admin.CodaveriSettings.programmingQuestionSettings": { - "defaultMessage": "프로그래밍 질문 설정" - }, - "course.admin.CodaveriSettings.programmingQuestionSettingsSubtitle": { - "defaultMessage": "다양한 평가의 프로그래밍 질문에 대해 코다베리를 평가자로 활성화/비활성화합니다." - }, - "course.admin.CodaveriSettings.succesfulUpdateAllEvaluator": { - "defaultMessage": "모든 질문을 {evaluator} 평가자를 사용하도록 성공적으로 업데이트했습니다" - }, - "course.admin.CodaveriSettings.getHelpUsageLimit": { - "defaultMessage": "학생당 도움 요청 메시지 제한" - }, - "course.admin.CodaveriSettings.getHelpUsageLimitDescription": { - "defaultMessage": "활성화되면 학생은 질문당 제한된 수의 메시지만 보낼 수 있습니다. 학생은 이 제한과 남은 메시지 수를 볼 수 있습니다." - }, - "course.admin.CodaveriSettings.maxGetHelpUserMessages": { - "defaultMessage": "질문당 최대 메시지 수" + "course.admin.CodaveriSettings.codaveriSettings": { + "defaultMessage": "코다베리 설정" }, - "course.admin.CodaveriSettings.codaveriModel": { - "defaultMessage": "모델" + "course.admin.CodaveriSettings.codaveriSettingsSubtitle": { + "defaultMessage": "현재 실험적인 기능입니다. 코다베리는 학생의 코드에 대한 코드 평가 및 자동 코드 피드백 서비스를 제공합니다." }, - "course.admin.CodaveriSettings.codaveriModelDescription": { - "defaultMessage": "Codaveri가 프로그래밍 문제에 대한 학생 도움 대화를 생성하는 데 사용하는 AI 모델입니다." + "course.admin.CodaveriSettings.codaveriSystemPrompt": { + "defaultMessage": "시스템 프롬프트" }, "course.admin.CodaveriSettings.codaveriSystemPromptDescription": { "defaultMessage": "여기에서 지침을 제공하여 Codaveri 모델의 동작을 사용자 지정할 수 있습니다.{br} 학생을 도울 때, 이 지침은 문제 자체에 설정한 지침에 추가로 따르게 됩니다.{br} 문제별 세부 사항을 참조하려면, 아래와 같이 대괄호로 작성된 다음 변수를 프롬프트에서 사용할 수 있습니다:" @@ -581,14 +563,8 @@ "course.admin.CodaveriSettings.codaveriSystemPromptStudentFilePathsLine": { "defaultMessage": "{studentFilePathsVar} : 학생이 작업 중인 파일 경로의 쉼표로 구분된 목록" }, - "course.admin.CodaveriSettings.codaveriEvaluatorSettings": { - "defaultMessage": "코다베리 평가자" - }, - "course.admin.CodaveriSettings.codaveriSettings": { - "defaultMessage": "코다베리 설정" - }, - "course.admin.CodaveriSettings.codaveriSettingsSubtitle": { - "defaultMessage": "현재 실험적인 기능입니다. 코다베리는 학생의 코드에 대한 코드 평가 및 자동 코드 피드백 서비스를 제공합니다." + "course.admin.CodaveriSettings.codaveriUseDefaultSystemPrompt": { + "defaultMessage": "기본 시스템 프롬프트 사용" }, "course.admin.CodaveriSettings.enableDisableButton": { "defaultMessage": "{enabled, select, true {활성화} other {비활성화}}" @@ -611,6 +587,12 @@ "course.admin.CodaveriSettings.errorOccurredWhenUpdatingLiveFeedbackSettings": { "defaultMessage": "실시간 피드백 설정을 업데이트하는 동안 오류가 발생했습니다." }, + "course.admin.CodaveriSettings.evaluatorUpdateSuccess": { + "defaultMessage": "{question}이(가) 이제 {evaluator} 평가자를 사용합니다" + }, + "course.admin.CodaveriSettings.expandAll": { + "defaultMessage": "모든 질문 펼치기" + }, "course.admin.CodaveriSettings.feedbackWorkflow": { "defaultMessage": "자동 게시 제출 댓글" }, @@ -626,12 +608,30 @@ "course.admin.CodaveriSettings.feedbackWorkflowPublish": { "defaultMessage": "학생에게 직접 피드백 게시" }, + "course.admin.CodaveriSettings.getHelpUsageLimit": { + "defaultMessage": "학생당 도움 요청 메시지 제한" + }, + "course.admin.CodaveriSettings.getHelpUsageLimitDescription": { + "defaultMessage": "활성화되면 학생은 질문당 제한된 수의 메시지만 보낼 수 있습니다. 학생은 이 제한과 남은 메시지 수를 볼 수 있습니다." + }, "course.admin.CodaveriSettings.liveFeedbackEnabledUpdateSuccess": { "defaultMessage": "{question}에 대한 실시간 피드백이 {liveFeedbackEnabled, select, true {활성화} other {비활성화}}되었습니다" }, "course.admin.CodaveriSettings.liveFeedbackSettings": { "defaultMessage": "실시간 피드백" }, + "course.admin.CodaveriSettings.maxGetHelpUserMessages": { + "defaultMessage": "질문당 최대 메시지 수" + }, + "course.admin.CodaveriSettings.programmingQuestionSettings": { + "defaultMessage": "프로그래밍 질문 설정" + }, + "course.admin.CodaveriSettings.programmingQuestionSettingsSubtitle": { + "defaultMessage": "다양한 평가의 프로그래밍 질문에 대해 코다베리를 평가자로 활성화/비활성화합니다." + }, + "course.admin.CodaveriSettings.succesfulUpdateAllEvaluator": { + "defaultMessage": "모든 질문을 {evaluator} 평가자를 사용하도록 성공적으로 업데이트했습니다" + }, "course.admin.CodaveriSettings.successfulUpdateAllLiveFeedbackEnabled": { "defaultMessage": "모든 질문에 대해 {liveFeedbackEnabled, select, true {활성화} other {비활성화}}된 실시간 피드백이 성공적으로 {liveFeedbackEnabled, select, true {활성화} other {비활성화}}되었습니다" }, @@ -677,6 +677,12 @@ "course.admin.CourseSettings.courseSettings": { "defaultMessage": "강좌 설정" }, + "course.admin.CourseSettings.courseSuspensionMessage": { + "defaultMessage": "과정 정지 메시지" + }, + "course.admin.CourseSettings.courseSuspensionMessageDescription": { + "defaultMessage": "이 메시지는 과정이 정지된 동안 사용자에게 표시됩니다. 기본 메시지를 표시하려면 비워 두세요." + }, "course.admin.CourseSettings.daysInAdvance": { "defaultMessage": "몇 일 전" }, @@ -764,23 +770,14 @@ "course.admin.CourseSettings.stragglersDescription": { "defaultMessage": "뒤처진 학생을 위해 다음 폐쇄 참조 시간이 연기됩니다." }, - "course.admin.CourseSettings.suspension": { - "defaultMessage": "접근 정지" - }, "course.admin.CourseSettings.suspendCourse": { "defaultMessage": "과정 정지" }, "course.admin.CourseSettings.suspendCourseDescription": { "defaultMessage": "정지된 과정은 모든 학생이 접근할 수 없습니다. 강사는 과정에 계속 접근할 수 있으며 모든 학생 데이터는 보존됩니다." }, - "course.admin.CourseSettings.unsuspendCourse": { - "defaultMessage": "과정 정지 해제" - }, - "course.admin.CourseSettings.courseSuspensionMessage": { - "defaultMessage": "과정 정지 메시지" - }, - "course.admin.CourseSettings.courseSuspensionMessageDescription": { - "defaultMessage": "이 메시지는 과정이 정지된 동안 사용자에게 표시됩니다. 기본 메시지를 표시하려면 비워 두세요." + "course.admin.CourseSettings.suspendCourseFailure": { + "defaultMessage": "과정을 정지하는 중 오류가 발생했습니다." }, "course.admin.CourseSettings.suspendCoursePromptText": { "defaultMessage": "이 과정을 정지하시겠습니까? 정지가 해제될 때까지 모든 학생이 접근할 수 없게 됩니다." @@ -788,20 +785,8 @@ "course.admin.CourseSettings.suspendCourseSuccess": { "defaultMessage": "이 과정이 정지되었습니다." }, - "course.admin.CourseSettings.suspendCourseFailure": { - "defaultMessage": "과정을 정지하는 중 오류가 발생했습니다." - }, - "course.admin.CourseSettings.unsuspendCourseSuccess": { - "defaultMessage": "이 과정의 정지가 해제되었습니다." - }, - "course.admin.CourseSettings.unsuspendCourseFailure": { - "defaultMessage": "과정 정지를 해제하는 중 오류가 발생했습니다." - }, - "course.admin.CourseSettings.userSuspensionMessage": { - "defaultMessage": "사용자 정지 메시지" - }, - "course.admin.CourseSettings.userSuspensionMessageDescription": { - "defaultMessage": "이 메시지는 이 과정에 대한 접근이 정지된 개별 사용자에게 표시됩니다. 기본 메시지를 표시하려면 비워 두세요." + "course.admin.CourseSettings.suspension": { + "defaultMessage": "접근 정지" }, "course.admin.CourseSettings.timeSettings": { "defaultMessage": "시간 설정" @@ -812,12 +797,27 @@ "course.admin.CourseSettings.titleRequired": { "defaultMessage": "강좌 이름이 필요합니다." }, + "course.admin.CourseSettings.unsuspendCourse": { + "defaultMessage": "과정 정지 해제" + }, + "course.admin.CourseSettings.unsuspendCourseFailure": { + "defaultMessage": "과정 정지를 해제하는 중 오류가 발생했습니다." + }, + "course.admin.CourseSettings.unsuspendCourseSuccess": { + "defaultMessage": "이 과정의 정지가 해제되었습니다." + }, "course.admin.CourseSettings.uploadANewImage": { "defaultMessage": "새 이미지 선택" }, "course.admin.CourseSettings.uploadingLogo": { "defaultMessage": "새 로고를 업로드하는 중..." }, + "course.admin.CourseSettings.userSuspensionMessage": { + "defaultMessage": "사용자 정지 메시지" + }, + "course.admin.CourseSettings.userSuspensionMessageDescription": { + "defaultMessage": "이 메시지는 이 과정에 대한 접근이 정지된 개별 사용자에게 표시됩니다. 기본 메시지를 표시하려면 비워 두세요." + }, "course.admin.CourseSettingst.confirmDeletePlaceholder": { "defaultMessage": "되돌릴 기회는 이것이 마지막입니다!" }, @@ -872,6 +872,15 @@ "course.admin.ForumsSettings.markPostAsAnswerSetting": { "defaultMessage": "게시물을 답변으로 표시할 사용자" }, + "course.admin.GradebookSettings.gradebookSettings": { + "defaultMessage": "성적부 설정" + }, + "course.admin.GradebookSettings.weightedViewEnabled": { + "defaultMessage": "가중 성적 보기 사용" + }, + "course.admin.GradebookSettings.weightedViewEnabledHint": { + "defaultMessage": "성적부에 \"가중 총점\" 보기를 추가하여 교직원이 탭별 가중치를 설정하고 가중 총점 열을 확인할 수 있습니다." + }, "course.admin.LeaderboardSettings.displayUserCount": { "defaultMessage": "사용자 수 표시" }, @@ -941,6 +950,9 @@ "course.admin.MaterialSettings.materialsSettings": { "defaultMessage": "자료 설정" }, + "course.admin.NotificationSettings.component": { + "defaultMessage": "구성 요소" + }, "course.admin.NotificationSettings.description": { "defaultMessage": "설명" }, @@ -1394,12 +1406,12 @@ "course.assessment.AssessmentForm.showMcqMrqSolution": { "defaultMessage": "MCQ/MRQ 솔루션 표시" }, - "course.assessment.AssessmentForm.showRubricToStudents": { - "defaultMessage": "학생에게 루브릭 세부사항 표시" - }, "course.assessment.AssessmentForm.showPrivate": { "defaultMessage": "개인 테스트 케이스 표시" }, + "course.assessment.AssessmentForm.showRubricToStudents": { + "defaultMessage": "학생에게 루브릭 세부사항 표시" + }, "course.assessment.AssessmentForm.singlePage": { "defaultMessage": "단일 페이지" }, @@ -1505,9 +1517,24 @@ "course.assessment.edit.update": { "defaultMessage": "저장" }, + "course.assessment.generation.allFieldsLocked": { + "defaultMessage": "모든 필드가 잠겨 있어 생성을 진행할 수 없습니다." + }, "course.assessment.generation.confirmDeleteConversation": { "defaultMessage": "\"{title}\" 및 모든 기록 항목을 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다!" }, + "course.assessment.generation.createMode": { + "defaultMessage": "새로 만들기" + }, + "course.assessment.generation.createModeTooltip": { + "defaultMessage": "처음부터 새로운 질문을 생성합니다" + }, + "course.assessment.generation.enhanceMode": { + "defaultMessage": "강화" + }, + "course.assessment.generation.enhanceModeTooltip": { + "defaultMessage": "현재 질문을 기반으로 확장합니다" + }, "course.assessment.generation.exportAction": { "defaultMessage": "내보내기" }, @@ -1517,123 +1544,75 @@ "course.assessment.generation.exportError": { "defaultMessage": "이 문제를 내보내는 중 오류가 발생했습니다: {error}" }, + "course.assessment.generation.generateError": { + "defaultMessage": "{title} 문항 생성 중 오류가 발생했습니다." + }, + "course.assessment.generation.generateMcqPage": { + "defaultMessage": "객관식 문항 생성" + }, + "course.assessment.generation.generateMrqPage": { + "defaultMessage": "다중 선택 문항 생성" + }, + "course.assessment.generation.generateMultipleSuccess": { + "defaultMessage": "{count}개의 문항이 성공적으로 생성되었습니다!" + }, + "course.assessment.generation.generateQuestion": { + "defaultMessage": "생성" + }, + "course.assessment.generation.generateSuccess": { + "defaultMessage": "{title} 생성에 성공했습니다." + }, + "course.assessment.generation.loadingSourceError": { + "defaultMessage": "원본 문항 데이터를 불러올 수 없습니다." + }, "course.assessment.generation.lockTooltip": { "defaultMessage": "이 섹션의 변경을 방지하려면 잠그세요" }, + "course.assessment.generation.mrq.exportDialogHeader": { + "defaultMessage": "문항 내보내기 ({exportCount}개 선택됨)" + }, + "course.assessment.generation.mrq.numberOfQuestionsField": { + "defaultMessage": "문항 수" + }, + "course.assessment.generation.mrq.numberOfQuestionsRange": { + "defaultMessage": "{min}에서 {max} 사이의 숫자를 입력하세요" + }, "course.assessment.generation.newTab": { "defaultMessage": "새로 만들기" }, "course.assessment.generation.openExportDialog": { "defaultMessage": "내보내기" }, + "course.assessment.generation.promptPlaceholder": { + "defaultMessage": "여기에 입력하세요..." + }, + "course.assessment.generation.requireNonEmptyOptionError": { + "defaultMessage": "문항에는 최소 하나의 빈칸이 아닌 선택지가 있어야 합니다" + }, "course.assessment.generation.resetConversation": { "defaultMessage": "초기화" }, + "course.assessment.generation.showInactive": { + "defaultMessage": "비활성 항목 보기" + }, "course.assessment.generation.unlockTooltip": { "defaultMessage": "이 섹션을 계속 편집하려면 잠금을 해제하세요" }, - "course.assessment.generation.mrq.numberOfQuestionsField": { - "defaultMessage": "문항 수" - }, - "course.assessment.generation.promptPlaceholder": { - "defaultMessage": "여기에 입력하세요..." - }, - "course.assessment.generation.generateQuestion": { - "defaultMessage": "생성" - }, - "course.assessment.generation.showInactive": { - "defaultMessage": "비활성 항목 보기" - }, - "course.assessment.generation.mrq.numberOfQuestionsRange": { - "defaultMessage": "{min}에서 {max} 사이의 숫자를 입력하세요" - }, - "course.assessment.generation.enhanceMode": { - "defaultMessage": "강화" - }, - "course.assessment.generation.createMode": { - "defaultMessage": "새로 만들기" - }, - "course.assessment.generation.enhanceModeTooltip": { - "defaultMessage": "현재 질문을 기반으로 확장합니다" - }, - "course.assessment.generation.createModeTooltip": { - "defaultMessage": "처음부터 새로운 질문을 생성합니다" - }, - "course.assessment.generation.mrq.exportDialogHeader": { - "defaultMessage": "문항 내보내기 ({exportCount}개 선택됨)" - }, - "course.assessment.generation.requireNonEmptyOptionError": { - "defaultMessage": "문항에는 최소 하나의 빈칸이 아닌 선택지가 있어야 합니다" - }, "course.assessment.generation.untitledQuestion": { "defaultMessage": "제목 없는 문항" }, - "course.assessment.question.multipleResponses.showOptions": { - "defaultMessage": "옵션 보기" - }, - "course.assessment.question.multipleResponses.hideOptions": { - "defaultMessage": "옵션 숨기기" - }, - "course.assessment.question.multipleResponses.noOptions": { - "defaultMessage": "옵션 없음" - }, - "course.assessment.question.multipleResponses.title": { - "defaultMessage": "제목" - }, - "course.assessment.generation.generateMrqPage": { - "defaultMessage": "다중 선택 문항 생성" - }, - "course.assessment.generation.generateMcqPage": { - "defaultMessage": "객관식 문항 생성" - }, - "course.assessment.generation.generateMultipleSuccess": { - "defaultMessage": "{count}개의 문항이 성공적으로 생성되었습니다!" - }, - "course.assessment.generation.generateSuccess": { - "defaultMessage": "{title} 생성에 성공했습니다." - }, - "course.assessment.generation.generateError": { - "defaultMessage": "{title} 문항 생성 중 오류가 발생했습니다." - }, - "course.assessment.generation.loadingSourceError": { - "defaultMessage": "원본 문항 데이터를 불러올 수 없습니다." - }, - "course.assessment.generation.allFieldsLocked": { - "defaultMessage": "모든 필드가 잠겨 있어 생성을 진행할 수 없습니다." - }, "course.assessment.liveFeedback.comments": { "defaultMessage": "댓글" }, - "course.assessment.liveFeedback.messageTimingTitle": { - "defaultMessage": "{usedAt}에 생성됨" - }, "course.assessment.liveFeedback.lineHeader": { "defaultMessage": "{lineNumber} 줄" }, - "course.assessment.submission.GetHelpChatPage.chatInputText": { - "defaultMessage": "어떻게 도와드릴까요?" - }, - "course.assessment.submission.GetHelpChatPage.chatMessagesRemaining": { - "defaultMessage": "{numMessages} / {maxMessages} 개 메시지 남음" - }, - "course.assessment.submission.GetHelpChatPage.noChatMessagesRemaining": { - "defaultMessage": "이 질문의 메시지 한도에 도달했습니다." - }, - "course.assessment.submission.GetHelpChatPage.codeUpdated": { - "defaultMessage": "코드가 업데이트되었습니다" - }, - "course.assessment.submission.GetHelpChatPage.ConversationArea.lineNumber": { - "defaultMessage": "{lineNumber} 줄" - }, - "course.assessment.submission.GetHelpChatPage.ConversationArea.fileNameAndLineNumber": { - "defaultMessage": "{filename}:{lineNumber}" - }, - "course.assessment.submission.GetHelpChatPage.ConversationArea.threadExpired": { - "defaultMessage": "위의 채팅이 종료되었습니다. 새 채팅을 시작하시겠습니까?" - }, "course.assessment.liveFeedback.liveFeedbackName": { "defaultMessage": "라이브 피드백" }, + "course.assessment.liveFeedback.messageTimingTitle": { + "defaultMessage": "{usedAt}에 생성됨" + }, "course.assessment.liveFeedback.questionTitle": { "defaultMessage": "질문 {index}" }, @@ -1718,6 +1697,54 @@ "course.assessment.newAssessment": { "defaultMessage": "새 평가" }, + "course.assessment.plagiarism.actions": { + "defaultMessage": "작업" + }, + "course.assessment.plagiarism.baseSubmission": { + "defaultMessage": "기본 제출" + }, + "course.assessment.plagiarism.comparedSubmission": { + "defaultMessage": "비교된 제출" + }, + "course.assessment.plagiarism.confirmStartMessage": { + "defaultMessage": "새 표절 검사를 실행하면 이전 결과가 제거됩니다." + }, + "course.assessment.plagiarism.confirmStartTitle": { + "defaultMessage": "표절 검사 확인?" + }, + "course.assessment.plagiarism.downloadPdf": { + "defaultMessage": "PDF 다운로드" + }, + "course.assessment.plagiarism.lastRunTime": { + "defaultMessage": "마지막 실행 시간: {date}" + }, + "course.assessment.plagiarism.notStarted": { + "defaultMessage": "표절 검사가 실행되지 않았습니다." + }, + "course.assessment.plagiarism.plagiarism": { + "defaultMessage": "표절 결과" + }, + "course.assessment.plagiarism.results": { + "defaultMessage": "표절 결과 (제출물 간 유사도)" + }, + "course.assessment.plagiarism.searchByStudentName": { + "defaultMessage": "학생 이름으로 검색" + }, + "course.assessment.plagiarism.showSelfPlagiarism": { + "defaultMessage": "자기 표절 비교 포함 (동일 학생, 다른 과정)" + }, + "course.assessment.plagiarism.similarityScore": { + "defaultMessage": "유사성 점수" + }, + "course.assessment.plagiarism.start": { + "defaultMessage": "새 표절 검사" + }, + "course.assessment.plagiarism.status": { + "defaultMessage": "표절 검사 상태" + }, + "course.assessment.plagiarism.viewReport": { + "defaultMessage": "보고서 보기" + }, "course.assessment.question.forumPostResponses.enableTextResponse": { "defaultMessage": "학생들이 추가 입력을 제공할 수 있도록 텍스트 필드 포함" }, @@ -1790,6 +1817,9 @@ "course.assessment.question.multipleResponses.grading": { "defaultMessage": "채점" }, + "course.assessment.question.multipleResponses.hideOptions": { + "defaultMessage": "옵션 숨기기" + }, "course.assessment.question.multipleResponses.ignoresRandomization": { "defaultMessage": "무작위화 무시" }, @@ -1826,6 +1856,9 @@ "course.assessment.question.multipleResponses.newResponseCannotUndo": { "defaultMessage": "이것은 새로운 응답입니다. 저장하기 전에 삭제하면 즉시 사라집니다." }, + "course.assessment.question.multipleResponses.noOptions": { + "defaultMessage": "옵션 없음" + }, "course.assessment.question.multipleResponses.noSkillsCanCreateSkills": { "defaultMessage": "이 강좌에는 아직 기술이 없습니다. 기술 페이지에서 새 기술을 생성할 수 있습니다." }, @@ -1862,6 +1895,9 @@ "course.assessment.question.multipleResponses.saveChangesFirstBeforeConvertingMcqMrq": { "defaultMessage": "이 질문을 변환하기 전에 변경 사항을 저장하세요." }, + "course.assessment.question.multipleResponses.showOptions": { + "defaultMessage": "옵션 보기" + }, "course.assessment.question.multipleResponses.skills": { "defaultMessage": "기술" }, @@ -1874,6 +1910,9 @@ "course.assessment.question.multipleResponses.staffOnlyCommentsHint": { "defaultMessage": "내부 메모 또는 문서화에 유용합니다. 학생들은 절대 볼 수 없습니다." }, + "course.assessment.question.multipleResponses.title": { + "defaultMessage": "제목" + }, "course.assessment.question.multipleResponses.undoDeleteChoice": { "defaultMessage": "삭제 취소 선택" }, @@ -1949,12 +1988,12 @@ "course.assessment.question.programming.defaultEvaluator": { "defaultMessage": "기본" }, - "course.assessment.question.programming.defaultEvaluatorDependencyTitle": { - "defaultMessage": "{name}: 설치된 종속성" - }, "course.assessment.question.programming.defaultEvaluatorDependencyDescription": { "defaultMessage": "제출된 코드는 컨테이너화된 환경에서 실행되며, 다음 종속성이 로컬에 설치되어 있습니다.{br}프로그래밍 문제에 아래에 없는 종속성이 필요하다면, 문의해 주세요. 추가 여부를 검토하겠습니다." }, + "course.assessment.question.programming.defaultEvaluatorDependencyTitle": { + "defaultMessage": "{name}: 설치된 종속성" + }, "course.assessment.question.programming.defaultEvaluatorHint": { "defaultMessage": "아무 문제 없이, 아래 평가 패키지에 따라 코드를 실행하고 테스트 결과를 보고합니다." }, @@ -2087,24 +2126,24 @@ "course.assessment.question.programming.packageCreationModeHint": { "defaultMessage": "이 질문이 성공적으로 생성되면 이 모드를 변경할 수 없습니다. 신중하게 선택하세요!" }, - "course.assessment.question.programming.packageImportSuccess": { - "defaultMessage": "패키지가 성공적으로 가져와졌습니다." + "course.assessment.question.programming.packageImportEvaluationError": { + "defaultMessage": "솔루션을 테스트 케이스와 비교하는 과정에서 오류가 발생했습니다. 다시 한 번 확인하고 시도해주세요." + }, + "course.assessment.question.programming.packageImportEvaluationTimeout": { + "defaultMessage": "요구된 시간 내에 평가자로부터 응답을 받지 못했습니다. 현재 모든 평가자가 사용 중일 수 있습니다. 나중에 다시 시도해주세요." + }, + "course.assessment.question.programming.packageImportGenericError": { + "defaultMessage": "패키지를 가져올 수 없습니다: {error}" }, "course.assessment.question.programming.packageImportInvalidPackage": { "defaultMessage": "패키지를 가져올 수 없습니다: 업로드된 패키지의 구조가 올바르지 않습니다." }, - "course.assessment.question.programming.packageImportEvaluationTimeout": { - "defaultMessage": "요구된 시간 내에 평가자로부터 응답을 받지 못했습니다. 현재 모든 평가자가 사용 중일 수 있습니다. 나중에 다시 시도해주세요." + "course.assessment.question.programming.packageImportSuccess": { + "defaultMessage": "패키지가 성공적으로 가져와졌습니다." }, "course.assessment.question.programming.packageImportTimeLimitExceeded": { "defaultMessage": "지정된 시간 제한 내에 테스트 케이스 평가를 완료하지 못했습니다." }, - "course.assessment.question.programming.packageImportEvaluationError": { - "defaultMessage": "솔루션을 테스트 케이스와 비교하는 과정에서 오류가 발생했습니다. 다시 한 번 확인하고 시도해주세요." - }, - "course.assessment.question.programming.packageImportGenericError": { - "defaultMessage": "패키지를 가져올 수 없습니다: {error}" - }, "course.assessment.question.programming.packageInfoOnline": { "defaultMessage": "생성된 평가 패키지" }, @@ -2207,155 +2246,197 @@ "course.assessment.question.programminquestion.questionSavedRedirecting": { "defaultMessage": "질문이 저장되었습니다." }, - "course.assessment.question.scribing.ScribingQuestionForm.cannotBeBlankValidationError": { - "defaultMessage": "공란으로 둘 수 없습니다." + "course.assessment.question.rubricPlayground.add": { + "defaultMessage": "추가" }, - "course.assessment.question.scribing.ScribingQuestionForm.chooseFileButton": { - "defaultMessage": "파일 선택" + "course.assessment.question.rubricPlayground.addExistingAnswers": { + "defaultMessage": "기존 답변 추가" }, - "course.assessment.question.scribing.ScribingQuestionForm.descriptionFieldLabel": { - "defaultMessage": "설명" + "course.assessment.question.rubricPlayground.addNewCategory": { + "defaultMessage": "새 카테고리 추가" }, - "course.assessment.question.scribing.ScribingQuestionForm.fetchFailureMessage": { - "defaultMessage": "오류가 발생했습니다. 다시 시도하세요." + "course.assessment.question.rubricPlayground.addNewGrade": { + "defaultMessage": "새 점수 추가" }, - "course.assessment.question.scribing.ScribingQuestionForm.fileAttachmentRequired": { - "defaultMessage": "파일 첨부 필요" + "course.assessment.question.rubricPlayground.addRandomStudentAnswers": { + "defaultMessage": "{inputComponent}개의 무작위 학생 답변 추가" }, - "course.assessment.question.scribing.ScribingQuestionForm.fileUploaded": { - "defaultMessage": "업로드된 파일:" + "course.assessment.question.rubricPlayground.addSampleAnswers": { + "defaultMessage": "샘플 답변 추가" }, - "course.assessment.question.scribing.ScribingQuestionForm.lessThanEqualZeroValidationError": { - "defaultMessage": "값은 0보다 커야 합니다." + "course.assessment.question.rubricPlayground.addSampleAnswersTitle": { + "defaultMessage": "샘플 답변 추가" }, - "course.assessment.question.scribing.ScribingQuestionForm.maximumGradeFieldLabel": { - "defaultMessage": "최대 등급" + "course.assessment.question.rubricPlayground.answer": { + "defaultMessage": "답변" }, - "course.assessment.question.scribing.ScribingQuestionForm.noFileChosenMessage": { - "defaultMessage": "선택된 파일이 없습니다" + "course.assessment.question.rubricPlayground.apply": { + "defaultMessage": "적용" }, - "course.assessment.question.scribing.ScribingQuestionForm.positiveNumberValidationError": { - "defaultMessage": "값은 양수여야 합니다." + "course.assessment.question.rubricPlayground.applyFailure": { + "defaultMessage": "채점 결과 적용 실패" }, - "course.assessment.question.scribing.ScribingQuestionForm.resolveErrorsMessage": { - "defaultMessage": "이 양식에 오류가 있습니다. 제출 전에 해결하세요." + "course.assessment.question.rubricPlayground.applySuccess": { + "defaultMessage": "채점 루브릭, 프롬프트 및 결과가 성공적으로 적용되었습니다." }, - "course.assessment.question.scribing.ScribingQuestionForm.scribingQuestionWarning": { - "defaultMessage": "참고: PDF 파일의 각 페이지는 동일한 질문 세부사항을 갖는 단일 스크라이빙 질문으로 생성됩니다. 선택 입력을 비워 두고 생성 후 질문을 다시 편집할 수 있습니다." + "course.assessment.question.rubricPlayground.applyWillGradeAllAnswers": { + "defaultMessage": "이 루브릭을 적용하면 이 페이지에서 아직 평가되지 않은 답변을 포함하여 모든 학생 답변에 점수가 할당됩니다." }, - "course.assessment.question.scribing.ScribingQuestionForm.skillsFieldLabel": { - "defaultMessage": "기술" + "course.assessment.question.rubricPlayground.applyingRubricGradingData": { + "defaultMessage": "루브릭 채점 데이터 적용 중..." }, - "course.assessment.question.scribing.ScribingQuestionForm.staffOnlyCommentsFieldLabel": { - "defaultMessage": "직원 전용 코멘트" + "course.assessment.question.rubricPlayground.categoryHeading": { + "defaultMessage": "카{index}" }, - "course.assessment.question.scribing.ScribingQuestionForm.submitButton": { - "defaultMessage": "제출" + "course.assessment.question.rubricPlayground.categoryName": { + "defaultMessage": "카테고리 이름" }, - "course.assessment.question.scribing.ScribingQuestionForm.submitFailureMessage": { - "defaultMessage": "오류가 발생했습니다. 다시 시도하세요." + "course.assessment.question.rubricPlayground.compare": { + "defaultMessage": "비교" }, - "course.assessment.question.scribing.ScribingQuestionForm.submittingMessage": { - "defaultMessage": "제출 중..." + "course.assessment.question.rubricPlayground.comparingRevisions": { + "defaultMessage": "{count}개 개정판 비교 중" }, - "course.assessment.question.scribing.ScribingQuestionForm.titleFieldLabel": { - "defaultMessage": "제목" + "course.assessment.question.rubricPlayground.confirmAIGradingApplication": { + "defaultMessage": "AI 채점 적용 확인" }, - "course.assessment.question.scribing.ScribingQuestionForm.valueMoreThan1000Error": { - "defaultMessage": "값은 1000보다 작아야 합니다." + "course.assessment.question.rubricPlayground.confirmProceed": { + "defaultMessage": "계속 진행하시겠습니까?" }, - "course.assessment.question.textResponses.addSolution": { - "defaultMessage": "새 솔루션 추가" + "course.assessment.question.rubricPlayground.dismiss": { + "defaultMessage": "닫기" }, - "course.assessment.question.textResponses.allowFileUpload": { - "defaultMessage": "답변에서 파일 업로드 허용" + "course.assessment.question.rubricPlayground.evaluate": { + "defaultMessage": "평가" }, - "course.assessment.question.textResponses.deleteSolution": { - "defaultMessage": "솔루션 삭제" + "course.assessment.question.rubricPlayground.evaluateAll": { + "defaultMessage": "모두 평가 ({count})" }, - "course.assessment.question.textResponses.exactMatch": { - "defaultMessage": "정확히 일치" + "course.assessment.question.rubricPlayground.evaluateRemaining": { + "defaultMessage": "나머지 평가 ({count})" }, - "course.assessment.question.textResponses.fileUploadNote": { - "defaultMessage": "참고: 파일 업로드 질문은 자동 채점이 불가능합니다. 자동 채점기는 항상 최대 등급을 부여합니다." + "course.assessment.question.rubricPlayground.evaluating": { + "defaultMessage": "평가 중" }, - "course.assessment.question.textResponses.noSolutionsNote": { - "defaultMessage": "솔루션이 없을 경우, 자동 채점기는 항상 최대 점수를 부여합니다." + "course.assessment.question.rubricPlayground.feedback": { + "defaultMessage": "피드백" }, - "course.assessment.question.textResponses.atLeastOneSolutionNote": { - "defaultMessage": "하나 이상의 솔루션이 제공된 경우, 학생들은 일반 텍스트만 입력할 수 있습니다." + "course.assessment.question.rubricPlayground.gradingCategories": { + "defaultMessage": "채점 카테고리" }, - "course.assessment.question.textResponses.exactMatchSolutionNote": { - "defaultMessage": "정확히 일치를 선택한 경우, 여러 줄의 솔루션은 학생의 답변과 정확히 일치해야 정답으로 채점됩니다. 이러한 일치가 발견된 경우, 자동 채점기는 다른 솔루션을 고려하지 않고 지정된 점수를 부여합니다." + "course.assessment.question.rubricPlayground.gradingPrompt": { + "defaultMessage": "채점 프롬프트" }, - "course.assessment.question.textResponses.solutionGradesExceedMaximumGradeNote": { - "defaultMessage": "학생의 답변이 여러 솔루션을 충족하는 경우, 자동 채점기는 문제의 최대 점수까지 해당 솔루션들의 점수 합계를 부여합니다." + "course.assessment.question.rubricPlayground.gradingPromptDescription": { + "defaultMessage": "채점 및 피드백 제공 시 AI를 안내하는 지침입니다." }, - "course.assessment.question.textResponses.grade": { - "defaultMessage": "등급" + "course.assessment.question.rubricPlayground.max": { + "defaultMessage": "최대" }, - "course.assessment.question.textResponses.keyword": { - "defaultMessage": "키워드" + "course.assessment.question.rubricPlayground.modelAnswer": { + "defaultMessage": "모범 답안" }, - "course.assessment.question.textResponses.newSolutionCannotUndo": { - "defaultMessage": "이것은 새 솔루션입니다. 저장하기 전에 삭제하면 즉시 사라집니다." + "course.assessment.question.rubricPlayground.modelAnswerDescription": { + "defaultMessage": "각 카테고리에서 최대 점수를 받는 예시입니다." }, - "course.assessment.question.textResponses.solution": { - "defaultMessage": "솔루션" + "course.assessment.question.rubricPlayground.noAnswers": { + "defaultMessage": "샘플 답변이 추가되지 않았습니다. 시작하려면 추가하세요." }, - "course.assessment.question.textResponses.solutionType": { - "defaultMessage": "솔루션 유형" + "course.assessment.question.rubricPlayground.notLatestRevisionWarning": { + "defaultMessage": "이 페이지에 저장된 최신 개정판이 아닌 루브릭을 적용하도록 선택했습니다." }, - "course.assessment.question.textResponses.solutionWillBeDeleted": { - "defaultMessage": "변경을 저장하면 이 솔루션이 삭제됩니다." + "course.assessment.question.rubricPlayground.questionGrade": { + "defaultMessage": "점수" }, - "course.assessment.question.textResponses.solutions": { - "defaultMessage": "솔루션" + "course.assessment.question.rubricPlayground.reevaluate": { + "defaultMessage": "재평가" }, - "course.assessment.question.textResponses.solutionsHint": { - "defaultMessage": "솔루션을 추가하면 학생의 답변을 자동으로 채점할 수 있습니다." + "course.assessment.question.rubricPlayground.reevaluateAll": { + "defaultMessage": "모두 재평가 ({count})" }, - "course.assessment.question.textResponses.undoDeleteSolution": { - "defaultMessage": "솔루션 삭제 취소" + "course.assessment.question.rubricPlayground.rubricPlayground": { + "defaultMessage": "루브릭 플레이그라운드" }, - "course.assessment.question.textResponses.zeroGrade": { - "defaultMessage": "0.0" + "course.assessment.question.rubricPlayground.sampleAnswerEvaluations": { + "defaultMessage": "샘플 답변 평가" }, - "course.assessment.question.textResponses.templateText": { - "defaultMessage": "템플릿" + "course.assessment.question.rubricPlayground.savedRubric": { + "defaultMessage": "저장된 루브릭, {date}" }, - "course.assessment.question.textResponses.templateTextDescription": { - "defaultMessage": "학생이 이 문제를 처음 시도할 때 답변 영역에 표시되는 텍스트입니다." + "course.assessment.question.rubricPlayground.searchAnswersPlaceholder": { + "defaultMessage": "학생 이름 또는 점수로 답변 검색" }, - "course.assessment.question.textResponses.regex": { - "defaultMessage": "정규 표현식" + "course.assessment.question.rubricPlayground.student": { + "defaultMessage": "학생" }, - "course.assessment.question.textResponses.invalidRegex": { - "defaultMessage": "유효하지 않은 정규 표현식입니다" + "course.assessment.question.rubricPlayground.totalGrade": { + "defaultMessage": "총점" }, - "course.assessment.question.textResponses.spreadsheetFormula": { - "defaultMessage": "스프레드시트 공식" + "course.assessment.question.rubricPlayground.viewEditRubric": { + "defaultMessage": "루브릭 보기 / 편집" }, - "course.assessment.question.textResponses.testSpreadsheet": { - "defaultMessage": "테스트 스프레드시트" + "course.assessment.question.rubricPlayground.writeAnswerPlaceholder": { + "defaultMessage": "여기에 답변을 작성하세요" }, - "course.assessment.question.textResponses.testSpreadsheetDescription": { - "defaultMessage": "학생 답변을 자동 채점하려면 테스트 스프레드시트가 필요합니다." + "course.assessment.question.rubricPlayground.writeCustomAnswer": { + "defaultMessage": "사용자 정의 답변 작성" }, - "course.assessment.question.textResponses.testSpreadsheetRequired": { - "defaultMessage": "테스트 스프레드시트 파일을 업로드해 주세요." + "course.assessment.question.scribing.ScribingQuestionForm.cannotBeBlankValidationError": { + "defaultMessage": "공란으로 둘 수 없습니다." }, - "course.assessment.question.textResponses.spreadsheetAdvancedOptions": { - "defaultMessage": "고급 옵션" + "course.assessment.question.scribing.ScribingQuestionForm.chooseFileButton": { + "defaultMessage": "파일 선택" }, - "course.assessment.question.textResponses.spreadsheetRandomization": { - "defaultMessage": "무작위화 활성화" + "course.assessment.question.scribing.ScribingQuestionForm.descriptionFieldLabel": { + "defaultMessage": "설명" }, - "course.assessment.question.textResponses.spreadsheetRandomizationDescription": { - "defaultMessage": "활성화하면 자동 채점 시 일부 스프레드시트 값이 무작위로 조정됩니다. 이는 공식이 사전 설정된 값 대신 올바른 답을 실제로 계산하는지 확인하는 데 유용합니다." + "course.assessment.question.scribing.ScribingQuestionForm.fetchFailureMessage": { + "defaultMessage": "오류가 발생했습니다. 다시 시도하세요." }, - "course.assessment.question.textResponses.numberOfRandomTests": { - "defaultMessage": "무작위 테스트 횟수" + "course.assessment.question.scribing.ScribingQuestionForm.fileAttachmentRequired": { + "defaultMessage": "파일 첨부 필요" + }, + "course.assessment.question.scribing.ScribingQuestionForm.fileUploaded": { + "defaultMessage": "업로드된 파일:" + }, + "course.assessment.question.scribing.ScribingQuestionForm.lessThanEqualZeroValidationError": { + "defaultMessage": "값은 0보다 커야 합니다." + }, + "course.assessment.question.scribing.ScribingQuestionForm.maximumGradeFieldLabel": { + "defaultMessage": "최대 등급" + }, + "course.assessment.question.scribing.ScribingQuestionForm.noFileChosenMessage": { + "defaultMessage": "선택된 파일이 없습니다" + }, + "course.assessment.question.scribing.ScribingQuestionForm.positiveNumberValidationError": { + "defaultMessage": "값은 양수여야 합니다." + }, + "course.assessment.question.scribing.ScribingQuestionForm.resolveErrorsMessage": { + "defaultMessage": "이 양식에 오류가 있습니다. 제출 전에 해결하세요." + }, + "course.assessment.question.scribing.ScribingQuestionForm.scribingQuestionWarning": { + "defaultMessage": "참고: PDF 파일의 각 페이지는 동일한 질문 세부사항을 갖는 단일 스크라이빙 질문으로 생성됩니다. 선택 입력을 비워 두고 생성 후 질문을 다시 편집할 수 있습니다." + }, + "course.assessment.question.scribing.ScribingQuestionForm.skillsFieldLabel": { + "defaultMessage": "기술" + }, + "course.assessment.question.scribing.ScribingQuestionForm.staffOnlyCommentsFieldLabel": { + "defaultMessage": "직원 전용 코멘트" + }, + "course.assessment.question.scribing.ScribingQuestionForm.submitButton": { + "defaultMessage": "제출" + }, + "course.assessment.question.scribing.ScribingQuestionForm.submitFailureMessage": { + "defaultMessage": "오류가 발생했습니다. 다시 시도하세요." + }, + "course.assessment.question.scribing.ScribingQuestionForm.submittingMessage": { + "defaultMessage": "제출 중..." + }, + "course.assessment.question.scribing.ScribingQuestionForm.titleFieldLabel": { + "defaultMessage": "제목" + }, + "course.assessment.question.scribing.ScribingQuestionForm.valueMoreThan1000Error": { + "defaultMessage": "값은 1000보다 작아야 합니다." }, "course.assessment.question.textResponses.SpreadsheetManager.fixedRandomSeed": { "defaultMessage": "고정 무작위 시드" @@ -2369,24 +2450,54 @@ "course.assessment.question.textResponses.SpreadsheetManager.fixedTimestampDescription": { "defaultMessage": "체크하면 현재 날짜/시간을 사용하는 공식(NOW, TODAY 등)이 이 특정 날짜/시간을 대신 사용합니다." }, - "course.assessment.question.textResponses.randomizationMode": { - "defaultMessage": "자동 채점 값 구성" + "course.assessment.question.textResponses.addSolution": { + "defaultMessage": "새 솔루션 추가" }, - "course.assessment.question.textResponses.randomizationModeDescription": { - "defaultMessage": "자동 채점 시 값을 어떻게 대체하거나 무작위화할지 설정하려면 셀을 클릭하세요." + "course.assessment.question.textResponses.allowFileUpload": { + "defaultMessage": "답변에서 파일 업로드 허용" }, - "course.assessment.question.textResponses.randomizationModeClearAll": { - "defaultMessage": "모두 지우기" + "course.assessment.question.textResponses.atLeastOneSolutionNote": { + "defaultMessage": "하나 이상의 솔루션이 제공된 경우, 학생들은 일반 텍스트만 입력할 수 있습니다." }, - "course.assessment.question.textResponses.randomizationModeRestoreDefaults": { - "defaultMessage": "기본값 복원" + "course.assessment.question.textResponses.dateRandomizationMode": { + "defaultMessage": "무작위 날짜 값 사용" }, - "course.assessment.question.textResponses.randomizationModePopoverTitle": { - "defaultMessage": "자동 채점 중..." + "course.assessment.question.textResponses.deleteSolution": { + "defaultMessage": "솔루션 삭제" + }, + "course.assessment.question.textResponses.exactMatch": { + "defaultMessage": "정확히 일치" + }, + "course.assessment.question.textResponses.exactMatchSolutionNote": { + "defaultMessage": "정확히 일치를 선택한 경우, 여러 줄의 솔루션은 학생의 답변과 정확히 일치해야 정답으로 채점됩니다. 이러한 일치가 발견된 경우, 자동 채점기는 다른 솔루션을 고려하지 않고 지정된 점수를 부여합니다." + }, + "course.assessment.question.textResponses.fileUploadNote": { + "defaultMessage": "참고: 파일 업로드 질문은 자동 채점이 불가능합니다. 자동 채점기는 항상 최대 등급을 부여합니다." + }, + "course.assessment.question.textResponses.grade": { + "defaultMessage": "등급" + }, + "course.assessment.question.textResponses.invalidRegex": { + "defaultMessage": "유효하지 않은 정규 표현식입니다" + }, + "course.assessment.question.textResponses.keyword": { + "defaultMessage": "키워드" + }, + "course.assessment.question.textResponses.newSolutionCannotUndo": { + "defaultMessage": "이것은 새 솔루션입니다. 저장하기 전에 삭제하면 즉시 사라집니다." }, "course.assessment.question.textResponses.noRandomizationMode": { "defaultMessage": "원래 값 유지" }, + "course.assessment.question.textResponses.noSolutionsNote": { + "defaultMessage": "솔루션이 없을 경우, 자동 채점기는 항상 최대 점수를 부여합니다." + }, + "course.assessment.question.textResponses.numberOfRandomTests": { + "defaultMessage": "무작위 테스트 횟수" + }, + "course.assessment.question.textResponses.numericRandomizationMode": { + "defaultMessage": "무작위 숫자 값 사용" + }, "course.assessment.question.textResponses.overrideRandomizationMode": { "defaultMessage": "지정된 값으로 덮어쓰기" }, @@ -2396,17 +2507,20 @@ "course.assessment.question.textResponses.overrideValue": { "defaultMessage": "값" }, - "course.assessment.question.textResponses.numericRandomizationMode": { - "defaultMessage": "무작위 숫자 값 사용" + "course.assessment.question.textResponses.randomizationMode": { + "defaultMessage": "자동 채점 값 구성" }, - "course.assessment.question.textResponses.roundToInteger": { - "defaultMessage": "정수로 반올림" + "course.assessment.question.textResponses.randomizationModeClearAll": { + "defaultMessage": "모두 지우기" }, - "course.assessment.question.textResponses.stringRandomizationMode": { - "defaultMessage": "값의 문자 무작위화" + "course.assessment.question.textResponses.randomizationModeDescription": { + "defaultMessage": "자동 채점 시 값을 어떻게 대체하거나 무작위화할지 설정하려면 셀을 클릭하세요." }, - "course.assessment.question.textResponses.stringRandomizationModeDescription": { - "defaultMessage": "무작위화할 각 문자 클래스는 같은 클래스의 다른 문자로 대체될 수 있습니다." + "course.assessment.question.textResponses.randomizationModePopoverTitle": { + "defaultMessage": "자동 채점 중..." + }, + "course.assessment.question.textResponses.randomizationModeRestoreDefaults": { + "defaultMessage": "기본값 복원" }, "course.assessment.question.textResponses.randomizeDigits": { "defaultMessage": "숫자 무작위화 (0-9)" @@ -2414,152 +2528,77 @@ "course.assessment.question.textResponses.randomizeLetters": { "defaultMessage": "문자 무작위화 (a-z)" }, - "course.assessment.question.textResponses.dateRandomizationMode": { - "defaultMessage": "무작위 날짜 값 사용" + "course.assessment.question.textResponses.regex": { + "defaultMessage": "정규 표현식" }, "course.assessment.question.textResponses.roundToDay": { "defaultMessage": "일 단위로 내림 (00:00 UTC)" }, + "course.assessment.question.textResponses.roundToInteger": { + "defaultMessage": "정수로 반올림" + }, "course.assessment.question.textResponses.shuffleRandomizationMode": { "defaultMessage": "다른 셀과 값 섞기" }, "course.assessment.question.textResponses.shuffleRandomizationModeDescription": { "defaultMessage": "\"섞기\"로 표시된 각 셀의 값은 무작위로 재배치됩니다. 전체 분포는 동일하게 유지되지만 각 값은 다른 셀에 배치될 수 있습니다." }, - "course.assessment.question.rubricPlayground.rubricPlayground": { - "defaultMessage": "루브릭 플레이그라운드" - }, - "course.assessment.question.rubricPlayground.savedRubric": { - "defaultMessage": "저장된 루브릭, {date}" + "course.assessment.question.textResponses.solution": { + "defaultMessage": "솔루션" }, - "course.assessment.question.rubricPlayground.viewEditRubric": { - "defaultMessage": "루브릭 보기 / 편집" + "course.assessment.question.textResponses.solutionGradesExceedMaximumGradeNote": { + "defaultMessage": "학생의 답변이 여러 솔루션을 충족하는 경우, 자동 채점기는 문제의 최대 점수까지 해당 솔루션들의 점수 합계를 부여합니다." }, - "course.assessment.question.rubricPlayground.evaluate": { - "defaultMessage": "평가" + "course.assessment.question.textResponses.solutionType": { + "defaultMessage": "솔루션 유형" }, - "course.assessment.question.rubricPlayground.compare": { - "defaultMessage": "비교" - }, - "course.assessment.question.rubricPlayground.apply": { - "defaultMessage": "적용" - }, - "course.assessment.question.rubricPlayground.confirmAIGradingApplication": { - "defaultMessage": "AI 채점 적용 확인" - }, - "course.assessment.question.rubricPlayground.applyingRubricGradingData": { - "defaultMessage": "루브릭 채점 데이터 적용 중..." - }, - "course.assessment.question.rubricPlayground.applySuccess": { - "defaultMessage": "채점 루브릭, 프롬프트 및 결과가 성공적으로 적용되었습니다." - }, - "course.assessment.question.rubricPlayground.applyFailure": { - "defaultMessage": "채점 결과 적용 실패" - }, - "course.assessment.question.rubricPlayground.notLatestRevisionWarning": { - "defaultMessage": "이 페이지에 저장된 최신 개정판이 아닌 루브릭을 적용하도록 선택했습니다." - }, - "course.assessment.question.rubricPlayground.applyWillGradeAllAnswers": { - "defaultMessage": "이 루브릭을 적용하면 이 페이지에서 아직 평가되지 않은 답변을 포함하여 모든 학생 답변에 점수가 할당됩니다." - }, - "course.assessment.question.rubricPlayground.confirmProceed": { - "defaultMessage": "계속 진행하시겠습니까?" - }, - "course.assessment.question.rubricPlayground.sampleAnswerEvaluations": { - "defaultMessage": "샘플 답변 평가" - }, - "course.assessment.question.rubricPlayground.addSampleAnswers": { - "defaultMessage": "샘플 답변 추가" - }, - "course.assessment.question.rubricPlayground.evaluateAll": { - "defaultMessage": "모두 평가 ({count})" - }, - "course.assessment.question.rubricPlayground.reevaluateAll": { - "defaultMessage": "모두 재평가 ({count})" - }, - "course.assessment.question.rubricPlayground.evaluateRemaining": { - "defaultMessage": "나머지 평가 ({count})" - }, - "course.assessment.question.rubricPlayground.comparingRevisions": { - "defaultMessage": "{count}개 개정판 비교 중" - }, - "course.assessment.question.rubricPlayground.addSampleAnswersTitle": { - "defaultMessage": "샘플 답변 추가" - }, - "course.assessment.question.rubricPlayground.add": { - "defaultMessage": "추가" - }, - "course.assessment.question.rubricPlayground.addExistingAnswers": { - "defaultMessage": "기존 답변 추가" - }, - "course.assessment.question.rubricPlayground.student": { - "defaultMessage": "학생" - }, - "course.assessment.question.rubricPlayground.questionGrade": { - "defaultMessage": "점수" - }, - "course.assessment.question.rubricPlayground.categoryHeading": { - "defaultMessage": "카{index}" - }, - "course.assessment.question.rubricPlayground.answer": { - "defaultMessage": "답변" - }, - "course.assessment.question.rubricPlayground.searchAnswersPlaceholder": { - "defaultMessage": "학생 이름 또는 점수로 답변 검색" - }, - "course.assessment.question.rubricPlayground.addRandomStudentAnswers": { - "defaultMessage": "{inputComponent}개의 무작위 학생 답변 추가" - }, - "course.assessment.question.rubricPlayground.writeCustomAnswer": { - "defaultMessage": "사용자 정의 답변 작성" - }, - "course.assessment.question.rubricPlayground.writeAnswerPlaceholder": { - "defaultMessage": "여기에 답변을 작성하세요" + "course.assessment.question.textResponses.solutionWillBeDeleted": { + "defaultMessage": "변경을 저장하면 이 솔루션이 삭제됩니다." }, - "course.assessment.question.rubricPlayground.dismiss": { - "defaultMessage": "닫기" + "course.assessment.question.textResponses.solutions": { + "defaultMessage": "솔루션" }, - "course.assessment.question.rubricPlayground.noAnswers": { - "defaultMessage": "샘플 답변이 추가되지 않았습니다. 시작하려면 추가하세요." + "course.assessment.question.textResponses.solutionsHint": { + "defaultMessage": "솔루션을 추가하면 학생의 답변을 자동으로 채점할 수 있습니다." }, - "course.assessment.question.rubricPlayground.reevaluate": { - "defaultMessage": "재평가" + "course.assessment.question.textResponses.spreadsheetAdvancedOptions": { + "defaultMessage": "고급 옵션" }, - "course.assessment.question.rubricPlayground.totalGrade": { - "defaultMessage": "총점" + "course.assessment.question.textResponses.spreadsheetFormula": { + "defaultMessage": "스프레드시트 공식" }, - "course.assessment.question.rubricPlayground.feedback": { - "defaultMessage": "피드백" + "course.assessment.question.textResponses.spreadsheetRandomization": { + "defaultMessage": "무작위화 활성화" }, - "course.assessment.question.rubricPlayground.evaluating": { - "defaultMessage": "평가 중" + "course.assessment.question.textResponses.spreadsheetRandomizationDescription": { + "defaultMessage": "활성화하면 자동 채점 시 일부 스프레드시트 값이 무작위로 조정됩니다. 이는 공식이 사전 설정된 값 대신 올바른 답을 실제로 계산하는지 확인하는 데 유용합니다." }, - "course.assessment.question.rubricPlayground.gradingPrompt": { - "defaultMessage": "채점 프롬프트" + "course.assessment.question.textResponses.stringRandomizationMode": { + "defaultMessage": "값의 문자 무작위화" }, - "course.assessment.question.rubricPlayground.gradingPromptDescription": { - "defaultMessage": "채점 및 피드백 제공 시 AI를 안내하는 지침입니다." + "course.assessment.question.textResponses.stringRandomizationModeDescription": { + "defaultMessage": "무작위화할 각 문자 클래스는 같은 클래스의 다른 문자로 대체될 수 있습니다." }, - "course.assessment.question.rubricPlayground.modelAnswer": { - "defaultMessage": "모범 답안" + "course.assessment.question.textResponses.templateText": { + "defaultMessage": "템플릿" }, - "course.assessment.question.rubricPlayground.modelAnswerDescription": { - "defaultMessage": "각 카테고리에서 최대 점수를 받는 예시입니다." + "course.assessment.question.textResponses.templateTextDescription": { + "defaultMessage": "학생이 이 문제를 처음 시도할 때 답변 영역에 표시되는 텍스트입니다." }, - "course.assessment.question.rubricPlayground.gradingCategories": { - "defaultMessage": "채점 카테고리" + "course.assessment.question.textResponses.testSpreadsheet": { + "defaultMessage": "테스트 스프레드시트" }, - "course.assessment.question.rubricPlayground.addNewCategory": { - "defaultMessage": "새 카테고리 추가" + "course.assessment.question.textResponses.testSpreadsheetDescription": { + "defaultMessage": "학생 답변을 자동 채점하려면 테스트 스프레드시트가 필요합니다." }, - "course.assessment.question.rubricPlayground.categoryName": { - "defaultMessage": "카테고리 이름" + "course.assessment.question.textResponses.testSpreadsheetRequired": { + "defaultMessage": "테스트 스프레드시트 파일을 업로드해 주세요." }, - "course.assessment.question.rubricPlayground.max": { - "defaultMessage": "최대" + "course.assessment.question.textResponses.undoDeleteSolution": { + "defaultMessage": "솔루션 삭제 취소" }, - "course.assessment.question.rubricPlayground.addNewGrade": { - "defaultMessage": "새 점수 추가" + "course.assessment.question.textResponses.zeroGrade": { + "defaultMessage": "0.0" }, "course.assessment.session.assessmentNotStarted": { "defaultMessage": "평가가 아직 시작되지 않았습니다. {startDate} 이후에 다시 방문하세요." @@ -2696,14 +2735,14 @@ "course.assessment.show.generate": { "defaultMessage": "질문 생성" }, - "course.assessment.show.generateTooltip": { - "defaultMessage": "Codaveri AI와 협업하여 문제를 생성하세요" + "course.assessment.show.generateFromProgrammingQuestion": { + "defaultMessage": "Codaveri AI로 유사한 질문 생성" }, "course.assessment.show.generateFromQuestion": { "defaultMessage": "AI로 유사한 질문 생성" }, - "course.assessment.show.generateFromProgrammingQuestion": { - "defaultMessage": "Codaveri AI로 유사한 질문 생성" + "course.assessment.show.generateTooltip": { + "defaultMessage": "Codaveri AI와 협업하여 문제를 생성하세요" }, "course.assessment.show.gradedTestCases": { "defaultMessage": "평가된 테스트 케이스" @@ -2718,7 +2757,7 @@ "defaultMessage": "아래 질문." }, "course.assessment.show.headsUpExistingSubmissions": { - "defaultMessage": "주의—기존 제출이 있습니다!" + "defaultMessage": "주의-기존 제출이 있습니다!" }, "course.assessment.show.hideOptions": { "defaultMessage": "옵션 숨기기" @@ -2837,15 +2876,15 @@ "course.assessment.show.showMcqMrqSolution": { "defaultMessage": "객관식/다중 응답형 질문 솔루션 보기" }, - "course.assessment.show.showRubricToStudents": { - "defaultMessage": "학생에게 루브릭 세부사항 표시" - }, "course.assessment.show.showMcqSubmitResult": { "defaultMessage": "객관식 질문 제출 결과 보기" }, "course.assessment.show.showOptions": { "defaultMessage": "옵션 보기" }, + "course.assessment.show.showRubricToStudents": { + "defaultMessage": "학생에게 루브릭 세부사항 표시" + }, "course.assessment.show.sureChangingQuestionType": { "defaultMessage": "이 질문 유형을 변경하시겠습니까?" }, @@ -2975,60 +3014,27 @@ "course.assessment.statistics.ancestorFail": { "defaultMessage": "이 평가의 이전 반복을 검색하지 못했습니다." }, - "course.assessment.statistics.ancestorStatisticsFail": { - "defaultMessage": "조상의 통계를 검색하지 못했습니다." - }, - "course.assessment.plagiarism.plagiarism": { - "defaultMessage": "표절 결과" - }, - "course.assessment.plagiarism.status": { - "defaultMessage": "표절 검사 상태" - }, - "course.assessment.plagiarism.lastRunTime": { - "defaultMessage": "마지막 실행 시간: {date}" - }, - "course.assessment.plagiarism.start": { - "defaultMessage": "새 표절 검사" - }, - "course.assessment.plagiarism.notStarted": { - "defaultMessage": "표절 검사가 실행되지 않았습니다." - }, - "course.assessment.plagiarism.confirmStartTitle": { - "defaultMessage": "표절 검사 확인?" - }, - "course.assessment.plagiarism.confirmStartMessage": { - "defaultMessage": "새 표절 검사를 실행하면 이전 결과가 제거됩니다." - }, - "course.assessment.plagiarism.results": { - "defaultMessage": "표절 결과 (제출물 간 유사도)" - }, - "course.assessment.plagiarism.baseSubmission": { - "defaultMessage": "기본 제출" - }, - "course.assessment.plagiarism.comparedSubmission": { - "defaultMessage": "비교된 제출" - }, - "course.assessment.plagiarism.similarityScore": { - "defaultMessage": "유사성 점수" - }, - "course.assessment.plagiarism.actions": { - "defaultMessage": "작업" + "course.assessment.statistics.ancestorSelect.current": { + "defaultMessage": "현재" }, - "course.assessment.plagiarism.viewReport": { - "defaultMessage": "보고서 보기" + "course.assessment.statistics.ancestorSelect.fromCourse": { + "defaultMessage": "{courseTitle}에서" }, - "course.assessment.plagiarism.downloadPdf": { - "defaultMessage": "PDF 다운로드" + "course.assessment.statistics.ancestorSelect.subtitle": { + "defaultMessage": "이 평가의 이전 버전과 비교:" }, - "course.assessment.plagiarism.searchByStudentName": { - "defaultMessage": "학생 이름으로 검색" + "course.assessment.statistics.ancestorSelect.title": { + "defaultMessage": "복제 기록" }, - "course.assessment.plagiarism.showSelfPlagiarism": { - "defaultMessage": "자기 표절 비교 포함 (동일 학생, 다른 과정)" + "course.assessment.statistics.ancestorStatisticsFail": { + "defaultMessage": "조상의 통계를 검색하지 못했습니다." }, "course.assessment.statistics.answers": { "defaultMessage": "답변" }, + "course.assessment.statistics.attemptCount": { + "defaultMessage": "시도 횟수" + }, "course.assessment.statistics.attempts.filename": { "defaultMessage": "{assessment}에 대한 질문별 시도 통계" }, @@ -3041,6 +3047,9 @@ "course.assessment.statistics.closePrompt": { "defaultMessage": "닫기" }, + "course.assessment.statistics.duplicationHistory": { + "defaultMessage": "복제 기록" + }, "course.assessment.statistics.fail": { "defaultMessage": "통계를 검색하지 못했습니다." }, @@ -3059,48 +3068,30 @@ "course.assessment.statistics.grader": { "defaultMessage": "평가자" }, + "course.assessment.statistics.gradesPerQuestion": { + "defaultMessage": "문제별 점수" + }, "course.assessment.statistics.grayCellLegend": { "defaultMessage": "미정 (질문은 자동 채점할 수 없음)" }, "course.assessment.statistics.group": { "defaultMessage": "그룹" }, - "course.assessment.statistics.ancestorSelect.current": { - "defaultMessage": "현재" - }, - "course.assessment.statistics.ancestorSelect.fromCourse": { - "defaultMessage": "{courseTitle}에서" - }, - "course.assessment.statistics.ancestorSelect.subtitle": { - "defaultMessage": "이 평가의 이전 버전과 비교:" - }, - "course.assessment.statistics.ancestorSelect.title": { - "defaultMessage": "복제 기록" - }, - "course.assessment.statistics.attemptCount": { - "defaultMessage": "시도 횟수" - }, - "course.assessment.statistics.duplicationHistory": { - "defaultMessage": "복제 기록" - }, - "course.assessment.statistics.gradesPerQuestion": { - "defaultMessage": "문제별 점수" + "course.assessment.statistics.header": { + "defaultMessage": "{title}에 대한 통계" }, "course.assessment.statistics.includePhantom": { "defaultMessage": "팬텀 학생 포함" }, - "course.assessment.statistics.liveFeedback": { - "defaultMessage": "도움 받기" - }, - "course.assessment.statistics.header": { - "defaultMessage": "{title}에 대한 통계" - }, "course.assessment.statistics.legendHigherusage": { "defaultMessage": "사용량이 많음" }, "course.assessment.statistics.legendLowerUsage": { "defaultMessage": "사용량이 적음" }, + "course.assessment.statistics.liveFeedback": { + "defaultMessage": "도움 받기" + }, "course.assessment.statistics.liveFeedback.filename": { "defaultMessage": "{assessment}에 대한 질문별 라이브 피드백 통계" }, @@ -3173,12 +3164,6 @@ "course.assessment.submission.Answer.rendererNotImplemented": { "defaultMessage": "이 질문 유형에 대한 디스플레이가 아직 구현되지 않았습니다." }, - "course.assessment.submission.answerTooLarge": { - "defaultMessage": "답변이 너무 큽니다" - }, - "course.assessment.submission.answerTooLargeError": { - "defaultMessage": "제출한 답변은 2MB 미만이어야 합니다." - }, "course.assessment.submission.CodaveriFeedbackStatus.codaveriFeedbackStatus": { "defaultMessage": "Codaveri 피드백 상태" }, @@ -3203,7 +3188,28 @@ "course.assessment.submission.FileInput.uploadLabel": { "defaultMessage": "파일을 업로드하려면 드래그 앤 드롭하거나 클릭하세요." }, - "course.assessment.submission.ImportedFileView.deleteConfirmation": { + "course.assessment.submission.GetHelpChatPage.ConversationArea.fileNameAndLineNumber": { + "defaultMessage": "{filename}:{lineNumber}" + }, + "course.assessment.submission.GetHelpChatPage.ConversationArea.lineNumber": { + "defaultMessage": "{lineNumber} 줄" + }, + "course.assessment.submission.GetHelpChatPage.ConversationArea.threadExpired": { + "defaultMessage": "위의 채팅이 종료되었습니다. 새 채팅을 시작하시겠습니까?" + }, + "course.assessment.submission.GetHelpChatPage.chatInputText": { + "defaultMessage": "어떻게 도와드릴까요?" + }, + "course.assessment.submission.GetHelpChatPage.chatMessagesRemaining": { + "defaultMessage": "{numMessages} / {maxMessages} 개 메시지 남음" + }, + "course.assessment.submission.GetHelpChatPage.codeUpdated": { + "defaultMessage": "코드가 업데이트되었습니다" + }, + "course.assessment.submission.GetHelpChatPage.noChatMessagesRemaining": { + "defaultMessage": "이 질문의 메시지 한도에 도달했습니다." + }, + "course.assessment.submission.ImportedFileView.deleteConfirmation": { "defaultMessage": "이 파일을 삭제하시겠습니까?" }, "course.assessment.submission.ImportedFileView.noFiles": { @@ -3260,9 +3266,6 @@ "course.assessment.submission.SubmissionsIndex.includePhantoms": { "defaultMessage": "팬텀 사용자 포함" }, - "lib.translations.myStudents": { - "defaultMessage": "내 학생들" - }, "course.assessment.submission.SubmissionsIndex.phantom": { "defaultMessage": "팬텀 사용자" }, @@ -3278,12 +3281,6 @@ "course.assessment.submission.SubmissionsIndex.remind": { "defaultMessage": "알림 이메일 보내기" }, - "lib.translations.staff": { - "defaultMessage": "스태프" - }, - "lib.translations.students": { - "defaultMessage": "학생들" - }, "course.assessment.submission.SubmissionsIndex.submissionStatus": { "defaultMessage": "상태" }, @@ -3473,6 +3470,12 @@ "course.assessment.submission.answerSubmitted": { "defaultMessage": "답변 제출됨" }, + "course.assessment.submission.answerTooLarge": { + "defaultMessage": "답변이 너무 큽니다" + }, + "course.assessment.submission.answerTooLargeError": { + "defaultMessage": "제출한 답변은 2MB 미만이어야 합니다." + }, "course.assessment.submission.answers.AnswerHeader.noPastAnswers": { "defaultMessage": "과거 답변이 없습니다." }, @@ -3587,6 +3590,12 @@ "course.assessment.submission.bonusEndAt": { "defaultMessage": "보너스 종료 시각" }, + "course.assessment.submission.checkAnswer": { + "defaultMessage": "답변 확인" + }, + "course.assessment.submission.checkAnswerWithLimit": { + "defaultMessage": "답변 확인 ({attemptsLeft, plural, one {# 시도} other {# 시도}} 남음)" + }, "course.assessment.submission.codaveriAutogradeFailure": { "defaultMessage": "Codaveri에서 코드를 평가하는 동안 오류가 발생했습니다. 몇 분 후에 코드를 다시 제출하거나 네트워크 응답의 오류 메시지를 확인하세요." }, @@ -3614,14 +3623,14 @@ "course.assessment.submission.comment.CommentCard.deleteConfirmation": { "defaultMessage": "이 댓글을 삭제하시겠습니까?" }, - "course.assessment.submission.comment.CommentCard.save": { - "defaultMessage": "저장" + "course.assessment.submission.comment.CommentCard.isAiGenerated": { + "defaultMessage": "AI 생성 댓글" }, "course.assessment.submission.comment.CommentCard.publish": { "defaultMessage": "게시" }, - "course.assessment.submission.comment.CommentCard.isAiGenerated": { - "defaultMessage": "AI 생성 댓글" + "course.assessment.submission.comment.CommentCard.save": { + "defaultMessage": "저장" }, "course.assessment.submission.comment.CommentField.comment": { "defaultMessage": "댓글" @@ -3860,14 +3869,14 @@ "course.assessment.submission.question": { "defaultMessage": "질문" }, - "course.assessment.submission.questionNumber": { - "defaultMessage": "Q{number}" + "course.assessment.submission.questionAnswer": { + "defaultMessage": "응답" }, "course.assessment.submission.questionDescription": { "defaultMessage": "설명" }, - "course.assessment.submission.questionAnswer": { - "defaultMessage": "응답" + "course.assessment.submission.questionNumber": { + "defaultMessage": "Q{number}" }, "course.assessment.submission.readOnlyEditor.expandComments": { "defaultMessage": "모든 댓글 확장" @@ -3890,15 +3899,6 @@ "course.assessment.submission.resetConfirmation": { "defaultMessage": "답변을 재설정하시겠습니까? 이 조치는 되돌릴 수 없으며 이 질문에 대한 모든 현재 작업이 손실됩니다." }, - "course.assessment.submission.checkAnswer": { - "defaultMessage": "답변 확인" - }, - "course.assessment.submission.checkAnswerWithLimit": { - "defaultMessage": "답변 확인 ({attemptsLeft, plural, one {# 시도} other {# 시도}} 남음)" - }, - "course.assessment.submission.submitWithLimit": { - "defaultMessage": "제출 ({attemptsLeft, plural, one {# 시도} other {# 시도}} 남음)" - }, "course.assessment.submission.saveDraft": { "defaultMessage": "초안 저장" }, @@ -3953,21 +3953,24 @@ "course.assessment.submission.submitShortcut": { "defaultMessage": "(Ctrl+Enter) 또는 (⌘+Enter)" }, + "course.assessment.submission.submitWithLimit": { + "defaultMessage": "제출 ({attemptsLeft, plural, one {# 시도} other {# 시도}} 남음)" + }, "course.assessment.submission.submitted": { "defaultMessage": "제출됨" }, "course.assessment.submission.submittedAt": { "defaultMessage": "제출 시각" }, - "course.assessment.submission.unknown": { - "defaultMessage": "알 수 없는 상태, 관리자에게 문의하세요" - }, "course.assessment.submission.totalGrade": { "defaultMessage": "총 등급" }, "course.assessment.submission.type": { "defaultMessage": "유형" }, + "course.assessment.submission.unknown": { + "defaultMessage": "알 수 없는 상태, 관리자에게 문의하세요" + }, "course.assessment.submission.unmark": { "defaultMessage": "제출로 되돌리기" }, @@ -4163,9 +4166,6 @@ "course.asssessment.submission.submitNoQuestionExplain": { "defaultMessage": "완료로 표시하시겠습니까?" }, - "course.admin.NotificationSettings.component": { - "defaultMessage": "구성 요소" - }, "course.componentTitles.course_achievements_component": { "defaultMessage": "성과" }, @@ -4250,15 +4250,6 @@ "course.courses.CourseAnnouncements.announcementHeader": { "defaultMessage": "최근 공지 사항" }, - "course.courses.CourseSuspendedAlert.header": { - "defaultMessage": "이 과정은 현재 정지되어 있습니다. 강사는 계속 접근할 수 있지만 학생은 접근할 수 없습니다." - }, - "course.courses.CourseSuspendedAlert.canSuspendMessage": { - "defaultMessage": "{link} 페이지에서 정지를 해제할 수 있습니다." - }, - "course.courses.CourseSuspendedAlert.cannotSuspendMessage": { - "defaultMessage": "이것이 실수라고 생각되면, 과정 관리자 또는 소유자에게 연락하여 정지를 해제해 달라고 요청하세요." - }, "course.courses.CourseDisplay.noCourse": { "defaultMessage": "아직 과정이 없습니다..." }, @@ -4304,6 +4295,15 @@ "course.courses.CourseShow.instructorsHeader": { "defaultMessage": "교사" }, + "course.courses.CourseSuspendedAlert.canSuspendMessage": { + "defaultMessage": "{link} 페이지에서 정지를 해제할 수 있습니다." + }, + "course.courses.CourseSuspendedAlert.cannotSuspendMessage": { + "defaultMessage": "이것이 실수라고 생각되면, 과정 관리자 또는 소유자에게 연락하여 정지를 해제해 달라고 요청하세요." + }, + "course.courses.CourseSuspendedAlert.header": { + "defaultMessage": "이 과정은 현재 정지되어 있습니다. 강사는 계속 접근할 수 있지만 학생은 접근할 수 없습니다." + }, "course.courses.CourseUserItem.differentCourseNameHint": { "defaultMessage": "이 과정의 관리자가 이 이름으로 초대했기 때문에 계정 이름과 다른 이름을 보고 계십니다." }, @@ -4472,15 +4472,15 @@ "course.courses.SidebarItem.home": { "defaultMessage": "홈" }, + "course.courses.SidebarItem.scholaistic.assessments": { + "defaultMessage": "롤플레잉 평가" + }, "course.courses.SidebarItem.stories.learn": { "defaultMessage": "배우기" }, "course.courses.SidebarItem.stories.missionControl": { "defaultMessage": "미션 컨트롤" }, - "course.courses.SidebarItem.scholaistic.assessments": { - "defaultMessage": "롤플레잉 평가" - }, "course.courses.TodoIgnoreButton.ignore.ignoreButtonText": { "defaultMessage": "무시" }, @@ -4523,6 +4523,12 @@ "course.discussion.topics.CommentCard.deleteSuccess": { "defaultMessage": "댓글이 성공적으로 삭제되었습니다." }, + "course.discussion.topics.CommentCard.isAiGenerated": { + "defaultMessage": "AI 생성 초안 댓글" + }, + "course.discussion.topics.CommentCard.publish": { + "defaultMessage": "게시" + }, "course.discussion.topics.CommentCard.publishFailure": { "defaultMessage": "피드백 게시 실패." }, @@ -4544,12 +4550,6 @@ "course.discussion.topics.CommentCard.updateSuccess": { "defaultMessage": "댓글이 성공적으로 업데이트되었습니다." }, - "course.discussion.topics.CommentCard.publish": { - "defaultMessage": "게시" - }, - "course.discussion.topics.CommentCard.isAiGenerated": { - "defaultMessage": "AI 생성 초안 댓글" - }, "course.discussion.topics.CommentField.comment": { "defaultMessage": "댓글" }, @@ -4823,21 +4823,6 @@ "course.enrolRequests.UserRequests.rejected": { "defaultMessage": "거부된 등록 요청" }, - "course.experiencePoints.downloadCsvButton": { - "defaultMessage": "CSV 다운로드" - }, - "course.experiencePoints.downloadFailure": { - "defaultMessage": "다운로드 요청을 처리하는 중 오류가 발생했습니다." - }, - "course.experiencePoints.downloadPending": { - "defaultMessage": "다운로드 요청을 처리하는 동안 기다려 주세요." - }, - "course.experiencePoints.downloadRequestSuccess": { - "defaultMessage": "다운로드 요청이 성공했습니다" - }, - "course.experiencePoints.filterByNameButton": { - "defaultMessage": "이름으로 필터링" - }, "course.experiencePoints.disbursement.DisbursementForm.createDisbursementFailure": { "defaultMessage": "경험치 부여 실패." }, @@ -4958,6 +4943,21 @@ "course.experiencePoints.disbursement.ForumPostTable.voteTally": { "defaultMessage": "투표 집계" }, + "course.experiencePoints.downloadCsvButton": { + "defaultMessage": "CSV 다운로드" + }, + "course.experiencePoints.downloadFailure": { + "defaultMessage": "다운로드 요청을 처리하는 중 오류가 발생했습니다." + }, + "course.experiencePoints.downloadPending": { + "defaultMessage": "다운로드 요청을 처리하는 동안 기다려 주세요." + }, + "course.experiencePoints.downloadRequestSuccess": { + "defaultMessage": "다운로드 요청이 성공했습니다" + }, + "course.experiencePoints.filterByNameButton": { + "defaultMessage": "이름으로 필터링" + }, "course.forum.FormShow.fetchTopicsFailure": { "defaultMessage": "포럼 주제 데이터를 검색하는 데 실패했습니다." }, @@ -5174,236 +5174,584 @@ "course.forum.ForumTopicTable.unresolved": { "defaultMessage": "질문 (미해결)" }, - "course.forum.ForumTopicTable.views": { - "defaultMessage": "조회수" + "course.forum.ForumTopicTable.views": { + "defaultMessage": "조회수" + }, + "course.forum.ForumTopicTable.votes": { + "defaultMessage": "투표" + }, + "course.forum.ForumsIndex.fetchForumsFailure": { + "defaultMessage": "포럼 데이터를 검색하는 데 실패했습니다." + }, + "course.forum.ForumsIndex.header": { + "defaultMessage": "포럼" + }, + "course.forum.ForumsIndex.markAllAsReadFailed": { + "defaultMessage": "모든 주제를 읽음으로 표시하는 데 실패했습니다. 나중에 다시 시도하세요." + }, + "course.forum.ForumsIndex.markAllAsReadSuccess": { + "defaultMessage": "모든 주제가 읽음으로 표시되었습니다." + }, + "course.forum.ForumsIndex.newForum": { + "defaultMessage": "새 포럼" + }, + "course.forum.HideButton.hide": { + "defaultMessage": "숨기기" + }, + "course.forum.HideButton.hideFailure": { + "defaultMessage": "주제 \"{title}\"을(를) 숨기는 데 실패했습니다 - {error}" + }, + "course.forum.HideButton.hideSuccess": { + "defaultMessage": "주제 \"{title}\"이(가) 성공적으로 숨겨졌습니다." + }, + "course.forum.HideButton.hideTooltip": { + "defaultMessage": "학생들에게 주제를 숨기기" + }, + "course.forum.HideButton.unhide": { + "defaultMessage": "숨기기 해제" + }, + "course.forum.HideButton.unhideFailure": { + "defaultMessage": "주제 \"{title}\"을(를) 보이는 것을 해제하는 데 실패했습니다 - {error}" + }, + "course.forum.HideButton.unhideSuccess": { + "defaultMessage": "주제 \"{title}\"이(가) 성공적으로 보이게 되었습니다." + }, + "course.forum.HideButton.unhideTooltip": { + "defaultMessage": "학생들에게 주제를 보이기" + }, + "course.forum.LockButton.lockTooltip": { + "defaultMessage": "이 주제에서 학생들이 게시하는 것을 멈추기 위해 잠금" + }, + "course.forum.LockButton.locked": { + "defaultMessage": "잠금" + }, + "course.forum.LockButton.lockedFailure": { + "defaultMessage": "주제 \"{title}\" 잠금에 실패했습니다 - {error}" + }, + "course.forum.LockButton.lockedSuccess": { + "defaultMessage": "주제 \"{title}\"이(가) 성공적으로 잠겼습니다." + }, + "course.forum.LockButton.unlockTooltip": { + "defaultMessage": "이 주제에서 학생들이 게시할 수 있도록 잠금 해제" + }, + "course.forum.LockButton.unlocked": { + "defaultMessage": "잠금 해제" + }, + "course.forum.LockButton.unlockedFailure": { + "defaultMessage": "주제 \"{title}\"의 잠금을 해제하는 데 실패했습니다 - {error}" + }, + "course.forum.LockButton.unlockedSuccess": { + "defaultMessage": "주제 \"{title}\"의 잠금이 성공적으로 해제되었습니다." + }, + "course.forum.MarkAllAsReadButton.AllReadTooltip": { + "defaultMessage": "만세! 모든 주제를 다 읽었습니다!" + }, + "course.forum.MarkAllAsReadButton.markAllAsRead": { + "defaultMessage": "모두 읽음으로 표시" + }, + "course.forum.MarkAllAsReadButton.markAllAsReadTooltip": { + "defaultMessage": "현재 페이지의 모든 포럼 게시물을 읽음으로 표시" + }, + "course.forum.MarkAnswerButton.markAsAnswer": { + "defaultMessage": "답변으로 표시" + }, + "course.forum.MarkAnswerButton.markedAsAnswer": { + "defaultMessage": "답변으로 표시됨" + }, + "course.forum.MarkAnswerButton.unmarkAsAnswer": { + "defaultMessage": "답변으로 표시 취소" + }, + "course.forum.MarkAnswerButton.updateFailure": { + "defaultMessage": "게시물 업데이트 실패 - {error}" + }, + "course.forum.NextUnreadButton.AllReadTooltip": { + "defaultMessage": "만세! 모든 주제가 읽혔습니다!" + }, + "course.forum.NextUnreadButton.nextUnread": { + "defaultMessage": "다음 읽지 않은 것" + }, + "course.forum.NextUnreadButton.nextUnreadTooltip": { + "defaultMessage": "다음 읽지 않은 주제로 이동" + }, + "course.forum.PostCreatorObject.anonymousUser": { + "defaultMessage": "익명 사용자" + }, + "course.forum.PostCreatorObject.maskUser": { + "defaultMessage": "사용자 가리기" + }, + "course.forum.PostCreatorObject.postAnonymously": { + "defaultMessage": "익명 게시" + }, + "course.forum.PostCreatorObject.unmaskUser": { + "defaultMessage": "사용자 가리기 해제" + }, + "course.forum.ReplyCard.emptyPost": { + "defaultMessage": "게시물을 비울 수 없습니다!" + }, + "course.forum.ReplyCard.postAnonymously": { + "defaultMessage": "익명 게시" + }, + "course.forum.ReplyCard.replyFailure": { + "defaultMessage": "게시물 제출 실패 - {error}" + }, + "course.forum.ReplyCard.replySuccess": { + "defaultMessage": "답글 게시물이 생성되었습니다." + }, + "course.forum.ReplyCard.replyTo": { + "defaultMessage": "{user}에게 답글" + }, + "course.forum.SubscribeButton.commonTranslations.manageMySubscription": { + "defaultMessage": "내 구독 관리" + }, + "course.forum.SubscribeButton.commonTranslations.subscribe": { + "defaultMessage": "구독" + }, + "course.forum.SubscribeButton.commonTranslations.unsubscribe": { + "defaultMessage": "구독 취소" + }, + "course.forum.SubscribeButton.commonTranslations.updateSubscriptionFailure": { + "defaultMessage": "구독 업데이트 실패 - {error}" + }, + "course.forum.SubscribeButton.forumTopicTranslations.adminSettingSubscribed": { + "defaultMessage": "포럼 주제 구독이 강좌 관리자에 의해 비활성화되었습니다." + }, + "course.forum.SubscribeButton.forumTopicTranslations.subscribeSuccess": { + "defaultMessage": "포럼 주제 {title}에 성공적으로 구독되었습니다." + }, + "course.forum.SubscribeButton.forumTopicTranslations.subscribeTooltip": { + "defaultMessage": "누군가가 이 포럼 주제에서 답변할 때 이메일 알림을 받으려면 구독하세요." + }, + "course.forum.SubscribeButton.forumTopicTranslations.unsubscribeSuccess": { + "defaultMessage": "포럼 주제 {title}에서 성공적으로 구독 취소되었습니다." + }, + "course.forum.SubscribeButton.forumTopicTranslations.unsubscribeTooltip": { + "defaultMessage": "누군가가 이 포럼 주제에서 답변할 때 이메일 알림을 받는 것을 중지하려면 구독 취소하세요." + }, + "course.forum.SubscribeButton.forumTopicTranslations.userSettingSubscribed": { + "defaultMessage": "이 과정의 포럼에서 \"새 게시물 및 답변\" 구독을 취소했습니다. 활성화하려면 {manageMySubscriptionLink}로 이동하세요." + }, + "course.forum.SubscribeButton.forumTranslations.adminSettingSubscribed": { + "defaultMessage": "새 포럼 주제의 구독이 강좌 관리자에 의해 비활성화되었습니다." + }, + "course.forum.SubscribeButton.forumTranslations.subscribeSuccess": { + "defaultMessage": "{title}에 성공적으로 구독되었습니다." + }, + "course.forum.SubscribeButton.forumTranslations.subscribeTooltip": { + "defaultMessage": "새 주제가 생성될 때 이메일 알림을 받으려면 구독하세요." + }, + "course.forum.SubscribeButton.forumTranslations.unsubscribeSuccess": { + "defaultMessage": "{title}에서 성공적으로 구독 취소되었습니다." + }, + "course.forum.SubscribeButton.forumTranslations.unsubscribeTooltip": { + "defaultMessage": "새 주제가 생성될 때 이메일 알림을 받는 것을 중지하려면 구독 취소하세요." + }, + "course.forum.SubscribeButton.forumTranslations.userSettingSubscribed": { + "defaultMessage": "이 과정의 포럼에서 \"새 주제\" 구독을 취소했습니다. 활성화하려면 {manageMySubscriptionLink}로 이동하세요." + }, + "course.forum.VotePostButton.updateFailure": { + "defaultMessage": "투표 수 업데이트 실패 - {error}" + }, + "course.forum.forum.markAllAsReadFailed": { + "defaultMessage": "이 포럼의 모든 주제를 읽음으로 표시하는 데 실패했습니다. 나중에 다시 시도하세요." + }, + "course.gradebook.AddExternalColumnPrompt.cancel": { + "defaultMessage": "취소" + }, + "course.gradebook.AddExternalColumnPrompt.create": { + "defaultMessage": "만들기" + }, + "course.gradebook.AddExternalColumnPrompt.error": { + "defaultMessage": "외부 평가를 생성할 수 없습니다." + }, + "course.gradebook.AddExternalColumnPrompt.maxLabel": { + "defaultMessage": "최대 점수" + }, + "course.gradebook.AddExternalColumnPrompt.nameLabel": { + "defaultMessage": "이름" + }, + "course.gradebook.AddExternalColumnPrompt.success": { + "defaultMessage": "외부 평가가 생성되었습니다." + }, + "course.gradebook.AddExternalColumnPrompt.title": { + "defaultMessage": "외부 평가 추가" + }, + "course.gradebook.ConfigureWeightsPrompt.allExcluded": { + "defaultMessage": "“{tab}”의 모든 평가가 제외되어 총점에 반영되지 않습니다." + }, + "course.gradebook.ConfigureWeightsPrompt.allExcludedCount": { + "defaultMessage": "전체 {n}개 제외됨" + }, + "course.gradebook.ConfigureWeightsPrompt.customMode": { + "defaultMessage": "사용자 지정" + }, + "course.gradebook.ConfigureWeightsPrompt.customSum": { + "defaultMessage": "평가 가중치: {sum} / {total}" + }, + "course.gradebook.ConfigureWeightsPrompt.defaultsHint": { + "defaultMessage": "아직 설정된 가중치가 없습니다. 모든 탭이 동일한 비중으로 반영되도록 제안된 기본값입니다. 저장하여 확정하거나 아래에서 조정하세요." + }, + "course.gradebook.ConfigureWeightsPrompt.descriptionDrop": { + "defaultMessage": "동일 모드에서는 평균을 내기 전에 각 학생의 점수가 가장 낮은 평가 N개를 선택적으로 제외할 수 있습니다." + }, + "course.gradebook.ConfigureWeightsPrompt.descriptionExclusion": { + "defaultMessage": "탭을 펼쳐 개별 평가를 성적에 포함하거나 제외하세요." + }, + "course.gradebook.ConfigureWeightsPrompt.descriptionIntro": { + "defaultMessage": "각 탭과 평가가 학생의 총 성적에 어떻게 반영되는지 관리합니다." + }, + "course.gradebook.ConfigureWeightsPrompt.descriptionModes": { + "defaultMessage": "“동일”(모든 평가가 탭의 가중치를 동일하게 나눔)또는 “사용자 지정”(각 평가의 비중을 설정)을 선택하세요." + }, + "course.gradebook.ConfigureWeightsPrompt.descriptionWeights": { + "defaultMessage": "각 탭의 가중치, 즉 총 성적에 기여하는 비중을 설정하세요. 가중치 합계는 100이어야 합니다." + }, + "course.gradebook.ConfigureWeightsPrompt.equalMode": { + "defaultMessage": "동일" + }, + "course.gradebook.ConfigureWeightsPrompt.excluded": { + "defaultMessage": "제외됨" + }, + "course.gradebook.ConfigureWeightsPrompt.excludedCount": { + "defaultMessage": "{n}개 제외됨" + }, + "course.gradebook.ConfigureWeightsPrompt.includeAssessment": { + "defaultMessage": "{assessment} 성적에 포함" + }, + "course.gradebook.ConfigureWeightsPrompt.modeAria": { + "defaultMessage": "{tab} 가중치 모드" + }, + "course.gradebook.ConfigureWeightsPrompt.ofGrade": { + "defaultMessage": "성적의 {pct}%" + }, + "course.gradebook.ConfigureWeightsPrompt.promptTitle": { + "defaultMessage": "기여도 설정" + }, + "course.gradebook.ConfigureWeightsPrompt.saveError": { + "defaultMessage": "가중치를 저장하지 못했습니다. 다시 시도해 주세요." + }, + "course.gradebook.ConfigureWeightsPrompt.total": { + "defaultMessage": "합계: {sum}%" + }, + "course.gradebook.ConfigureWeightsPrompt.unbalanced": { + "defaultMessage": "저장하기 전에 “{tab}”의 평가 가중치 합계가 해당 탭의 총 가중치와 같아야 합니다." + }, + "course.gradebook.ConfigureWeightsPrompt.valueTooHigh": { + "defaultMessage": "값은 최대 100이어야 합니다" + }, + "course.gradebook.ConfigureWeightsPrompt.valueTooLow": { + "defaultMessage": "값은 최소 0이어야 합니다" + }, + "course.gradebook.ConfigureWeightsPrompt.weightsDoNotSum": { + "defaultMessage": "가중치 합계가 100이 아닙니다. 저장은 가능하지만 총점이 정확하지 않을 수 있습니다." + }, + "course.gradebook.DeleteExternalColumnPrompt.body": { + "defaultMessage": "\"{title}\"을(를) 삭제하시겠습니까? 이 작업은 해당 열과 그 안의 모든 학생 성적을 영구적으로 제거합니다. 이 작업은 되돌릴 수 없습니다." + }, + "course.gradebook.DeleteExternalColumnPrompt.cancel": { + "defaultMessage": "취소" + }, + "course.gradebook.DeleteExternalColumnPrompt.confirm": { + "defaultMessage": "삭제" + }, + "course.gradebook.DeleteExternalColumnPrompt.error": { + "defaultMessage": "외부 평가를 삭제할 수 없습니다." + }, + "course.gradebook.DeleteExternalColumnPrompt.title": { + "defaultMessage": "외부 평가 삭제" + }, + "course.gradebook.ExternalGradeConflictPrompt.body": { + "defaultMessage": "이 학생들은 이미 해당 구성 요소에 대한 성적이 있습니다. 기존 성적을 유지하시겠습니까, 아니면 파일의 값으로 대체하시겠습니까? 새 학생과 빈 셀은 영향을 받지 않습니다." + }, + "course.gradebook.ExternalGradeConflictPrompt.goBack": { + "defaultMessage": "돌아가기" + }, + "course.gradebook.ExternalGradeConflictPrompt.keepExisting": { + "defaultMessage": "기존 항목 유지" + }, + "course.gradebook.ExternalGradeConflictPrompt.replace": { + "defaultMessage": "대체" + }, + "course.gradebook.ExternalGradeConflictPrompt.title": { + "defaultMessage": "성적 충돌 해결" + }, + "course.gradebook.ExternalGradeConflictTable.component": { + "defaultMessage": "구성 요소" + }, + "course.gradebook.ExternalGradeConflictTable.existing": { + "defaultMessage": "기존 성적" + }, + "course.gradebook.ExternalGradeConflictTable.inFile": { + "defaultMessage": "파일 내 성적" + }, + "course.gradebook.ExternalGradeConflictTable.mismatch": { + "defaultMessage": "이 식별자는 이제 기존 성적을 가져올 때의 학생과 다른 학생으로 확인됩니다." + }, + "course.gradebook.ExternalGradeConflictTable.student": { + "defaultMessage": "학생" + }, + "course.gradebook.GradeLinkHint.hint": { + "defaultMessage": "각 성적은 학생 제출물의 점수 합계입니다. 성적을 클릭하면 해당 제출물을 열고 점수를 조정할 수 있습니다." + }, + "course.gradebook.GradebookColumnTree.alwaysIncluded": { + "defaultMessage": "필수 항목" + }, + "course.gradebook.GradebookColumnTree.gamification": { + "defaultMessage": "게임화 관련" + }, + "course.gradebook.GradebookColumnTree.grades": { + "defaultMessage": "성적" + }, + "course.gradebook.GradebookColumnTree.studentInfo": { + "defaultMessage": "학생 정보" + }, + "course.gradebook.GradebookIndex.addExternal": { + "defaultMessage": "외부 평가 추가" + }, + "course.gradebook.GradebookIndex.allAssessments": { + "defaultMessage": "전체 평가" + }, + "course.gradebook.GradebookIndex.applyAndExport": { + "defaultMessage": "적용 및 내보내기" + }, + "course.gradebook.GradebookIndex.byWeight": { + "defaultMessage": "가중 총점" + }, + "course.gradebook.GradebookIndex.dialogTitle": { + "defaultMessage": "열 선택" + }, + "course.gradebook.GradebookIndex.exportAllTooltip": { + "defaultMessage": "선택한 행 없음 - 모든 행이 내보내집니다." + }, + "course.gradebook.GradebookIndex.exportButton": { + "defaultMessage": "전체 행 내보내기" }, - "course.forum.ForumTopicTable.votes": { - "defaultMessage": "투표" + "course.gradebook.GradebookIndex.exportRows": { + "defaultMessage": "{count, plural, other {# 행}} 내보내기" }, - "course.forum.ForumsIndex.fetchForumsFailure": { - "defaultMessage": "포럼 데이터를 검색하는 데 실패했습니다." + "course.gradebook.GradebookIndex.fetchFailure": { + "defaultMessage": "성적부를 불러오지 못했습니다." }, - "course.forum.ForumsIndex.header": { - "defaultMessage": "포럼" + "course.gradebook.GradebookIndex.gradebook": { + "defaultMessage": "성적부" }, - "course.forum.ForumsIndex.markAllAsReadFailed": { - "defaultMessage": "모든 주제를 읽음으로 표시하는 데 실패했습니다. 나중에 다시 시도하세요." + "course.gradebook.GradebookIndex.noStudents": { + "defaultMessage": "학생 없음" }, - "course.forum.ForumsIndex.markAllAsReadSuccess": { - "defaultMessage": "모든 주제가 읽음으로 표시되었습니다." + "course.gradebook.GradebookIndex.noStudentsHint": { + "defaultMessage": "학생이 강좌에 참여하면 여기에 성적이 표시됩니다." }, - "course.forum.ForumsIndex.newForum": { - "defaultMessage": "새 포럼" + "course.gradebook.GradebookIndex.searchStudents": { + "defaultMessage": "학생 검색" }, - "course.forum.HideButton.hide": { - "defaultMessage": "숨기기" + "course.gradebook.GradebookIndex.selectColumns": { + "defaultMessage": "열 선택" }, - "course.forum.HideButton.hideFailure": { - "defaultMessage": "주제 \"{title}\"을(를) 숨기는 데 실패했습니다 - {error}" + "course.gradebook.GradebookTable.delete": { + "defaultMessage": "삭제" }, - "course.forum.HideButton.hideSuccess": { - "defaultMessage": "주제 \"{title}\"이(가) 성공적으로 숨겨졌습니다." + "course.gradebook.GradebookTable.externalBadge": { + "defaultMessage": "외부" }, - "course.forum.HideButton.hideTooltip": { - "defaultMessage": "학생들에게 주제를 숨기기" + "course.gradebook.GradebookTable.externalGradeAria": { + "defaultMessage": "{name}의 {title} 성적" }, - "course.forum.HideButton.unhide": { - "defaultMessage": "숨기기 해제" + "course.gradebook.GradebookTable.externalMaxAria": { + "defaultMessage": "{title} 최대 점수" }, - "course.forum.HideButton.unhideFailure": { - "defaultMessage": "주제 \"{title}\"을(를) 보이는 것을 해제하는 데 실패했습니다 - {error}" + "course.gradebook.GradebookTable.gradeSaveError": { + "defaultMessage": "성적을 저장할 수 없습니다. 다시 시도해 주세요." }, - "course.forum.HideButton.unhideSuccess": { - "defaultMessage": "주제 \"{title}\"이(가) 성공적으로 보이게 되었습니다." + "course.gradebook.GradebookTable.manageAria": { + "defaultMessage": "{title} 관리" }, - "course.forum.HideButton.unhideTooltip": { - "defaultMessage": "학생들에게 주제를 보이기" + "course.gradebook.GradebookTable.maxMarks": { + "defaultMessage": "최고 점수" }, - "course.forum.LockButton.lockTooltip": { - "defaultMessage": "이 주제에서 학생들이 게시하는 것을 멈추기 위해 잠금" + "course.gradebook.GradebookTable.maxSaveError": { + "defaultMessage": "최대 점수를 저장할 수 없습니다. 다시 시도해 주세요." }, - "course.forum.LockButton.locked": { - "defaultMessage": "잠금" + "course.gradebook.GradebookTable.noDataColumnsHint": { + "defaultMessage": "성적 열을 선택하지 않았습니다. 내보내기에는 학생 정보만 포함됩니다." }, - "course.forum.LockButton.lockedFailure": { - "defaultMessage": "주제 \"{title}\" 잠금에 실패했습니다 - {error}" + "course.gradebook.GradebookTable.noDataColumnsHintWithGamification": { + "defaultMessage": "성적 또는 게임화 열을 선택하지 않았습니다. 내보내기에는 학생 정보만 포함됩니다." }, - "course.forum.LockButton.lockedSuccess": { - "defaultMessage": "주제 \"{title}\"이(가) 성공적으로 잠겼습니다." + "course.gradebook.GradebookTable.rename": { + "defaultMessage": "이름 변경" }, - "course.forum.LockButton.unlockTooltip": { - "defaultMessage": "이 주제에서 학생들이 게시할 수 있도록 잠금 해제" + "course.gradebook.GradebookWeightedTable.collapseRow": { + "defaultMessage": "{name} 접기" }, - "course.forum.LockButton.unlocked": { - "defaultMessage": "잠금 해제" + "course.gradebook.GradebookWeightedTable.configureWeights": { + "defaultMessage": "가중치 설정" }, - "course.forum.LockButton.unlockedFailure": { - "defaultMessage": "주제 \"{title}\"의 잠금을 해제하는 데 실패했습니다 - {error}" + "course.gradebook.GradebookWeightedTable.defaultWeights": { + "defaultMessage": "기본 가중치를 표시하고 있습니다. 모든 탭이 동일하게 반영됩니다. \"가중치 설정\"을 클릭하여 직접 설정하세요." }, - "course.forum.LockButton.unlockedSuccess": { - "defaultMessage": "주제 \"{title}\"의 잠금이 성공적으로 해제되었습니다." + "course.gradebook.GradebookWeightedTable.defaultWeightsNoAccess": { + "defaultMessage": "기본 가중치를 표시하고 있습니다. 가중치가 설정되기 전까지 모든 탭이 동일하게 반영됩니다." }, - "course.forum.MarkAllAsReadButton.AllReadTooltip": { - "defaultMessage": "만세! 모든 주제를 다 읽었습니다!" + "course.gradebook.GradebookWeightedTable.displayMode": { + "defaultMessage": "표시 모드" }, - "course.forum.MarkAllAsReadButton.markAllAsRead": { - "defaultMessage": "모두 읽음으로 표시" + "course.gradebook.GradebookWeightedTable.displayPercent": { + "defaultMessage": "백분율" }, - "course.forum.MarkAllAsReadButton.markAllAsReadTooltip": { - "defaultMessage": "현재 페이지의 모든 포럼 게시물을 읽음으로 표시" + "course.gradebook.GradebookWeightedTable.displayPercentTooltip": { + "defaultMessage": "학생이 각 탭에서 획득한 비율입니다. 비중이 20%인 탭에서 100%는 해당 탭의 20점을 모두 획득했음을 의미합니다." }, - "course.forum.MarkAnswerButton.markAsAnswer": { - "defaultMessage": "답변으로 표시" + "course.gradebook.GradebookWeightedTable.displayPoints": { + "defaultMessage": "점수" }, - "course.forum.MarkAnswerButton.markedAsAnswer": { - "defaultMessage": "답변으로 표시됨" + "course.gradebook.GradebookWeightedTable.displayPointsTooltip": { + "defaultMessage": "각 탭이 기여하는 성적 점수입니다. 각 열의 합이 예상 총점이 됩니다." }, - "course.forum.MarkAnswerButton.unmarkAsAnswer": { - "defaultMessage": "답변으로 표시 취소" + "course.gradebook.GradebookWeightedTable.downloadCsv": { + "defaultMessage": "CSV로 다운로드" }, - "course.forum.MarkAnswerButton.updateFailure": { - "defaultMessage": "게시물 업데이트 실패 - {error}" + "course.gradebook.GradebookWeightedTable.email": { + "defaultMessage": "이메일" }, - "course.forum.NextUnreadButton.AllReadTooltip": { - "defaultMessage": "만세! 모든 주제가 읽혔습니다!" + "course.gradebook.GradebookWeightedTable.excluded": { + "defaultMessage": "제외됨" }, - "course.forum.NextUnreadButton.nextUnread": { - "defaultMessage": "다음 읽지 않은 것" + "course.gradebook.GradebookWeightedTable.expandRow": { + "defaultMessage": "{name} 펼치기" }, - "course.forum.NextUnreadButton.nextUnreadTooltip": { - "defaultMessage": "다음 읽지 않은 주제로 이동" + "course.gradebook.GradebookWeightedTable.name": { + "defaultMessage": "이름" }, - "course.forum.PostCreatorObject.anonymousUser": { - "defaultMessage": "익명 사용자" + "course.gradebook.GradebookWeightedTable.noWeightsConfigured": { + "defaultMessage": "설정된 가중치가 없습니다. 모든 탭의 가중치가 0입니다. \"가중치 설정\"을 클릭하여 가중치를 지정하세요." }, - "course.forum.PostCreatorObject.maskUser": { - "defaultMessage": "사용자 가리기" + "course.gradebook.GradebookWeightedTable.noWeightsNoAccess": { + "defaultMessage": "아직 탭 가중치가 설정되지 않았습니다." }, - "course.forum.PostCreatorObject.postAnonymously": { - "defaultMessage": "익명 게시" + "course.gradebook.GradebookWeightedTable.outOfWeight": { + "defaultMessage": "/{weight}" }, - "course.forum.PostCreatorObject.unmaskUser": { - "defaultMessage": "사용자 가리기 해제" + "course.gradebook.GradebookWeightedTable.percentOfGrade": { + "defaultMessage": "성적의 {weight}%" }, - "course.forum.ReplyCard.emptyPost": { - "defaultMessage": "게시물을 비울 수 없습니다!" + "course.gradebook.GradebookWeightedTable.percentTotalExact": { + "defaultMessage": "합계 100%" }, - "course.forum.ReplyCard.postAnonymously": { - "defaultMessage": "익명 게시" + "course.gradebook.GradebookWeightedTable.percentTotalWarning": { + "defaultMessage": "합계 {weight}%" }, - "course.forum.ReplyCard.replyFailure": { - "defaultMessage": "게시물 제출 실패 - {error}" + "course.gradebook.GradebookWeightedTable.searchStudents": { + "defaultMessage": "학생 검색" }, - "course.forum.ReplyCard.replySuccess": { - "defaultMessage": "답글 게시물이 생성되었습니다." + "course.gradebook.GradebookWeightedTable.total": { + "defaultMessage": "총점" }, - "course.forum.ReplyCard.replyTo": { - "defaultMessage": "{user}에게 답글" + "course.gradebook.GradebookWeightedTable.weightsDoNotSum": { + "defaultMessage": "가중치 합계가 100이 아닙니다. 총점이 정확하지 않을 수 있습니다." }, - "course.forum.SubscribeButton.commonTranslations.manageMySubscription": { - "defaultMessage": "내 구독 관리" + "course.gradebook.ImportExternalAssessmentsButton.label": { + "defaultMessage": "외부 평가 가져오기" }, - "course.forum.SubscribeButton.commonTranslations.subscribe": { - "defaultMessage": "구독" + "course.gradebook.ImportWizard.addComponent": { + "defaultMessage": "구성 요소 추가" }, - "course.forum.SubscribeButton.commonTranslations.unsubscribe": { - "defaultMessage": "구독 취소" + "course.gradebook.ImportWizard.back": { + "defaultMessage": "뒤로" }, - "course.forum.SubscribeButton.commonTranslations.updateSubscriptionFailure": { - "defaultMessage": "구독 업데이트 실패 - {error}" + "course.gradebook.ImportWizard.cancel": { + "defaultMessage": "취소" }, - "course.forum.SubscribeButton.forumTopicTranslations.adminSettingSubscribed": { - "defaultMessage": "포럼 주제 구독이 강좌 관리자에 의해 비활성화되었습니다." + "course.gradebook.ImportWizard.commitError": { + "defaultMessage": "가져오기에 실패했습니다. 아무것도 저장되지 않았습니다." }, - "course.forum.SubscribeButton.forumTopicTranslations.subscribeSuccess": { - "defaultMessage": "포럼 주제 {title}에 성공적으로 구독되었습니다." + "course.gradebook.ImportWizard.committed": { + "defaultMessage": "가져오기가 완료되었습니다." }, - "course.forum.SubscribeButton.forumTopicTranslations.subscribeTooltip": { - "defaultMessage": "누군가가 이 포럼 주제에서 답변할 때 이메일 알림을 받으려면 구독하세요." + "course.gradebook.ImportWizard.componentName": { + "defaultMessage": "구성 요소 이름" }, - "course.forum.SubscribeButton.forumTopicTranslations.unsubscribeSuccess": { - "defaultMessage": "포럼 주제 {title}에서 성공적으로 구독 취소되었습니다." + "course.gradebook.ImportWizard.continue": { + "defaultMessage": "가져오기 확인" }, - "course.forum.SubscribeButton.forumTopicTranslations.unsubscribeTooltip": { - "defaultMessage": "누군가가 이 포럼 주제에서 답변할 때 이메일 알림을 받는 것을 중지하려면 구독 취소하세요." + "course.gradebook.ImportWizard.downloadTemplate": { + "defaultMessage": "템플릿 다운로드" }, - "course.forum.SubscribeButton.forumTopicTranslations.userSettingSubscribed": { - "defaultMessage": "이 과정의 포럼에서 \"새 게시물 및 답변\" 구독을 취소했습니다. 활성화하려면 {manageMySubscriptionLink}로 이동하세요." + "course.gradebook.ImportWizard.email": { + "defaultMessage": "이메일" }, - "course.forum.SubscribeButton.forumTranslations.adminSettingSubscribed": { - "defaultMessage": "새 포럼 주제의 구독이 강좌 관리자에 의해 비활성화되었습니다." + "course.gradebook.ImportWizard.identifierMode": { + "defaultMessage": "학생 매칭 기준" }, - "course.forum.SubscribeButton.forumTranslations.subscribeSuccess": { - "defaultMessage": "{title}에 성공적으로 구독되었습니다." + "course.gradebook.ImportWizard.malformed": { + "defaultMessage": "다음 셀은 올바른 숫자가 아닙니다: {cells}" }, - "course.forum.SubscribeButton.forumTranslations.subscribeTooltip": { - "defaultMessage": "새 주제가 생성될 때 이메일 알림을 받으려면 구독하세요." + "course.gradebook.ImportWizard.maxMarks": { + "defaultMessage": "최대 점수" }, - "course.forum.SubscribeButton.forumTranslations.unsubscribeSuccess": { - "defaultMessage": "{title}에서 성공적으로 구독 취소되었습니다." + "course.gradebook.ImportWizard.next": { + "defaultMessage": "다음" }, - "course.forum.SubscribeButton.forumTranslations.unsubscribeTooltip": { - "defaultMessage": "새 주제가 생성될 때 이메일 알림을 받는 것을 중지하려면 구독 취소하세요." + "course.gradebook.ImportWizard.previewError": { + "defaultMessage": "파일을 확인할 수 없습니다. 다시 시도해 주세요." }, - "course.forum.SubscribeButton.forumTranslations.userSettingSubscribed": { - "defaultMessage": "이 과정의 포럼에서 \"새 주제\" 구독을 취소했습니다. 활성화하려면 {manageMySubscriptionLink}로 이동하세요." + "course.gradebook.ImportWizard.stepDefine": { + "defaultMessage": "구성 요소 정의" }, - "course.forum.VotePostButton.updateFailure": { - "defaultMessage": "투표 수 업데이트 실패 - {error}" + "course.gradebook.ImportWizard.stepUpload": { + "defaultMessage": "템플릿 및 업로드" }, - "course.forum.forum.markAllAsReadFailed": { - "defaultMessage": "이 포럼의 모든 주제를 읽음으로 표시하는 데 실패했습니다. 나중에 다시 시도하세요." + "course.gradebook.ImportWizard.stepVerify": { + "defaultMessage": "확인" }, - "course.gradebook.GradebookColumnTree.grades": { - "defaultMessage": "성적" + "course.gradebook.ImportWizard.studentId": { + "defaultMessage": "학생 ID" }, - "course.gradebook.GradebookColumnTree.studentInfo": { - "defaultMessage": "학생 정보" + "course.gradebook.ImportWizard.studentIdHint": { + "defaultMessage": "매칭에는 각 학생의 현재 학생 ID가 사용됩니다. 사용자 관리에서 학생 ID를 최신 상태로 유지하세요." }, - "course.gradebook.GradebookColumnTree.alwaysIncluded": { - "defaultMessage": "필수 항목" + "course.gradebook.ImportWizard.title": { + "defaultMessage": "외부 평가 가져오기" }, - "course.gradebook.GradebookColumnTree.gamification": { - "defaultMessage": "게임화 관련" + "course.gradebook.ImportWizard.unresolved": { + "defaultMessage": "다음 식별자를 강좌에서 찾을 수 없습니다: {ids}" }, - "course.gradebook.GradebookIndex.dialogTitle": { - "defaultMessage": "열 선택" + "course.gradebook.ImportWizard.updatesExisting": { + "defaultMessage": "기존 항목 업데이트 - 성적부에서 관리됨" }, - "course.gradebook.GradebookIndex.exportAllTooltip": { - "defaultMessage": "선택한 행 없음 - 모든 행이 내보내집니다." + "course.gradebook.ImportWizard.upload": { + "defaultMessage": "작성한 CSV 업로드" }, - "course.gradebook.GradebookIndex.exportButton": { - "defaultMessage": "전체 행 내보내기" + "course.gradebook.ImportWizard.verify": { + "defaultMessage": "확인" }, - "course.gradebook.GradebookIndex.exportRows": { - "defaultMessage": "{count, plural, other {# 행}} 내보내기" + "course.gradebook.ImportWizard.weightage": { + "defaultMessage": "가중치" }, - "course.gradebook.GradebookIndex.selectColumns": { - "defaultMessage": "열 선택" + "course.gradebook.ProjectedTotalHint.policy": { + "defaultMessage": "총점은 채점되지 않은 평가를 0점으로 계산합니다." }, - "course.gradebook.GradebookIndex.applyAndExport": { - "defaultMessage": "적용 및 내보내기" + "course.gradebook.RenameExternalColumnPrompt.cancel": { + "defaultMessage": "취소" }, - "course.gradebook.GradebookIndex.fetchFailure": { - "defaultMessage": "성적부를 불러오지 못했습니다." + "course.gradebook.RenameExternalColumnPrompt.error": { + "defaultMessage": "외부 평가의 이름을 변경할 수 없습니다." }, - "course.gradebook.GradebookIndex.gradebook": { - "defaultMessage": "성적부" + "course.gradebook.RenameExternalColumnPrompt.nameLabel": { + "defaultMessage": "이름" }, - "course.gradebook.GradebookIndex.searchStudents": { - "defaultMessage": "학생 검색" + "course.gradebook.RenameExternalColumnPrompt.save": { + "defaultMessage": "저장" }, - "course.gradebook.GradebookIndex.noStudents": { - "defaultMessage": "학생 없음" + "course.gradebook.RenameExternalColumnPrompt.title": { + "defaultMessage": "외부 평가 이름 변경" }, - "course.gradebook.GradebookTable.maxMarks": { - "defaultMessage": "최고 점수" + "course.gradebook.TotalHint.policy": { + "defaultMessage": "총점은 채점되지 않은 평가를 0점으로 계산합니다." }, - "course.gradebook.GradebookTable.noDataColumnsHint": { - "defaultMessage": "성적 열을 선택하지 않았습니다. 내보내기에는 학생 정보만 포함됩니다." + "course.gradebook.WeightedViewHint.hint": { + "defaultMessage": "가중 총점이 필요하신가요? 각 탭이 학생의 전체 성적에 반영되는 비중을 설정하고 여기에서 가중 총점을 확인할 수 있습니다. {link}에서 활성화하세요." }, - "course.gradebook.GradebookTable.noDataColumnsHintWithGamification": { - "defaultMessage": "성적 또는 게임화 열을 선택하지 않았습니다. 내보내기에는 학생 정보만 포함됩니다." + "course.gradebook.WeightedViewHint.settingsLink": { + "defaultMessage": "성적부 설정" }, "course.group.GroupCreationForm.description": { "defaultMessage": "설명 (선택사항)" @@ -5681,27 +6029,27 @@ "course.leaderboard.LeaderboardTable.average": { "defaultMessage": "평균" }, - "course.leaderboard.LeaderboardTable.experience": { - "defaultMessage": "경험" + "course.leaderboard.LeaderboardTable.averageAchievements": { + "defaultMessage": "평균 성과" }, - "course.leaderboard.LeaderboardTable.rank": { - "defaultMessage": "순위" + "course.leaderboard.LeaderboardTable.averageExperience": { + "defaultMessage": "평균 경험치" }, - "course.leaderboard.LeaderboardTable.name": { - "defaultMessage": "이름" + "course.leaderboard.LeaderboardTable.experience": { + "defaultMessage": "경험" }, "course.leaderboard.LeaderboardTable.level": { "defaultMessage": "레벨" }, - "course.leaderboard.LeaderboardTable.averageExperience": { - "defaultMessage": "평균 경험치" - }, - "course.leaderboard.LeaderboardTable.averageAchievements": { - "defaultMessage": "평균 성과" - }, "course.leaderboard.LeaderboardTable.members": { "defaultMessage": "회원" }, + "course.leaderboard.LeaderboardTable.name": { + "defaultMessage": "이름" + }, + "course.leaderboard.LeaderboardTable.rank": { + "defaultMessage": "순위" + }, "course.leaderboard.LeaderboardTable.titleAchievements": { "defaultMessage": "성과별" }, @@ -5978,6 +6326,15 @@ "course.material.folders.UploadFilesButton.uploadFilesTooltip": { "defaultMessage": "업로드" }, + "course.material.folders.WorkbinTable.lastModified": { + "defaultMessage": "마지막 수정" + }, + "course.material.folders.WorkbinTable.name": { + "defaultMessage": "이름" + }, + "course.material.folders.WorkbinTable.startAt": { + "defaultMessage": "시작 시간" + }, "course.material.folders.WorkbinTableButtons.DeletionFailure": { "defaultMessage": "삭제할 수 없습니다" }, @@ -5990,29 +6347,17 @@ "course.material.folders.WorkbinTableButtons.tableButtonDeleteTooltip": { "defaultMessage": "삭제" }, - "course.material.folders.WorkbinTable.name": { - "defaultMessage": "이름" - }, - "course.material.folders.WorkbinTable.lastModified": { - "defaultMessage": "마지막 수정" - }, - "course.material.folders.WorkbinTable.startAt": { - "defaultMessage": "시작 시간" - }, - "course.plagiarism.PlagiarismIndex.header.plagiarism": { - "defaultMessage": "표절 검사" + "course.plagiarism.PlagiarismIndex.assessments.actions": { + "defaultMessage": "작업" }, "course.plagiarism.PlagiarismIndex.assessments.assessment": { "defaultMessage": "평가" }, - "course.plagiarism.PlagiarismIndex.assessments.numSubmitted": { - "defaultMessage": "# 제출" - }, - "course.plagiarism.PlagiarismIndex.assessments.numCheckableQuestions": { - "defaultMessage": "# 검사 가능한 질문" + "course.plagiarism.PlagiarismIndex.assessments.confirmRerunMessage": { + "defaultMessage": "선택한 평가 중 일부는 이미 완료된 표절 검사가 있습니다. 새 표절 검사를 실행하면 이전 결과가 제거됩니다." }, - "course.plagiarism.PlagiarismIndex.assessments.lastSubmittedAt": { - "defaultMessage": "마지막 제출 시각" + "course.plagiarism.PlagiarismIndex.assessments.confirmRerunTitle": { + "defaultMessage": "표절 검사를 확인하시겠습니까?" }, "course.plagiarism.PlagiarismIndex.assessments.lastRunStatus": { "defaultMessage": "상태" @@ -6020,17 +6365,14 @@ "course.plagiarism.PlagiarismIndex.assessments.lastRunTime": { "defaultMessage": "마지막 실행 시각" }, - "course.plagiarism.PlagiarismIndex.assessments.statusNotStarted": { - "defaultMessage": "시작되지 않음" - }, - "course.plagiarism.PlagiarismIndex.assessments.statusRunning": { - "defaultMessage": "실행 중" + "course.plagiarism.PlagiarismIndex.assessments.lastSubmittedAt": { + "defaultMessage": "마지막 제출 시각" }, - "course.plagiarism.PlagiarismIndex.assessments.statusCompleted": { - "defaultMessage": "완료됨" + "course.plagiarism.PlagiarismIndex.assessments.newSubmissionsWarning": { + "defaultMessage": "마지막 표절 검사 이후 새 제출물이 감지되었습니다" }, - "course.plagiarism.PlagiarismIndex.assessments.statusFailed": { - "defaultMessage": "실패" + "course.plagiarism.PlagiarismIndex.assessments.noNewSubmissionsWarning": { + "defaultMessage": "마지막 표절 검사 이후 새 제출물이 없습니다" }, "course.plagiarism.PlagiarismIndex.assessments.noPlagiarismCheckableQuestions": { "defaultMessage": "검사 가능한 질문이 없습니다" @@ -6038,38 +6380,110 @@ "course.plagiarism.PlagiarismIndex.assessments.notEnoughSubmissions": { "defaultMessage": "제출이 충분하지 않습니다" }, + "course.plagiarism.PlagiarismIndex.assessments.numCheckableQuestions": { + "defaultMessage": "# 검사 가능한 질문" + }, + "course.plagiarism.PlagiarismIndex.assessments.numSubmitted": { + "defaultMessage": "# 제출" + }, "course.plagiarism.PlagiarismIndex.assessments.runAssessmentsPlagiarism": { "defaultMessage": "새 표절 검사 ({count})" }, - "course.plagiarism.PlagiarismIndex.assessments.runPlagiarismCheckSuccess": { - "defaultMessage": "표절 검사를 시작했습니다 {count, plural, =1 {# 평가} other {# 평가}}" + "course.plagiarism.PlagiarismIndex.assessments.runPlagiarismCheck": { + "defaultMessage": "표절 검사 실행" }, "course.plagiarism.PlagiarismIndex.assessments.runPlagiarismCheckError": { "defaultMessage": "일부 평가에 대한 표절 검사를 시작하지 못했습니다" }, + "course.plagiarism.PlagiarismIndex.assessments.runPlagiarismCheckSuccess": { + "defaultMessage": "표절 검사를 시작했습니다 {count, plural, =1 {# 평가} other {# 평가}}" + }, "course.plagiarism.PlagiarismIndex.assessments.searchByAssessmentTitle": { "defaultMessage": "평가 제목으로 검색" }, - "course.plagiarism.PlagiarismIndex.assessments.actions": { - "defaultMessage": "작업" + "course.plagiarism.PlagiarismIndex.assessments.statusCompleted": { + "defaultMessage": "완료됨" }, - "course.plagiarism.PlagiarismIndex.assessments.runPlagiarismCheck": { - "defaultMessage": "표절 검사 실행" + "course.plagiarism.PlagiarismIndex.assessments.statusFailed": { + "defaultMessage": "실패" + }, + "course.plagiarism.PlagiarismIndex.assessments.statusNotStarted": { + "defaultMessage": "시작되지 않음" + }, + "course.plagiarism.PlagiarismIndex.assessments.statusRunning": { + "defaultMessage": "실행 중" }, "course.plagiarism.PlagiarismIndex.assessments.viewResults": { "defaultMessage": "결과 보기" }, - "course.plagiarism.PlagiarismIndex.assessments.newSubmissionsWarning": { - "defaultMessage": "마지막 표절 검사 이후 새 제출물이 감지되었습니다" + "course.plagiarism.PlagiarismIndex.header.plagiarism": { + "defaultMessage": "표절 검사" }, - "course.plagiarism.PlagiarismIndex.assessments.noNewSubmissionsWarning": { - "defaultMessage": "마지막 표절 검사 이후 새 제출물이 없습니다" + "course.statistics.StatisticsIndex.assessments.averageGrade": { + "defaultMessage": "평균 점수" }, - "course.plagiarism.PlagiarismIndex.assessments.confirmRerunTitle": { - "defaultMessage": "표절 검사를 확인하시겠습니까?" + "course.statistics.StatisticsIndex.assessments.averageTimeTaken": { + "defaultMessage": "평균 소요 시간" }, - "course.plagiarism.PlagiarismIndex.assessments.confirmRerunMessage": { - "defaultMessage": "선택한 평가 중 일부는 이미 완료된 표절 검사가 있습니다. 새 표절 검사를 실행하면 이전 결과가 제거됩니다." + "course.statistics.StatisticsIndex.assessments.category": { + "defaultMessage": "카테고리" + }, + "course.statistics.StatisticsIndex.assessments.csvFileTitle": { + "defaultMessage": "평가 통계" + }, + "course.statistics.StatisticsIndex.assessments.downloadCsv": { + "defaultMessage": "다운로드" + }, + "course.statistics.StatisticsIndex.assessments.downloadScoreSummary": { + "defaultMessage": "다음 평가의 점수 요약을 다운로드하시겠습니까?" + }, + "course.statistics.StatisticsIndex.assessments.downloadScoreSummaryFailure": { + "defaultMessage": "점수 요약 다운로드 중 오류가 발생했습니다" + }, + "course.statistics.StatisticsIndex.assessments.downloadScoreSummaryPending": { + "defaultMessage": "다운로드를 처리 중입니다. 잠시 기다려주세요." + }, + "course.statistics.StatisticsIndex.assessments.downloadScoreSummarySuccess": { + "defaultMessage": "점수 요약을 성공적으로 다운로드했습니다" + }, + "course.statistics.StatisticsIndex.assessments.numAttemptedStudents": { + "defaultMessage": "시도한 학생 수" + }, + "course.statistics.StatisticsIndex.assessments.numLateStudents": { + "defaultMessage": "지각한 학생 수" + }, + "course.statistics.StatisticsIndex.assessments.numSubmittedStudents": { + "defaultMessage": "제출한 학생 수" + }, + "course.statistics.StatisticsIndex.assessments.searchBar": { + "defaultMessage": "평가 제목, 탭 또는 카테고리로 검색" + }, + "course.statistics.StatisticsIndex.assessments.selectedNUsers": { + "defaultMessage": "{numUsers}명 학생의 점수 요약을 다운로드하시겠습니까?" + }, + "course.statistics.StatisticsIndex.assessments.startAt": { + "defaultMessage": "시작 시간" + }, + "course.statistics.StatisticsIndex.assessments.stdevGrade": { + "defaultMessage": "점수 표준편차" + }, + "course.statistics.StatisticsIndex.assessments.stdevTimeTaken": { + "defaultMessage": "소요 시간 표준편차" + }, + "course.statistics.StatisticsIndex.assessments.subtitle": { + "defaultMessage": "개별 학생 성적을 확인하고 내보내려면 성적부를 여세요." + }, + "course.statistics.StatisticsIndex.assessments.subtitleDisabled": { + "defaultMessage": "개별 학생 성적을 확인하고 내보내려면 성적부을 활성화하세요." + }, + "course.statistics.StatisticsIndex.assessments.tab": { + "defaultMessage": "탭" + }, + "course.statistics.StatisticsIndex.assessments.tableTitle": { + "defaultMessage": "평가 통계 ({numStudents}명의 학생)" + }, + "course.statistics.StatisticsIndex.assessments.title": { + "defaultMessage": "제목" }, "course.statistics.StatisticsIndex.course.StudentPerformanceTable.achievementCount": { "defaultMessage": "성과 개수 (총계: {courseAchievementCount})" @@ -6146,9 +6560,6 @@ "course.statistics.StatisticsIndex.course.StudentPerformanceTable.videoSubmissionCountHeader": { "defaultMessage": "시청한 비디오 (총계: {courseVideoCount})" }, - "course.statistics.StatisticsIndex.course.searchBar": { - "defaultMessage": "학생 이름으로 검색" - }, "course.statistics.StatisticsIndex.course.StudentProgressionChart.deadlines": { "defaultMessage": "마감일" }, @@ -6188,6 +6599,9 @@ "course.statistics.StatisticsIndex.course.progressionError": { "defaultMessage": "과정 진행 통계를 가져오는 동안 문제가 발생했습니다! 새로고침해서 다시 시도하세요." }, + "course.statistics.StatisticsIndex.course.searchBar": { + "defaultMessage": "학생 이름으로 검색" + }, "course.statistics.StatisticsIndex.header.statistics": { "defaultMessage": "통계" }, @@ -6260,6 +6674,9 @@ "course.statistics.StatisticsIndex.staff.averageMarkingTime": { "defaultMessage": "평균 평가 시간" }, + "course.statistics.StatisticsIndex.staff.csvFileTitle": { + "defaultMessage": "교직원 통계" + }, "course.statistics.StatisticsIndex.staff.error": { "defaultMessage": "교직원 통계를 가져오는 동안 문제가 발생했습니다! 새로고침해서 다시 시도하세요." }, @@ -6272,21 +6689,24 @@ "course.statistics.StatisticsIndex.staff.numStudents": { "defaultMessage": "# 학생" }, + "course.statistics.StatisticsIndex.staff.searchBar": { + "defaultMessage": "교직원 이름으로 검색" + }, "course.statistics.StatisticsIndex.staff.stddev": { "defaultMessage": "표준 편차" }, "course.statistics.StatisticsIndex.staff.tableTitle": { "defaultMessage": "교직원 통계" }, - "course.statistics.StatisticsIndex.staff.csvFileTitle": { - "defaultMessage": "교직원 통계" - }, - "course.statistics.StatisticsIndex.staff.searchBar": { - "defaultMessage": "교직원 이름으로 검색" - }, "course.statistics.StatisticsIndex.staffFailure": { "defaultMessage": "교직원 데이터를 가져오는 데 실패했습니다!" }, + "course.statistics.StatisticsIndex.students.csvFileTitle": { + "defaultMessage": "학생 통계" + }, + "course.statistics.StatisticsIndex.students.email": { + "defaultMessage": "이메일" + }, "course.statistics.StatisticsIndex.students.error": { "defaultMessage": "학생 통계를 가져오는 동안 문제가 발생했습니다! 새로고침해서 다시 시도하세요." }, @@ -6302,12 +6722,12 @@ "course.statistics.StatisticsIndex.students.name": { "defaultMessage": "이름" }, - "course.statistics.StatisticsIndex.students.email": { - "defaultMessage": "이메일" - }, "course.statistics.StatisticsIndex.students.noStudents": { "defaultMessage": "아직 이 과정에 학생이 없습니다..." }, + "course.statistics.StatisticsIndex.students.searchBar": { + "defaultMessage": "학생 이름, 학생 유형 또는 외부 ID로 검색" + }, "course.statistics.StatisticsIndex.students.showMyStudentsOnly": { "defaultMessage": "내 학생만 보기" }, @@ -6326,12 +6746,6 @@ "course.statistics.StatisticsIndex.students.videoSubmissionCount": { "defaultMessage": "시청한 비디오 (총계: {courseVideoCount})" }, - "course.statistics.StatisticsIndex.students.csvFileTitle": { - "defaultMessage": "학생 통계" - }, - "course.statistics.StatisticsIndex.students.searchBar": { - "defaultMessage": "학생 이름, 학생 유형 또는 외부 ID로 검색" - }, "course.statistics.StatisticsIndex.studentsFailure": { "defaultMessage": "학생 데이터를 가져오는 데 실패했습니다!" }, @@ -7022,6 +7436,27 @@ "course.userInvitation.InviteUsersRegistrationCode.registrationCodeNote": { "defaultMessage": "초대받은 사용자가 이 초대 코드를 사용하여 과정에 등록할 경우, 초대 페이지에서 해당 상태가 올바르게 반영되지 않을 수 있습니다." }, + "course.userInvitations.ExternalIdConflictPrompt.body": { + "defaultMessage": "이 사용자들은 이미 등록되었거나 초대가 대기 중입니다. 새로운 초대 이메일은 발송되지 않습니다. 현재 외부 ID를 유지하거나 파일의 값으로 교체하시겠습니까?" + }, + "course.userInvitations.ExternalIdConflictPrompt.goBack": { + "defaultMessage": "돌아가기" + }, + "course.userInvitations.ExternalIdConflictPrompt.keepExisting": { + "defaultMessage": "현재 유지" + }, + "course.userInvitations.ExternalIdConflictPrompt.pendingCourseUserUpdates": { + "defaultMessage": "대기 중인 수강생 업데이트 ({count}개)" + }, + "course.userInvitations.ExternalIdConflictPrompt.pendingInvitationUpdates": { + "defaultMessage": "대기 중인 초대 업데이트 ({count}개)" + }, + "course.userInvitations.ExternalIdConflictPrompt.replace": { + "defaultMessage": "교체" + }, + "course.userInvitations.ExternalIdConflictPrompt.title": { + "defaultMessage": "외부 ID 업데이트 확인" + }, "course.userInvitations.IndividualInvitations.appendNewRow": { "defaultMessage": "행 추가" }, @@ -7037,6 +7472,33 @@ "course.userInvitations.IndividualInvitations.removeInvitation": { "defaultMessage": "초대 삭제" }, + "course.userInvitations.InvitationActionButtons.deletionConfirm": { + "defaultMessage": "{name} ({email})에 대한 초대를 삭제하시겠습니까?" + }, + "course.userInvitations.InvitationActionButtons.deletionFailure": { + "defaultMessage": "사용자 삭제에 실패했습니다 - {error}" + }, + "course.userInvitations.InvitationActionButtons.deletionSuccess": { + "defaultMessage": "{name}에 대한 초대가 삭제되었습니다." + }, + "course.userInvitations.InvitationActionButtons.deletionTooltip": { + "defaultMessage": "초대 삭제" + }, + "course.userInvitations.InvitationActionButtons.resendFailure": { + "defaultMessage": "초대 재전송에 실패했습니다." + }, + "course.userInvitations.InvitationActionButtons.resendSuccess": { + "defaultMessage": "{email}로 초대 이메일을 다시 보냈습니다!" + }, + "course.userInvitations.InvitationActionButtons.resendTooltip": { + "defaultMessage": "초대 재전송" + }, + "course.userInvitations.InvitationResultDialog.actionableTitle": { + "defaultMessage": "실패 ({count})" + }, + "course.userInvitations.InvitationResultDialog.blankHeaderWarning": { + "defaultMessage": "헤더가 없는 열이 하나 이상 있어 해당 데이터는 무시되었습니다." + }, "course.userInvitations.InvitationResultDialog.body": { "defaultMessage": "{newInvitationsCount, plural, =0 {새로운 사용자가 없습니다.} one {새 사용자 #명이} other {새 사용자 #명이}} Coursemology에 초대되었습니다. {newCourseUsersCount, plural, =0 {Coursemology 계정을 가진 사용자가 없습니다.} one {Coursemology 계정을 가진 새로운 사용자가 #명이} other {Coursemology 계정을 가진 새로운 사용자가 #명이}} 이 과정에 추가되었습니다." }, @@ -7055,15 +7517,24 @@ "course.userInvitations.InvitationResultDialog.existingCourseUsersInfo": { "defaultMessage": "이 사용자들은 이미 과정에 등록되어 있습니다. 재등록되지 않습니다." }, - "course.userInvitations.InvitationResultDialog.externalIdUpdatedInfo": { - "defaultMessage": "외부 ID가 지정된 경우 업데이트되었습니다." - }, "course.userInvitations.InvitationResultDialog.existingInvitations": { "defaultMessage": "기존 초대장 ({count})" }, "course.userInvitations.InvitationResultDialog.existingInvitationsInfo": { "defaultMessage": "이 사용자들은 이미 대기 중인 초대장이 있습니다. 재초대되지 않습니다." }, + "course.userInvitations.InvitationResultDialog.externalIdUpdatedInfo": { + "defaultMessage": "외부 ID가 지정된 경우 업데이트되었습니다." + }, + "course.userInvitations.InvitationResultDialog.failedInvitations": { + "defaultMessage": "전송 실패 ({count})" + }, + "course.userInvitations.InvitationResultDialog.failedInvitationsInfo": { + "defaultMessage": "초대 이메일 전송 중 오류가 발생했습니다. 다시 시도해 주세요." + }, + "course.userInvitations.InvitationResultDialog.failedRowsSubtitle": { + "defaultMessage": "빨간색으로 강조된 {count}개 행 전송 실패" + }, "course.userInvitations.InvitationResultDialog.header": { "defaultMessage": "초대 요약" }, @@ -7073,14 +7544,8 @@ "course.userInvitations.InvitationResultDialog.newInvitations": { "defaultMessage": "새 초대장 ({count})" }, - "course.userInvitations.InvitationResultDialog.actionableTitle": { - "defaultMessage": "실패 ({count})" - }, - "course.userInvitations.InvitationResultDialog.failedInvitations": { - "defaultMessage": "전송 실패 ({count})" - }, - "course.userInvitations.InvitationResultDialog.failedInvitationsInfo": { - "defaultMessage": "초대 이메일 전송 중 오류가 발생했습니다. 다시 시도해 주세요." + "course.userInvitations.InvitationResultDialog.summary": { + "defaultMessage": "새 초대장 {newInvitations}개 발송, {newEnrollments}명 직접 등록, {alreadyInCourse}명은 이미 과정에 있습니다." }, "course.userInvitations.InvitationResultDialog.summaryFailed": { "defaultMessage": "{count}건이 실패했습니다." @@ -7088,14 +7553,8 @@ "course.userInvitations.InvitationResultDialog.updatedSubtitle": { "defaultMessage": "{count}개 업데이트됨 · 먼저 표시" }, - "course.userInvitations.InvitationResultDialog.blankHeaderWarning": { - "defaultMessage": "헤더가 없는 열이 하나 이상 있어 해당 데이터는 무시되었습니다." - }, - "course.userInvitations.InvitationResultDialog.summary": { - "defaultMessage": "새 초대장 {newInvitations}개 발송, {newEnrollments}명 직접 등록, {alreadyInCourse}명은 이미 과정에 있습니다." - }, - "course.userInvitations.InvitationResultDialog.failedRowsSubtitle": { - "defaultMessage": "빨간색으로 강조된 {count}개 행 전송 실패" + "course.userInvitations.InvitationResultExistingTable.previouslyLabel": { + "defaultMessage": "이전 값: {value}" }, "course.userInvitations.InvitationResultFailedTable.duplicateEmailInFile": { "defaultMessage": "업로드 파일에 중복된 이메일 주소가 있습니다" @@ -7106,18 +7565,15 @@ "course.userInvitations.InvitationResultFailedTable.externalIdTaken": { "defaultMessage": "해당 외부 ID는 이미 다른 과정 구성원에게 할당되어 있습니다" }, + "course.userInvitations.InvitationResultFailedTable.externalIdTakenEnrolled": { + "defaultMessage": "이미 과정 구성원입니다 - 외부 ID를 적용할 수 없습니다(이미 다른 구성원에게 할당됨)" + }, "course.userInvitations.InvitationResultFailedTable.failedToSend": { "defaultMessage": "초대 이메일 전송에 실패했습니다. 다시 시도해 주세요 - 문제가 지속되면 저희에게 문의해 주세요" }, - "course.userInvitations.InvitationResultFailedTable.externalIdTakenEnrolled": { - "defaultMessage": "이미 과정 구성원입니다 — 외부 ID를 적용할 수 없습니다(이미 다른 구성원에게 할당됨)" - }, "course.userInvitations.InvitationResultSkippedTable.previouslyLabel": { "defaultMessage": "이전 값: {value}" }, - "course.userInvitations.InvitationResultExistingTable.previouslyLabel": { - "defaultMessage": "이전 값: {value}" - }, "course.userInvitations.InvitationsBarChart.accepted": { "defaultMessage": "수락된 초대" }, @@ -7154,14 +7610,17 @@ "course.userInvitations.InviteUsersFileUpload.failureGeneric": { "defaultMessage": "사용자 초대에 실패했습니다. 데이터가 올바르게 형식화되었는지 확인하세요." }, + "course.userInvitations.InviteUsersFileUpload.fileRequired": { + "defaultMessage": "업로드할 CSV 파일을 선택해 주세요." + }, "course.userInvitations.InviteUsersFileUpload.fileUploadExample": { "defaultMessage": "이름,이메일,외부 ID,역할,팬텀{br}John,test1@example.com,A0123456,student,y{br}Mary,test2@example.com,A0123457,teaching_assistant,n" }, "course.userInvitations.InviteUsersFileUpload.fileUploadExamplePersonalTimeline": { "defaultMessage": "이름,이메일,외부 ID,역할,팬텀,개인 타임라인{br}John,test1@example.com,A0123456,student,y,otot{br}Mary,test2@example.com,A0123457,teaching_assistant,n,fixed" }, - "course.userInvitations.InviteUsersFileUpload.fileUploadInfoRequired": { - "defaultMessage": "CSV에는 \"이름\"과 \"이메일\" 열이 모두 포함되어야 합니다. 다른 모든 열은 선택 사항입니다." + "course.userInvitations.InviteUsersFileUpload.fileUploadInfo": { + "defaultMessage": "다음 형식으로 .csv 파일을 업로드하세요:" }, "course.userInvitations.InviteUsersFileUpload.fileUploadInfoEmail": { "defaultMessage": "각 초대는 과정 내에서 고유한 이메일 주소를 사용해야 합니다. 중복된 이메일은 건너뜁니다." @@ -7169,24 +7628,21 @@ "course.userInvitations.InviteUsersFileUpload.fileUploadInfoExternalId": { "defaultMessage": "외부 ID가 제공된 경우, 해당 외부 ID는 과정 내에서 고유해야 합니다." }, - "course.userInvitations.InviteUsersFileUpload.fileUploadInfo": { - "defaultMessage": "다음 형식으로 .csv 파일을 업로드하세요:" - }, "course.userInvitations.InviteUsersFileUpload.fileUploadInfoPersonalTimeline": { "defaultMessage": "개인 타임라인은 [fixed, otot, stragglers, fomo]로 설정할 수 있으며, 생략 시 과정 기본값: {defaultTimelineAlgorithm} 입니다." }, "course.userInvitations.InviteUsersFileUpload.fileUploadInfoPhantom": { "defaultMessage": "팬텀은 true/false로 설정할 수 있으며, true 값은 ['t', 'true', 'y', 'yes'] (대소문자 무관)으로 지정됩니다. 생략 시 기본값은 false입니다." }, + "course.userInvitations.InviteUsersFileUpload.fileUploadInfoRequired": { + "defaultMessage": "CSV에는 \"이름\"과 \"이메일\" 열이 모두 포함되어야 합니다. 다른 모든 열은 선택 사항입니다." + }, "course.userInvitations.InviteUsersFileUpload.fileUploadInfoRole": { "defaultMessage": "역할은 [학생, 관찰자, 티칭 어시스턴트, 관리자, 소유자]로 설정할 수 있으며, 생략 시 기본값은 학생입니다. 티칭 어시스턴트는 사용자 초대를 학생으로만 할 수 있습니다." }, "course.userInvitations.InviteUsersFileUpload.importInProgress": { "defaultMessage": "사용자를 가져오는 중입니다. 잠시만 기다려 주세요…" }, - "course.userInvitations.InviteUsersFileUpload.fileRequired": { - "defaultMessage": "업로드할 CSV 파일을 선택해 주세요." - }, "course.userInvitations.InviteUsersFileUpload.template": { "defaultMessage": "(템플릿 파일)" }, @@ -7199,27 +7655,6 @@ "course.userInvitations.InviteUsersfileUploadForm.invite": { "defaultMessage": "파일에서 사용자 초대" }, - "course.userInvitations.InvitationActionButtons.deletionConfirm": { - "defaultMessage": "{name} ({email})에 대한 초대를 삭제하시겠습니까?" - }, - "course.userInvitations.InvitationActionButtons.deletionFailure": { - "defaultMessage": "사용자 삭제에 실패했습니다 - {error}" - }, - "course.userInvitations.InvitationActionButtons.deletionSuccess": { - "defaultMessage": "{name}에 대한 초대가 삭제되었습니다." - }, - "course.userInvitations.InvitationActionButtons.deletionTooltip": { - "defaultMessage": "초대 삭제" - }, - "course.userInvitations.InvitationActionButtons.resendFailure": { - "defaultMessage": "초대 재전송에 실패했습니다." - }, - "course.userInvitations.InvitationActionButtons.resendSuccess": { - "defaultMessage": "{email}로 초대 이메일을 다시 보냈습니다!" - }, - "course.userInvitations.InvitationActionButtons.resendTooltip": { - "defaultMessage": "초대 재전송" - }, "course.userInvitations.RegistrationCodeButton.registrationCode": { "defaultMessage": "등록 코드" }, @@ -7238,24 +7673,24 @@ "course.userInvitations.UserInvitationsTable.accepted": { "defaultMessage": "수락됨" }, + "course.userInvitations.UserInvitationsTable.confirmedTooltip": { + "defaultMessage": "{confirmedAt}에 수락됨" + }, "course.userInvitations.UserInvitationsTable.failed": { "defaultMessage": "실패" }, "course.userInvitations.UserInvitationsTable.noInvitations": { "defaultMessage": "초대가 없습니다." }, - "course.userInvitations.UserInvitationsTable.searchText": { - "defaultMessage": "이름, 이메일 또는 외부 ID로 검색" - }, "course.userInvitations.UserInvitationsTable.pending": { "defaultMessage": "대기 중" }, + "course.userInvitations.UserInvitationsTable.searchText": { + "defaultMessage": "이름, 이메일 또는 외부 ID로 검색" + }, "course.userInvitations.UserInvitationsTable.sentTooltip": { "defaultMessage": "{sentAt}에 전송됨" }, - "course.userInvitations.UserInvitationsTable.confirmedTooltip": { - "defaultMessage": "{confirmedAt}에 수락됨" - }, "course.userNotification.AchievementGainedPopup.unlocked": { "defaultMessage": "업적 달성!" }, @@ -7292,6 +7727,12 @@ "course.users.ManageUsersTable.ManageUsersTable.searchText": { "defaultMessage": "이름, 이메일 또는 외부 ID로 검색" }, + "course.users.ManageUsersTable.addIdFailure": { + "defaultMessage": "외부 ID를 {newId}로 설정하지 못했습니다." + }, + "course.users.ManageUsersTable.addIdSuccess": { + "defaultMessage": "외부 ID가 {newId}로 설정되었습니다." + }, "course.users.ManageUsersTable.assignToTimeline": { "defaultMessage": "타임라인에 할당" }, @@ -7322,6 +7763,12 @@ "course.users.ManageUsersTable.changeAlgorithmSuccess": { "defaultMessage": "{name}의 타임라인 알고리즘을 {timeline}(으)로 업데이트했습니다." }, + "course.users.ManageUsersTable.changeIdFailure": { + "defaultMessage": "ID를 {oldId}에서 {newId}로 변경하지 못했습니다." + }, + "course.users.ManageUsersTable.changeIdSuccess": { + "defaultMessage": "ID가 {oldId}에서 {newId}로 변경되었습니다." + }, "course.users.ManageUsersTable.changeRoleFailure": { "defaultMessage": "{name}의 역할을 {role}(으)로 업데이트하지 못했습니다." }, @@ -7337,29 +7784,29 @@ "course.users.ManageUsersTable.defaultTimeline": { "defaultMessage": "기본값" }, - "course.users.ManageUsersTable.group": { - "defaultMessage": "그룹: {name}" + "course.users.ManageUsersTable.deleteIdFailure": { + "defaultMessage": "외부 ID를 삭제하지 못했습니다." }, - "course.users.ManageUsersTable.phantomSuccess": { - "defaultMessage": "{name} {isPhantom, select, true {은(는) 이제 팬텀 사용자입니다} other {은(는) 이제 일반 사용자입니다}}." + "course.users.ManageUsersTable.deleteIdSuccess": { + "defaultMessage": "외부 ID가 삭제되었습니다." }, - "course.users.ManageUsersTable.addIdFailure": { - "defaultMessage": "외부 ID를 {newId}로 설정하지 못했습니다." + "course.users.ManageUsersTable.deletionConfirm": { + "defaultMessage": "{role} {name} ({email})을(를) 삭제하시겠습니까?" }, - "course.users.ManageUsersTable.addIdSuccess": { - "defaultMessage": "외부 ID가 {newId}로 설정되었습니다." + "course.users.ManageUsersTable.deletionFailure": { + "defaultMessage": "사용자 삭제에 실패했습니다." }, - "course.users.ManageUsersTable.changeIdFailure": { - "defaultMessage": "ID를 {oldId}에서 {newId}로 변경하지 못했습니다." + "course.users.ManageUsersTable.deletionScheduled": { + "defaultMessage": "{role} {name} ({email}) 삭제가 예약되었습니다." }, - "course.users.ManageUsersTable.changeIdSuccess": { - "defaultMessage": "ID가 {oldId}에서 {newId}로 변경되었습니다." + "course.users.ManageUsersTable.deletionSuccess": { + "defaultMessage": "사용자가 삭제되었습니다." }, - "course.users.ManageUsersTable.deleteIdFailure": { - "defaultMessage": "외부 ID를 삭제하지 못했습니다." + "course.users.ManageUsersTable.group": { + "defaultMessage": "그룹: {name}" }, - "course.users.ManageUsersTable.deleteIdSuccess": { - "defaultMessage": "외부 ID가 삭제되었습니다." + "course.users.ManageUsersTable.phantomSuccess": { + "defaultMessage": "{name} {isPhantom, select, true {은(는) 이제 팬텀 사용자입니다} other {은(는) 이제 일반 사용자입니다}}." }, "course.users.ManageUsersTable.renameFailure": { "defaultMessage": "{oldName}을(를) {newName}(으)로 이름 변경하지 못했습니다." @@ -7370,6 +7817,24 @@ "course.users.ManageUsersTable.selectedNUsers": { "defaultMessage": "{n, plural, =1 {#명의 사용자} other {#명의 사용자들}}이 선택되었습니다." }, + "course.users.ManageUsersTable.suspend": { + "defaultMessage": "정지" + }, + "course.users.ManageUsersTable.suspendFailure": { + "defaultMessage": "{name}을(를) 정지하지 못했습니다." + }, + "course.users.ManageUsersTable.suspendSuccess": { + "defaultMessage": "{name}이(가) 이제 정지되었습니다. 정지가 해제될 때까지 이 과정에 접근할 수 없습니다." + }, + "course.users.ManageUsersTable.unsuspend": { + "defaultMessage": "정지 해제" + }, + "course.users.ManageUsersTable.unsuspendFailure": { + "defaultMessage": "{name}의 정지를 해제하지 못했습니다." + }, + "course.users.ManageUsersTable.unsuspendSuccess": { + "defaultMessage": "{name}의 정지가 해제되었습니다. 이제 과정에 접근할 수 있습니다." + }, "course.users.ManageUsersTable.updateFailure": { "defaultMessage": "사용자 업데이트에 실패했습니다 - {error}" }, @@ -7478,36 +7943,6 @@ "course.users.UpgradeToStaff.upgradeSuccess": { "defaultMessage": "{count, plural, =0 {사용자가 없습니다.} one {#명의 사용자가} other {#명의 사용자가}} {role}(으)로 승격되었습니다." }, - "course.users.ManageUsersTable.deletionConfirm": { - "defaultMessage": "{role} {name} ({email})을(를) 삭제하시겠습니까?" - }, - "course.users.ManageUsersTable.deletionFailure": { - "defaultMessage": "사용자 삭제에 실패했습니다." - }, - "course.users.ManageUsersTable.deletionScheduled": { - "defaultMessage": "{role} {name} ({email}) 삭제가 예약되었습니다." - }, - "course.users.ManageUsersTable.deletionSuccess": { - "defaultMessage": "사용자가 삭제되었습니다." - }, - "course.users.ManageUsersTable.suspend": { - "defaultMessage": "정지" - }, - "course.users.ManageUsersTable.suspendFailure": { - "defaultMessage": "{name}을(를) 정지하지 못했습니다." - }, - "course.users.ManageUsersTable.suspendSuccess": { - "defaultMessage": "{name}이(가) 이제 정지되었습니다. 정지가 해제될 때까지 이 과정에 접근할 수 없습니다." - }, - "course.users.ManageUsersTable.unsuspend": { - "defaultMessage": "정지 해제" - }, - "course.users.ManageUsersTable.unsuspendFailure": { - "defaultMessage": "{name}의 정지를 해제하지 못했습니다." - }, - "course.users.ManageUsersTable.unsuspendSuccess": { - "defaultMessage": "{name}의 정지가 해제되었습니다. 이제 과정에 접근할 수 있습니다." - }, "course.users.UserManagementTabs.enrolRequestsTitle": { "defaultMessage": "등록 요청" }, @@ -7646,27 +8081,27 @@ "course.video.VideoShow.videoTitle": { "defaultMessage": "비디오 - {title}" }, + "course.video.VideoTable.actions": { + "defaultMessage": "작업" + }, + "course.video.VideoTable.averageWatched": { + "defaultMessage": "평균 시청 비율" + }, "course.video.VideoTable.noVideo": { "defaultMessage": "비디오 없음" }, - "course.video.VideoTable.title": { - "defaultMessage": "제목" + "course.video.VideoTable.published": { + "defaultMessage": "게시됨" }, "course.video.VideoTable.startAt": { "defaultMessage": "시작 시간" }, + "course.video.VideoTable.title": { + "defaultMessage": "제목" + }, "course.video.VideoTable.watchCount": { "defaultMessage": "시청 횟수" }, - "course.video.VideoTable.averageWatched": { - "defaultMessage": "평균 시청 비율" - }, - "course.video.VideoTable.published": { - "defaultMessage": "게시됨" - }, - "course.video.VideoTable.actions": { - "defaultMessage": "작업" - }, "course.video.VideosIndex.fetchVideosFailure": { "defaultMessage": "비디오를 가져오지 못했습니다." }, @@ -7853,12 +8288,12 @@ "lib.components.core.Expandable.showMore": { "defaultMessage": "더 보기" }, - "lib.components.core.Note.noteHeader": { - "defaultMessage": "노트" - }, "lib.components.core.Note.errorHeader": { "defaultMessage": "오류" }, + "lib.components.core.Note.noteHeader": { + "defaultMessage": "노트" + }, "lib.components.core.banners.ServerUnreachableBanner.refreshPage": { "defaultMessage": "페이지 새로고침" }, @@ -7952,41 +8387,107 @@ "lib.components.extensions.conditions.errorOccurredWhenCreatingCondition": { "defaultMessage": "이 조건을 생성하는 동안 오류가 발생했습니다." }, - "lib.components.extensions.conditions.errorOccurredWhenDeletingCondition": { - "defaultMessage": "이 조건을 삭제하는 동안 오류가 발생했습니다." + "lib.components.extensions.conditions.errorOccurredWhenDeletingCondition": { + "defaultMessage": "이 조건을 삭제하는 동안 오류가 발생했습니다." + }, + "lib.components.extensions.conditions.errorOccurredWhenUpdatingCondition": { + "defaultMessage": "이 조건을 업데이트하는 동안 오류가 발생했습니다." + }, + "lib.components.extensions.conditions.level": { + "defaultMessage": "레벨" + }, + "lib.components.extensions.conditions.scoreZeroPercentNotice": { + "defaultMessage": "0% 이상 점수는 이 평가가 채점된 이후에 조건이 충족되도록 요구합니다. 최소 점수가 지정되지 않은 경우, 이 조건은 단순 제출만 요구합니다." + }, + "lib.components.extensions.conditions.scoringAtLeast": { + "defaultMessage": "최소 점수" + }, + "lib.components.extensions.conditions.specifyLevel": { + "defaultMessage": "최소 레벨 지정" + }, + "lib.components.extensions.conditions.survey": { + "defaultMessage": "설문 조사" + }, + "lib.components.extensions.conditions.type": { + "defaultMessage": "유형" + }, + "lib.components.extensions.conditions.updateCondition": { + "defaultMessage": "조건 업데이트" + }, + "lib.components.form.fields.DateTimePickerField.invalidDateTime": { + "defaultMessage": "잘못된 날짜 및/또는 시간" + }, + "lib.components.form.fields.SingleFileInput.dropzone": { + "defaultMessage": "여기에 파일을 끌어놓거나 클릭하여 파일을 선택하세요." + }, + "lib.components.form.fields.SingleFileInput.removeFile": { + "defaultMessage": "파일 제거" + }, + "lib.components.getHelp.filter.filterAssessmentLabel": { + "defaultMessage": "평가로 필터링" + }, + "lib.components.getHelp.filter.filterCourseLabel": { + "defaultMessage": "과정으로 필터링" + }, + "lib.components.getHelp.filter.filterEndDateLabel": { + "defaultMessage": "종료 날짜" + }, + "lib.components.getHelp.filter.filterStartDateLabel": { + "defaultMessage": "시작 날짜" + }, + "lib.components.getHelp.filter.filterStudentLabel": { + "defaultMessage": "학생으로 필터링" + }, + "lib.components.getHelp.filter.lastFourteenDays": { + "defaultMessage": "최근 14일" + }, + "lib.components.getHelp.filter.lastSevenDays": { + "defaultMessage": "최근 7일" + }, + "lib.components.getHelp.filter.lastSixMonths": { + "defaultMessage": "최근 6개월" + }, + "lib.components.getHelp.filter.lastThirtyDays": { + "defaultMessage": "최근 30일" + }, + "lib.components.getHelp.filter.lastTwelveMonths": { + "defaultMessage": "최근 12개월" + }, + "lib.components.getHelp.header": { + "defaultMessage": "최근 도움 요청 활동 ({total, plural, other {#개 대화}})" }, - "lib.components.extensions.conditions.errorOccurredWhenUpdatingCondition": { - "defaultMessage": "이 조건을 업데이트하는 동안 오류가 발생했습니다." + "lib.components.getHelp.table.assessmentTitle": { + "defaultMessage": "평가" }, - "lib.components.extensions.conditions.level": { - "defaultMessage": "레벨" + "lib.components.getHelp.table.courseTitle": { + "defaultMessage": "과정" }, - "lib.components.extensions.conditions.scoreZeroPercentNotice": { - "defaultMessage": "0% 이상 점수는 이 평가가 채점된 이후에 조건이 충족되도록 요구합니다. 최소 점수가 지정되지 않은 경우, 이 조건은 단순 제출만 요구합니다." + "lib.components.getHelp.table.createdAt": { + "defaultMessage": "마지막 메시지 시간" }, - "lib.components.extensions.conditions.scoringAtLeast": { - "defaultMessage": "최소 점수" + "lib.components.getHelp.table.instanceTitle": { + "defaultMessage": "인스턴스" }, - "lib.components.extensions.conditions.specifyLevel": { - "defaultMessage": "최소 레벨 지정" + "lib.components.getHelp.table.lastMessage": { + "defaultMessage": "마지막 메시지" }, - "lib.components.extensions.conditions.survey": { - "defaultMessage": "설문 조사" + "lib.components.getHelp.table.messageCount": { + "defaultMessage": "메시지 수" }, - "lib.components.extensions.conditions.type": { - "defaultMessage": "유형" + "lib.components.getHelp.table.questionNumber": { + "defaultMessage": "질문" }, - "lib.components.extensions.conditions.updateCondition": { - "defaultMessage": "조건 업데이트" + "lib.components.getHelp.table.studentName": { + "defaultMessage": "이름" }, - "lib.components.form.fields.DateTimePickerField.invalidDateTime": { - "defaultMessage": "잘못된 날짜 및/또는 시간" + "lib.components.getHelp.validation.endDateBeforeStartDate": { + "defaultMessage": "종료일은 시작일 이후이거나 같아야 합니다" }, - "lib.components.form.fields.SingleFileInput.dropzone": { - "defaultMessage": "여기에 파일을 끌어놓거나 클릭하여 파일을 선택하세요." + "lib.components.getHelp.validation.exceedDateRange": { + "defaultMessage": "날짜 범위는 365일을 초과할 수 없습니다" }, - "lib.components.form.fields.SingleFileInput.removeFile": { - "defaultMessage": "파일 제거" + "lib.components.getHelp.validation.invalidDateSelection": { + "defaultMessage": "잘못된 날짜" }, "lib.components.navigation.AdminPopupMenuList.adminPanel": { "defaultMessage": "시스템 관리자 패널" @@ -8024,6 +8525,21 @@ "lib.components.navigation.CourseSwitcherPopupMenu.thisCourse": { "defaultMessage": "이 과정" }, + "lib.components.table.MuiColumnPickerPrompt.apply": { + "defaultMessage": "뷰에 적용" + }, + "lib.components.table.MuiColumnPickerPrompt.cancel": { + "defaultMessage": "취소" + }, + "lib.components.table.MuiColumnPickerPrompt.defaultTitle": { + "defaultMessage": "열 선택" + }, + "lib.components.table.MuiTableToolbar.directExport": { + "defaultMessage": "내보내기" + }, + "lib.components.table.MuiTableToolbar.exportTrigger": { + "defaultMessage": "내보내기…" + }, "lib.hooks.router.usePrompt.sureYouWantToLeave": { "defaultMessage": "이 페이지를 떠나시겠습니까? 저장되지 않은 변경 사항이 손실됩니다." }, @@ -8138,21 +8654,21 @@ "lib.translations.course.users.manageUsersHeader": { "defaultMessage": "사용자 관리" }, - "lib.translations.course.users.roles.student": { - "defaultMessage": "학생" - }, - "lib.translations.course.users.roles.teachingAssistant": { - "defaultMessage": "조교" + "lib.translations.course.users.roles.manager": { + "defaultMessage": "관리자" }, "lib.translations.course.users.roles.observer": { "defaultMessage": "관찰자" }, - "lib.translations.course.users.roles.manager": { - "defaultMessage": "관리자" - }, "lib.translations.course.users.roles.owner": { "defaultMessage": "소유자" }, + "lib.translations.course.users.roles.student": { + "defaultMessage": "학생" + }, + "lib.translations.course.users.roles.teachingAssistant": { + "defaultMessage": "조교" + }, "lib.translations.experimental": { "defaultMessage": "실험적" }, @@ -8228,24 +8744,6 @@ "lib.translations.form.messages.unsavedChanges": { "defaultMessage": "저장되지 않은 변경 사항이 있습니다." }, - "lib.translations.instance.users.roles.normal": { - "defaultMessage": "일반 사용자" - }, - "lib.translations.instance.users.roles.instructor": { - "defaultMessage": "교사" - }, - "lib.translations.instance.users.roles.administrator": { - "defaultMessage": "관리자" - }, - "lib.translations.myStudentsIncludingPhantoms": { - "defaultMessage": "내 학생들 (팬텀 포함)" - }, - "lib.translations.studentsIncludingPhantoms": { - "defaultMessage": "학생들 (팬텀 포함)" - }, - "lib.translations.staffIncludingPhantoms": { - "defaultMessage": "스태프 (팬텀 포함)" - }, "lib.translations.form.startAt": { "defaultMessage": "시작 시각" }, @@ -8282,6 +8780,15 @@ "lib.translations.form.validation.startEndDateValidationError": { "defaultMessage": "시작 날짜 이후여야 합니다." }, + "lib.translations.instance.users.roles.administrator": { + "defaultMessage": "관리자" + }, + "lib.translations.instance.users.roles.instructor": { + "defaultMessage": "교사" + }, + "lib.translations.instance.users.roles.normal": { + "defaultMessage": "일반 사용자" + }, "lib.translations.messages.fetchingError": { "defaultMessage": "데이터를 로드하는 중 오류가 발생했습니다. 다시 시도하세요." }, @@ -8291,9 +8798,27 @@ "lib.translations.messages.loadImageError": { "defaultMessage": "이미지를 로드하는 중 오류가 발생했습니다. 다른 이미지를 선택해 보십시오." }, + "lib.translations.myStudents": { + "defaultMessage": "내 학생들" + }, + "lib.translations.myStudentsIncludingPhantoms": { + "defaultMessage": "내 학생들 (팬텀 포함)" + }, "lib.translations.no": { "defaultMessage": "아니오" }, + "lib.translations.staff": { + "defaultMessage": "스태프" + }, + "lib.translations.staffIncludingPhantoms": { + "defaultMessage": "스태프 (팬텀 포함)" + }, + "lib.translations.students": { + "defaultMessage": "학생들" + }, + "lib.translations.studentsIncludingPhantoms": { + "defaultMessage": "학생들 (팬텀 포함)" + }, "lib.translations.summary": { "defaultMessage": "요약" }, @@ -8330,15 +8855,15 @@ "lib.translations.table.column.createdAt": { "defaultMessage": "생성 시각" }, + "lib.translations.table.column.currentExternalId": { + "defaultMessage": "현재 외부 ID" + }, "lib.translations.table.column.designation": { "defaultMessage": "지정" }, "lib.translations.table.column.email": { "defaultMessage": "이메일" }, - "lib.translations.table.column.externalId": { - "defaultMessage": "외부 ID" - }, "lib.translations.table.column.endAt": { "defaultMessage": "종료 시각" }, @@ -8348,6 +8873,9 @@ "lib.translations.table.column.experiencePointsAwarded": { "defaultMessage": "획득한 경험치" }, + "lib.translations.table.column.externalId": { + "defaultMessage": "외부 ID" + }, "lib.translations.table.column.groups": { "defaultMessage": "그룹" }, @@ -8390,6 +8918,9 @@ "lib.translations.table.column.name": { "defaultMessage": "이름" }, + "lib.translations.table.column.newExternalId": { + "defaultMessage": "새 외부 ID" + }, "lib.translations.table.column.optional": { "defaultMessage": "선택" }, @@ -8471,30 +9002,15 @@ "material.attemptLoader.errorAccessingMaterial": { "defaultMessage": "이 자료에 접근하는 중 오류가 발생했습니다. 나중에 다시 시도해 주세요." }, - "system.admin.instance.instance.InstanceAdminNavigator.announcements": { - "defaultMessage": "공지사항" - }, - "system.admin.instance.instance.InstanceAdminNavigator.components": { - "defaultMessage": "구성 요소" - }, - "system.admin.instance.instance.InstanceAdminNavigator.courses": { - "defaultMessage": "과정" - }, - "system.admin.instance.instance.InstanceAdminNavigator.roleRequests": { - "defaultMessage": "역할 요청" - }, - "system.admin.instance.instance.InstanceAdminNavigator.users": { - "defaultMessage": "사용자" - }, - "system.admin.instance.instance.InstanceAdminNavigator.getHelp": { - "defaultMessage": "도움 받기" - }, "system.admin.admin.AdminNavigator.announcements": { "defaultMessage": "시스템 공지사항" }, "system.admin.admin.AdminNavigator.courses": { "defaultMessage": "과정" }, + "system.admin.admin.AdminNavigator.getHelp": { + "defaultMessage": "도움 받기" + }, "system.admin.admin.AdminNavigator.instances": { "defaultMessage": "인스턴스" }, @@ -8504,9 +9020,6 @@ "system.admin.admin.AdminNavigator.users": { "defaultMessage": "사용자" }, - "system.admin.admin.AdminNavigator.getHelp": { - "defaultMessage": "도움 받기" - }, "system.admin.admin.AnnouncementsIndex.fetchAnnouncementsFailure": { "defaultMessage": "공지사항을 가져올 수 없습니다." }, @@ -8597,18 +9110,18 @@ "system.admin.admin.UsersButton.deletionConfirm": { "defaultMessage": "정말로 계속하시겠습니까?" }, - "system.admin.admin.UsersButton.deletionFailure": { - "defaultMessage": "사용자 삭제에 실패했습니다 - {error}" - }, - "system.admin.admin.UsersButton.deletionSuccess": { - "defaultMessage": "사용자가 삭제되었습니다." - }, "system.admin.admin.UsersButton.deletionConfirmTitle": { "defaultMessage": "{role} 사용자 {name} ({email}) 삭제 중" }, + "system.admin.admin.UsersButton.deletionFailure": { + "defaultMessage": "사용자 삭제에 실패했습니다 - {error}" + }, "system.admin.admin.UsersButton.deletionPromptContent": { "defaultMessage": "이 사용자를 삭제하면 다음 {count, plural, one {과목} other {과목들}}에 연결된 데이터가 영구적으로 삭제됩니다:" }, + "system.admin.admin.UsersButton.deletionSuccess": { + "defaultMessage": "사용자가 삭제되었습니다." + }, "system.admin.admin.UsersIndex.activeUsers": { "defaultMessage": "활성 사용자: {allCount} ({adminCount} 관리자, {normalCount} 일반){br}(지난 7일 동안 활성)" }, @@ -8624,9 +9137,6 @@ "system.admin.admin.UsersTable.changeRoleSuccess": { "defaultMessage": "{name}의 역할이 {role}(으)로 변경되었습니다." }, - "system.admin.users.UsersTable.instanceEntry": { - "defaultMessage": "{instanceName}{courseCount, plural, =0 {} one { (1개 과목)} other { ({courseCount}개 과목)}}" - }, "system.admin.admin.UsersTable.renameSuccess": { "defaultMessage": "{oldName}이(가) {newName}(으)로 이름이 변경되었습니다." }, @@ -8654,6 +9164,24 @@ "system.admin.instance.instance.IndividualInvitations.invite": { "defaultMessage": "모든 사용자 초대" }, + "system.admin.instance.instance.InstanceAdminNavigator.announcements": { + "defaultMessage": "공지사항" + }, + "system.admin.instance.instance.InstanceAdminNavigator.components": { + "defaultMessage": "구성 요소" + }, + "system.admin.instance.instance.InstanceAdminNavigator.courses": { + "defaultMessage": "과정" + }, + "system.admin.instance.instance.InstanceAdminNavigator.getHelp": { + "defaultMessage": "도움 받기" + }, + "system.admin.instance.instance.InstanceAdminNavigator.roleRequests": { + "defaultMessage": "역할 요청" + }, + "system.admin.instance.instance.InstanceAdminNavigator.users": { + "defaultMessage": "사용자" + }, "system.admin.instance.instance.InstanceAnnouncementsIndex.fetchAnnouncementsFailure": { "defaultMessage": "공지사항을 가져올 수 없습니다." }, @@ -8774,6 +9302,27 @@ "system.admin.instance.instance.InstanceUsersTabs.usersTab": { "defaultMessage": "사용자" }, + "system.admin.instance.instance.InvitationActionButtons.deletionConfirm": { + "defaultMessage": "{name} ({email})에 대한 초대를 삭제하시겠습니까?" + }, + "system.admin.instance.instance.InvitationActionButtons.deletionFailure": { + "defaultMessage": "사용자를 삭제하지 못했습니다 - {error}" + }, + "system.admin.instance.instance.InvitationActionButtons.deletionSuccess": { + "defaultMessage": "{name}의 초대가 삭제되었습니다." + }, + "system.admin.instance.instance.InvitationActionButtons.deletionTooltip": { + "defaultMessage": "초대 삭제" + }, + "system.admin.instance.instance.InvitationActionButtons.resendFailure": { + "defaultMessage": "초대를 다시 보내지 못했습니다 - {error}" + }, + "system.admin.instance.instance.InvitationActionButtons.resendSuccess": { + "defaultMessage": "{email}로 초대 이메일을 다시 보냈습니다!" + }, + "system.admin.instance.instance.InvitationActionButtons.resendTooltip": { + "defaultMessage": "초대 다시 보내기" + }, "system.admin.instance.instance.InvitationResultDialog.close": { "defaultMessage": "닫기" }, @@ -8804,27 +9353,6 @@ "system.admin.instance.instance.InvitationResultDialog.newInvitations": { "defaultMessage": "새 초대 ({count})" }, - "system.admin.instance.instance.InvitationActionButtons.deletionConfirm": { - "defaultMessage": "{name} ({email})에 대한 초대를 삭제하시겠습니까?" - }, - "system.admin.instance.instance.InvitationActionButtons.deletionFailure": { - "defaultMessage": "사용자를 삭제하지 못했습니다 - {error}" - }, - "system.admin.instance.instance.InvitationActionButtons.deletionSuccess": { - "defaultMessage": "{name}의 초대가 삭제되었습니다." - }, - "system.admin.instance.instance.InvitationActionButtons.deletionTooltip": { - "defaultMessage": "초대 삭제" - }, - "system.admin.instance.instance.InvitationActionButtons.resendFailure": { - "defaultMessage": "초대를 다시 보내지 못했습니다 - {error}" - }, - "system.admin.instance.instance.InvitationActionButtons.resendSuccess": { - "defaultMessage": "{email}로 초대 이메일을 다시 보냈습니다!" - }, - "system.admin.instance.instance.InvitationActionButtons.resendTooltip": { - "defaultMessage": "초대 다시 보내기" - }, "system.admin.instance.instance.PendingRoleRequestsButton.approveFailure": { "defaultMessage": "역할 요청을 승인하지 못했습니다 - {error}" }, @@ -8870,6 +9398,9 @@ "system.admin.instance.instance.UserInvitationsTable.accepted": { "defaultMessage": "수락됨" }, + "system.admin.instance.instance.UserInvitationsTable.confirmedTooltip": { + "defaultMessage": "{confirmedAt}에 수락됨" + }, "system.admin.instance.instance.UserInvitationsTable.failed": { "defaultMessage": "실패" }, @@ -8882,27 +9413,24 @@ "system.admin.instance.instance.UserInvitationsTable.sentTooltip": { "defaultMessage": "{sentAt}에 전송됨" }, - "system.admin.instance.instance.UserInvitationsTable.confirmedTooltip": { - "defaultMessage": "{confirmedAt}에 수락됨" - }, "system.admin.instance.instance.UsersButton.deleteTooltip": { "defaultMessage": "사용자 제거" }, "system.admin.instance.instance.UsersButton.deletionConfirm": { "defaultMessage": "정말로 계속하시겠습니까?" }, - "system.admin.instance.instance.UsersButton.deletionFailure": { - "defaultMessage": "사용자 제거에 실패했습니다 - {error}" - }, - "system.admin.instance.instance.UsersButton.deletionSuccess": { - "defaultMessage": "사용자가 이 인스턴스에서 제거되었습니다." - }, "system.admin.instance.instance.UsersButton.deletionConfirmTitle": { "defaultMessage": "{role} 사용자 {name} ({email}) 제거 중" }, + "system.admin.instance.instance.UsersButton.deletionFailure": { + "defaultMessage": "사용자 제거에 실패했습니다 - {error}" + }, "system.admin.instance.instance.UsersButton.deletionPromptContent": { "defaultMessage": "이 사용자를 제거하면 다음 {count, plural, one {과목} other {과목들}}에서 오류가 발생할 수 있습니다:" }, + "system.admin.instance.instance.UsersButton.deletionSuccess": { + "defaultMessage": "사용자가 이 인스턴스에서 제거되었습니다." + }, "system.admin.instance.instance.UsersTable.changeRoleSuccess": { "defaultMessage": "{name}의 역할이 {role}(으)로 성공적으로 변경되었습니다." }, @@ -8924,6 +9452,9 @@ "system.admin.users.UsersTable.fetchFilteredUsersFailure": { "defaultMessage": "사용자를 가져오지 못했습니다." }, + "system.admin.users.UsersTable.instanceEntry": { + "defaultMessage": "{instanceName}{courseCount, plural, =0 {} one { (1개 과목)} other { ({courseCount}개 과목)}}" + }, "user.accountSettings": { "defaultMessage": "계정 설정" }, diff --git a/client/locales/zh.json b/client/locales/zh.json index 9d5c753e3e..fa69b4eb5b 100644 --- a/client/locales/zh.json +++ b/client/locales/zh.json @@ -29,6 +29,9 @@ "app.DashboardPage.yourCourses": { "defaultMessage": "你的课程" }, + "app.ErrorPage.courseSuspended": { + "defaultMessage": "此课程已暂停。" + }, "app.ErrorPage.error": { "defaultMessage": "咔嘣,一颗流星刚刚坠毁" }, @@ -59,14 +62,11 @@ "app.ErrorPage.notFoundSubtitle": { "defaultMessage": "检查你输入的地址是否正确,请重试或者返回主页。" }, - "app.ErrorPage.userSuspended": { - "defaultMessage": "您访问此课程的权限已被暂停。" - }, "app.ErrorPage.suspendedSubtitle": { "defaultMessage": "请联系您的讲师或课程工作人员。" }, - "app.ErrorPage.courseSuspended": { - "defaultMessage": "此课程已暂停。" + "app.ErrorPage.userSuspended": { + "defaultMessage": "您访问此课程的权限已被暂停。" }, "app.Footer.contactUs": { "defaultMessage": "联系我们" @@ -80,12 +80,12 @@ "app.Footer.instructorsGuide": { "defaultMessage": "讲师使用指南" }, - "app.Footer.reportIssue": { - "defaultMessage": "报告问题" - }, "app.Footer.privacyPolicy": { "defaultMessage": "隐私政策" }, + "app.Footer.reportIssue": { + "defaultMessage": "报告问题" + }, "app.Footer.termsOfService": { "defaultMessage": "服务条款" }, @@ -263,23 +263,23 @@ "course.achievement.AchievementAward.AchievementAwardManager.saveChanges": { "defaultMessage": "保存更改" }, + "course.achievement.AchievementAward.AchievementAwardSummary.awardedStudents": { + "defaultMessage": "已授予学生" + }, "course.achievement.AchievementAward.AchievementAwardSummary.name": { "defaultMessage": "姓名" }, - "course.achievement.AchievementAward.AchievementAwardSummary.userType": { - "defaultMessage": "用户类型" + "course.achievement.AchievementAward.AchievementAwardSummary.normalStudent": { + "defaultMessage": "普通学生" }, - "course.achievement.AchievementAward.AchievementAwardSummary.awardedStudents": { - "defaultMessage": "已授予学生" + "course.achievement.AchievementAward.AchievementAwardSummary.phantomStudent": { + "defaultMessage": "旁听生" }, "course.achievement.AchievementAward.AchievementAwardSummary.revokedStudents": { "defaultMessage": "已撤销学生" }, - "course.achievement.AchievementAward.AchievementAwardSummary.phantomStudent": { - "defaultMessage": "旁听生" - }, - "course.achievement.AchievementAward.AchievementAwardSummary.normalStudent": { - "defaultMessage": "普通学生" + "course.achievement.AchievementAward.AchievementAwardSummary.userType": { + "defaultMessage": "用户类型" }, "course.achievement.AchievementAward.awardAchievement": { "defaultMessage": "获奖成就" @@ -353,26 +353,26 @@ "course.achievement.AchievementShow.studentsWithAchievement": { "defaultMessage": "有此成就的学生" }, - "course.achievement.AchievementTable.noAchievement": { - "defaultMessage": "暂无成就" + "course.achievement.AchievementTable.actions": { + "defaultMessage": "操作" }, "course.achievement.AchievementTable.badge": { "defaultMessage": "徽章" }, - "course.achievement.AchievementTable.title": { - "defaultMessage": "标题" - }, "course.achievement.AchievementTable.description": { "defaultMessage": "描述" }, - "course.achievement.AchievementTable.requirements": { - "defaultMessage": "要求" + "course.achievement.AchievementTable.noAchievement": { + "defaultMessage": "暂无成就" }, "course.achievement.AchievementTable.published": { "defaultMessage": "已发布" }, - "course.achievement.AchievementTable.actions": { - "defaultMessage": "操作" + "course.achievement.AchievementTable.requirements": { + "defaultMessage": "要求" + }, + "course.achievement.AchievementTable.title": { + "defaultMessage": "标题" }, "course.achievement.AchievementsIndex.achievements": { "defaultMessage": "成就" @@ -515,48 +515,9 @@ "course.admin.AssessmentSettings.toTab": { "defaultMessage": "到 {tab}" }, - "course.admin.CodaveriSettings.codaveriModel": { - "defaultMessage": "模型" - }, - "course.admin.CodaveriSettings.codaveriModelDescription": { - "defaultMessage": "Codaveri 使用的 AI 模型,用于为学生的编程问题生成帮助对话。" - }, - "course.admin.CodaveriSettings.codaveriSystemPromptDescription": { - "defaultMessage": "您可以在此提供指令以自定义 Codaveri 模型的行为。{br} 在帮助学生时,这些指令将与您在具体题目中设置的指令一并执行。{br}要引用题目相关的细节,您可以在提示中使用以下变量,并按照如下方式用括号写出:" - }, - "course.admin.CodaveriSettings.codaveriSystemPromptProblemDescriptionLine": { - "defaultMessage": "{problemDescriptionVar} :编程问题的完整描述。" - }, - "course.admin.CodaveriSettings.codaveriSystemPromptStudentFilePathsLine": { - "defaultMessage": "{studentFilePathsVar} :学生正在处理的文件路径(以逗号分隔)。" - }, - "course.admin.CodaveriSettings.codaveriSettingsSubtitle": { - "defaultMessage": "目前这是一项实验性功能。 Codaveri 为学生的代码提供代码测验和自动代码反馈服务。" - }, - "course.admin.CodaveriSettings.codaveriSettings": { - "defaultMessage": "Codaveri 设置" - }, - "course.admin.CodaveriSettings.error": { - "defaultMessage": "更新 codaveri 设置时出错。" - }, "course.admin.CodaveriSettings.Some": { "defaultMessage": "一些" }, - "course.admin.CodaveriSettings.feedbackWorkflow": { - "defaultMessage": "自动提交后评论" - }, - "course.admin.CodaveriSettings.feedbackWorkflowDescription": { - "defaultMessage": "当包含编程题目的提交被最终提交时," - }, - "course.admin.CodaveriSettings.feedbackWorkflowNone": { - "defaultMessage": "不生成反馈" - }, - "course.admin.CodaveriSettings.feedbackWorkflowDraft": { - "defaultMessage": "生成草稿反馈,需要工作人员批准" - }, - "course.admin.CodaveriSettings.feedbackWorkflowPublish": { - "defaultMessage": "直接向学生发布反馈" - }, "course.admin.CodaveriSettings.assessments": { "defaultMessage": "评估" }, @@ -569,32 +530,83 @@ "course.admin.CodaveriSettings.codaveriEngineDescription": { "defaultMessage": "用于生成编程代码反馈的 Codaveri 引擎类型" }, + "course.admin.CodaveriSettings.codaveriEvaluatorSettings": { + "defaultMessage": "Codaveri 评估器" + }, + "course.admin.CodaveriSettings.codaveriModel": { + "defaultMessage": "模型" + }, + "course.admin.CodaveriSettings.codaveriModelDescription": { + "defaultMessage": "Codaveri 使用的 AI 模型,用于为学生的编程问题生成帮助对话。" + }, "course.admin.CodaveriSettings.codaveriOverrideSystemPrompt": { "defaultMessage": "使用自定义系统提示" }, "course.admin.CodaveriSettings.codaveriOverrideSystemPromptDescription": { "defaultMessage": "在帮助学生时,这些指令将与您在题目本身设置的任何指令一起执行。要引用题目特定的详细信息,您可以在提示中使用这些变量,并按照如下所示用括号写出:" }, + "course.admin.CodaveriSettings.codaveriSettings": { + "defaultMessage": "Codaveri 设置" + }, + "course.admin.CodaveriSettings.codaveriSettingsSubtitle": { + "defaultMessage": "目前这是一项实验性功能。 Codaveri 为学生的代码提供代码测验和自动代码反馈服务。" + }, "course.admin.CodaveriSettings.codaveriSystemPrompt": { "defaultMessage": "系统提示" }, + "course.admin.CodaveriSettings.codaveriSystemPromptDescription": { + "defaultMessage": "您可以在此提供指令以自定义 Codaveri 模型的行为。{br} 在帮助学生时,这些指令将与您在具体题目中设置的指令一并执行。{br}要引用题目相关的细节,您可以在提示中使用以下变量,并按照如下方式用括号写出:" + }, + "course.admin.CodaveriSettings.codaveriSystemPromptProblemDescriptionLine": { + "defaultMessage": "{problemDescriptionVar} :编程问题的完整描述。" + }, + "course.admin.CodaveriSettings.codaveriSystemPromptStudentFilePathsLine": { + "defaultMessage": "{studentFilePathsVar} :学生正在处理的文件路径(以逗号分隔)。" + }, "course.admin.CodaveriSettings.codaveriUseDefaultSystemPrompt": { "defaultMessage": "使用默认系统提示" }, + "course.admin.CodaveriSettings.enableDisableButton": { + "defaultMessage": "{enabled, select, true {启用} other {禁用}}" + }, + "course.admin.CodaveriSettings.enableDisableEvaluator": { + "defaultMessage": "{enabled, select, true {启用} other {禁用}} Codaveri 评估器 对 {questionCount} 道编程题目在 {title} 中?" + }, + "course.admin.CodaveriSettings.enableDisableEvaluatorDescription": { + "defaultMessage": "这 {type} 中的 {questionCount} 道编程题目将使用 {enabled, select, true {Codaveri} other {默认}} 评估器" + }, + "course.admin.CodaveriSettings.enableDisableLiveFeedback": { + "defaultMessage": "{enabled, select, true {启用} other {禁用}} 实时帮助 对 {questionCount} 道编程题目在 {title} 中?" + }, + "course.admin.CodaveriSettings.error": { + "defaultMessage": "更新 codaveri 设置时出错。" + }, + "course.admin.CodaveriSettings.errorOccurredWhenUpdatingCodaveriEvaluatorSettings": { + "defaultMessage": "更新 Codaveri 评估器设置时发生了错误。" + }, + "course.admin.CodaveriSettings.errorOccurredWhenUpdatingLiveFeedbackSettings": { + "defaultMessage": "更新实时帮助设置时发生了错误。" + }, "course.admin.CodaveriSettings.evaluatorUpdateSuccess": { "defaultMessage": "{question} 现在使用 {evaluator} 评估器" }, "course.admin.CodaveriSettings.expandAll": { "defaultMessage": "展开所有问题" }, - "course.admin.CodaveriSettings.programmingQuestionSettings": { - "defaultMessage": "编程题目设置" + "course.admin.CodaveriSettings.feedbackWorkflow": { + "defaultMessage": "自动提交后评论" }, - "course.admin.CodaveriSettings.programmingQuestionSettingsSubtitle": { - "defaultMessage": "为各种评估中的编程题目启用/禁用 Codaveri 作为评估器。" + "course.admin.CodaveriSettings.feedbackWorkflowDescription": { + "defaultMessage": "当包含编程题目的提交被最终提交时," }, - "course.admin.CodaveriSettings.succesfulUpdateAllEvaluator": { - "defaultMessage": "成功更新所有问题以使用 {evaluator} 评估器" + "course.admin.CodaveriSettings.feedbackWorkflowDraft": { + "defaultMessage": "生成草稿反馈,需要工作人员批准" + }, + "course.admin.CodaveriSettings.feedbackWorkflowNone": { + "defaultMessage": "不生成反馈" + }, + "course.admin.CodaveriSettings.feedbackWorkflowPublish": { + "defaultMessage": "直接向学生发布反馈" }, "course.admin.CodaveriSettings.getHelpUsageLimit": { "defaultMessage": "限制每位学生的获取帮助消息数" @@ -602,35 +614,23 @@ "course.admin.CodaveriSettings.getHelpUsageLimitDescription": { "defaultMessage": "如果启用,学生将只能发送有限数量的消息。学生将能够看到此限制以及剩余的消息数量。" }, - "course.admin.CodaveriSettings.maxGetHelpUserMessages": { - "defaultMessage": "每个问题的最大消息数" - }, - "course.admin.CodaveriSettings.errorOccurredWhenUpdatingCodaveriEvaluatorSettings": { - "defaultMessage": "更新 Codaveri 评估器设置时发生了错误。" - }, - "course.admin.CodaveriSettings.codaveriEvaluatorSettings": { - "defaultMessage": "Codaveri 评估器" + "course.admin.CodaveriSettings.liveFeedbackEnabledUpdateSuccess": { + "defaultMessage": "对于 {question},实时帮助现在已 {liveFeedbackEnabled, select, true {启用} other {禁用}}" }, "course.admin.CodaveriSettings.liveFeedbackSettings": { "defaultMessage": "实时帮助" }, - "course.admin.CodaveriSettings.errorOccurredWhenUpdatingLiveFeedbackSettings": { - "defaultMessage": "更新实时帮助设置时发生了错误。" - }, - "course.admin.CodaveriSettings.enableDisableButton": { - "defaultMessage": "{enabled, select, true {启用} other {禁用}}" - }, - "course.admin.CodaveriSettings.enableDisableEvaluator": { - "defaultMessage": "{enabled, select, true {启用} other {禁用}} Codaveri 评估器 对 {questionCount} 道编程题目在 {title} 中?" + "course.admin.CodaveriSettings.maxGetHelpUserMessages": { + "defaultMessage": "每个问题的最大消息数" }, - "course.admin.CodaveriSettings.enableDisableLiveFeedback": { - "defaultMessage": "{enabled, select, true {启用} other {禁用}} 实时帮助 对 {questionCount} 道编程题目在 {title} 中?" + "course.admin.CodaveriSettings.programmingQuestionSettings": { + "defaultMessage": "编程题目设置" }, - "course.admin.CodaveriSettings.enableDisableEvaluatorDescription": { - "defaultMessage": "这 {type} 中的 {questionCount} 道编程题目将使用 {enabled, select, true {Codaveri} other {默认}} 评估器" + "course.admin.CodaveriSettings.programmingQuestionSettingsSubtitle": { + "defaultMessage": "为各种评估中的编程题目启用/禁用 Codaveri 作为评估器。" }, - "course.admin.CodaveriSettings.liveFeedbackEnabledUpdateSuccess": { - "defaultMessage": "对于 {question},实时帮助现在已 {liveFeedbackEnabled, select, true {启用} other {禁用}}" + "course.admin.CodaveriSettings.succesfulUpdateAllEvaluator": { + "defaultMessage": "成功更新所有问题以使用 {evaluator} 评估器" }, "course.admin.CodaveriSettings.successfulUpdateAllLiveFeedbackEnabled": { "defaultMessage": "成功地将所有问题的实时帮助设置为 {liveFeedbackEnabled, select, true {启用} other {禁用}}" @@ -677,6 +677,12 @@ "course.admin.CourseSettings.courseSettings": { "defaultMessage": "课程设置" }, + "course.admin.CourseSettings.courseSuspensionMessage": { + "defaultMessage": "课程暂停消息" + }, + "course.admin.CourseSettings.courseSuspensionMessageDescription": { + "defaultMessage": "此消息将在课程暂停期间显示给用户。留空以显示默认消息。" + }, "course.admin.CourseSettings.daysInAdvance": { "defaultMessage": "提前几天" }, @@ -764,23 +770,14 @@ "course.admin.CourseSettings.stragglersDescription": { "defaultMessage": "不让任何人掉队;如果学生延迟完成测验,随后的关闭参考时间将被推迟。" }, - "course.admin.CourseSettings.suspension": { - "defaultMessage": "访问暂停" - }, "course.admin.CourseSettings.suspendCourse": { "defaultMessage": "暂停课程" }, "course.admin.CourseSettings.suspendCourseDescription": { "defaultMessage": "被暂停的课程对所有学生不可访问。讲师仍可访问课程,所有学生数据将被保留。" }, - "course.admin.CourseSettings.unsuspendCourse": { - "defaultMessage": "解除课程暂停" - }, - "course.admin.CourseSettings.courseSuspensionMessage": { - "defaultMessage": "课程暂停消息" - }, - "course.admin.CourseSettings.courseSuspensionMessageDescription": { - "defaultMessage": "此消息将在课程暂停期间显示给用户。留空以显示默认消息。" + "course.admin.CourseSettings.suspendCourseFailure": { + "defaultMessage": "暂停课程时发生错误。" }, "course.admin.CourseSettings.suspendCoursePromptText": { "defaultMessage": "确定要暂停此课程吗?所有学生将无法访问,直到暂停被解除。" @@ -788,20 +785,8 @@ "course.admin.CourseSettings.suspendCourseSuccess": { "defaultMessage": "此课程已被暂停。" }, - "course.admin.CourseSettings.suspendCourseFailure": { - "defaultMessage": "暂停课程时发生错误。" - }, - "course.admin.CourseSettings.unsuspendCourseSuccess": { - "defaultMessage": "此课程的暂停已解除。" - }, - "course.admin.CourseSettings.unsuspendCourseFailure": { - "defaultMessage": "解除课程暂停时发生错误。" - }, - "course.admin.CourseSettings.userSuspensionMessage": { - "defaultMessage": "用户暂停消息" - }, - "course.admin.CourseSettings.userSuspensionMessageDescription": { - "defaultMessage": "此消息将显示给访问此课程的权限已被暂停的个别用户。留空以显示默认消息。" + "course.admin.CourseSettings.suspension": { + "defaultMessage": "访问暂停" }, "course.admin.CourseSettings.timeSettings": { "defaultMessage": "时间设置" @@ -812,12 +797,27 @@ "course.admin.CourseSettings.titleRequired": { "defaultMessage": "课程名称必填。" }, + "course.admin.CourseSettings.unsuspendCourse": { + "defaultMessage": "解除课程暂停" + }, + "course.admin.CourseSettings.unsuspendCourseFailure": { + "defaultMessage": "解除课程暂停时发生错误。" + }, + "course.admin.CourseSettings.unsuspendCourseSuccess": { + "defaultMessage": "此课程的暂停已解除。" + }, "course.admin.CourseSettings.uploadANewImage": { "defaultMessage": "选择新图片" }, "course.admin.CourseSettings.uploadingLogo": { "defaultMessage": "正在上传你的新Logo..." }, + "course.admin.CourseSettings.userSuspensionMessage": { + "defaultMessage": "用户暂停消息" + }, + "course.admin.CourseSettings.userSuspensionMessageDescription": { + "defaultMessage": "此消息将显示给访问此课程的权限已被暂停的个别用户。留空以显示默认消息。" + }, "course.admin.CourseSettingst.confirmDeletePlaceholder": { "defaultMessage": "这是你撤消的最后机会!" }, @@ -872,6 +872,15 @@ "course.admin.ForumsSettings.markPostAsAnswerSetting": { "defaultMessage": "可以将帖子标作答案的用户" }, + "course.admin.GradebookSettings.gradebookSettings": { + "defaultMessage": "成绩册设置" + }, + "course.admin.GradebookSettings.weightedViewEnabled": { + "defaultMessage": "启用加权成绩视图" + }, + "course.admin.GradebookSettings.weightedViewEnabledHint": { + "defaultMessage": "在成绩册中启用“加权总成绩”视图,教职员可以配置各标签页的权重并查看加权总成绩列。" + }, "course.admin.LeaderboardSettings.displayUserCount": { "defaultMessage": "显示用户数" }, @@ -941,6 +950,9 @@ "course.admin.MaterialSettings.materialsSettings": { "defaultMessage": "资料设置" }, + "course.admin.NotificationSettings.component": { + "defaultMessage": "组件" + }, "course.admin.NotificationSettings.description": { "defaultMessage": "描述" }, @@ -1388,12 +1400,12 @@ "course.assessment.AssessmentForm.showMcqMrqSolution": { "defaultMessage": "显示 单选题/多选题 解决方案" }, - "course.assessment.AssessmentForm.showRubricToStudents": { - "defaultMessage": "向学生显示评分细则" - }, "course.assessment.AssessmentForm.showPrivate": { "defaultMessage": "显示私有测试用例" }, + "course.assessment.AssessmentForm.showRubricToStudents": { + "defaultMessage": "向学生显示评分细则" + }, "course.assessment.AssessmentForm.singlePage": { "defaultMessage": "单页" }, @@ -1496,8 +1508,23 @@ "course.assessment.edit.update": { "defaultMessage": "保存" }, - "course.assessment.generation.confirmDeleteConversation": { - "defaultMessage": "您确定要删除 \"{title}\" 及其所有历史记录吗?此操作不可撤销!" + "course.assessment.generation.allFieldsLocked": { + "defaultMessage": "所有字段都已锁定,无法生成内容。" + }, + "course.assessment.generation.confirmDeleteConversation": { + "defaultMessage": "您确定要删除 \"{title}\" 及其所有历史记录吗?此操作不可撤销!" + }, + "course.assessment.generation.createMode": { + "defaultMessage": "新建" + }, + "course.assessment.generation.createModeTooltip": { + "defaultMessage": "从头生成新的问题" + }, + "course.assessment.generation.enhanceMode": { + "defaultMessage": "增强" + }, + "course.assessment.generation.enhanceModeTooltip": { + "defaultMessage": "在当前问题的基础上进行构建" }, "course.assessment.generation.exportAction": { "defaultMessage": "导出" @@ -1508,89 +1535,77 @@ "course.assessment.generation.exportError": { "defaultMessage": "导出此问题时发生错误:{error}" }, - "course.assessment.generation.lockTooltip": { - "defaultMessage": "锁定以防止更改此部分" + "course.assessment.generation.generateError": { + "defaultMessage": "生成题目 {title} 时发生错误。" }, - "course.assessment.generation.newTab": { - "defaultMessage": "新建" + "course.assessment.generation.generateMcqPage": { + "defaultMessage": "生成单选题" }, - "course.assessment.generation.openExportDialog": { - "defaultMessage": "导出" + "course.assessment.generation.generateMrqPage": { + "defaultMessage": "生成多选题" }, - "course.assessment.generation.resetConversation": { - "defaultMessage": "重置" + "course.assessment.generation.generateMultipleSuccess": { + "defaultMessage": "成功生成了 {count} 道题目!" }, - "course.assessment.generation.unlockTooltip": { - "defaultMessage": "解锁以继续编辑此部分" + "course.assessment.generation.generateQuestion": { + "defaultMessage": "生成" }, - "course.assessment.generation.mrq.numberOfQuestionsField": { - "defaultMessage": "题目数量" + "course.assessment.generation.generateSuccess": { + "defaultMessage": "{title} 生成成功。" }, - "course.assessment.generation.promptPlaceholder": { - "defaultMessage": "请输入内容..." + "course.assessment.generation.loadingSourceError": { + "defaultMessage": "无法加载原始题目信息。" }, - "course.assessment.generation.generateQuestion": { - "defaultMessage": "生成" + "course.assessment.generation.lockTooltip": { + "defaultMessage": "锁定以防止更改此部分" }, - "course.assessment.generation.showInactive": { - "defaultMessage": "显示未启用项" + "course.assessment.generation.mrq.exportDialogHeader": { + "defaultMessage": "导出题目(已选择 {exportCount} 项)" + }, + "course.assessment.generation.mrq.numberOfQuestionsField": { + "defaultMessage": "题目数量" }, "course.assessment.generation.mrq.numberOfQuestionsRange": { "defaultMessage": "请输入 {min} 到 {max} 之间的数字" }, - "course.assessment.generation.enhanceMode": { - "defaultMessage": "增强" - }, - "course.assessment.generation.createMode": { + "course.assessment.generation.newTab": { "defaultMessage": "新建" }, - "course.assessment.generation.enhanceModeTooltip": { - "defaultMessage": "在当前问题的基础上进行构建" - }, - "course.assessment.generation.createModeTooltip": { - "defaultMessage": "从头生成新的问题" + "course.assessment.generation.openExportDialog": { + "defaultMessage": "导出" }, - "course.assessment.generation.mrq.exportDialogHeader": { - "defaultMessage": "导出题目(已选择 {exportCount} 项)" + "course.assessment.generation.promptPlaceholder": { + "defaultMessage": "请输入内容..." }, "course.assessment.generation.requireNonEmptyOptionError": { "defaultMessage": "题目必须至少包含一个非空选项" }, - "course.assessment.generation.untitledQuestion": { - "defaultMessage": "无标题题目" - }, - "course.assessment.question.multipleResponses.showOptions": { - "defaultMessage": "显示选项" - }, - "course.assessment.question.multipleResponses.hideOptions": { - "defaultMessage": "隐藏选项" - }, - "course.assessment.question.multipleResponses.noOptions": { - "defaultMessage": "无选项" + "course.assessment.generation.resetConversation": { + "defaultMessage": "重置" }, - "course.assessment.question.multipleResponses.title": { - "defaultMessage": "标题" + "course.assessment.generation.showInactive": { + "defaultMessage": "显示未启用项" }, - "course.assessment.generation.generateMrqPage": { - "defaultMessage": "生成多选题" + "course.assessment.generation.unlockTooltip": { + "defaultMessage": "解锁以继续编辑此部分" }, - "course.assessment.generation.generateMcqPage": { - "defaultMessage": "生成单选题" + "course.assessment.generation.untitledQuestion": { + "defaultMessage": "无标题题目" }, - "course.assessment.generation.generateMultipleSuccess": { - "defaultMessage": "成功生成了 {count} 道题目!" + "course.assessment.liveFeedback.comments": { + "defaultMessage": "评论" }, - "course.assessment.generation.generateSuccess": { - "defaultMessage": "{title} 生成成功。" + "course.assessment.liveFeedback.lineHeader": { + "defaultMessage": "第 {lineNumber} 行" }, - "course.assessment.generation.generateError": { - "defaultMessage": "生成题目 {title} 时发生错误。" + "course.assessment.liveFeedback.liveFeedbackName": { + "defaultMessage": "实时反馈" }, - "course.assessment.generation.loadingSourceError": { - "defaultMessage": "无法加载原始题目信息。" + "course.assessment.liveFeedback.messageTimingTitle": { + "defaultMessage": "生成时间:{usedAt}" }, - "course.assessment.generation.allFieldsLocked": { - "defaultMessage": "所有字段都已锁定,无法生成内容。" + "course.assessment.liveFeedback.questionTitle": { + "defaultMessage": "题目 {index}" }, "course.assessment.monitoring.alivePresenceHint": { "defaultMessage": "及时收到最后一次心跳" @@ -1673,6 +1688,54 @@ "course.assessment.newAssessment": { "defaultMessage": "新测验" }, + "course.assessment.plagiarism.actions": { + "defaultMessage": "操作" + }, + "course.assessment.plagiarism.baseSubmission": { + "defaultMessage": "基准提交" + }, + "course.assessment.plagiarism.comparedSubmission": { + "defaultMessage": "比较提交" + }, + "course.assessment.plagiarism.confirmStartMessage": { + "defaultMessage": "运行新的抄袭检查将删除之前的结果。" + }, + "course.assessment.plagiarism.confirmStartTitle": { + "defaultMessage": "确认抄袭检查?" + }, + "course.assessment.plagiarism.downloadPdf": { + "defaultMessage": "下载 PDF" + }, + "course.assessment.plagiarism.lastRunTime": { + "defaultMessage": "上次运行时间:{date}" + }, + "course.assessment.plagiarism.notStarted": { + "defaultMessage": "尚未运行抄袭检查" + }, + "course.assessment.plagiarism.plagiarism": { + "defaultMessage": "抄袭结果" + }, + "course.assessment.plagiarism.results": { + "defaultMessage": "抄袭结果(提交之间的相似度)" + }, + "course.assessment.plagiarism.searchByStudentName": { + "defaultMessage": "按学生姓名搜索" + }, + "course.assessment.plagiarism.showSelfPlagiarism": { + "defaultMessage": "包含自我抄袭比较(同一学生,不同课程)" + }, + "course.assessment.plagiarism.similarityScore": { + "defaultMessage": "相似性分数" + }, + "course.assessment.plagiarism.start": { + "defaultMessage": "新的抄袭检查" + }, + "course.assessment.plagiarism.status": { + "defaultMessage": "抄袭检查状态" + }, + "course.assessment.plagiarism.viewReport": { + "defaultMessage": "查看报告" + }, "course.assessment.question.forumPostResponses.enableTextResponse": { "defaultMessage": "包括一个文本字段,供学生进一步输入信息" }, @@ -1745,6 +1808,9 @@ "course.assessment.question.multipleResponses.grading": { "defaultMessage": "评分" }, + "course.assessment.question.multipleResponses.hideOptions": { + "defaultMessage": "隐藏选项" + }, "course.assessment.question.multipleResponses.ignoresRandomization": { "defaultMessage": "忽略随机" }, @@ -1781,6 +1847,9 @@ "course.assessment.question.multipleResponses.newResponseCannotUndo": { "defaultMessage": "这是一个新选项。如果在保存前删除,它会立即消失。" }, + "course.assessment.question.multipleResponses.noOptions": { + "defaultMessage": "无选项" + }, "course.assessment.question.multipleResponses.noSkillsCanCreateSkills": { "defaultMessage": "本课程中还没有设置技能,你可以在 技能 页面中创建。" }, @@ -1817,6 +1886,9 @@ "course.assessment.question.multipleResponses.saveChangesFirstBeforeConvertingMcqMrq": { "defaultMessage": "尝试转换此问题类型前,请先保存更改。" }, + "course.assessment.question.multipleResponses.showOptions": { + "defaultMessage": "显示选项" + }, "course.assessment.question.multipleResponses.skills": { "defaultMessage": "技能" }, @@ -1829,6 +1901,9 @@ "course.assessment.question.multipleResponses.staffOnlyCommentsHint": { "defaultMessage": "适用于内部笔记或文档,对学生不可见。" }, + "course.assessment.question.multipleResponses.title": { + "defaultMessage": "标题" + }, "course.assessment.question.multipleResponses.undoDeleteChoice": { "defaultMessage": "撤销删除选择" }, @@ -1904,12 +1979,12 @@ "course.assessment.question.programming.defaultEvaluator": { "defaultMessage": "默认" }, - "course.assessment.question.programming.defaultEvaluatorDependencyTitle": { - "defaultMessage": "{name}: 已安装的依赖项" - }, "course.assessment.question.programming.defaultEvaluatorDependencyDescription": { "defaultMessage": "提交的代码将在一个容器化环境中运行,并且以下依赖项已本地安装。{br}如果您的编程问题需要未列出的依赖项,请联系我们,我们将考虑添加它。" }, + "course.assessment.question.programming.defaultEvaluatorDependencyTitle": { + "defaultMessage": "{name}: 已安装的依赖项" + }, "course.assessment.question.programming.defaultEvaluatorHint": { "defaultMessage": "无额外操作,只需按照下面的包运行代码,并报告测试结果即可。" }, @@ -2042,24 +2117,24 @@ "course.assessment.question.programming.packageCreationModeHint": { "defaultMessage": "一旦成功创建此问题,无法更改此模式,请谨慎选择。" }, - "course.assessment.question.programming.packageImportSuccess": { - "defaultMessage": "包已被正确引入。" + "course.assessment.question.programming.packageImportEvaluationError": { + "defaultMessage": "评估您的解决方案时发生错误。请仔细检查测试用例并重试。" + }, + "course.assessment.question.programming.packageImportEvaluationTimeout": { + "defaultMessage": "在规定时间内未收到评估器的响应。这可能表示所有评估器当前都很忙,请稍后再试。" + }, + "course.assessment.question.programming.packageImportGenericError": { + "defaultMessage": "无法导入软件包:{error}" }, "course.assessment.question.programming.packageImportInvalidPackage": { "defaultMessage": "无法导入软件包:上传的软件包结构无效。" }, - "course.assessment.question.programming.packageImportEvaluationTimeout": { - "defaultMessage": "在规定时间内未收到评估器的响应。这可能表示所有评估器当前都很忙,请稍后再试。" + "course.assessment.question.programming.packageImportSuccess": { + "defaultMessage": "包已被正确引入。" }, "course.assessment.question.programming.packageImportTimeLimitExceeded": { "defaultMessage": "解决方案未能在规定时间内完成测试用例的评估。" }, - "course.assessment.question.programming.packageImportEvaluationError": { - "defaultMessage": "评估您的解决方案时发生错误。请仔细检查测试用例并重试。" - }, - "course.assessment.question.programming.packageImportGenericError": { - "defaultMessage": "无法导入软件包:{error}" - }, "course.assessment.question.programming.packageInfoOnline": { "defaultMessage": "生成评估包" }, @@ -2162,359 +2237,359 @@ "course.assessment.question.programminquestion.questionSavedRedirecting": { "defaultMessage": "问题已保存" }, - "course.assessment.question.scribing.ScribingQuestionForm.cannotBeBlankValidationError": { - "defaultMessage": "不能留空。" + "course.assessment.question.rubricPlayground.add": { + "defaultMessage": "添加" }, - "course.assessment.question.scribing.ScribingQuestionForm.chooseFileButton": { - "defaultMessage": "选择文件" + "course.assessment.question.rubricPlayground.addExistingAnswers": { + "defaultMessage": "添加现有答案" }, - "course.assessment.question.scribing.ScribingQuestionForm.descriptionFieldLabel": { - "defaultMessage": "描述" + "course.assessment.question.rubricPlayground.addNewCategory": { + "defaultMessage": "添加新类别" }, - "course.assessment.question.scribing.ScribingQuestionForm.fetchFailureMessage": { - "defaultMessage": "发生错误,请重试。" + "course.assessment.question.rubricPlayground.addNewGrade": { + "defaultMessage": "添加新分数" }, - "course.assessment.question.scribing.ScribingQuestionForm.fileAttachmentRequired": { - "defaultMessage": "需要文件附件。" + "course.assessment.question.rubricPlayground.addRandomStudentAnswers": { + "defaultMessage": "添加 {inputComponent} 个随机学生答案" }, - "course.assessment.question.scribing.ScribingQuestionForm.fileUploaded": { - "defaultMessage": "已上传文件:" + "course.assessment.question.rubricPlayground.addSampleAnswers": { + "defaultMessage": "添加示例答案" }, - "course.assessment.question.scribing.ScribingQuestionForm.lessThanEqualZeroValidationError": { - "defaultMessage": "值必须大于 0。" + "course.assessment.question.rubricPlayground.addSampleAnswersTitle": { + "defaultMessage": "添加示例答案" }, - "course.assessment.question.scribing.ScribingQuestionForm.maximumGradeFieldLabel": { - "defaultMessage": "最高等级" + "course.assessment.question.rubricPlayground.answer": { + "defaultMessage": "答案" }, - "course.assessment.question.scribing.ScribingQuestionForm.noFileChosenMessage": { - "defaultMessage": "没有选中任何文件" + "course.assessment.question.rubricPlayground.apply": { + "defaultMessage": "应用" }, - "course.assessment.question.scribing.ScribingQuestionForm.positiveNumberValidationError": { - "defaultMessage": "必须为正值。" + "course.assessment.question.rubricPlayground.applyFailure": { + "defaultMessage": "应用评分结果失败" }, - "course.assessment.question.scribing.ScribingQuestionForm.resolveErrorsMessage": { - "defaultMessage": "此表单有错误,请在提交前解决。" + "course.assessment.question.rubricPlayground.applySuccess": { + "defaultMessage": "评分标准、提示和结果已成功应用。" }, - "course.assessment.question.scribing.ScribingQuestionForm.scribingQuestionWarning": { - "defaultMessage": "注意:PDF 文件的每一页都将创建为单个 Scribing 问题,每个问题都采用相同的问题详细信息。你可以选择将可选输入留空并在创建后返回再次编辑问题。" + "course.assessment.question.rubricPlayground.applyWillGradeAllAnswers": { + "defaultMessage": "应用此评分标准将为所有学生答案分配成绩,包括此页面上尚未评估的答案。" }, - "course.assessment.question.scribing.ScribingQuestionForm.skillsFieldLabel": { - "defaultMessage": "技能" + "course.assessment.question.rubricPlayground.applyingRubricGradingData": { + "defaultMessage": "正在应用评分标准数据..." }, - "course.assessment.question.scribing.ScribingQuestionForm.staffOnlyCommentsFieldLabel": { - "defaultMessage": "仅限工作人员评论" + "course.assessment.question.rubricPlayground.categoryHeading": { + "defaultMessage": "类{index}" }, - "course.assessment.question.scribing.ScribingQuestionForm.submitButton": { - "defaultMessage": "提交" + "course.assessment.question.rubricPlayground.categoryName": { + "defaultMessage": "类别名称" }, - "course.assessment.question.scribing.ScribingQuestionForm.submitFailureMessage": { - "defaultMessage": "发生错误,请重试。" + "course.assessment.question.rubricPlayground.compare": { + "defaultMessage": "比较" }, - "course.assessment.question.scribing.ScribingQuestionForm.submittingMessage": { - "defaultMessage": "提交中..." + "course.assessment.question.rubricPlayground.comparingRevisions": { + "defaultMessage": "正在比较 {count} 个版本" }, - "course.assessment.question.scribing.ScribingQuestionForm.titleFieldLabel": { - "defaultMessage": "标题" + "course.assessment.question.rubricPlayground.confirmAIGradingApplication": { + "defaultMessage": "确认应用AI评分" }, - "course.assessment.question.scribing.ScribingQuestionForm.valueMoreThan1000Error": { - "defaultMessage": "值必须小于 1000。" + "course.assessment.question.rubricPlayground.confirmProceed": { + "defaultMessage": "您确定要继续吗?" }, - "course.assessment.question.textResponses.addSolution": { - "defaultMessage": "添加一个新答案" + "course.assessment.question.rubricPlayground.dismiss": { + "defaultMessage": "关闭" }, - "course.assessment.question.textResponses.allowFileUpload": { - "defaultMessage": "允许在回答中上传文件" + "course.assessment.question.rubricPlayground.evaluate": { + "defaultMessage": "评估" }, - "course.assessment.question.textResponses.deleteSolution": { - "defaultMessage": "删除答案" + "course.assessment.question.rubricPlayground.evaluateAll": { + "defaultMessage": "全部评估 ({count})" }, - "course.assessment.question.textResponses.exactMatch": { - "defaultMessage": "精确匹配" + "course.assessment.question.rubricPlayground.evaluateRemaining": { + "defaultMessage": "评估剩余 ({count})" }, - "course.assessment.question.textResponses.fileUploadNote": { - "defaultMessage": "注意:无法自动评分文件上传题,将始终给出最高分。" + "course.assessment.question.rubricPlayground.evaluating": { + "defaultMessage": "评估中" }, - "course.assessment.question.textResponses.noSolutionsNote": { - "defaultMessage": "如果没有提供答案,自动打分器将始终给出最高分。" + "course.assessment.question.rubricPlayground.feedback": { + "defaultMessage": "反馈" }, - "course.assessment.question.textResponses.atLeastOneSolutionNote": { - "defaultMessage": "如果提供了至少一个答案,学生只能输入纯文本。" + "course.assessment.question.rubricPlayground.gradingCategories": { + "defaultMessage": "评分类别" }, - "course.assessment.question.textResponses.exactMatchSolutionNote": { - "defaultMessage": "如果选择\"精确匹配\",多行答案必须与学生答案完全匹配,才能被评为正确。如果找到匹配,自动打分器将给出指定分数,不再考虑其他答案。" + "course.assessment.question.rubricPlayground.gradingPrompt": { + "defaultMessage": "评分提示" }, - "course.assessment.question.textResponses.solutionGradesExceedMaximumGradeNote": { - "defaultMessage": "如果学生答案满足多个答案条件,自动打分器将给出这些答案分数的总和,最高不超过题目的最高分。" + "course.assessment.question.rubricPlayground.gradingPromptDescription": { + "defaultMessage": "指导AI进行评分和提供反馈的说明。" }, - "course.assessment.question.textResponses.grade": { - "defaultMessage": "得分" + "course.assessment.question.rubricPlayground.max": { + "defaultMessage": "最大值" }, - "course.assessment.question.textResponses.keyword": { - "defaultMessage": "关键词" + "course.assessment.question.rubricPlayground.modelAnswer": { + "defaultMessage": "标准答案" }, - "course.assessment.question.textResponses.newSolutionCannotUndo": { - "defaultMessage": "这是一个新答案。如果在保存前删除,它会立即消失。" + "course.assessment.question.rubricPlayground.modelAnswerDescription": { + "defaultMessage": "每个类别获得最高分的示例。" }, - "course.assessment.question.textResponses.solution": { - "defaultMessage": "答案" + "course.assessment.question.rubricPlayground.noAnswers": { + "defaultMessage": "尚未添加示例答案。添加一些以开始。" }, - "course.assessment.question.textResponses.solutionType": { - "defaultMessage": "答案类型" + "course.assessment.question.rubricPlayground.notLatestRevisionWarning": { + "defaultMessage": "您选择应用的评分标准不是此页面上保存的最新版本。" }, - "course.assessment.question.textResponses.solutionWillBeDeleted": { - "defaultMessage": "保存更改后,该答案将被删除。" + "course.assessment.question.rubricPlayground.questionGrade": { + "defaultMessage": "成绩" }, - "course.assessment.question.textResponses.solutions": { - "defaultMessage": "答案" + "course.assessment.question.rubricPlayground.reevaluate": { + "defaultMessage": "重新评估" }, - "course.assessment.question.textResponses.solutionsHint": { - "defaultMessage": "添加答案以启用自动打分。" + "course.assessment.question.rubricPlayground.reevaluateAll": { + "defaultMessage": "全部重新评估 ({count})" }, - "course.assessment.question.textResponses.undoDeleteSolution": { - "defaultMessage": "撤销删除答案" + "course.assessment.question.rubricPlayground.rubricPlayground": { + "defaultMessage": "评分标准试验场" }, - "course.assessment.question.textResponses.zeroGrade": { - "defaultMessage": "0.0" + "course.assessment.question.rubricPlayground.sampleAnswerEvaluations": { + "defaultMessage": "示例答案评估" }, - "course.assessment.question.textResponses.templateText": { - "defaultMessage": "模版" + "course.assessment.question.rubricPlayground.savedRubric": { + "defaultMessage": "已保存的评分标准,{date}" }, - "course.assessment.question.textResponses.templateTextDescription": { - "defaultMessage": "学生第一次尝试此题时,答题区域中出现的文字。" + "course.assessment.question.rubricPlayground.searchAnswersPlaceholder": { + "defaultMessage": "按学生姓名或成绩搜索答案" }, - "course.assessment.question.textResponses.regex": { - "defaultMessage": "正则表达式" + "course.assessment.question.rubricPlayground.student": { + "defaultMessage": "学生" }, - "course.assessment.question.textResponses.invalidRegex": { - "defaultMessage": "无效的正则表达式" + "course.assessment.question.rubricPlayground.totalGrade": { + "defaultMessage": "总分" }, - "course.assessment.question.textResponses.spreadsheetFormula": { - "defaultMessage": "电子表格公式" + "course.assessment.question.rubricPlayground.viewEditRubric": { + "defaultMessage": "查看 / 编辑评分标准" }, - "course.assessment.question.textResponses.testSpreadsheet": { - "defaultMessage": "测试电子表格" + "course.assessment.question.rubricPlayground.writeAnswerPlaceholder": { + "defaultMessage": "在此处编写答案" }, - "course.assessment.question.textResponses.testSpreadsheetDescription": { - "defaultMessage": "需要上传测试电子表格以自动评分学生答案。" + "course.assessment.question.rubricPlayground.writeCustomAnswer": { + "defaultMessage": "编写自定义答案" }, - "course.assessment.question.textResponses.testSpreadsheetRequired": { - "defaultMessage": "请上传测试电子表格文件。" + "course.assessment.question.scribing.ScribingQuestionForm.cannotBeBlankValidationError": { + "defaultMessage": "不能留空。" }, - "course.assessment.question.textResponses.spreadsheetAdvancedOptions": { - "defaultMessage": "高级选项" + "course.assessment.question.scribing.ScribingQuestionForm.chooseFileButton": { + "defaultMessage": "选择文件" }, - "course.assessment.question.textResponses.spreadsheetRandomization": { - "defaultMessage": "启用随机化" + "course.assessment.question.scribing.ScribingQuestionForm.descriptionFieldLabel": { + "defaultMessage": "描述" }, - "course.assessment.question.textResponses.spreadsheetRandomizationDescription": { - "defaultMessage": "启用后,自动评分时将随机调整部分电子表格数值。这有助于确保公式确实计算出正确答案,而不是预设值。" + "course.assessment.question.scribing.ScribingQuestionForm.fetchFailureMessage": { + "defaultMessage": "发生错误,请重试。" }, - "course.assessment.question.textResponses.numberOfRandomTests": { - "defaultMessage": "随机测试次数" + "course.assessment.question.scribing.ScribingQuestionForm.fileAttachmentRequired": { + "defaultMessage": "需要文件附件。" }, - "course.assessment.question.textResponses.SpreadsheetManager.fixedRandomSeed": { - "defaultMessage": "固定随机种子" + "course.assessment.question.scribing.ScribingQuestionForm.fileUploaded": { + "defaultMessage": "已上传文件:" }, - "course.assessment.question.textResponses.SpreadsheetManager.fixedRandomSeedDescription": { - "defaultMessage": "勾选后,随机化将每次产生相同结果。这会影响电子表格数值随机化和电子表格中的随机函数(RAND、RANDBETWEEN 等)。" + "course.assessment.question.scribing.ScribingQuestionForm.lessThanEqualZeroValidationError": { + "defaultMessage": "值必须大于 0。" }, - "course.assessment.question.textResponses.SpreadsheetManager.fixedTimestamp": { - "defaultMessage": "固定日期和时间" + "course.assessment.question.scribing.ScribingQuestionForm.maximumGradeFieldLabel": { + "defaultMessage": "最高等级" }, - "course.assessment.question.textResponses.SpreadsheetManager.fixedTimestampDescription": { - "defaultMessage": "勾选后,使用当前日期/时间的公式(NOW、TODAY 等)将改用此特定日期/时间。" + "course.assessment.question.scribing.ScribingQuestionForm.noFileChosenMessage": { + "defaultMessage": "没有选中任何文件" }, - "course.assessment.question.textResponses.randomizationMode": { - "defaultMessage": "自动评分值配置" + "course.assessment.question.scribing.ScribingQuestionForm.positiveNumberValidationError": { + "defaultMessage": "必须为正值。" }, - "course.assessment.question.textResponses.randomizationModeDescription": { - "defaultMessage": "点击任意单元格以配置在自动评分时如何替换或随机化其值。" + "course.assessment.question.scribing.ScribingQuestionForm.resolveErrorsMessage": { + "defaultMessage": "此表单有错误,请在提交前解决。" }, - "course.assessment.question.textResponses.randomizationModeClearAll": { - "defaultMessage": "全部清除" + "course.assessment.question.scribing.ScribingQuestionForm.scribingQuestionWarning": { + "defaultMessage": "注意:PDF 文件的每一页都将创建为单个 Scribing 问题,每个问题都采用相同的问题详细信息。你可以选择将可选输入留空并在创建后返回再次编辑问题。" }, - "course.assessment.question.textResponses.randomizationModeRestoreDefaults": { - "defaultMessage": "恢复默认值" + "course.assessment.question.scribing.ScribingQuestionForm.skillsFieldLabel": { + "defaultMessage": "技能" }, - "course.assessment.question.textResponses.randomizationModePopoverTitle": { - "defaultMessage": "在自动评分时..." + "course.assessment.question.scribing.ScribingQuestionForm.staffOnlyCommentsFieldLabel": { + "defaultMessage": "仅限工作人员评论" }, - "course.assessment.question.textResponses.noRandomizationMode": { - "defaultMessage": "保留原始值" + "course.assessment.question.scribing.ScribingQuestionForm.submitButton": { + "defaultMessage": "提交" }, - "course.assessment.question.textResponses.overrideRandomizationMode": { - "defaultMessage": "覆盖为指定值" + "course.assessment.question.scribing.ScribingQuestionForm.submitFailureMessage": { + "defaultMessage": "发生错误,请重试。" }, - "course.assessment.question.textResponses.overrideRandomizationModeDescription": { - "defaultMessage": "以\"=\"开头的值将被视为公式。" + "course.assessment.question.scribing.ScribingQuestionForm.submittingMessage": { + "defaultMessage": "提交中..." }, - "course.assessment.question.textResponses.overrideValue": { - "defaultMessage": "值" + "course.assessment.question.scribing.ScribingQuestionForm.titleFieldLabel": { + "defaultMessage": "标题" }, - "course.assessment.question.textResponses.numericRandomizationMode": { - "defaultMessage": "使用随机数值" + "course.assessment.question.scribing.ScribingQuestionForm.valueMoreThan1000Error": { + "defaultMessage": "值必须小于 1000。" }, - "course.assessment.question.textResponses.roundToInteger": { - "defaultMessage": "取整到整数" + "course.assessment.question.textResponses.SpreadsheetManager.fixedRandomSeed": { + "defaultMessage": "固定随机种子" }, - "course.assessment.question.textResponses.stringRandomizationMode": { - "defaultMessage": "随机化值中的字符" + "course.assessment.question.textResponses.SpreadsheetManager.fixedRandomSeedDescription": { + "defaultMessage": "勾选后,随机化将每次产生相同结果。这会影响电子表格数值随机化和电子表格中的随机函数(RAND、RANDBETWEEN 等)。" }, - "course.assessment.question.textResponses.stringRandomizationModeDescription": { - "defaultMessage": "要随机化的每个字符类可以用同一类中的不同字符替换。" + "course.assessment.question.textResponses.SpreadsheetManager.fixedTimestamp": { + "defaultMessage": "固定日期和时间" }, - "course.assessment.question.textResponses.randomizeDigits": { - "defaultMessage": "随机化数字 (0-9)" + "course.assessment.question.textResponses.SpreadsheetManager.fixedTimestampDescription": { + "defaultMessage": "勾选后,使用当前日期/时间的公式(NOW、TODAY 等)将改用此特定日期/时间。" }, - "course.assessment.question.textResponses.randomizeLetters": { - "defaultMessage": "随机化字母 (a-z)" + "course.assessment.question.textResponses.addSolution": { + "defaultMessage": "添加一个新答案" + }, + "course.assessment.question.textResponses.allowFileUpload": { + "defaultMessage": "允许在回答中上传文件" + }, + "course.assessment.question.textResponses.atLeastOneSolutionNote": { + "defaultMessage": "如果提供了至少一个答案,学生只能输入纯文本。" }, "course.assessment.question.textResponses.dateRandomizationMode": { "defaultMessage": "使用随机日期值" }, - "course.assessment.question.textResponses.roundToDay": { - "defaultMessage": "向下取整到整天 (00:00 UTC)" - }, - "course.assessment.question.textResponses.shuffleRandomizationMode": { - "defaultMessage": "与其他单元格随机排列值" + "course.assessment.question.textResponses.deleteSolution": { + "defaultMessage": "删除答案" }, - "course.assessment.question.textResponses.shuffleRandomizationModeDescription": { - "defaultMessage": "每个标记为\"随机排列\"的单元格值将被随机重新分配。总体分布保持不变,但每个值可能出现在不同的单元格中。" + "course.assessment.question.textResponses.exactMatch": { + "defaultMessage": "精确匹配" }, - "course.assessment.question.rubricPlayground.rubricPlayground": { - "defaultMessage": "评分标准试验场" + "course.assessment.question.textResponses.exactMatchSolutionNote": { + "defaultMessage": "如果选择\"精确匹配\",多行答案必须与学生答案完全匹配,才能被评为正确。如果找到匹配,自动打分器将给出指定分数,不再考虑其他答案。" }, - "course.assessment.question.rubricPlayground.savedRubric": { - "defaultMessage": "已保存的评分标准,{date}" + "course.assessment.question.textResponses.fileUploadNote": { + "defaultMessage": "注意:无法自动评分文件上传题,将始终给出最高分。" }, - "course.assessment.question.rubricPlayground.viewEditRubric": { - "defaultMessage": "查看 / 编辑评分标准" + "course.assessment.question.textResponses.grade": { + "defaultMessage": "得分" }, - "course.assessment.question.rubricPlayground.evaluate": { - "defaultMessage": "评估" + "course.assessment.question.textResponses.invalidRegex": { + "defaultMessage": "无效的正则表达式" }, - "course.assessment.question.rubricPlayground.compare": { - "defaultMessage": "比较" + "course.assessment.question.textResponses.keyword": { + "defaultMessage": "关键词" }, - "course.assessment.question.rubricPlayground.apply": { - "defaultMessage": "应用" + "course.assessment.question.textResponses.newSolutionCannotUndo": { + "defaultMessage": "这是一个新答案。如果在保存前删除,它会立即消失。" }, - "course.assessment.question.rubricPlayground.confirmAIGradingApplication": { - "defaultMessage": "确认应用AI评分" + "course.assessment.question.textResponses.noRandomizationMode": { + "defaultMessage": "保留原始值" }, - "course.assessment.question.rubricPlayground.applyingRubricGradingData": { - "defaultMessage": "正在应用评分标准数据..." + "course.assessment.question.textResponses.noSolutionsNote": { + "defaultMessage": "如果没有提供答案,自动打分器将始终给出最高分。" }, - "course.assessment.question.rubricPlayground.applySuccess": { - "defaultMessage": "评分标准、提示和结果已成功应用。" + "course.assessment.question.textResponses.numberOfRandomTests": { + "defaultMessage": "随机测试次数" }, - "course.assessment.question.rubricPlayground.applyFailure": { - "defaultMessage": "应用评分结果失败" + "course.assessment.question.textResponses.numericRandomizationMode": { + "defaultMessage": "使用随机数值" }, - "course.assessment.question.rubricPlayground.notLatestRevisionWarning": { - "defaultMessage": "您选择应用的评分标准不是此页面上保存的最新版本。" + "course.assessment.question.textResponses.overrideRandomizationMode": { + "defaultMessage": "覆盖为指定值" }, - "course.assessment.question.rubricPlayground.applyWillGradeAllAnswers": { - "defaultMessage": "应用此评分标准将为所有学生答案分配成绩,包括此页面上尚未评估的答案。" + "course.assessment.question.textResponses.overrideRandomizationModeDescription": { + "defaultMessage": "以\"=\"开头的值将被视为公式。" }, - "course.assessment.question.rubricPlayground.confirmProceed": { - "defaultMessage": "您确定要继续吗?" + "course.assessment.question.textResponses.overrideValue": { + "defaultMessage": "值" }, - "course.assessment.question.rubricPlayground.sampleAnswerEvaluations": { - "defaultMessage": "示例答案评估" + "course.assessment.question.textResponses.randomizationMode": { + "defaultMessage": "自动评分值配置" }, - "course.assessment.question.rubricPlayground.addSampleAnswers": { - "defaultMessage": "添加示例答案" + "course.assessment.question.textResponses.randomizationModeClearAll": { + "defaultMessage": "全部清除" }, - "course.assessment.question.rubricPlayground.evaluateAll": { - "defaultMessage": "全部评估 ({count})" + "course.assessment.question.textResponses.randomizationModeDescription": { + "defaultMessage": "点击任意单元格以配置在自动评分时如何替换或随机化其值。" }, - "course.assessment.question.rubricPlayground.reevaluateAll": { - "defaultMessage": "全部重新评估 ({count})" + "course.assessment.question.textResponses.randomizationModePopoverTitle": { + "defaultMessage": "在自动评分时..." }, - "course.assessment.question.rubricPlayground.evaluateRemaining": { - "defaultMessage": "评估剩余 ({count})" + "course.assessment.question.textResponses.randomizationModeRestoreDefaults": { + "defaultMessage": "恢复默认值" }, - "course.assessment.question.rubricPlayground.comparingRevisions": { - "defaultMessage": "正在比较 {count} 个版本" + "course.assessment.question.textResponses.randomizeDigits": { + "defaultMessage": "随机化数字 (0-9)" }, - "course.assessment.question.rubricPlayground.addSampleAnswersTitle": { - "defaultMessage": "添加示例答案" + "course.assessment.question.textResponses.randomizeLetters": { + "defaultMessage": "随机化字母 (a-z)" }, - "course.assessment.question.rubricPlayground.add": { - "defaultMessage": "添加" + "course.assessment.question.textResponses.regex": { + "defaultMessage": "正则表达式" }, - "course.assessment.question.rubricPlayground.addExistingAnswers": { - "defaultMessage": "添加现有答案" + "course.assessment.question.textResponses.roundToDay": { + "defaultMessage": "向下取整到整天 (00:00 UTC)" }, - "course.assessment.question.rubricPlayground.student": { - "defaultMessage": "学生" + "course.assessment.question.textResponses.roundToInteger": { + "defaultMessage": "取整到整数" }, - "course.assessment.question.rubricPlayground.questionGrade": { - "defaultMessage": "成绩" + "course.assessment.question.textResponses.shuffleRandomizationMode": { + "defaultMessage": "与其他单元格随机排列值" }, - "course.assessment.question.rubricPlayground.categoryHeading": { - "defaultMessage": "类{index}" + "course.assessment.question.textResponses.shuffleRandomizationModeDescription": { + "defaultMessage": "每个标记为\"随机排列\"的单元格值将被随机重新分配。总体分布保持不变,但每个值可能出现在不同的单元格中。" }, - "course.assessment.question.rubricPlayground.answer": { + "course.assessment.question.textResponses.solution": { "defaultMessage": "答案" }, - "course.assessment.question.rubricPlayground.searchAnswersPlaceholder": { - "defaultMessage": "按学生姓名或成绩搜索答案" - }, - "course.assessment.question.rubricPlayground.addRandomStudentAnswers": { - "defaultMessage": "添加 {inputComponent} 个随机学生答案" - }, - "course.assessment.question.rubricPlayground.writeCustomAnswer": { - "defaultMessage": "编写自定义答案" + "course.assessment.question.textResponses.solutionGradesExceedMaximumGradeNote": { + "defaultMessage": "如果学生答案满足多个答案条件,自动打分器将给出这些答案分数的总和,最高不超过题目的最高分。" }, - "course.assessment.question.rubricPlayground.writeAnswerPlaceholder": { - "defaultMessage": "在此处编写答案" + "course.assessment.question.textResponses.solutionType": { + "defaultMessage": "答案类型" }, - "course.assessment.question.rubricPlayground.dismiss": { - "defaultMessage": "关闭" + "course.assessment.question.textResponses.solutionWillBeDeleted": { + "defaultMessage": "保存更改后,该答案将被删除。" }, - "course.assessment.question.rubricPlayground.noAnswers": { - "defaultMessage": "尚未添加示例答案。添加一些以开始。" + "course.assessment.question.textResponses.solutions": { + "defaultMessage": "答案" }, - "course.assessment.question.rubricPlayground.reevaluate": { - "defaultMessage": "重新评估" + "course.assessment.question.textResponses.solutionsHint": { + "defaultMessage": "添加答案以启用自动打分。" }, - "course.assessment.question.rubricPlayground.totalGrade": { - "defaultMessage": "总分" + "course.assessment.question.textResponses.spreadsheetAdvancedOptions": { + "defaultMessage": "高级选项" }, - "course.assessment.question.rubricPlayground.feedback": { - "defaultMessage": "反馈" + "course.assessment.question.textResponses.spreadsheetFormula": { + "defaultMessage": "电子表格公式" }, - "course.assessment.question.rubricPlayground.evaluating": { - "defaultMessage": "评估中" + "course.assessment.question.textResponses.spreadsheetRandomization": { + "defaultMessage": "启用随机化" }, - "course.assessment.question.rubricPlayground.gradingPrompt": { - "defaultMessage": "评分提示" + "course.assessment.question.textResponses.spreadsheetRandomizationDescription": { + "defaultMessage": "启用后,自动评分时将随机调整部分电子表格数值。这有助于确保公式确实计算出正确答案,而不是预设值。" }, - "course.assessment.question.rubricPlayground.gradingPromptDescription": { - "defaultMessage": "指导AI进行评分和提供反馈的说明。" + "course.assessment.question.textResponses.stringRandomizationMode": { + "defaultMessage": "随机化值中的字符" }, - "course.assessment.question.rubricPlayground.modelAnswer": { - "defaultMessage": "标准答案" + "course.assessment.question.textResponses.stringRandomizationModeDescription": { + "defaultMessage": "要随机化的每个字符类可以用同一类中的不同字符替换。" }, - "course.assessment.question.rubricPlayground.modelAnswerDescription": { - "defaultMessage": "每个类别获得最高分的示例。" + "course.assessment.question.textResponses.templateText": { + "defaultMessage": "模版" }, - "course.assessment.question.rubricPlayground.gradingCategories": { - "defaultMessage": "评分类别" + "course.assessment.question.textResponses.templateTextDescription": { + "defaultMessage": "学生第一次尝试此题时,答题区域中出现的文字。" }, - "course.assessment.question.rubricPlayground.addNewCategory": { - "defaultMessage": "添加新类别" + "course.assessment.question.textResponses.testSpreadsheet": { + "defaultMessage": "测试电子表格" }, - "course.assessment.question.rubricPlayground.categoryName": { - "defaultMessage": "类别名称" + "course.assessment.question.textResponses.testSpreadsheetDescription": { + "defaultMessage": "需要上传测试电子表格以自动评分学生答案。" }, - "course.assessment.question.rubricPlayground.max": { - "defaultMessage": "最大值" + "course.assessment.question.textResponses.testSpreadsheetRequired": { + "defaultMessage": "请上传测试电子表格文件。" }, - "course.assessment.question.rubricPlayground.addNewGrade": { - "defaultMessage": "添加新分数" + "course.assessment.question.textResponses.undoDeleteSolution": { + "defaultMessage": "撤销删除答案" + }, + "course.assessment.question.textResponses.zeroGrade": { + "defaultMessage": "0.0" }, "course.assessment.session.assessmentNotStarted": { "defaultMessage": "测试尚未开始,请在 {startDate} 之后再来。" @@ -2651,14 +2726,14 @@ "course.assessment.show.generate": { "defaultMessage": "生成问题" }, - "course.assessment.show.generateTooltip": { - "defaultMessage": "与 Codaveri AI 合作创建问题" + "course.assessment.show.generateFromProgrammingQuestion": { + "defaultMessage": "使用 Codaveri AI 生成类似问题" }, "course.assessment.show.generateFromQuestion": { "defaultMessage": "使用 AI 生成类似问题" }, - "course.assessment.show.generateFromProgrammingQuestion": { - "defaultMessage": "使用 Codaveri AI 生成类似问题" + "course.assessment.show.generateTooltip": { + "defaultMessage": "与 Codaveri AI 合作创建问题" }, "course.assessment.show.gradedTestCases": { "defaultMessage": "为测试用例打分" @@ -2673,7 +2748,7 @@ "defaultMessage": "下面的问题。" }, "course.assessment.show.headsUpExistingSubmissions": { - "defaultMessage": "注意——提交已存在!" + "defaultMessage": "注意--提交已存在!" }, "course.assessment.show.hideOptions": { "defaultMessage": "隐藏选项" @@ -2792,15 +2867,15 @@ "course.assessment.show.showMcqMrqSolution": { "defaultMessage": "显示多选题解决方案" }, - "course.assessment.show.showRubricToStudents": { - "defaultMessage": "向学生显示评分细则" - }, "course.assessment.show.showMcqSubmitResult": { "defaultMessage": "显示多选题提交结果" }, "course.assessment.show.showOptions": { "defaultMessage": "显示选项" }, + "course.assessment.show.showRubricToStudents": { + "defaultMessage": "向学生显示评分细则" + }, "course.assessment.show.sureChangingQuestionType": { "defaultMessage": "确定要更改此问题类型吗?" }, @@ -2927,93 +3002,30 @@ "course.assessment.skills.SkillsTable.uncategorised": { "defaultMessage": "未分类技能" }, - "course.assessment.liveFeedback.questionTitle": { - "defaultMessage": "题目 {index}" - }, - "course.assessment.liveFeedback.messageTimingTitle": { - "defaultMessage": "生成时间:{usedAt}" - }, - "course.assessment.liveFeedback.liveFeedbackName": { - "defaultMessage": "实时反馈" - }, - "course.assessment.liveFeedback.comments": { - "defaultMessage": "评论" - }, - "course.assessment.liveFeedback.lineHeader": { - "defaultMessage": "第 {lineNumber} 行" - }, - "course.assessment.submission.GetHelpChatPage.chatInputText": { - "defaultMessage": "我们如何帮助您?" - }, - "course.assessment.submission.GetHelpChatPage.chatMessagesRemaining": { - "defaultMessage": "剩余 {numMessages} / {maxMessages} 条消息" - }, - "course.assessment.submission.GetHelpChatPage.noChatMessagesRemaining": { - "defaultMessage": "您已达到此问题的消息限制。" - }, - "course.assessment.submission.GetHelpChatPage.codeUpdated": { - "defaultMessage": "代码已更新" - }, - "course.assessment.submission.GetHelpChatPage.ConversationArea.lineNumber": { - "defaultMessage": "第 {lineNumber} 行" - }, - "course.assessment.submission.GetHelpChatPage.ConversationArea.fileNameAndLineNumber": { - "defaultMessage": "{filename}:{lineNumber}" - }, - "course.assessment.submission.GetHelpChatPage.ConversationArea.threadExpired": { - "defaultMessage": "上面的聊天已结束。开始新的聊天?" - }, - "course.assessment.plagiarism.plagiarism": { - "defaultMessage": "抄袭结果" - }, - "course.assessment.plagiarism.status": { - "defaultMessage": "抄袭检查状态" - }, - "course.assessment.plagiarism.lastRunTime": { - "defaultMessage": "上次运行时间:{date}" - }, - "course.assessment.plagiarism.start": { - "defaultMessage": "新的抄袭检查" - }, - "course.assessment.plagiarism.notStarted": { - "defaultMessage": "尚未运行抄袭检查" - }, - "course.assessment.plagiarism.confirmStartTitle": { - "defaultMessage": "确认抄袭检查?" - }, - "course.assessment.plagiarism.confirmStartMessage": { - "defaultMessage": "运行新的抄袭检查将删除之前的结果。" - }, - "course.assessment.plagiarism.results": { - "defaultMessage": "抄袭结果(提交之间的相似度)" - }, - "course.assessment.plagiarism.baseSubmission": { - "defaultMessage": "基准提交" - }, - "course.assessment.plagiarism.comparedSubmission": { - "defaultMessage": "比较提交" - }, - "course.assessment.plagiarism.similarityScore": { - "defaultMessage": "相似性分数" + "course.assessment.statistics.ancestorFail": { + "defaultMessage": "无法获取此测试的过去结果。" }, - "course.assessment.plagiarism.actions": { - "defaultMessage": "操作" + "course.assessment.statistics.ancestorSelect.current": { + "defaultMessage": "当前" }, - "course.assessment.plagiarism.viewReport": { - "defaultMessage": "查看报告" + "course.assessment.statistics.ancestorSelect.fromCourse": { + "defaultMessage": "来自 {courseTitle}" }, - "course.assessment.plagiarism.downloadPdf": { - "defaultMessage": "下载 PDF" + "course.assessment.statistics.ancestorSelect.subtitle": { + "defaultMessage": "与此测验的过去版本进行比较:" }, - "course.assessment.plagiarism.searchByStudentName": { - "defaultMessage": "按学生姓名搜索" + "course.assessment.statistics.ancestorSelect.title": { + "defaultMessage": "复制历史" }, - "course.assessment.plagiarism.showSelfPlagiarism": { - "defaultMessage": "包含自我抄袭比较(同一学生,不同课程)" + "course.assessment.statistics.ancestorStatisticsFail": { + "defaultMessage": "获取祖先统计数据失败。" }, "course.assessment.statistics.answers": { "defaultMessage": "答案" }, + "course.assessment.statistics.attemptCount": { + "defaultMessage": "尝试次数" + }, "course.assessment.statistics.attempts.filename": { "defaultMessage": "{assessment} 的题目尝试统计" }, @@ -3026,21 +3038,51 @@ "course.assessment.statistics.closePrompt": { "defaultMessage": "关闭" }, + "course.assessment.statistics.duplicationHistory": { + "defaultMessage": "复制历史" + }, + "course.assessment.statistics.fail": { + "defaultMessage": "获取统计数据失败。" + }, + "course.assessment.statistics.gradeDistribution": { + "defaultMessage": "成绩分布" + }, + "course.assessment.statistics.gradeViolin.datasetLabel": { + "defaultMessage": "分布" + }, + "course.assessment.statistics.gradeViolin.xAxisLabel": { + "defaultMessage": "得分" + }, + "course.assessment.statistics.gradeViolin.yAxisLabel": { + "defaultMessage": "提交" + }, "course.assessment.statistics.grader": { "defaultMessage": "评分者" }, + "course.assessment.statistics.gradesPerQuestion": { + "defaultMessage": "每题分数" + }, "course.assessment.statistics.grayCellLegend": { "defaultMessage": "未决定 (问题无法自动评分)" }, "course.assessment.statistics.group": { "defaultMessage": "组别" }, + "course.assessment.statistics.header": { + "defaultMessage": "{title} 的统计数据" + }, + "course.assessment.statistics.includePhantom": { + "defaultMessage": "包括虚拟学生" + }, "course.assessment.statistics.legendHigherusage": { "defaultMessage": "使用较多" }, "course.assessment.statistics.legendLowerUsage": { "defaultMessage": "使用较少" }, + "course.assessment.statistics.liveFeedback": { + "defaultMessage": "获取帮助" + }, "course.assessment.statistics.liveFeedback.filename": { "defaultMessage": "{assessment} 的题目实时反馈统计" }, @@ -3077,66 +3119,6 @@ "course.assessment.statistics.questionIndex": { "defaultMessage": "题目 {index}" }, - "course.assessment.statistics.totalFeedbackCount": { - "defaultMessage": "总计" - }, - "course.assessment.statistics.totalGrade": { - "defaultMessage": "总分" - }, - "course.assessment.statistics.workflowState": { - "defaultMessage": "状态" - }, - "course.assessment.statistics.ancestorFail": { - "defaultMessage": "无法获取此测试的过去结果。" - }, - "course.assessment.statistics.ancestorStatisticsFail": { - "defaultMessage": "获取祖先统计数据失败。" - }, - "course.assessment.statistics.fail": { - "defaultMessage": "获取统计数据失败。" - }, - "course.assessment.statistics.gradeDistribution": { - "defaultMessage": "成绩分布" - }, - "course.assessment.statistics.gradeViolin.datasetLabel": { - "defaultMessage": "分布" - }, - "course.assessment.statistics.gradeViolin.xAxisLabel": { - "defaultMessage": "得分" - }, - "course.assessment.statistics.gradeViolin.yAxisLabel": { - "defaultMessage": "提交" - }, - "course.assessment.statistics.ancestorSelect.current": { - "defaultMessage": "当前" - }, - "course.assessment.statistics.ancestorSelect.fromCourse": { - "defaultMessage": "来自 {courseTitle}" - }, - "course.assessment.statistics.ancestorSelect.subtitle": { - "defaultMessage": "与此测验的过去版本进行比较:" - }, - "course.assessment.statistics.ancestorSelect.title": { - "defaultMessage": "复制历史" - }, - "course.assessment.statistics.attemptCount": { - "defaultMessage": "尝试次数" - }, - "course.assessment.statistics.duplicationHistory": { - "defaultMessage": "复制历史" - }, - "course.assessment.statistics.gradesPerQuestion": { - "defaultMessage": "每题分数" - }, - "course.assessment.statistics.includePhantom": { - "defaultMessage": "包括虚拟学生" - }, - "course.assessment.statistics.liveFeedback": { - "defaultMessage": "获取帮助" - }, - "course.assessment.statistics.header": { - "defaultMessage": "{title} 的统计数据" - }, "course.assessment.statistics.statistics": { "defaultMessage": "统计数据" }, @@ -3158,9 +3140,24 @@ "course.assessment.statistics.submissionTimeGradeChart.xAxisLabel.withoutDeadline": { "defaultMessage": "提交日期" }, + "course.assessment.statistics.totalFeedbackCount": { + "defaultMessage": "总计" + }, + "course.assessment.statistics.totalGrade": { + "defaultMessage": "总分" + }, + "course.assessment.statistics.workflowState": { + "defaultMessage": "状态" + }, "course.assessment.submission.Annotations.comment": { "defaultMessage": "添加评论" }, + "course.assessment.submission.Answer.missingAnswer": { + "defaultMessage": "此问题没有已提交的答案--可能是因为提交之后又添加了新问题。" + }, + "course.assessment.submission.Answer.rendererNotImplemented": { + "defaultMessage": "此问题类型的显示尚未实现。" + }, "course.assessment.submission.CodaveriFeedbackStatus.codaveriFeedbackStatus": { "defaultMessage": "Codaveri反馈状态" }, @@ -3185,38 +3182,35 @@ "course.assessment.submission.FileInput.uploadLabel": { "defaultMessage": "拖放或点击上传文件" }, - "course.assessment.submission.ImportedFileView.deleteConfirmation": { - "defaultMessage": "你确定要删除此文件吗?" - }, - "course.assessment.submission.ImportedFileView.noFiles": { - "defaultMessage": "未上传文件。" + "course.assessment.submission.GetHelpChatPage.ConversationArea.fileNameAndLineNumber": { + "defaultMessage": "{filename}:{lineNumber}" }, - "course.assessment.submission.ImportedFileView.uploadedFiles": { - "defaultMessage": "上传的文件:" + "course.assessment.submission.GetHelpChatPage.ConversationArea.lineNumber": { + "defaultMessage": "第 {lineNumber} 行" }, - "course.assessment.submission.Answer.missingAnswer": { - "defaultMessage": "此问题没有已提交的答案——可能是因为提交之后又添加了新问题。" + "course.assessment.submission.GetHelpChatPage.ConversationArea.threadExpired": { + "defaultMessage": "上面的聊天已结束。开始新的聊天?" }, - "course.assessment.submission.answers.AnswerHeader.noPastAnswers": { - "defaultMessage": "没有过去的答案。" + "course.assessment.submission.GetHelpChatPage.chatInputText": { + "defaultMessage": "我们如何帮助您?" }, - "course.assessment.submission.Answer.rendererNotImplemented": { - "defaultMessage": "此问题类型的显示尚未实现。" + "course.assessment.submission.GetHelpChatPage.chatMessagesRemaining": { + "defaultMessage": "剩余 {numMessages} / {maxMessages} 条消息" }, - "course.assessment.submission.answerTooLarge": { - "defaultMessage": "答案过大" + "course.assessment.submission.GetHelpChatPage.codeUpdated": { + "defaultMessage": "代码已更新" }, - "course.assessment.submission.answerTooLargeError": { - "defaultMessage": "您的答案必须小于 2 MB。" + "course.assessment.submission.GetHelpChatPage.noChatMessagesRemaining": { + "defaultMessage": "您已达到此问题的消息限制。" }, - "course.assessment.submission.publishAutoFeedbackConfirmationHeader": { - "defaultMessage": "您即将发布 {count} 条自动编程反馈。" + "course.assessment.submission.ImportedFileView.deleteConfirmation": { + "defaultMessage": "你确定要删除此文件吗?" }, - "course.assessment.submission.publishAutoFeedbackConfirmationPleaseRate": { - "defaultMessage": "请评价本次测验自动编程反馈的整体质量。您的评分将帮助我们改进自动编程反馈生成,以便所有用户受益。" + "course.assessment.submission.ImportedFileView.noFiles": { + "defaultMessage": "未上传文件。" }, - "course.assessment.submission.publishAutoFeedbackSuccess": { - "defaultMessage": "所有自动编程反馈均已发布。" + "course.assessment.submission.ImportedFileView.uploadedFiles": { + "defaultMessage": "上传的文件:" }, "course.assessment.submission.SubmissionAnswer.viewPastAnswers": { "defaultMessage": "查看过去的答案" @@ -3266,9 +3260,6 @@ "course.assessment.submission.SubmissionsIndex.includePhantoms": { "defaultMessage": "包括旁听学生" }, - "lib.translations.myStudents": { - "defaultMessage": "我的学生" - }, "course.assessment.submission.SubmissionsIndex.phantom": { "defaultMessage": "旁听用户" }, @@ -3284,12 +3275,6 @@ "course.assessment.submission.SubmissionsIndex.remind": { "defaultMessage": "发送提醒邮件" }, - "lib.translations.staff": { - "defaultMessage": "职员" - }, - "lib.translations.students": { - "defaultMessage": "学生" - }, "course.assessment.submission.SubmissionsIndex.submissionStatus": { "defaultMessage": "提交状态" }, @@ -3479,6 +3464,15 @@ "course.assessment.submission.answerSubmitted": { "defaultMessage": "答案已提交" }, + "course.assessment.submission.answerTooLarge": { + "defaultMessage": "答案过大" + }, + "course.assessment.submission.answerTooLargeError": { + "defaultMessage": "您的答案必须小于 2 MB。" + }, + "course.assessment.submission.answers.AnswerHeader.noPastAnswers": { + "defaultMessage": "没有过去的答案。" + }, "course.assessment.submission.answers.ForumPostResponse.ForumCard.forumCardTitleTypeNoneSelected": { "defaultMessage": "论坛" }, @@ -3557,6 +3551,18 @@ "course.assessment.submission.answers.Programming.ProgrammingFile.sizeTooBig": { "defaultMessage": "文件太大,无法显示。" }, + "course.assessment.submission.answers.Programming.ProgrammingFiles.liveFeedbackItemDelete": { + "defaultMessage": "忽略" + }, + "course.assessment.submission.answers.Programming.ProgrammingFiles.liveFeedbackItemDislike": { + "defaultMessage": "不喜欢" + }, + "course.assessment.submission.answers.Programming.ProgrammingFiles.liveFeedbackItemLike": { + "defaultMessage": "喜欢" + }, + "course.assessment.submission.answers.Programming.ProgrammingFiles.liveFeedbackItemLineHeading": { + "defaultMessage": "线 {linenum}" + }, "course.assessment.submission.attemptedAt": { "defaultMessage": "试图在" }, @@ -3578,14 +3584,14 @@ "course.assessment.submission.bonusEndAt": { "defaultMessage": "奖金结束于" }, - "course.assessment.submission.codaveriAutogradeFailure": { - "defaultMessage": "(T_T) 抱歉,codaveri 自动打分气罢工了。尝试在几分钟后再次提交你的代码或检查网络响应中的错误消息。" + "course.assessment.submission.checkAnswer": { + "defaultMessage": "检查答案" }, - "course.assessment.submission.liveFeedbackNoneGenerated": { - "defaultMessage": "问题 {questionIndex}:未生成反馈。" + "course.assessment.submission.checkAnswerWithLimit": { + "defaultMessage": "检查答案({attemptsLeft, plural, one {# 次} other {# 次}}剩余)" }, - "course.assessment.submission.liveFeedbackSuccess": { - "defaultMessage": "问题 {questionIndex}:反馈生成成功。" + "course.assessment.submission.codaveriAutogradeFailure": { + "defaultMessage": "(T_T) 抱歉,codaveri 自动打分气罢工了。尝试在几分钟后再次提交你的代码或检查网络响应中的错误消息。" }, "course.assessment.submission.comment.CodaveriCommentCard.finalise": { "defaultMessage": "完成并发布反馈" @@ -3611,14 +3617,14 @@ "course.assessment.submission.comment.CommentCard.deleteConfirmation": { "defaultMessage": "你确定要删除此评论吗?" }, - "course.assessment.submission.comment.CommentCard.save": { - "defaultMessage": "保存" + "course.assessment.submission.comment.CommentCard.isAiGenerated": { + "defaultMessage": "AI 生成的评论" }, "course.assessment.submission.comment.CommentCard.publish": { "defaultMessage": "发布" }, - "course.assessment.submission.comment.CommentCard.isAiGenerated": { - "defaultMessage": "AI 生成的评论" + "course.assessment.submission.comment.CommentCard.save": { + "defaultMessage": "保存" }, "course.assessment.submission.comment.CommentField.comment": { "defaultMessage": "评论" @@ -3635,18 +3641,6 @@ "course.assessment.submission.comments": { "defaultMessage": "注释" }, - "course.assessment.submission.answers.Programming.ProgrammingFiles.liveFeedbackItemDelete": { - "defaultMessage": "忽略" - }, - "course.assessment.submission.answers.Programming.ProgrammingFiles.liveFeedbackItemDislike": { - "defaultMessage": "不喜欢" - }, - "course.assessment.submission.answers.Programming.ProgrammingFiles.liveFeedbackItemLike": { - "defaultMessage": "喜欢" - }, - "course.assessment.submission.answers.Programming.ProgrammingFiles.liveFeedbackItemLineHeading": { - "defaultMessage": "线 {linenum}" - }, "course.assessment.submission.continue": { "defaultMessage": "继续" }, @@ -3773,6 +3767,12 @@ "course.assessment.submission.lateSubmission": { "defaultMessage": "这次提交是迟到的!你可能想对迟交的学生进行处罚。" }, + "course.assessment.submission.liveFeedbackNoneGenerated": { + "defaultMessage": "问题 {questionIndex}:未生成反馈。" + }, + "course.assessment.submission.liveFeedbackSuccess": { + "defaultMessage": "问题 {questionIndex}:反馈生成成功。" + }, "course.assessment.submission.loadingComment": { "defaultMessage": "正在加载评论字段..." }, @@ -3839,6 +3839,15 @@ "course.assessment.submission.publish": { "defaultMessage": "发布等级" }, + "course.assessment.submission.publishAutoFeedbackConfirmationHeader": { + "defaultMessage": "您即将发布 {count} 条自动编程反馈。" + }, + "course.assessment.submission.publishAutoFeedbackConfirmationPleaseRate": { + "defaultMessage": "请评价本次测验自动编程反馈的整体质量。您的评分将帮助我们改进自动编程反馈生成,以便所有用户受益。" + }, + "course.assessment.submission.publishAutoFeedbackSuccess": { + "defaultMessage": "所有自动编程反馈均已发布。" + }, "course.assessment.submission.publishConfirmation": { "defaultMessage": "你确定要发布所有 {graded} 评分提交({selectedUsers})吗?此操作不可逆转!所有评分的提交都将发布,用户将能够看到自己的成绩。" }, @@ -3854,14 +3863,14 @@ "course.assessment.submission.question": { "defaultMessage": "题" }, - "course.assessment.submission.questionNumber": { - "defaultMessage": "Q{数字}" + "course.assessment.submission.questionAnswer": { + "defaultMessage": "作答" }, "course.assessment.submission.questionDescription": { "defaultMessage": "描述" }, - "course.assessment.submission.questionAnswer": { - "defaultMessage": "作答" + "course.assessment.submission.questionNumber": { + "defaultMessage": "Q{数字}" }, "course.assessment.submission.readOnlyEditor.expandComments": { "defaultMessage": "展开所有评论" @@ -3884,15 +3893,6 @@ "course.assessment.submission.resetConfirmation": { "defaultMessage": "你确定要重置你的答案吗?这个操作是不可逆的,你将失去你当前为这个问题所做的所有工作。" }, - "course.assessment.submission.checkAnswer": { - "defaultMessage": "检查答案" - }, - "course.assessment.submission.checkAnswerWithLimit": { - "defaultMessage": "检查答案({attemptsLeft, plural, one {# 次} other {# 次}}剩余)" - }, - "course.assessment.submission.submitWithLimit": { - "defaultMessage": "提交({attemptsLeft, plural, one {# 次} other {# 次}}剩余)" - }, "course.assessment.submission.saveDraft": { "defaultMessage": "保存草稿" }, @@ -3947,21 +3947,24 @@ "course.assessment.submission.submitShortcut": { "defaultMessage": "(Ctrl+Enter) 或 (⌘+Enter)" }, + "course.assessment.submission.submitWithLimit": { + "defaultMessage": "提交({attemptsLeft, plural, one {# 次} other {# 次}}剩余)" + }, "course.assessment.submission.submitted": { "defaultMessage": "已提交" }, "course.assessment.submission.submittedAt": { "defaultMessage": "提交于" }, - "course.assessment.submission.unknown": { - "defaultMessage": "未知状态,请联系管理员" - }, "course.assessment.submission.totalGrade": { "defaultMessage": "总成绩" }, "course.assessment.submission.type": { "defaultMessage": "类型" }, + "course.assessment.submission.unknown": { + "defaultMessage": "未知状态,请联系管理员" + }, "course.assessment.submission.unmark": { "defaultMessage": "恢复提交" }, @@ -4157,9 +4160,6 @@ "course.asssessment.submission.submitNoQuestionExplain": { "defaultMessage": "标记为完成?" }, - "course.admin.NotificationSettings.component": { - "defaultMessage": "组件" - }, "course.componentTitles.course_achievements_component": { "defaultMessage": "成就" }, @@ -4244,15 +4244,6 @@ "course.courses.CourseAnnouncements.announcementHeader": { "defaultMessage": "公告" }, - "course.courses.CourseSuspendedAlert.header": { - "defaultMessage": "此课程已暂停。讲师仍可访问,但学生无法访问。" - }, - "course.courses.CourseSuspendedAlert.canSuspendMessage": { - "defaultMessage": "您可以在{link}页面解除暂停。" - }, - "course.courses.CourseSuspendedAlert.cannotSuspendMessage": { - "defaultMessage": "如果您认为这是错误,请联系课程管理员或所有者请其解除暂停。" - }, "course.courses.CourseDisplay.noCourse": { "defaultMessage": "还没有课程..." }, @@ -4298,6 +4289,15 @@ "course.courses.CourseShow.instructorsHeader": { "defaultMessage": "导师" }, + "course.courses.CourseSuspendedAlert.canSuspendMessage": { + "defaultMessage": "您可以在{link}页面解除暂停。" + }, + "course.courses.CourseSuspendedAlert.cannotSuspendMessage": { + "defaultMessage": "如果您认为这是错误,请联系课程管理员或所有者请其解除暂停。" + }, + "course.courses.CourseSuspendedAlert.header": { + "defaultMessage": "此课程已暂停。讲师仍可访问,但学生无法访问。" + }, "course.courses.CourseUserItem.differentCourseNameHint": { "defaultMessage": "你看到的名字与你的账户名不同,因为该课程管理员是用此名称邀请你的。" }, @@ -4466,15 +4466,15 @@ "course.courses.SidebarItem.home": { "defaultMessage": "主页" }, + "course.courses.SidebarItem.scholaistic.assessments": { + "defaultMessage": "角色扮演评估" + }, "course.courses.SidebarItem.stories.learn": { "defaultMessage": "学习" }, "course.courses.SidebarItem.stories.missionControl": { "defaultMessage": "任务控制" }, - "course.courses.SidebarItem.scholaistic.assessments": { - "defaultMessage": "角色扮演评估" - }, "course.courses.TodoIgnoreButton.ignore.ignoreButtonText": { "defaultMessage": "忽视" }, @@ -4517,6 +4517,12 @@ "course.discussion.topics.CommentCard.deleteSuccess": { "defaultMessage": "已成功删除评论。" }, + "course.discussion.topics.CommentCard.isAiGenerated": { + "defaultMessage": "AI 生成的草稿评论" + }, + "course.discussion.topics.CommentCard.publish": { + "defaultMessage": "发布" + }, "course.discussion.topics.CommentCard.publishFailure": { "defaultMessage": "无法发布反馈。" }, @@ -4538,12 +4544,6 @@ "course.discussion.topics.CommentCard.updateSuccess": { "defaultMessage": "已成功更新评论。" }, - "course.discussion.topics.CommentCard.publish": { - "defaultMessage": "发布" - }, - "course.discussion.topics.CommentCard.isAiGenerated": { - "defaultMessage": "AI 生成的草稿评论" - }, "course.discussion.topics.CommentField.comment": { "defaultMessage": "评论" }, @@ -4715,15 +4715,15 @@ "course.duplication.Duplication.duplicateData": { "defaultMessage": "复制数据" }, - "course.duplication.Duplication.fromCourse": { - "defaultMessage": "复制数据从{courseTitle}" - }, "course.duplication.Duplication.duplicationDisabled": { "defaultMessage": "本课程禁止复制。" }, "course.duplication.Duplication.existingCourse": { "defaultMessage": "现有课程" }, + "course.duplication.Duplication.fromCourse": { + "defaultMessage": "复制数据从{courseTitle}" + }, "course.duplication.Duplication.items": { "defaultMessage": "已选项目" }, @@ -4817,21 +4817,6 @@ "course.enrolRequests.UserRequests.rejected": { "defaultMessage": "拒绝的注册请求" }, - "course.experiencePoints.downloadCsvButton": { - "defaultMessage": "下载 CSV" - }, - "course.experiencePoints.downloadFailure": { - "defaultMessage": "处理您的下载请求时发生错误。" - }, - "course.experiencePoints.downloadPending": { - "defaultMessage": "请稍候,正在处理您的下载请求。" - }, - "course.experiencePoints.downloadRequestSuccess": { - "defaultMessage": "您的下载请求已成功" - }, - "course.experiencePoints.filterByNameButton": { - "defaultMessage": "按姓名筛选" - }, "course.experiencePoints.disbursement.DisbursementForm.createDisbursementFailure": { "defaultMessage": "奖励经验值失败。" }, @@ -4952,6 +4937,21 @@ "course.experiencePoints.disbursement.ForumPostTable.voteTally": { "defaultMessage": "点赞总数" }, + "course.experiencePoints.downloadCsvButton": { + "defaultMessage": "下载 CSV" + }, + "course.experiencePoints.downloadFailure": { + "defaultMessage": "处理您的下载请求时发生错误。" + }, + "course.experiencePoints.downloadPending": { + "defaultMessage": "请稍候,正在处理您的下载请求。" + }, + "course.experiencePoints.downloadRequestSuccess": { + "defaultMessage": "您的下载请求已成功" + }, + "course.experiencePoints.filterByNameButton": { + "defaultMessage": "按姓名筛选" + }, "course.forum.FormShow.fetchTopicsFailure": { "defaultMessage": "无法检索论坛主题数据。" }, @@ -5192,45 +5192,45 @@ "course.forum.HideButton.hide": { "defaultMessage": "隐藏" }, - "course.forum.HideButton.hideTooltip": { - "defaultMessage": "对学生隐藏主题" - }, "course.forum.HideButton.hideFailure": { "defaultMessage": "未能隐藏主题\"{title}\"- {error}" }, "course.forum.HideButton.hideSuccess": { "defaultMessage": "主题\"{title}\"已成功隐藏。" }, + "course.forum.HideButton.hideTooltip": { + "defaultMessage": "对学生隐藏主题" + }, "course.forum.HideButton.unhide": { "defaultMessage": "取消隐藏" }, - "course.forum.HideButton.unhideTooltip": { - "defaultMessage": "向学生显示主题" - }, "course.forum.HideButton.unhideFailure": { "defaultMessage": "未能取消隐藏主题\"{title}\"- {error}" }, "course.forum.HideButton.unhideSuccess": { "defaultMessage": "主题\"{title}\"已成功取消隐藏。" }, - "course.forum.LockButton.locked": { - "defaultMessage": "锁定" + "course.forum.HideButton.unhideTooltip": { + "defaultMessage": "向学生显示主题" }, "course.forum.LockButton.lockTooltip": { "defaultMessage": "锁定以禁止学生在此主题中发帖" }, + "course.forum.LockButton.locked": { + "defaultMessage": "锁定" + }, "course.forum.LockButton.lockedFailure": { "defaultMessage": "无法锁定主题\"{title}\"- {error}" }, "course.forum.LockButton.lockedSuccess": { "defaultMessage": "主题\"{title}\"已成功锁定。" }, - "course.forum.LockButton.unlocked": { - "defaultMessage": "解锁" - }, "course.forum.LockButton.unlockTooltip": { "defaultMessage": "解锁以允许学生在此主题中发帖" }, + "course.forum.LockButton.unlocked": { + "defaultMessage": "解锁" + }, "course.forum.LockButton.unlockedFailure": { "defaultMessage": "无法解锁主题\"{title}\" - {error}" }, @@ -5342,62 +5342,410 @@ "course.forum.SubscribeButton.forumTranslations.userSettingSubscribed": { "defaultMessage": "你已取消订阅本课程中论坛的“新主题”。请前往 {manageMySubscriptionLink} 启用它。" }, - "course.forum.VotePostButton.updateFailure": { - "defaultMessage": "更新点赞数量失败 - {error}" + "course.forum.VotePostButton.updateFailure": { + "defaultMessage": "更新点赞数量失败 - {error}" + }, + "course.forum.forum.markAllAsReadFailed": { + "defaultMessage": "未能将此论坛中的所有主题标记为已读。请稍后再试。" + }, + "course.gradebook.AddExternalColumnPrompt.cancel": { + "defaultMessage": "取消" + }, + "course.gradebook.AddExternalColumnPrompt.create": { + "defaultMessage": "创建" + }, + "course.gradebook.AddExternalColumnPrompt.error": { + "defaultMessage": "无法创建外部评估。" + }, + "course.gradebook.AddExternalColumnPrompt.maxLabel": { + "defaultMessage": "最高分" + }, + "course.gradebook.AddExternalColumnPrompt.nameLabel": { + "defaultMessage": "名称" + }, + "course.gradebook.AddExternalColumnPrompt.success": { + "defaultMessage": "外部评估已创建。" + }, + "course.gradebook.AddExternalColumnPrompt.title": { + "defaultMessage": "添加外部评估" + }, + "course.gradebook.ConfigureWeightsPrompt.allExcluded": { + "defaultMessage": "“{tab}”中的所有评估均已排除,且不会计入总成绩。" + }, + "course.gradebook.ConfigureWeightsPrompt.allExcludedCount": { + "defaultMessage": "已排除全部 {n} 个" + }, + "course.gradebook.ConfigureWeightsPrompt.customMode": { + "defaultMessage": "自定义" + }, + "course.gradebook.ConfigureWeightsPrompt.customSum": { + "defaultMessage": "评估权重:{sum} / {total}" + }, + "course.gradebook.ConfigureWeightsPrompt.defaultsHint": { + "defaultMessage": "尚未设置权重。以下为建议默认值,所有标签页均按相同比重计算。保存以确认,或在下方进行调整。" + }, + "course.gradebook.ConfigureWeightsPrompt.descriptionDrop": { + "defaultMessage": "在等权模式下,可选择在求平均分前剔除每位学生得分最低的 N 个评估。" + }, + "course.gradebook.ConfigureWeightsPrompt.descriptionExclusion": { + "defaultMessage": "展开标签页以将个别评估纳入或排除在评分之外。" + }, + "course.gradebook.ConfigureWeightsPrompt.descriptionIntro": { + "defaultMessage": "控制各标签页和评估如何计入每位学生的总成绩。" + }, + "course.gradebook.ConfigureWeightsPrompt.descriptionModes": { + "defaultMessage": "选择“等权”(所有评估平分该标签页的权重)或“自定义”(设置每个评估所占的份额)。" + }, + "course.gradebook.ConfigureWeightsPrompt.descriptionWeights": { + "defaultMessage": "设置每个标签页的权重,即其对总成绩的贡献比例(权重合计应为 100)。" + }, + "course.gradebook.ConfigureWeightsPrompt.equalMode": { + "defaultMessage": "等权" + }, + "course.gradebook.ConfigureWeightsPrompt.excluded": { + "defaultMessage": "已排除" + }, + "course.gradebook.ConfigureWeightsPrompt.excludedCount": { + "defaultMessage": "已排除 {n} 个" + }, + "course.gradebook.ConfigureWeightsPrompt.includeAssessment": { + "defaultMessage": "将 {assessment} 计入成绩" + }, + "course.gradebook.ConfigureWeightsPrompt.modeAria": { + "defaultMessage": "{tab} 权重模式" + }, + "course.gradebook.ConfigureWeightsPrompt.ofGrade": { + "defaultMessage": "占成绩的 {pct}%" + }, + "course.gradebook.ConfigureWeightsPrompt.promptTitle": { + "defaultMessage": "配置贡献比例" + }, + "course.gradebook.ConfigureWeightsPrompt.saveError": { + "defaultMessage": "保存权重失败。请重试。" + }, + "course.gradebook.ConfigureWeightsPrompt.total": { + "defaultMessage": "总计:{sum}%" + }, + "course.gradebook.ConfigureWeightsPrompt.unbalanced": { + "defaultMessage": "保存前,“{tab}”的评估权重合计必须等于该标签页的总权重。" + }, + "course.gradebook.ConfigureWeightsPrompt.valueTooHigh": { + "defaultMessage": "数值最多为 100" + }, + "course.gradebook.ConfigureWeightsPrompt.valueTooLow": { + "defaultMessage": "数值至少为 0" + }, + "course.gradebook.ConfigureWeightsPrompt.weightsDoNotSum": { + "defaultMessage": "权重合计不为 100。仍可保存;总成绩可能不准确。" + }, + "course.gradebook.DeleteExternalColumnPrompt.body": { + "defaultMessage": "要删除\"{title}\"吗?这将永久移除该列及其中每位学生的成绩。此操作无法撤销。" + }, + "course.gradebook.DeleteExternalColumnPrompt.cancel": { + "defaultMessage": "取消" + }, + "course.gradebook.DeleteExternalColumnPrompt.confirm": { + "defaultMessage": "删除" + }, + "course.gradebook.DeleteExternalColumnPrompt.error": { + "defaultMessage": "无法删除外部评估。" + }, + "course.gradebook.DeleteExternalColumnPrompt.title": { + "defaultMessage": "删除外部评估" + }, + "course.gradebook.ExternalGradeConflictPrompt.body": { + "defaultMessage": "这些学生在这些组成部分中已有成绩。要保留他们现有的成绩,还是用文件中的值替换?新学生和空白单元格不受影响。" + }, + "course.gradebook.ExternalGradeConflictPrompt.goBack": { + "defaultMessage": "返回" + }, + "course.gradebook.ExternalGradeConflictPrompt.keepExisting": { + "defaultMessage": "保留现有成绩" + }, + "course.gradebook.ExternalGradeConflictPrompt.replace": { + "defaultMessage": "替换" + }, + "course.gradebook.ExternalGradeConflictPrompt.title": { + "defaultMessage": "解决成绩冲突" + }, + "course.gradebook.ExternalGradeConflictTable.component": { + "defaultMessage": "组成部分" + }, + "course.gradebook.ExternalGradeConflictTable.existing": { + "defaultMessage": "现有成绩" + }, + "course.gradebook.ExternalGradeConflictTable.inFile": { + "defaultMessage": "文件中的成绩" + }, + "course.gradebook.ExternalGradeConflictTable.mismatch": { + "defaultMessage": "此标识符现在对应的学生与现有成绩导入时对应的学生不同。" + }, + "course.gradebook.ExternalGradeConflictTable.student": { + "defaultMessage": "学生" + }, + "course.gradebook.GradeLinkHint.hint": { + "defaultMessage": "每个成绩都是学生提交内容中各项分数的总和。点击任一成绩即可打开该提交内容并调整分数。" + }, + "course.gradebook.GradebookColumnTree.alwaysIncluded": { + "defaultMessage": "必选项" + }, + "course.gradebook.GradebookColumnTree.gamification": { + "defaultMessage": "游戏化相关" + }, + "course.gradebook.GradebookColumnTree.grades": { + "defaultMessage": "成绩" + }, + "course.gradebook.GradebookColumnTree.studentInfo": { + "defaultMessage": "学生信息" + }, + "course.gradebook.GradebookIndex.addExternal": { + "defaultMessage": "添加外部评估" + }, + "course.gradebook.GradebookIndex.allAssessments": { + "defaultMessage": "全部评估" + }, + "course.gradebook.GradebookIndex.applyAndExport": { + "defaultMessage": "应用并导出" + }, + "course.gradebook.GradebookIndex.byWeight": { + "defaultMessage": "加权总成绩" + }, + "course.gradebook.GradebookIndex.dialogTitle": { + "defaultMessage": "选择列" + }, + "course.gradebook.GradebookIndex.exportAllTooltip": { + "defaultMessage": "未选择行 - 将导出所有行。" + }, + "course.gradebook.GradebookIndex.exportButton": { + "defaultMessage": "导出所有行" + }, + "course.gradebook.GradebookIndex.exportRows": { + "defaultMessage": "导出 {count, plural, other {# 行}}" + }, + "course.gradebook.GradebookIndex.fetchFailure": { + "defaultMessage": "无法获取成绩册。" + }, + "course.gradebook.GradebookIndex.gradebook": { + "defaultMessage": "成绩册" + }, + "course.gradebook.GradebookIndex.noStudents": { + "defaultMessage": "无学生" + }, + "course.gradebook.GradebookIndex.noStudentsHint": { + "defaultMessage": "学生加入课程后,成绩将显示在这里。" + }, + "course.gradebook.GradebookIndex.searchStudents": { + "defaultMessage": "搜索学生" + }, + "course.gradebook.GradebookIndex.selectColumns": { + "defaultMessage": "选择列" + }, + "course.gradebook.GradebookTable.delete": { + "defaultMessage": "删除" + }, + "course.gradebook.GradebookTable.externalBadge": { + "defaultMessage": "外部" + }, + "course.gradebook.GradebookTable.externalGradeAria": { + "defaultMessage": "{name} 的 {title} 成绩" + }, + "course.gradebook.GradebookTable.externalMaxAria": { + "defaultMessage": "{title} 最高分" + }, + "course.gradebook.GradebookTable.gradeSaveError": { + "defaultMessage": "无法保存成绩。请重试。" + }, + "course.gradebook.GradebookTable.manageAria": { + "defaultMessage": "管理 {title}" + }, + "course.gradebook.GradebookTable.maxMarks": { + "defaultMessage": "最高分" + }, + "course.gradebook.GradebookTable.maxSaveError": { + "defaultMessage": "无法保存最高分。请重试。" + }, + "course.gradebook.GradebookTable.noDataColumnsHint": { + "defaultMessage": "未选择任何成绩列--导出内容将仅包含学生信息。" + }, + "course.gradebook.GradebookTable.noDataColumnsHintWithGamification": { + "defaultMessage": "未选择任何成绩或游戏化列--导出内容将仅包含学生信息。" + }, + "course.gradebook.GradebookTable.rename": { + "defaultMessage": "重命名" + }, + "course.gradebook.GradebookWeightedTable.collapseRow": { + "defaultMessage": "收起 {name}" + }, + "course.gradebook.GradebookWeightedTable.configureWeights": { + "defaultMessage": "配置权重" + }, + "course.gradebook.GradebookWeightedTable.defaultWeights": { + "defaultMessage": "正在显示默认权重--所有标签页比重相同。点击“配置权重”进行自定义设置。" + }, + "course.gradebook.GradebookWeightedTable.defaultWeightsNoAccess": { + "defaultMessage": "正在显示默认权重--在配置权重之前,所有标签页比重相同。" + }, + "course.gradebook.GradebookWeightedTable.displayMode": { + "defaultMessage": "显示模式" + }, + "course.gradebook.GradebookWeightedTable.displayPercent": { + "defaultMessage": "百分比" + }, + "course.gradebook.GradebookWeightedTable.displayPercentTooltip": { + "defaultMessage": "学生在各标签页所获得的比例。在比重为 20% 的标签页获得 100%,即表示学生获得了该标签页的全部 20 个成绩分。" + }, + "course.gradebook.GradebookWeightedTable.displayPoints": { + "defaultMessage": "分数" + }, + "course.gradebook.GradebookWeightedTable.displayPointsTooltip": { + "defaultMessage": "各标签页贡献的成绩分数。各列相加即为预计总成绩。" + }, + "course.gradebook.GradebookWeightedTable.downloadCsv": { + "defaultMessage": "下载为 CSV" + }, + "course.gradebook.GradebookWeightedTable.email": { + "defaultMessage": "电子邮件" + }, + "course.gradebook.GradebookWeightedTable.excluded": { + "defaultMessage": "已排除" + }, + "course.gradebook.GradebookWeightedTable.expandRow": { + "defaultMessage": "展开 {name}" + }, + "course.gradebook.GradebookWeightedTable.name": { + "defaultMessage": "姓名" + }, + "course.gradebook.GradebookWeightedTable.noWeightsConfigured": { + "defaultMessage": "尚未配置权重--所有标签页的权重均为 0。点击“配置权重”以分配权重。" + }, + "course.gradebook.GradebookWeightedTable.noWeightsNoAccess": { + "defaultMessage": "尚未配置任何标签页权重。" + }, + "course.gradebook.GradebookWeightedTable.outOfWeight": { + "defaultMessage": "/{weight}" + }, + "course.gradebook.GradebookWeightedTable.percentOfGrade": { + "defaultMessage": "占成绩的 {weight}%" + }, + "course.gradebook.GradebookWeightedTable.percentTotalExact": { + "defaultMessage": "合计 100%" + }, + "course.gradebook.GradebookWeightedTable.percentTotalWarning": { + "defaultMessage": "合计 {weight}%" + }, + "course.gradebook.GradebookWeightedTable.searchStudents": { + "defaultMessage": "搜索学生" + }, + "course.gradebook.GradebookWeightedTable.total": { + "defaultMessage": "总成绩" + }, + "course.gradebook.GradebookWeightedTable.weightsDoNotSum": { + "defaultMessage": "权重合计不为 100。总成绩可能不准确。" + }, + "course.gradebook.ImportExternalAssessmentsButton.label": { + "defaultMessage": "导入外部评估" + }, + "course.gradebook.ImportWizard.addComponent": { + "defaultMessage": "添加组成部分" + }, + "course.gradebook.ImportWizard.back": { + "defaultMessage": "返回" + }, + "course.gradebook.ImportWizard.cancel": { + "defaultMessage": "取消" + }, + "course.gradebook.ImportWizard.commitError": { + "defaultMessage": "导入失败。未保存任何内容。" + }, + "course.gradebook.ImportWizard.committed": { + "defaultMessage": "导入完成。" + }, + "course.gradebook.ImportWizard.componentName": { + "defaultMessage": "组成部分名称" + }, + "course.gradebook.ImportWizard.continue": { + "defaultMessage": "确认导入" + }, + "course.gradebook.ImportWizard.downloadTemplate": { + "defaultMessage": "下载模板" + }, + "course.gradebook.ImportWizard.email": { + "defaultMessage": "电子邮件" + }, + "course.gradebook.ImportWizard.identifierMode": { + "defaultMessage": "匹配学生的依据" + }, + "course.gradebook.ImportWizard.malformed": { + "defaultMessage": "以下单元格不是有效数字:{cells}" + }, + "course.gradebook.ImportWizard.maxMarks": { + "defaultMessage": "最高分" + }, + "course.gradebook.ImportWizard.next": { + "defaultMessage": "下一步" + }, + "course.gradebook.ImportWizard.previewError": { + "defaultMessage": "无法验证文件。请重试。" + }, + "course.gradebook.ImportWizard.stepDefine": { + "defaultMessage": "定义组成部分" }, - "course.forum.forum.markAllAsReadFailed": { - "defaultMessage": "未能将此论坛中的所有主题标记为已读。请稍后再试。" + "course.gradebook.ImportWizard.stepUpload": { + "defaultMessage": "模板和上传" }, - "course.gradebook.GradebookColumnTree.grades": { - "defaultMessage": "成绩" + "course.gradebook.ImportWizard.stepVerify": { + "defaultMessage": "验证" }, - "course.gradebook.GradebookColumnTree.studentInfo": { - "defaultMessage": "学生信息" + "course.gradebook.ImportWizard.studentId": { + "defaultMessage": "学生 ID" }, - "course.gradebook.GradebookColumnTree.alwaysIncluded": { - "defaultMessage": "必选项" + "course.gradebook.ImportWizard.studentIdHint": { + "defaultMessage": "匹配会使用每位学生当前的学生 ID。请在\"管理用户\"中保持学生 ID 为最新。" }, - "course.gradebook.GradebookColumnTree.gamification": { - "defaultMessage": "游戏化相关" + "course.gradebook.ImportWizard.title": { + "defaultMessage": "导入外部评估" }, - "course.gradebook.GradebookIndex.dialogTitle": { - "defaultMessage": "选择列" + "course.gradebook.ImportWizard.unresolved": { + "defaultMessage": "在课程中找不到以下标识符:{ids}" }, - "course.gradebook.GradebookIndex.exportAllTooltip": { - "defaultMessage": "未选择行 - 将导出所有行。" + "course.gradebook.ImportWizard.updatesExisting": { + "defaultMessage": "更新现有项目 - 在成绩册中管理" }, - "course.gradebook.GradebookIndex.exportButton": { - "defaultMessage": "导出所有行" + "course.gradebook.ImportWizard.upload": { + "defaultMessage": "上传已填写的 CSV" }, - "course.gradebook.GradebookIndex.exportRows": { - "defaultMessage": "导出 {count, plural, other {# 行}}" + "course.gradebook.ImportWizard.verify": { + "defaultMessage": "验证" }, - "course.gradebook.GradebookIndex.selectColumns": { - "defaultMessage": "选择列" + "course.gradebook.ImportWizard.weightage": { + "defaultMessage": "权重" }, - "course.gradebook.GradebookIndex.applyAndExport": { - "defaultMessage": "应用并导出" + "course.gradebook.ProjectedTotalHint.policy": { + "defaultMessage": "总分会将未评分的评估计为 0。" }, - "course.gradebook.GradebookIndex.fetchFailure": { - "defaultMessage": "无法获取成绩册。" + "course.gradebook.RenameExternalColumnPrompt.cancel": { + "defaultMessage": "取消" }, - "course.gradebook.GradebookIndex.gradebook": { - "defaultMessage": "成绩册" + "course.gradebook.RenameExternalColumnPrompt.error": { + "defaultMessage": "无法重命名外部评估。" }, - "course.gradebook.GradebookIndex.searchStudents": { - "defaultMessage": "搜索学生" + "course.gradebook.RenameExternalColumnPrompt.nameLabel": { + "defaultMessage": "名称" }, - "course.gradebook.GradebookIndex.noStudents": { - "defaultMessage": "无学生" + "course.gradebook.RenameExternalColumnPrompt.save": { + "defaultMessage": "保存" }, - "course.gradebook.GradebookTable.maxMarks": { - "defaultMessage": "最高分" + "course.gradebook.RenameExternalColumnPrompt.title": { + "defaultMessage": "重命名外部评估" }, - "course.gradebook.GradebookTable.noDataColumnsHint": { - "defaultMessage": "未选择任何成绩列——导出内容将仅包含学生信息。" + "course.gradebook.TotalHint.policy": { + "defaultMessage": "总成绩将未评分的评估按 0 分计算。" }, - "course.gradebook.GradebookTable.noDataColumnsHintWithGamification": { - "defaultMessage": "未选择任何成绩或游戏化列——导出内容将仅包含学生信息。" + "course.gradebook.WeightedViewHint.hint": { + "defaultMessage": "需要加权总成绩吗?您可以设置每个标签页在每位学生总成绩中所占的比重,并在此查看加权总成绩。请在{link}中启用。" + }, + "course.gradebook.WeightedViewHint.settingsLink": { + "defaultMessage": "成绩册设置" }, "course.group.GroupCreationForm.description": { "defaultMessage": "说明(可选)" @@ -5675,27 +6023,27 @@ "course.leaderboard.LeaderboardTable.average": { "defaultMessage": "平均的" }, - "course.leaderboard.LeaderboardTable.experience": { - "defaultMessage": "经验" + "course.leaderboard.LeaderboardTable.averageAchievements": { + "defaultMessage": "平均成就" }, - "course.leaderboard.LeaderboardTable.rank": { - "defaultMessage": "排名" + "course.leaderboard.LeaderboardTable.averageExperience": { + "defaultMessage": "平均经验值" }, - "course.leaderboard.LeaderboardTable.name": { - "defaultMessage": "姓名" + "course.leaderboard.LeaderboardTable.experience": { + "defaultMessage": "经验" }, "course.leaderboard.LeaderboardTable.level": { "defaultMessage": "级别" }, - "course.leaderboard.LeaderboardTable.averageExperience": { - "defaultMessage": "平均经验值" - }, - "course.leaderboard.LeaderboardTable.averageAchievements": { - "defaultMessage": "平均成就" - }, "course.leaderboard.LeaderboardTable.members": { "defaultMessage": "成员" }, + "course.leaderboard.LeaderboardTable.name": { + "defaultMessage": "姓名" + }, + "course.leaderboard.LeaderboardTable.rank": { + "defaultMessage": "排名" + }, "course.leaderboard.LeaderboardTable.titleAchievements": { "defaultMessage": "按成就" }, @@ -5972,6 +6320,15 @@ "course.material.folders.UploadFilesButton.uploadFilesTooltip": { "defaultMessage": "上传" }, + "course.material.folders.WorkbinTable.lastModified": { + "defaultMessage": "最后修改" + }, + "course.material.folders.WorkbinTable.name": { + "defaultMessage": "名称" + }, + "course.material.folders.WorkbinTable.startAt": { + "defaultMessage": "开始于" + }, "course.material.folders.WorkbinTableButtons.DeletionFailure": { "defaultMessage": "无法删除" }, @@ -5984,29 +6341,17 @@ "course.material.folders.WorkbinTableButtons.tableButtonDeleteTooltip": { "defaultMessage": "删除" }, - "course.material.folders.WorkbinTable.name": { - "defaultMessage": "名称" - }, - "course.material.folders.WorkbinTable.lastModified": { - "defaultMessage": "最后修改" - }, - "course.material.folders.WorkbinTable.startAt": { - "defaultMessage": "开始于" - }, - "course.plagiarism.PlagiarismIndex.header.plagiarism": { - "defaultMessage": "抄袭检查" + "course.plagiarism.PlagiarismIndex.assessments.actions": { + "defaultMessage": "操作" }, "course.plagiarism.PlagiarismIndex.assessments.assessment": { "defaultMessage": "测验" }, - "course.plagiarism.PlagiarismIndex.assessments.numSubmitted": { - "defaultMessage": "# 提交" - }, - "course.plagiarism.PlagiarismIndex.assessments.numCheckableQuestions": { - "defaultMessage": "# 可检查问题" + "course.plagiarism.PlagiarismIndex.assessments.confirmRerunMessage": { + "defaultMessage": "某些选定的测验已经完成了抄袭检查。运行新的抄袭检查将删除之前的结果。" }, - "course.plagiarism.PlagiarismIndex.assessments.lastSubmittedAt": { - "defaultMessage": "最后提交于" + "course.plagiarism.PlagiarismIndex.assessments.confirmRerunTitle": { + "defaultMessage": "确认抄袭检查?" }, "course.plagiarism.PlagiarismIndex.assessments.lastRunStatus": { "defaultMessage": "状态" @@ -6014,17 +6359,14 @@ "course.plagiarism.PlagiarismIndex.assessments.lastRunTime": { "defaultMessage": "最后运行于" }, - "course.plagiarism.PlagiarismIndex.assessments.statusNotStarted": { - "defaultMessage": "未开始" - }, - "course.plagiarism.PlagiarismIndex.assessments.statusRunning": { - "defaultMessage": "运行中" + "course.plagiarism.PlagiarismIndex.assessments.lastSubmittedAt": { + "defaultMessage": "最后提交于" }, - "course.plagiarism.PlagiarismIndex.assessments.statusCompleted": { - "defaultMessage": "已完成" + "course.plagiarism.PlagiarismIndex.assessments.newSubmissionsWarning": { + "defaultMessage": "自上次抄袭检查以来检测到新提交" }, - "course.plagiarism.PlagiarismIndex.assessments.statusFailed": { - "defaultMessage": "失败" + "course.plagiarism.PlagiarismIndex.assessments.noNewSubmissionsWarning": { + "defaultMessage": "自上次抄袭检查以来没有新提交" }, "course.plagiarism.PlagiarismIndex.assessments.noPlagiarismCheckableQuestions": { "defaultMessage": "没有可检查的问题" @@ -6032,38 +6374,110 @@ "course.plagiarism.PlagiarismIndex.assessments.notEnoughSubmissions": { "defaultMessage": "提交数量不足" }, + "course.plagiarism.PlagiarismIndex.assessments.numCheckableQuestions": { + "defaultMessage": "# 可检查问题" + }, + "course.plagiarism.PlagiarismIndex.assessments.numSubmitted": { + "defaultMessage": "# 提交" + }, "course.plagiarism.PlagiarismIndex.assessments.runAssessmentsPlagiarism": { "defaultMessage": "新的抄袭检查 ({count})" }, - "course.plagiarism.PlagiarismIndex.assessments.runPlagiarismCheckSuccess": { - "defaultMessage": "已开始 {count, plural, =1 {# 个测验} other {# 个测验}} 的抄袭检查" + "course.plagiarism.PlagiarismIndex.assessments.runPlagiarismCheck": { + "defaultMessage": "运行抄袭检查" }, "course.plagiarism.PlagiarismIndex.assessments.runPlagiarismCheckError": { "defaultMessage": "无法为某些测验开始抄袭检查" }, + "course.plagiarism.PlagiarismIndex.assessments.runPlagiarismCheckSuccess": { + "defaultMessage": "已开始 {count, plural, =1 {# 个测验} other {# 个测验}} 的抄袭检查" + }, "course.plagiarism.PlagiarismIndex.assessments.searchByAssessmentTitle": { "defaultMessage": "按测验标题搜索" }, - "course.plagiarism.PlagiarismIndex.assessments.actions": { - "defaultMessage": "操作" + "course.plagiarism.PlagiarismIndex.assessments.statusCompleted": { + "defaultMessage": "已完成" }, - "course.plagiarism.PlagiarismIndex.assessments.runPlagiarismCheck": { - "defaultMessage": "运行抄袭检查" + "course.plagiarism.PlagiarismIndex.assessments.statusFailed": { + "defaultMessage": "失败" + }, + "course.plagiarism.PlagiarismIndex.assessments.statusNotStarted": { + "defaultMessage": "未开始" + }, + "course.plagiarism.PlagiarismIndex.assessments.statusRunning": { + "defaultMessage": "运行中" }, "course.plagiarism.PlagiarismIndex.assessments.viewResults": { "defaultMessage": "查看结果" }, - "course.plagiarism.PlagiarismIndex.assessments.newSubmissionsWarning": { - "defaultMessage": "自上次抄袭检查以来检测到新提交" + "course.plagiarism.PlagiarismIndex.header.plagiarism": { + "defaultMessage": "抄袭检查" }, - "course.plagiarism.PlagiarismIndex.assessments.noNewSubmissionsWarning": { - "defaultMessage": "自上次抄袭检查以来没有新提交" + "course.statistics.StatisticsIndex.assessments.averageGrade": { + "defaultMessage": "平均成绩" }, - "course.plagiarism.PlagiarismIndex.assessments.confirmRerunTitle": { - "defaultMessage": "确认抄袭检查?" + "course.statistics.StatisticsIndex.assessments.averageTimeTaken": { + "defaultMessage": "平均时间" }, - "course.plagiarism.PlagiarismIndex.assessments.confirmRerunMessage": { - "defaultMessage": "某些选定的测验已经完成了抄袭检查。运行新的抄袭检查将删除之前的结果。" + "course.statistics.StatisticsIndex.assessments.category": { + "defaultMessage": "类别" + }, + "course.statistics.StatisticsIndex.assessments.csvFileTitle": { + "defaultMessage": "测验统计" + }, + "course.statistics.StatisticsIndex.assessments.downloadCsv": { + "defaultMessage": "下载" + }, + "course.statistics.StatisticsIndex.assessments.downloadScoreSummary": { + "defaultMessage": "下载以下测验的成绩摘要?" + }, + "course.statistics.StatisticsIndex.assessments.downloadScoreSummaryFailure": { + "defaultMessage": "下载成绩摘要时出错" + }, + "course.statistics.StatisticsIndex.assessments.downloadScoreSummaryPending": { + "defaultMessage": "正在处理您的下载。请稍候。" + }, + "course.statistics.StatisticsIndex.assessments.downloadScoreSummarySuccess": { + "defaultMessage": "成功下载成绩摘要" + }, + "course.statistics.StatisticsIndex.assessments.numAttemptedStudents": { + "defaultMessage": "尝试人数" + }, + "course.statistics.StatisticsIndex.assessments.numLateStudents": { + "defaultMessage": "迟交人数" + }, + "course.statistics.StatisticsIndex.assessments.numSubmittedStudents": { + "defaultMessage": "已提交人数" + }, + "course.statistics.StatisticsIndex.assessments.searchBar": { + "defaultMessage": "按测验标题、选项卡或类别搜索" + }, + "course.statistics.StatisticsIndex.assessments.selectedNUsers": { + "defaultMessage": "下载 {numUsers} 个学生的成绩摘要?" + }, + "course.statistics.StatisticsIndex.assessments.startAt": { + "defaultMessage": "开始于" + }, + "course.statistics.StatisticsIndex.assessments.stdevGrade": { + "defaultMessage": "成绩标准差" + }, + "course.statistics.StatisticsIndex.assessments.stdevTimeTaken": { + "defaultMessage": "时间标准差" + }, + "course.statistics.StatisticsIndex.assessments.subtitle": { + "defaultMessage": "若要查看和导出单个学生的成绩,请打开成绩册。" + }, + "course.statistics.StatisticsIndex.assessments.subtitleDisabled": { + "defaultMessage": "要查看和导出个别学生的成绩,请启用 成绩册。" + }, + "course.statistics.StatisticsIndex.assessments.tab": { + "defaultMessage": "选项卡" + }, + "course.statistics.StatisticsIndex.assessments.tableTitle": { + "defaultMessage": "测验统计({numStudents} 个学生)" + }, + "course.statistics.StatisticsIndex.assessments.title": { + "defaultMessage": "标题" }, "course.statistics.StatisticsIndex.course.StudentPerformanceTable.achievementCount": { "defaultMessage": "成就数(总计:{courseAchievementCount})" @@ -6140,9 +6554,6 @@ "course.statistics.StatisticsIndex.course.StudentPerformanceTable.videoSubmissionCountHeader": { "defaultMessage": "已观看视频 (总计: {courseVideoCount})" }, - "course.statistics.StatisticsIndex.course.searchBar": { - "defaultMessage": "按学生姓名搜索" - }, "course.statistics.StatisticsIndex.course.StudentProgressionChart.deadlines": { "defaultMessage": "截止日期" }, @@ -6182,6 +6593,9 @@ "course.statistics.StatisticsIndex.course.progressionError": { "defaultMessage": "获取课程进度统计时出了点问题! 请刷新重试。" }, + "course.statistics.StatisticsIndex.course.searchBar": { + "defaultMessage": "按学生姓名搜索" + }, "course.statistics.StatisticsIndex.header.statistics": { "defaultMessage": "数据" }, @@ -6254,6 +6668,9 @@ "course.statistics.StatisticsIndex.staff.averageMarkingTime": { "defaultMessage": "平均时间/测验" }, + "course.statistics.StatisticsIndex.staff.csvFileTitle": { + "defaultMessage": "员工统计" + }, "course.statistics.StatisticsIndex.staff.error": { "defaultMessage": "获取员工统计信息时出了点问题!请刷新重试。" }, @@ -6266,21 +6683,24 @@ "course.statistics.StatisticsIndex.staff.numStudents": { "defaultMessage": "# 学生" }, + "course.statistics.StatisticsIndex.staff.searchBar": { + "defaultMessage": "按员工姓名搜索" + }, "course.statistics.StatisticsIndex.staff.stddev": { "defaultMessage": "标准偏差" }, "course.statistics.StatisticsIndex.staff.tableTitle": { "defaultMessage": "员工统计" }, - "course.statistics.StatisticsIndex.staff.csvFileTitle": { - "defaultMessage": "员工统计" - }, - "course.statistics.StatisticsIndex.staff.searchBar": { - "defaultMessage": "按员工姓名搜索" - }, "course.statistics.StatisticsIndex.staffFailure": { "defaultMessage": "获取员工数据失败!" }, + "course.statistics.StatisticsIndex.students.csvFileTitle": { + "defaultMessage": "学生统计" + }, + "course.statistics.StatisticsIndex.students.email": { + "defaultMessage": "电子邮件" + }, "course.statistics.StatisticsIndex.students.error": { "defaultMessage": "获取学生数据时出了点问题!请刷新重试。" }, @@ -6296,12 +6716,12 @@ "course.statistics.StatisticsIndex.students.name": { "defaultMessage": "姓名" }, - "course.statistics.StatisticsIndex.students.email": { - "defaultMessage": "电子邮件" - }, "course.statistics.StatisticsIndex.students.noStudents": { "defaultMessage": "该课程还没有学生" }, + "course.statistics.StatisticsIndex.students.searchBar": { + "defaultMessage": "按学生姓名、学生类型或外部编号搜索" + }, "course.statistics.StatisticsIndex.students.showMyStudentsOnly": { "defaultMessage": "只显示我的学生" }, @@ -6317,14 +6737,8 @@ "course.statistics.StatisticsIndex.students.videoPercentWatched": { "defaultMessage": "平均 % 已观看" }, - "course.statistics.StatisticsIndex.students.videoSubmissionCount": { - "defaultMessage": "已观看的视频(总计:{courseVideoCount})" - }, - "course.statistics.StatisticsIndex.students.csvFileTitle": { - "defaultMessage": "学生统计" - }, - "course.statistics.StatisticsIndex.students.searchBar": { - "defaultMessage": "按学生姓名、学生类型或外部编号搜索" + "course.statistics.StatisticsIndex.students.videoSubmissionCount": { + "defaultMessage": "已观看的视频(总计:{courseVideoCount})" }, "course.statistics.StatisticsIndex.studentsFailure": { "defaultMessage": "获取学生数据失败!" @@ -7016,6 +7430,27 @@ "course.userInvitation.InviteUsersRegistrationCode.registrationCodeNote": { "defaultMessage": "已被邀请并使用此邀请代码注册课程的用户,不会在邀请页面中显示正确状态。" }, + "course.userInvitations.ExternalIdConflictPrompt.body": { + "defaultMessage": "这些用户已经注册或有待处理的邀请。不会向他们发送新的邀请邮件。您希望保留其当前的外部编号,还是用文件中的值替换它们?" + }, + "course.userInvitations.ExternalIdConflictPrompt.goBack": { + "defaultMessage": "返回" + }, + "course.userInvitations.ExternalIdConflictPrompt.keepExisting": { + "defaultMessage": "保留现有" + }, + "course.userInvitations.ExternalIdConflictPrompt.pendingCourseUserUpdates": { + "defaultMessage": "待处理课程成员更新({count})" + }, + "course.userInvitations.ExternalIdConflictPrompt.pendingInvitationUpdates": { + "defaultMessage": "待处理邀请更新({count})" + }, + "course.userInvitations.ExternalIdConflictPrompt.replace": { + "defaultMessage": "替换" + }, + "course.userInvitations.ExternalIdConflictPrompt.title": { + "defaultMessage": "确认外部编号更新" + }, "course.userInvitations.IndividualInvitations.appendNewRow": { "defaultMessage": "添加行" }, @@ -7031,6 +7466,33 @@ "course.userInvitations.IndividualInvitations.removeInvitation": { "defaultMessage": "删除邀请" }, + "course.userInvitations.InvitationActionButtons.deletionConfirm": { + "defaultMessage": "你确定要删除对{name} ({email}) 的邀请吗?" + }, + "course.userInvitations.InvitationActionButtons.deletionFailure": { + "defaultMessage": "无法删除用户 - {error}" + }, + "course.userInvitations.InvitationActionButtons.deletionSuccess": { + "defaultMessage": "对 {name} 的邀请已删除。" + }, + "course.userInvitations.InvitationActionButtons.deletionTooltip": { + "defaultMessage": "删除邀请" + }, + "course.userInvitations.InvitationActionButtons.resendFailure": { + "defaultMessage": "无法重新发送邀请。" + }, + "course.userInvitations.InvitationActionButtons.resendSuccess": { + "defaultMessage": "向 {email} 重新发送电子邮件邀请!" + }, + "course.userInvitations.InvitationActionButtons.resendTooltip": { + "defaultMessage": "重新发送邀请" + }, + "course.userInvitations.InvitationResultDialog.actionableTitle": { + "defaultMessage": "失败({count})" + }, + "course.userInvitations.InvitationResultDialog.blankHeaderWarning": { + "defaultMessage": "有一个或多个列缺少标题,其数据已被忽略。" + }, "course.userInvitations.InvitationResultDialog.body": { "defaultMessage": "{newInvitationsCount, plural, =0 {No new users were} one {# new user has been} other {# new users have been}} 已被邀请到 Coursemology。 {newCourseUsersCount, plural, =0 {No user with Coursemology account has been} one {# new user with existing Coursemology account has been} other {# new users with existing Coursemology accounts have been}} 添加到此课程。" }, @@ -7058,6 +7520,18 @@ "course.userInvitations.InvitationResultDialog.existingInvitationsInfo": { "defaultMessage": "这些用户已有待处理的邀请。他们未被重新邀请。" }, + "course.userInvitations.InvitationResultDialog.externalIdUpdatedInfo": { + "defaultMessage": "如有指定,外部编号已更新。" + }, + "course.userInvitations.InvitationResultDialog.failedInvitations": { + "defaultMessage": "发送失败({count})" + }, + "course.userInvitations.InvitationResultDialog.failedInvitationsInfo": { + "defaultMessage": "发送邀请邮件时出错,请重试。" + }, + "course.userInvitations.InvitationResultDialog.failedRowsSubtitle": { + "defaultMessage": "红色高亮显示的 {count} 行发送失败" + }, "course.userInvitations.InvitationResultDialog.header": { "defaultMessage": "邀请摘要" }, @@ -7067,14 +7541,8 @@ "course.userInvitations.InvitationResultDialog.newInvitations": { "defaultMessage": "新邀请({count})" }, - "course.userInvitations.InvitationResultDialog.actionableTitle": { - "defaultMessage": "失败({count})" - }, - "course.userInvitations.InvitationResultDialog.failedInvitations": { - "defaultMessage": "发送失败({count})" - }, - "course.userInvitations.InvitationResultDialog.failedInvitationsInfo": { - "defaultMessage": "发送邀请邮件时出错,请重试。" + "course.userInvitations.InvitationResultDialog.summary": { + "defaultMessage": "已发出 {newInvitations} 封新邀请,{newEnrollments} 人直接加入,{alreadyInCourse} 人已在课程中。" }, "course.userInvitations.InvitationResultDialog.summaryFailed": { "defaultMessage": "{count} 个失败。" @@ -7082,14 +7550,8 @@ "course.userInvitations.InvitationResultDialog.updatedSubtitle": { "defaultMessage": "{count} 条已更新 · 优先显示" }, - "course.userInvitations.InvitationResultDialog.blankHeaderWarning": { - "defaultMessage": "有一个或多个列缺少标题,其数据已被忽略。" - }, - "course.userInvitations.InvitationResultDialog.summary": { - "defaultMessage": "已发出 {newInvitations} 封新邀请,{newEnrollments} 人直接加入,{alreadyInCourse} 人已在课程中。" - }, - "course.userInvitations.InvitationResultDialog.failedRowsSubtitle": { - "defaultMessage": "红色高亮显示的 {count} 行发送失败" + "course.userInvitations.InvitationResultExistingTable.previouslyLabel": { + "defaultMessage": "之前的值:{value}" }, "course.userInvitations.InvitationResultFailedTable.duplicateEmailInFile": { "defaultMessage": "上传文件中存在重复的电子邮件地址" @@ -7100,18 +7562,15 @@ "course.userInvitations.InvitationResultFailedTable.externalIdTaken": { "defaultMessage": "该外部编号已分配给另一名课程成员" }, + "course.userInvitations.InvitationResultFailedTable.externalIdTakenEnrolled": { + "defaultMessage": "已是课程成员 - 外部编号未能应用(已分配给另一名成员)" + }, "course.userInvitations.InvitationResultFailedTable.failedToSend": { "defaultMessage": "邀请邮件发送失败,请重试 - 如问题持续发生,请联系我们获取帮助" }, - "course.userInvitations.InvitationResultFailedTable.externalIdTakenEnrolled": { - "defaultMessage": "已是课程成员 — 外部编号未能应用(已分配给另一名成员)" - }, "course.userInvitations.InvitationResultSkippedTable.previouslyLabel": { "defaultMessage": "之前的值:{value}" }, - "course.userInvitations.InvitationResultExistingTable.previouslyLabel": { - "defaultMessage": "之前的值:{value}" - }, "course.userInvitations.InvitationsBarChart.accepted": { "defaultMessage": "已接受邀请" }, @@ -7148,14 +7607,17 @@ "course.userInvitations.InviteUsersFileUpload.failureGeneric": { "defaultMessage": "邀请用户失败。请确保你的数据格式正确。" }, + "course.userInvitations.InviteUsersFileUpload.fileRequired": { + "defaultMessage": "请选择要上传的 CSV 文件。" + }, "course.userInvitations.InviteUsersFileUpload.fileUploadExample": { "defaultMessage": "姓名,电子邮件,外部编号,角色,旁听学生{br}John,test1@example.com,A0123456,student,y{br}Mary,test2@example.com,A0123457,teaching_assistant,n" }, "course.userInvitations.InviteUsersFileUpload.fileUploadExamplePersonalTimeline": { "defaultMessage": "姓名,电子邮件,外部编号,角色,旁听学生,个人时间线{br}John,test1@example.com,A0123456,student,y,otot{br}Mary,test2@example.com,A0123457,teaching_assistant,n,fixed" }, - "course.userInvitations.InviteUsersFileUpload.fileUploadInfoRequired": { - "defaultMessage": "CSV 必须同时包含“姓名”和“电子邮件”列。所有其他列均为可选。" + "course.userInvitations.InviteUsersFileUpload.fileUploadInfo": { + "defaultMessage": "上传具有以下格式的 .csv 文件:" }, "course.userInvitations.InviteUsersFileUpload.fileUploadInfoEmail": { "defaultMessage": "每个邀请在课程内必须使用唯一的电子邮件地址。重复的电子邮件将被跳过。" @@ -7163,24 +7625,21 @@ "course.userInvitations.InviteUsersFileUpload.fileUploadInfoExternalId": { "defaultMessage": "如果提供了外部编号,则这些外部编号在课程内必须唯一。" }, - "course.userInvitations.InviteUsersFileUpload.fileUploadInfo": { - "defaultMessage": "上传具有以下格式的 .csv 文件:" - }, "course.userInvitations.InviteUsersFileUpload.fileUploadInfoPersonalTimeline": { "defaultMessage": "个人时间线可以是[fixed, otot, stragglers, fomo],若省略则默认为 {defaultTimelineAlgorithm}。" }, "course.userInvitations.InviteUsersFileUpload.fileUploadInfoPhantom": { "defaultMessage": "旁听学生可以是 true/false,具有以下值 ['t', 'true', 'y', 'yes'](不区分大小写),若省略则默认为 false。" }, + "course.userInvitations.InviteUsersFileUpload.fileUploadInfoRequired": { + "defaultMessage": "CSV 必须同时包含“姓名”和“电子邮件”列。所有其他列均为可选。" + }, "course.userInvitations.InviteUsersFileUpload.fileUploadInfoRole": { "defaultMessage": "角色可以是[student, observer, teaching_assistant, manager, owner],如果省略则默认为学生。用户只能被助教邀请为学生。" }, "course.userInvitations.InviteUsersFileUpload.importInProgress": { "defaultMessage": "正在导入用户,请稍候…" }, - "course.userInvitations.InviteUsersFileUpload.fileRequired": { - "defaultMessage": "请选择要上传的 CSV 文件。" - }, "course.userInvitations.InviteUsersFileUpload.template": { "defaultMessage": "(模板文件)" }, @@ -7193,27 +7652,6 @@ "course.userInvitations.InviteUsersfileUploadForm.invite": { "defaultMessage": "从文件邀请用户" }, - "course.userInvitations.InvitationActionButtons.deletionConfirm": { - "defaultMessage": "你确定要删除对{name} ({email}) 的邀请吗?" - }, - "course.userInvitations.InvitationActionButtons.deletionFailure": { - "defaultMessage": "无法删除用户 - {error}" - }, - "course.userInvitations.InvitationActionButtons.deletionSuccess": { - "defaultMessage": "对 {name} 的邀请已删除。" - }, - "course.userInvitations.InvitationActionButtons.deletionTooltip": { - "defaultMessage": "删除邀请" - }, - "course.userInvitations.InvitationActionButtons.resendFailure": { - "defaultMessage": "无法重新发送邀请。" - }, - "course.userInvitations.InvitationActionButtons.resendSuccess": { - "defaultMessage": "向 {email} 重新发送电子邮件邀请!" - }, - "course.userInvitations.InvitationActionButtons.resendTooltip": { - "defaultMessage": "重新发送邀请" - }, "course.userInvitations.RegistrationCodeButton.registrationCode": { "defaultMessage": "注册码" }, @@ -7232,24 +7670,24 @@ "course.userInvitations.UserInvitationsTable.accepted": { "defaultMessage": "已接受" }, + "course.userInvitations.UserInvitationsTable.confirmedTooltip": { + "defaultMessage": "已于{confirmedAt}接受" + }, "course.userInvitations.UserInvitationsTable.failed": { "defaultMessage": "失败" }, "course.userInvitations.UserInvitationsTable.noInvitations": { "defaultMessage": "没有邀请。" }, - "course.userInvitations.UserInvitationsTable.searchText": { - "defaultMessage": "按姓名、电子邮件或外部ID搜索" - }, "course.userInvitations.UserInvitationsTable.pending": { "defaultMessage": "待处理" }, + "course.userInvitations.UserInvitationsTable.searchText": { + "defaultMessage": "按姓名、电子邮件或外部ID搜索" + }, "course.userInvitations.UserInvitationsTable.sentTooltip": { "defaultMessage": "已于{sentAt}发送" }, - "course.userInvitations.UserInvitationsTable.confirmedTooltip": { - "defaultMessage": "已于{confirmedAt}接受" - }, "course.userNotification.AchievementGainedPopup.unlocked": { "defaultMessage": "成就解锁!" }, @@ -7286,6 +7724,12 @@ "course.users.ManageUsersTable.ManageUsersTable.searchText": { "defaultMessage": "按姓名、电子邮件或外部ID搜索" }, + "course.users.ManageUsersTable.addIdFailure": { + "defaultMessage": "无法将外部编号设置为 {newId}" + }, + "course.users.ManageUsersTable.addIdSuccess": { + "defaultMessage": "外部编号已设置为 {newId}" + }, "course.users.ManageUsersTable.assignToTimeline": { "defaultMessage": "分配到时间线" }, @@ -7316,6 +7760,12 @@ "course.users.ManageUsersTable.changeAlgorithmSuccess": { "defaultMessage": "将 {name} 的时间线算法更新到 {timeline}" }, + "course.users.ManageUsersTable.changeIdFailure": { + "defaultMessage": "无法将编号从 {oldId} 更改为 {newId}" + }, + "course.users.ManageUsersTable.changeIdSuccess": { + "defaultMessage": "编号已从 {oldId} 更改为 {newId}" + }, "course.users.ManageUsersTable.changeRoleFailure": { "defaultMessage": "无法将 {name} 的角色更改为 {role}。" }, @@ -7331,29 +7781,29 @@ "course.users.ManageUsersTable.defaultTimeline": { "defaultMessage": "默认" }, - "course.users.ManageUsersTable.group": { - "defaultMessage": "组:{name}" + "course.users.ManageUsersTable.deleteIdFailure": { + "defaultMessage": "无法删除外部编号" }, - "course.users.ManageUsersTable.phantomSuccess": { - "defaultMessage": "{name} {isPhantom, select, true {现在是旁听用户} other {现在是普通用户} }。" + "course.users.ManageUsersTable.deleteIdSuccess": { + "defaultMessage": "外部编号已删除" }, - "course.users.ManageUsersTable.addIdFailure": { - "defaultMessage": "无法将外部编号设置为 {newId}" + "course.users.ManageUsersTable.deletionConfirm": { + "defaultMessage": "你确定要删除{role} {name} ({email}) 吗?" }, - "course.users.ManageUsersTable.addIdSuccess": { - "defaultMessage": "外部编号已设置为 {newId}" + "course.users.ManageUsersTable.deletionFailure": { + "defaultMessage": "删除用户失败。" }, - "course.users.ManageUsersTable.changeIdFailure": { - "defaultMessage": "无法将编号从 {oldId} 更改为 {newId}" + "course.users.ManageUsersTable.deletionScheduled": { + "defaultMessage": "{role} {name} ({email}) 已计划删除。" }, - "course.users.ManageUsersTable.changeIdSuccess": { - "defaultMessage": "编号已从 {oldId} 更改为 {newId}" + "course.users.ManageUsersTable.deletionSuccess": { + "defaultMessage": "用户已被删除。" }, - "course.users.ManageUsersTable.deleteIdFailure": { - "defaultMessage": "无法删除外部编号" + "course.users.ManageUsersTable.group": { + "defaultMessage": "组:{name}" }, - "course.users.ManageUsersTable.deleteIdSuccess": { - "defaultMessage": "外部编号已删除" + "course.users.ManageUsersTable.phantomSuccess": { + "defaultMessage": "{name} {isPhantom, select, true {现在是旁听用户} other {现在是普通用户} }。" }, "course.users.ManageUsersTable.renameFailure": { "defaultMessage": "无法将 {oldName} 重命名为 {newName}" @@ -7364,6 +7814,24 @@ "course.users.ManageUsersTable.selectedNUsers": { "defaultMessage": "已选择 {n} 个用户" }, + "course.users.ManageUsersTable.suspend": { + "defaultMessage": "暂停" + }, + "course.users.ManageUsersTable.suspendFailure": { + "defaultMessage": "无法暂停 {name}。" + }, + "course.users.ManageUsersTable.suspendSuccess": { + "defaultMessage": "{name} 现已被暂停。在取消暂停之前,他们无法访问此课程。" + }, + "course.users.ManageUsersTable.unsuspend": { + "defaultMessage": "取消暂停" + }, + "course.users.ManageUsersTable.unsuspendFailure": { + "defaultMessage": "无法取消暂停 {name}。" + }, + "course.users.ManageUsersTable.unsuspendSuccess": { + "defaultMessage": "{name} 不再被暂停。他们现在可以访问课程。" + }, "course.users.ManageUsersTable.updateFailure": { "defaultMessage": "无法更新用户 - {error}" }, @@ -7472,36 +7940,6 @@ "course.users.UpgradeToStaff.upgradeSuccess": { "defaultMessage": "{count, plural, =0 {无用户} one {# 新用户已经} other {# 新用户已经}} 升级到 {role}" }, - "course.users.ManageUsersTable.deletionConfirm": { - "defaultMessage": "你确定要删除{role} {name} ({email}) 吗?" - }, - "course.users.ManageUsersTable.deletionFailure": { - "defaultMessage": "删除用户失败。" - }, - "course.users.ManageUsersTable.deletionScheduled": { - "defaultMessage": "{role} {name} ({email}) 已计划删除。" - }, - "course.users.ManageUsersTable.deletionSuccess": { - "defaultMessage": "用户已被删除。" - }, - "course.users.ManageUsersTable.suspend": { - "defaultMessage": "暂停" - }, - "course.users.ManageUsersTable.suspendFailure": { - "defaultMessage": "无法暂停 {name}。" - }, - "course.users.ManageUsersTable.suspendSuccess": { - "defaultMessage": "{name} 现已被暂停。在取消暂停之前,他们无法访问此课程。" - }, - "course.users.ManageUsersTable.unsuspend": { - "defaultMessage": "取消暂停" - }, - "course.users.ManageUsersTable.unsuspendFailure": { - "defaultMessage": "无法取消暂停 {name}。" - }, - "course.users.ManageUsersTable.unsuspendSuccess": { - "defaultMessage": "{name} 不再被暂停。他们现在可以访问课程。" - }, "course.users.UserManagementTabs.enrolRequestsTitle": { "defaultMessage": "注册请求" }, @@ -7640,27 +8078,27 @@ "course.video.VideoShow.videoTitle": { "defaultMessage": "视频 - {title}" }, + "course.video.VideoTable.actions": { + "defaultMessage": "操作" + }, + "course.video.VideoTable.averageWatched": { + "defaultMessage": "平均观看百分比" + }, "course.video.VideoTable.noVideo": { "defaultMessage": "没有视频" }, - "course.video.VideoTable.title": { - "defaultMessage": "标题" + "course.video.VideoTable.published": { + "defaultMessage": "已发布" }, "course.video.VideoTable.startAt": { "defaultMessage": "开始于" }, + "course.video.VideoTable.title": { + "defaultMessage": "标题" + }, "course.video.VideoTable.watchCount": { "defaultMessage": "观看次数" }, - "course.video.VideoTable.averageWatched": { - "defaultMessage": "平均观看百分比" - }, - "course.video.VideoTable.published": { - "defaultMessage": "已发布" - }, - "course.video.VideoTable.actions": { - "defaultMessage": "操作" - }, "course.video.VideosIndex.fetchVideosFailure": { "defaultMessage": "无法检索视频。" }, @@ -7847,12 +8285,12 @@ "lib.components.core.Expandable.showMore": { "defaultMessage": "显示更多" }, - "lib.components.core.Note.noteHeader": { - "defaultMessage": "提示" - }, "lib.components.core.Note.errorHeader": { "defaultMessage": "错误" }, + "lib.components.core.Note.noteHeader": { + "defaultMessage": "提示" + }, "lib.components.core.banners.ServerUnreachableBanner.refreshPage": { "defaultMessage": "刷新页面" }, @@ -7982,6 +8420,72 @@ "lib.components.form.fields.SingleFileInput.removeFile": { "defaultMessage": "删除文件" }, + "lib.components.getHelp.filter.filterAssessmentLabel": { + "defaultMessage": "按测验筛选" + }, + "lib.components.getHelp.filter.filterCourseLabel": { + "defaultMessage": "按课程筛选" + }, + "lib.components.getHelp.filter.filterEndDateLabel": { + "defaultMessage": "结束日期" + }, + "lib.components.getHelp.filter.filterStartDateLabel": { + "defaultMessage": "开始日期" + }, + "lib.components.getHelp.filter.filterStudentLabel": { + "defaultMessage": "按学生筛选" + }, + "lib.components.getHelp.filter.lastFourteenDays": { + "defaultMessage": "最近14天" + }, + "lib.components.getHelp.filter.lastSevenDays": { + "defaultMessage": "最近7天" + }, + "lib.components.getHelp.filter.lastSixMonths": { + "defaultMessage": "最近6个月" + }, + "lib.components.getHelp.filter.lastThirtyDays": { + "defaultMessage": "最近30天" + }, + "lib.components.getHelp.filter.lastTwelveMonths": { + "defaultMessage": "最近12个月" + }, + "lib.components.getHelp.header": { + "defaultMessage": "最近的获取帮助活动 ({total, plural, other {#个对话}})" + }, + "lib.components.getHelp.table.assessmentTitle": { + "defaultMessage": "测验" + }, + "lib.components.getHelp.table.courseTitle": { + "defaultMessage": "课程" + }, + "lib.components.getHelp.table.createdAt": { + "defaultMessage": "最后消息时间" + }, + "lib.components.getHelp.table.instanceTitle": { + "defaultMessage": "实例" + }, + "lib.components.getHelp.table.lastMessage": { + "defaultMessage": "最后消息" + }, + "lib.components.getHelp.table.messageCount": { + "defaultMessage": "消息数" + }, + "lib.components.getHelp.table.questionNumber": { + "defaultMessage": "问题" + }, + "lib.components.getHelp.table.studentName": { + "defaultMessage": "姓名" + }, + "lib.components.getHelp.validation.endDateBeforeStartDate": { + "defaultMessage": "结束日期必须大于或等于开始日期" + }, + "lib.components.getHelp.validation.exceedDateRange": { + "defaultMessage": "日期范围不能超过365天" + }, + "lib.components.getHelp.validation.invalidDateSelection": { + "defaultMessage": "无效日期" + }, "lib.components.navigation.AdminPopupMenuList.adminPanel": { "defaultMessage": "系统管理面板" }, @@ -8018,6 +8522,21 @@ "lib.components.navigation.CourseSwitcherPopupMenu.thisCourse": { "defaultMessage": "此课程" }, + "lib.components.table.MuiColumnPickerPrompt.apply": { + "defaultMessage": "应用" + }, + "lib.components.table.MuiColumnPickerPrompt.cancel": { + "defaultMessage": "取消" + }, + "lib.components.table.MuiColumnPickerPrompt.defaultTitle": { + "defaultMessage": "选择列" + }, + "lib.components.table.MuiTableToolbar.directExport": { + "defaultMessage": "导出" + }, + "lib.components.table.MuiTableToolbar.exportTrigger": { + "defaultMessage": "导出…" + }, "lib.hooks.router.usePrompt.sureYouWantToLeave": { "defaultMessage": "确定要离开此页面吗?你将丢失未保存的更改。" }, @@ -8132,21 +8651,21 @@ "lib.translations.course.users.manageUsersHeader": { "defaultMessage": "管理用户" }, - "lib.translations.course.users.roles.student": { - "defaultMessage": "学生" - }, - "lib.translations.course.users.roles.teachingAssistant": { - "defaultMessage": "助教" + "lib.translations.course.users.roles.manager": { + "defaultMessage": "管理员" }, "lib.translations.course.users.roles.observer": { "defaultMessage": "观察者" }, - "lib.translations.course.users.roles.manager": { - "defaultMessage": "管理员" - }, "lib.translations.course.users.roles.owner": { "defaultMessage": "拥有者" }, + "lib.translations.course.users.roles.student": { + "defaultMessage": "学生" + }, + "lib.translations.course.users.roles.teachingAssistant": { + "defaultMessage": "助教" + }, "lib.translations.experimental": { "defaultMessage": "实验性的" }, @@ -8258,14 +8777,14 @@ "lib.translations.form.validation.startEndDateValidationError": { "defaultMessage": "必须在开始日期之后" }, - "lib.translations.instance.users.roles.normal": { - "defaultMessage": "普通用户" + "lib.translations.instance.users.roles.administrator": { + "defaultMessage": "平台管理员" }, "lib.translations.instance.users.roles.instructor": { "defaultMessage": "教学导师" }, - "lib.translations.instance.users.roles.administrator": { - "defaultMessage": "平台管理员" + "lib.translations.instance.users.roles.normal": { + "defaultMessage": "普通用户" }, "lib.translations.messages.fetchingError": { "defaultMessage": "加载数据时出错。请重新加载并重试。" @@ -8276,17 +8795,26 @@ "lib.translations.messages.loadImageError": { "defaultMessage": "加载图片时出错。请尝试选择另一张。" }, + "lib.translations.myStudents": { + "defaultMessage": "我的学生" + }, "lib.translations.myStudentsIncludingPhantoms": { "defaultMessage": "我的学生(包括旁听学生)" }, - "lib.translations.studentsIncludingPhantoms": { - "defaultMessage": "学生(包括旁听学生)" + "lib.translations.no": { + "defaultMessage": "否" + }, + "lib.translations.staff": { + "defaultMessage": "职员" }, "lib.translations.staffIncludingPhantoms": { "defaultMessage": "职员(包括旁听学生)" }, - "lib.translations.no": { - "defaultMessage": "否" + "lib.translations.students": { + "defaultMessage": "学生" + }, + "lib.translations.studentsIncludingPhantoms": { + "defaultMessage": "学生(包括旁听学生)" }, "lib.translations.summary": { "defaultMessage": "概括" @@ -8324,15 +8852,15 @@ "lib.translations.table.column.createdAt": { "defaultMessage": "创建于" }, + "lib.translations.table.column.currentExternalId": { + "defaultMessage": "当前外部编号" + }, "lib.translations.table.column.designation": { "defaultMessage": "职位" }, "lib.translations.table.column.email": { "defaultMessage": "电子邮件" }, - "lib.translations.table.column.externalId": { - "defaultMessage": "外部编号" - }, "lib.translations.table.column.endAt": { "defaultMessage": "结束于" }, @@ -8342,6 +8870,9 @@ "lib.translations.table.column.experiencePointsAwarded": { "defaultMessage": "获得的经验值" }, + "lib.translations.table.column.externalId": { + "defaultMessage": "外部编号" + }, "lib.translations.table.column.groups": { "defaultMessage": "组" }, @@ -8384,6 +8915,9 @@ "lib.translations.table.column.name": { "defaultMessage": "姓名" }, + "lib.translations.table.column.newExternalId": { + "defaultMessage": "新外部编号" + }, "lib.translations.table.column.optional": { "defaultMessage": "选填" }, @@ -8465,30 +8999,15 @@ "material.attemptLoader.errorAccessingMaterial": { "defaultMessage": "获取该资料时发生错误,请稍后再试。" }, - "system.admin.instance.instance.InstanceAdminNavigator.announcements": { - "defaultMessage": "公告" - }, - "system.admin.instance.instance.InstanceAdminNavigator.components": { - "defaultMessage": "组件" - }, - "system.admin.instance.instance.InstanceAdminNavigator.courses": { - "defaultMessage": "课程" - }, - "system.admin.instance.instance.InstanceAdminNavigator.roleRequests": { - "defaultMessage": "角色要求" - }, - "system.admin.instance.instance.InstanceAdminNavigator.users": { - "defaultMessage": "用户" - }, - "system.admin.instance.instance.InstanceAdminNavigator.getHelp": { - "defaultMessage": "获取帮助" - }, "system.admin.admin.AdminNavigator.announcements": { "defaultMessage": "系统公告" }, "system.admin.admin.AdminNavigator.courses": { "defaultMessage": "课程" }, + "system.admin.admin.AdminNavigator.getHelp": { + "defaultMessage": "获取帮助" + }, "system.admin.admin.AdminNavigator.instances": { "defaultMessage": "实例" }, @@ -8498,9 +9017,6 @@ "system.admin.admin.AdminNavigator.users": { "defaultMessage": "用户" }, - "system.admin.admin.AdminNavigator.getHelp": { - "defaultMessage": "获取帮助" - }, "system.admin.admin.AnnouncementsIndex.fetchAnnouncementsFailure": { "defaultMessage": "无法获取公告" }, @@ -8591,18 +9107,18 @@ "system.admin.admin.UsersButton.deletionConfirm": { "defaultMessage": "您确定要继续此操作吗?" }, - "system.admin.admin.UsersButton.deletionFailure": { - "defaultMessage": "删除用户失败 - {error}" - }, - "system.admin.admin.UsersButton.deletionSuccess": { - "defaultMessage": "用户已被删除。" - }, "system.admin.admin.UsersButton.deletionConfirmTitle": { "defaultMessage": "正在删除{role}用户 {name}({email})" }, + "system.admin.admin.UsersButton.deletionFailure": { + "defaultMessage": "删除用户失败 - {error}" + }, "system.admin.admin.UsersButton.deletionPromptContent": { "defaultMessage": "删除该用户将永久删除以下{count, plural, one {课程} other {课程}}中的相关数据:" }, + "system.admin.admin.UsersButton.deletionSuccess": { + "defaultMessage": "用户已被删除。" + }, "system.admin.admin.UsersIndex.activeUsers": { "defaultMessage": "活跃用户:{allCount}({adminCount} 管理员,{normalCount} 普通用户){br}(过去7天内活跃)" }, @@ -8618,9 +9134,6 @@ "system.admin.admin.UsersTable.changeRoleSuccess": { "defaultMessage": "已成功将 {name} 的角色更改为 {role}。" }, - "system.admin.users.UsersTable.instanceEntry": { - "defaultMessage": "{instanceName}{courseCount, plural, =0 {} one {(1 门课程)} other {({courseCount} 门课程)}}" - }, "system.admin.admin.UsersTable.renameSuccess": { "defaultMessage": "{oldName} 已重命名为 {newName}。" }, @@ -8648,6 +9161,24 @@ "system.admin.instance.instance.IndividualInvitations.invite": { "defaultMessage": "邀请所有用户" }, + "system.admin.instance.instance.InstanceAdminNavigator.announcements": { + "defaultMessage": "公告" + }, + "system.admin.instance.instance.InstanceAdminNavigator.components": { + "defaultMessage": "组件" + }, + "system.admin.instance.instance.InstanceAdminNavigator.courses": { + "defaultMessage": "课程" + }, + "system.admin.instance.instance.InstanceAdminNavigator.getHelp": { + "defaultMessage": "获取帮助" + }, + "system.admin.instance.instance.InstanceAdminNavigator.roleRequests": { + "defaultMessage": "角色要求" + }, + "system.admin.instance.instance.InstanceAdminNavigator.users": { + "defaultMessage": "用户" + }, "system.admin.instance.instance.InstanceAnnouncementsIndex.fetchAnnouncementsFailure": { "defaultMessage": "无法获取公告" }, @@ -8768,6 +9299,27 @@ "system.admin.instance.instance.InstanceUsersTabs.usersTab": { "defaultMessage": "用户" }, + "system.admin.instance.instance.InvitationActionButtons.deletionConfirm": { + "defaultMessage": "你确定要删除对{name} ({email}) 的邀请吗?" + }, + "system.admin.instance.instance.InvitationActionButtons.deletionFailure": { + "defaultMessage": "无法删除用户 - {error}" + }, + "system.admin.instance.instance.InvitationActionButtons.deletionSuccess": { + "defaultMessage": "{name} 的邀请已删除。" + }, + "system.admin.instance.instance.InvitationActionButtons.deletionTooltip": { + "defaultMessage": "删除邀请" + }, + "system.admin.instance.instance.InvitationActionButtons.resendFailure": { + "defaultMessage": "未能重新发送邀请 - {error}" + }, + "system.admin.instance.instance.InvitationActionButtons.resendSuccess": { + "defaultMessage": "向 {email} 重新发送电子邮件邀请!" + }, + "system.admin.instance.instance.InvitationActionButtons.resendTooltip": { + "defaultMessage": "重新发送邀请" + }, "system.admin.instance.instance.InvitationResultDialog.close": { "defaultMessage": "关闭" }, @@ -8798,27 +9350,6 @@ "system.admin.instance.instance.InvitationResultDialog.newInvitations": { "defaultMessage": "新邀请({count})" }, - "system.admin.instance.instance.InvitationActionButtons.deletionConfirm": { - "defaultMessage": "你确定要删除对{name} ({email}) 的邀请吗?" - }, - "system.admin.instance.instance.InvitationActionButtons.deletionFailure": { - "defaultMessage": "无法删除用户 - {error}" - }, - "system.admin.instance.instance.InvitationActionButtons.deletionSuccess": { - "defaultMessage": "{name} 的邀请已删除。" - }, - "system.admin.instance.instance.InvitationActionButtons.deletionTooltip": { - "defaultMessage": "删除邀请" - }, - "system.admin.instance.instance.InvitationActionButtons.resendFailure": { - "defaultMessage": "未能重新发送邀请 - {error}" - }, - "system.admin.instance.instance.InvitationActionButtons.resendSuccess": { - "defaultMessage": "向 {email} 重新发送电子邮件邀请!" - }, - "system.admin.instance.instance.InvitationActionButtons.resendTooltip": { - "defaultMessage": "重新发送邀请" - }, "system.admin.instance.instance.PendingRoleRequestsButton.approveFailure": { "defaultMessage": "未能批准角色请求 - {error}" }, @@ -8864,6 +9395,9 @@ "system.admin.instance.instance.UserInvitationsTable.accepted": { "defaultMessage": "已接受" }, + "system.admin.instance.instance.UserInvitationsTable.confirmedTooltip": { + "defaultMessage": "已于{confirmedAt}接受" + }, "system.admin.instance.instance.UserInvitationsTable.failed": { "defaultMessage": "失败" }, @@ -8876,27 +9410,24 @@ "system.admin.instance.instance.UserInvitationsTable.sentTooltip": { "defaultMessage": "已于{sentAt}发送" }, - "system.admin.instance.instance.UserInvitationsTable.confirmedTooltip": { - "defaultMessage": "已于{confirmedAt}接受" - }, "system.admin.instance.instance.UsersButton.deleteTooltip": { "defaultMessage": "移除用户" }, "system.admin.instance.instance.UsersButton.deletionConfirm": { "defaultMessage": "您确定要继续此操作吗?" }, - "system.admin.instance.instance.UsersButton.deletionFailure": { - "defaultMessage": "无法删除用户 - {error}" - }, - "system.admin.instance.instance.UsersButton.deletionSuccess": { - "defaultMessage": "用户已从该实例中移除。" - }, "system.admin.instance.instance.UsersButton.deletionConfirmTitle": { "defaultMessage": "正在移除{role}用户 {name}({email})" }, + "system.admin.instance.instance.UsersButton.deletionFailure": { + "defaultMessage": "无法删除用户 - {error}" + }, "system.admin.instance.instance.UsersButton.deletionPromptContent": { "defaultMessage": "移除该用户可能会导致以下{count, plural, one {课程} other {课程}}出现错误:" }, + "system.admin.instance.instance.UsersButton.deletionSuccess": { + "defaultMessage": "用户已从该实例中移除。" + }, "system.admin.instance.instance.UsersTable.changeRoleSuccess": { "defaultMessage": "已成功将 {name} 的角色更改为 {role}。" }, @@ -8918,6 +9449,9 @@ "system.admin.users.UsersTable.fetchFilteredUsersFailure": { "defaultMessage": "无法获取用户。" }, + "system.admin.users.UsersTable.instanceEntry": { + "defaultMessage": "{instanceName}{courseCount, plural, =0 {} one {(1 门课程)} other {({courseCount} 门课程)}}" + }, "user.accountSettings": { "defaultMessage": "账户设置" }, diff --git a/config/locales/en/activerecord/errors.yml b/config/locales/en/activerecord/errors.yml index 713858a6dc..c425d123fc 100644 --- a/config/locales/en/activerecord/errors.yml +++ b/config/locales/en/activerecord/errors.yml @@ -6,6 +6,10 @@ en: attributes: reference_timelines: must_have_at_most_one_default: 'must have at most one default' + course/gradebook/contribution: + attributes: + base: + exactly_one_contributor: "must reference exactly one contributor (a tab or an external assessment)" course/announcement: attributes: end_at: diff --git a/config/locales/ko/activerecord/errors.yml b/config/locales/ko/activerecord/errors.yml index 6b6c01e11c..76f97ba371 100644 --- a/config/locales/ko/activerecord/errors.yml +++ b/config/locales/ko/activerecord/errors.yml @@ -6,6 +6,10 @@ ko: attributes: reference_timelines: must_have_at_most_one_default: '최대 하나의 기본값만 있어야 합니다' + course/gradebook/contribution: + attributes: + base: + exactly_one_contributor: '정확히 하나의 기여 대상(탭 또는 외부 평가)을 참조해야 합니다' course/announcement: attributes: end_at: diff --git a/config/locales/zh/activerecord/errors.yml b/config/locales/zh/activerecord/errors.yml index 6a654814f3..c67c1acf63 100644 --- a/config/locales/zh/activerecord/errors.yml +++ b/config/locales/zh/activerecord/errors.yml @@ -6,6 +6,10 @@ zh: attributes: reference_timelines: must_have_at_most_one_default: '至少要包含一个默认值' + course/gradebook/contribution: + attributes: + base: + exactly_one_contributor: '必须且只能引用一个贡献项(一个标签页或一个外部评估)' course/announcement: attributes: end_at: diff --git a/config/routes.rb b/config/routes.rb index 0ff051754c..9e8094d214 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -502,6 +502,11 @@ resource :gradebook, only: [] do get '/' => 'gradebook#index' patch '/weights' => 'gradebook#update_weights' + resources :external_assessments, only: [] do + member do + put 'grades' => 'external_assessments#grades' + end + end end scope module: :discussion do diff --git a/db/migrate/20260615000000_create_course_external_assessments_and_grades.rb b/db/migrate/20260615000000_create_course_external_assessments_and_grades.rb new file mode 100644 index 0000000000..28a240a467 --- /dev/null +++ b/db/migrate/20260615000000_create_course_external_assessments_and_grades.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true +class CreateCourseExternalAssessmentsAndGrades < ActiveRecord::Migration[7.2] + def change + create_table :course_external_assessments do |t| + t.references :course, null: false, + foreign_key: { to_table: :courses, + name: 'fk_course_external_assessments_course_id' }, + index: { name: 'fk__course_external_assessments_course_id' } + t.string :title, null: false + t.decimal :maximum_grade, precision: 4, scale: 1, null: false + t.references :creator, null: false, + foreign_key: { to_table: :users, + name: 'fk_course_external_assessments_creator_id' }, + index: { name: 'fk__course_external_assessments_creator_id' } + t.references :updater, null: false, + foreign_key: { to_table: :users, + name: 'fk_course_external_assessments_updater_id' }, + index: { name: 'fk__course_external_assessments_updater_id' } + t.timestamps null: false + end + add_index :course_external_assessments, [:course_id, :title], + unique: true, name: 'index_course_external_assessments_on_course_id_and_title' + + create_table :course_external_assessment_grades do |t| + t.references :external_assessment, null: false, + foreign_key: { to_table: :course_external_assessments, + name: 'fk_course_external_assessment_grades_' \ + 'external_assessment_id' }, + index: { name: 'fk__course_external_assessment_grades_external_assessment_id' } + t.references :course_user, null: false, + foreign_key: { to_table: :course_users, + name: 'fk_course_external_assessment_grades_course_user_id' }, + index: { name: 'fk__course_external_assessment_grades_course_user_id' } + t.decimal :grade, precision: 4, scale: 1, null: true + t.string :imported_identifier, null: true + t.references :creator, null: false, + foreign_key: { to_table: :users, name: 'fk_course_external_assessment_grades_creator_id' }, + index: { name: 'fk__course_external_assessment_grades_creator_id' } + t.references :updater, null: false, + foreign_key: { to_table: :users, name: 'fk_course_external_assessment_grades_updater_id' }, + index: { name: 'fk__course_external_assessment_grades_updater_id' } + t.timestamps null: false + end + add_index :course_external_assessment_grades, [:external_assessment_id, :course_user_id], + unique: true, name: 'index_course_external_assessment_grades_on_ea_id_and_cu_id' + end +end diff --git a/db/migrate/20260616000000_add_external_assessment_to_gradebook_contributions.rb b/db/migrate/20260616000000_add_external_assessment_to_gradebook_contributions.rb new file mode 100644 index 0000000000..9bfad2e985 --- /dev/null +++ b/db/migrate/20260616000000_add_external_assessment_to_gradebook_contributions.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true +class AddExternalAssessmentToGradebookContributions < ActiveRecord::Migration[7.2] + def change + add_reference :course_gradebook_contributions, :external_assessment, null: true, + foreign_key: { to_table: :course_external_assessments, on_delete: :cascade }, + index: { unique: true, + name: 'index_course_gradebook_contributions_on_external_assessment_id' } + + # Exactly one contributor: either a native tab, or an external assessment. + add_check_constraint :course_gradebook_contributions, + '(tab_id IS NOT NULL) <> (external_assessment_id IS NOT NULL)', + name: 'chk_gradebook_contribution_exactly_one_contributor' + end +end diff --git a/db/migrate/20260622000000_add_bounds_to_course_external_assessments.rb b/db/migrate/20260622000000_add_bounds_to_course_external_assessments.rb new file mode 100644 index 0000000000..423a2dfd6c --- /dev/null +++ b/db/migrate/20260622000000_add_bounds_to_course_external_assessments.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true +class AddBoundsToCourseExternalAssessments < ActiveRecord::Migration[7.2] + def change + add_column :course_external_assessments, :floor_at_zero, :boolean, null: false, default: true + add_column :course_external_assessments, :cap_at_maximum, :boolean, null: false, default: true + end +end diff --git a/db/migrate/20260623000000_change_external_assessment_grade_precision_to_two_decimals.rb b/db/migrate/20260623000000_change_external_assessment_grade_precision_to_two_decimals.rb new file mode 100644 index 0000000000..f6ffa1c940 --- /dev/null +++ b/db/migrate/20260623000000_change_external_assessment_grade_precision_to_two_decimals.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true +# External grades are imported from Canvas and SoftMark, both of which record marks +# to two decimal places. The columns were decimal(4,1), which silently rounds an +# imported 87.25 to 87.3 on store. Widen to decimal(5,2) — same 3 integer digits +# (max 999.99), one extra decimal. Externals only; native grades stay decimal(4,1). +class ChangeExternalAssessmentGradePrecisionToTwoDecimals < ActiveRecord::Migration[7.2] + def up + change_column :course_external_assessment_grades, :grade, + :decimal, precision: 5, scale: 2, null: true + change_column :course_external_assessments, :maximum_grade, + :decimal, precision: 5, scale: 2, null: false + end + + def down + change_column :course_external_assessment_grades, :grade, + :decimal, precision: 4, scale: 1, null: true + change_column :course_external_assessments, :maximum_grade, + :decimal, precision: 4, scale: 1, null: false + end +end diff --git a/db/schema.rb b/db/schema.rb index d1a22b40e8..3171a997e1 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.2].define(version: 2026_06_11_000000) do +ActiveRecord::Schema[7.2].define(version: 2026_06_23_000000) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" enable_extension "uuid-ossp" @@ -762,6 +762,38 @@ t.index ["updater_id"], name: "fk__course_experience_points_records_updater_id" end + create_table "course_external_assessment_grades", force: :cascade do |t| + t.bigint "external_assessment_id", null: false + t.bigint "course_user_id", null: false + t.decimal "grade", precision: 5, scale: 2 + t.string "imported_identifier" + t.bigint "creator_id", null: false + t.bigint "updater_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["course_user_id"], name: "fk__course_external_assessment_grades_course_user_id" + t.index ["creator_id"], name: "fk__course_external_assessment_grades_creator_id" + t.index ["external_assessment_id", "course_user_id"], name: "index_course_external_assessment_grades_on_ea_id_and_cu_id", unique: true + t.index ["external_assessment_id"], name: "fk__course_external_assessment_grades_external_assessment_id" + t.index ["updater_id"], name: "fk__course_external_assessment_grades_updater_id" + end + + create_table "course_external_assessments", force: :cascade do |t| + t.bigint "course_id", null: false + t.string "title", null: false + t.decimal "maximum_grade", precision: 5, scale: 2, null: false + t.bigint "creator_id", null: false + t.bigint "updater_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.boolean "floor_at_zero", default: true, null: false + t.boolean "cap_at_maximum", default: true, null: false + t.index ["course_id", "title"], name: "index_course_external_assessments_on_course_id_and_title", unique: true + t.index ["course_id"], name: "fk__course_external_assessments_course_id" + t.index ["creator_id"], name: "fk__course_external_assessments_creator_id" + t.index ["updater_id"], name: "fk__course_external_assessments_updater_id" + end + create_table "course_forum_discussion_references", force: :cascade do |t| t.datetime "created_at", precision: nil, null: false t.datetime "updated_at", precision: nil, null: false @@ -879,10 +911,13 @@ t.bigint "updater_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.bigint "external_assessment_id" t.index ["course_id"], name: "fk__course_gradebook_contributions_course_id" t.index ["creator_id"], name: "fk__course_gradebook_contributions_creator_id" + t.index ["external_assessment_id"], name: "index_course_gradebook_contributions_on_external_assessment_id", unique: true t.index ["tab_id"], name: "index_course_gradebook_contributions_on_tab_id", unique: true t.index ["updater_id"], name: "fk__course_gradebook_contributions_updater_id" + t.check_constraint "(tab_id IS NOT NULL) <> (external_assessment_id IS NOT NULL)", name: "chk_gradebook_contribution_exactly_one_contributor" end create_table "course_group_categories", force: :cascade do |t| @@ -1925,6 +1960,13 @@ add_foreign_key "course_experience_points_records", "users", column: "awarder_id", name: "fk_course_experience_points_records_awarder_id" add_foreign_key "course_experience_points_records", "users", column: "creator_id", name: "fk_course_experience_points_records_creator_id" add_foreign_key "course_experience_points_records", "users", column: "updater_id", name: "fk_course_experience_points_records_updater_id" + add_foreign_key "course_external_assessment_grades", "course_external_assessments", column: "external_assessment_id", name: "fk_course_external_assessment_grades_external_assessment_id" + add_foreign_key "course_external_assessment_grades", "course_users", name: "fk_course_external_assessment_grades_course_user_id" + add_foreign_key "course_external_assessment_grades", "users", column: "creator_id", name: "fk_course_external_assessment_grades_creator_id" + add_foreign_key "course_external_assessment_grades", "users", column: "updater_id", name: "fk_course_external_assessment_grades_updater_id" + add_foreign_key "course_external_assessments", "courses", name: "fk_course_external_assessments_course_id" + add_foreign_key "course_external_assessments", "users", column: "creator_id", name: "fk_course_external_assessments_creator_id" + add_foreign_key "course_external_assessments", "users", column: "updater_id", name: "fk_course_external_assessments_updater_id" add_foreign_key "course_forum_discussion_references", "course_forum_discussions", column: "discussion_id", name: "fk_course_forum_discussion_references_discussion_id" add_foreign_key "course_forum_discussion_references", "course_forum_imports", column: "forum_import_id", name: "fk_course_forum_discussion_references_forum_import_id" add_foreign_key "course_forum_discussion_references", "users", column: "creator_id", name: "fk_course_forum_discussion_references_creator_id" @@ -1948,6 +1990,7 @@ add_foreign_key "course_gradebook_assessment_contributions", "users", column: "creator_id" add_foreign_key "course_gradebook_assessment_contributions", "users", column: "updater_id" add_foreign_key "course_gradebook_contributions", "course_assessment_tabs", column: "tab_id", on_delete: :cascade + add_foreign_key "course_gradebook_contributions", "course_external_assessments", column: "external_assessment_id", on_delete: :cascade add_foreign_key "course_gradebook_contributions", "courses" add_foreign_key "course_gradebook_contributions", "users", column: "creator_id" add_foreign_key "course_gradebook_contributions", "users", column: "updater_id" diff --git a/spec/controllers/course/external_assessments_controller_spec.rb b/spec/controllers/course/external_assessments_controller_spec.rb new file mode 100644 index 0000000000..36d3273be9 --- /dev/null +++ b/spec/controllers/course/external_assessments_controller_spec.rb @@ -0,0 +1,80 @@ +# frozen_string_literal: true +require 'rails_helper' + +RSpec.describe Course::ExternalAssessmentsController, type: :controller do + let(:instance) { Instance.default } + + with_tenant(:instance) do + let(:course) { create(:course) } + let(:ta) { create(:course_teaching_assistant, course: course) } + + describe '#grades' do + render_views + let!(:external) { create(:course_external_assessment, course: course) } + let(:gb_student) { create(:course_student, course: course) } + + context 'as a teaching assistant (grading-capable staff)' do + before { controller_sign_in(controller, ta.user) } + + # The gradebook frontend keys students by user_id (json.studentId == course_user.user_id), + # so #grades must resolve the course_user from the `studentId` param, not a course_user PK. + it 'inserts a grade for a student who has none' do + expect do + put :grades, params: { course_id: course.id, id: external.id, format: :json, + studentId: gb_student.user_id, grade: 88 } + end.to change { Course::ExternalAssessmentGrade.count }.by(1) + expect(response).to be_successful + data = JSON.parse(response.body) + expect(data['studentId']).to eq(gb_student.user_id) + expect(data['assessmentId']).to eq(-external.id) + expect(data['grade']).to eq(88.0) + expect(Course::ExternalAssessmentGrade.last.course_user).to eq(gb_student) + end + + it 'updates an existing grade in place (no duplicate row)' do + grade = create(:course_external_assessment_grade, + external_assessment: external, course_user: gb_student, grade: 10) + expect do + put :grades, params: { course_id: course.id, id: external.id, format: :json, + studentId: gb_student.user_id, grade: 20 } + end.not_to(change { Course::ExternalAssessmentGrade.count }) + expect(grade.reload.grade).to eq(20) + end + + it 'stores a grade with two decimal places without rounding' do + put :grades, params: { course_id: course.id, id: external.id, format: :json, + studentId: gb_student.user_id, grade: '87.25' } + expect(response).to be_successful + expect(Course::ExternalAssessmentGrade.last.grade).to eq(BigDecimal('87.25')) + end + + it 'clears a grade to null (ungraded) when grade is blank' do + grade = create(:course_external_assessment_grade, + external_assessment: external, course_user: gb_student, grade: 10) + put :grades, params: { course_id: course.id, id: external.id, format: :json, + studentId: gb_student.user_id, grade: '' } + expect(grade.reload.grade).to be_nil + end + + it 'returns 404 when the student does not belong to the course' do + other_student = create(:course_student) + put :grades, params: { course_id: course.id, id: external.id, format: :json, + studentId: other_student.user_id, grade: 50 } + expect(response).to have_http_status(:not_found) + end + end + + context 'as a student' do + let(:viewer) { create(:course_student, course: course) } + before { controller_sign_in(controller, viewer.user) } + + it 'is denied' do + expect do + put :grades, params: { course_id: course.id, id: external.id, format: :json, + studentId: gb_student.user_id, grade: 5 } + end.to raise_error(CanCan::AccessDenied) + end + end + end + end +end diff --git a/spec/controllers/course/gradebook_controller_spec.rb b/spec/controllers/course/gradebook_controller_spec.rb index 59397f4120..74d54d758f 100644 --- a/spec/controllers/course/gradebook_controller_spec.rb +++ b/spec/controllers/course/gradebook_controller_spec.rb @@ -199,6 +199,114 @@ expect(sub['grade']).to be_nil end end + + context 'when the course has an external assessment' do + render_views + let(:ta) { create(:course_teaching_assistant, course: course) } + let(:gb_student) { create(:course_student, course: course) } + let!(:external) do + create(:course_external_assessment, course: course, title: 'Midterm', maximum_grade: 50) + end + let!(:external_grade) do + create(:course_external_assessment_grade, + external_assessment: external, course_user: gb_student, grade: 41) + end + before { controller_sign_in(controller, ta.user) } + + it 'merges the external into assessments with a negative id and external flag' do + subject + data = JSON.parse(response.body) + ext_row = data['assessments'].find { |a| a['id'] == -external.id } + expect(ext_row).to be_present + expect(ext_row['title']).to eq('Midterm') + expect(ext_row['external']).to be(true) + expect(ext_row['maxGrade']).to eq(50.0) + expect(ext_row['tabId']).to eq(external.synthetic_tab_id) + end + + it 'merges the external grade into submissions with a negative assessmentId' do + subject + data = JSON.parse(response.body) + sub = data['submissions'].find { |s| s['assessmentId'] == -external.id } + expect(sub).to be_present + expect(sub['studentId']).to eq(gb_student.user_id) + expect(sub['grade']).to eq(41.0) + end + + it 'emits a synthetic External Assessments category' do + subject + data = JSON.parse(response.body) + cat = data['categories'].find { |c| c['id'] == Course::ExternalAssessment::SYNTHETIC_CATEGORY_ID } + expect(cat).to be_present + expect(cat['title']).to eq('External Assessments') + end + + it 'emits a synthetic tab with negative id under the synthetic category' do + subject + data = JSON.parse(response.body) + tab = data['tabs'].find { |t| t['id'] == external.synthetic_tab_id } + expect(tab).to be_present + expect(tab['categoryId']).to eq(Course::ExternalAssessment::SYNTHETIC_CATEGORY_ID) + end + + it 'creates no real tab or category for the external' do + tab_count_before = Course::Assessment::Tab.count + cat_count_before = Course::Assessment::Category.count + subject + expect(Course::Assessment::Tab.count).to eq(tab_count_before) + expect(Course::Assessment::Category.count).to eq(cat_count_before) + expect(Course::Assessment::Category.where(title: 'External Assessments')).to be_empty + end + end + end + + describe 'GET #index with externals' do + render_views + let!(:course) { create(:course) } + let!(:external) do + Course::ExternalAssessment.create_for_course!(course: course, title: 'Midterm', + maximum_grade: 50.0, weight: 40) + end + let(:ta) { create(:course_teaching_assistant, course: course) } + + before do + ctx = Struct.new(:current_course, :key).new(course, Course::GradebookComponent.key) + Course::Settings::GradebookComponent.new(ctx).weighted_view_enabled = true + course.save! + controller_sign_in(controller, ta.user) + end + + subject(:body) do + get(:index, params: { course_id: course }, format: :json) + JSON.parse(response.body) + end + + it 'emits a synthetic External Assessments category' do + cat = body['categories'].find { |c| c['id'] == Course::ExternalAssessment::SYNTHETIC_CATEGORY_ID } + expect(cat['title']).to eq('External Assessments') + end + + it 'emits one synthetic tab per external carrying its weight' do + tab = body['tabs'].find { |t| t['id'] == -external.id } + expect(tab['categoryId']).to eq(Course::ExternalAssessment::SYNTHETIC_CATEGORY_ID) + expect(tab['gradebookWeight']).to eq(40.0) + expect(tab['weightMode']).to eq('equal') + end + + it 'emits the external as a negative-id leaf under its synthetic tab' do + leaf = body['assessments'].find { |a| a['id'] == -external.id } + expect(leaf['external']).to be(true) + expect(leaf['tabId']).to eq(-external.id) + end + + it 'creates no real tab or category for the external' do + tab_count_before = Course::Assessment::Tab.count + cat_count_before = Course::Assessment::Category.count + body + expect(Course::Assessment::Tab.count).to eq(tab_count_before) + expect(Course::Assessment::Category.count).to eq(cat_count_before) + expect(Course::Assessment::Category.where(title: 'External Assessments')).to be_empty + end end describe 'PATCH update_weights' do @@ -310,13 +418,13 @@ def weight_for(tab) it 'persists custom mode + assessment weights and echoes them back' do post :update_weights, as: :json, params: { course_id: course.id, - weights: [{ + weights: [ tabId: tab.id, weight: '50', weightMode: 'custom', assessmentWeights: [ { assessmentId: a1.id, weight: '30' }, { assessmentId: a2.id, weight: '20' } ] - }] + ] } expect(response).to have_http_status(:ok) body = JSON.parse(response.body) @@ -332,10 +440,10 @@ def weight_for(tab) it 'returns 422 when custom weights do not sum to the tab total' do post :update_weights, as: :json, params: { course_id: course.id, - weights: [{ + weights: [ tabId: tab.id, weight: '50', weightMode: 'custom', - assessmentWeights: [{ assessmentId: a1.id, weight: '10' }] - }] + assessmentWeights: [assessmentId: a1.id, weight: '10'] + ] } expect(response).to have_http_status(:unprocessable_entity) end @@ -343,10 +451,10 @@ def weight_for(tab) it 'persists and echoes per-assessment exclusion in equal mode' do post :update_weights, as: :json, params: { course_id: course.id, - weights: [{ + weights: [ tabId: tab.id, weight: '50', weightMode: 'equal', excludedAssessmentIds: [a1.id] - }] + ] } expect(response).to have_http_status(:ok) expect(a1.reload.gradebook_assessment_contribution.excluded).to eq(true) diff --git a/spec/factories/course_external_assessments.rb b/spec/factories/course_external_assessments.rb new file mode 100644 index 0000000000..5aa07599ba --- /dev/null +++ b/spec/factories/course_external_assessments.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true +FactoryBot.define do + factory :course_external_assessment, class: Course::ExternalAssessment do + course + sequence(:title) { |n| "External #{n}" } + maximum_grade { 100.0 } + end + + factory :course_external_assessment_grade, class: Course::ExternalAssessmentGrade do + external_assessment { association(:course_external_assessment) } + course_user { association(:course_user) } + grade { 50.0 } + end +end diff --git a/spec/factories/course_gradebook_contributions.rb b/spec/factories/course_gradebook_contributions.rb index 606994f4aa..94ff157305 100644 --- a/spec/factories/course_gradebook_contributions.rb +++ b/spec/factories/course_gradebook_contributions.rb @@ -1,9 +1,10 @@ # frozen_string_literal: true FactoryBot.define do - factory :course_gradebook_contribution, class: Course::Gradebook::Contribution.name do - association :tab, factory: :course_assessment_tab - course { tab.category.course } + factory :course_gradebook_contribution, class: Course::Gradebook::Contribution do + course + tab { association(:course_assessment_tab, course: course) } weight { 0 } weight_mode { :equal } + keep_highest { 0 } end end diff --git a/spec/models/course/external_assessment_grade_spec.rb b/spec/models/course/external_assessment_grade_spec.rb new file mode 100644 index 0000000000..6f0acb69c7 --- /dev/null +++ b/spec/models/course/external_assessment_grade_spec.rb @@ -0,0 +1,78 @@ +# frozen_string_literal: true +require 'rails_helper' + +RSpec.describe Course::ExternalAssessmentGrade, type: :model do + let(:instance) { Instance.default } + + with_tenant(:instance) do + describe 'validations' do + subject { build(:course_external_assessment_grade) } + + it { is_expected.to be_valid } + + it 'allows a null grade (ungraded)' do + subject.grade = nil + expect(subject).to be_valid + end + + it 'allows a grade greater than the maximum (no ceiling, bonus-consistent)' do + subject.external_assessment.maximum_grade = 10 + subject.grade = 15 + expect(subject).to be_valid + end + + it 'allows a negative grade (penalties; floor applied via floor_at_zero, not validation)' do + subject.grade = -5 + expect(subject).to be_valid + end + + it 'enforces one grade per (external_assessment, course_user)' do + existing = create(:course_external_assessment_grade) + duplicate = build(:course_external_assessment_grade, + external_assessment: existing.external_assessment, + course_user: existing.course_user) + expect(duplicate).not_to be_valid + end + + it 'allows the same course_user under a different external_assessment' do + existing = create(:course_external_assessment_grade) + other = build(:course_external_assessment_grade, course_user: existing.course_user) + expect(other).to be_valid + end + + it 'allows the same external_assessment for a different course_user' do + existing = create(:course_external_assessment_grade) + other = build(:course_external_assessment_grade, + external_assessment: existing.external_assessment) + expect(other).to be_valid + end + + it 'requires a course_user' do + subject.course_user = nil + expect(subject).not_to be_valid + end + + it 'rejects a non-numeric grade string' do + subject.grade = 'abc' + expect(subject).not_to be_valid + end + + it 'requires an external_assessment' do + subject.external_assessment = nil + expect(subject).not_to be_valid + end + end + + describe 'determinacy — grade binds to course_user, not the identifier string' do + it 'does not move an existing grade when the student external_id changes after import' do + grade = create(:course_external_assessment_grade, imported_identifier: 'A0001X', grade: 5) + course_user = grade.course_user + + course_user.update!(external_id: 'A9999Z') + + expect(grade.reload.course_user_id).to eq(course_user.id) + expect(grade.grade).to eq(5) + end + end + end +end diff --git a/spec/models/course/external_assessment_spec.rb b/spec/models/course/external_assessment_spec.rb new file mode 100644 index 0000000000..aebd75e4b3 --- /dev/null +++ b/spec/models/course/external_assessment_spec.rb @@ -0,0 +1,128 @@ +# frozen_string_literal: true +require 'rails_helper' + +RSpec.describe Course::ExternalAssessment, type: :model do + let(:instance) { Instance.default } + + with_tenant(:instance) do + let(:course) { create(:course) } + + describe 'associations' do + it { is_expected.to belong_to(:course) } + it { is_expected.to have_one(:gradebook_contribution).dependent(:destroy) } + it { is_expected.to have_many(:external_assessment_grades).dependent(:delete_all) } + end + + describe 'dependent destroy' do + it 'destroys the gradebook contribution and grades when destroyed' do + external = described_class.create_for_course!(course: course, title: 'Final', maximum_grade: 80.0) + create(:course_external_assessment_grade, external_assessment: external) + expect do + external.destroy + end.to change(Course::Gradebook::Contribution, :count).by(-1). + and change(Course::ExternalAssessmentGrade, :count).by(-1) + end + end + + describe 'validations' do + subject { build(:course_external_assessment, course: course) } + it { is_expected.to validate_presence_of(:title) } + it { is_expected.to validate_length_of(:title).is_at_most(255) } + it { is_expected.to validate_presence_of(:maximum_grade) } + + it 'enforces course-scoped unique titles' do + create(:course_external_assessment, course: course, title: 'Midterm') + dup = build(:course_external_assessment, course: course, title: 'Midterm') + expect(dup).not_to be_valid + expect(dup.errors[:title]).to include(I18n.t('errors.messages.taken')) + end + + it 'allows the same title in different courses' do + create(:course_external_assessment, course: course, title: 'Midterm') + other = build(:course_external_assessment, course: create(:course), title: 'Midterm') + expect(other).to be_valid + end + + it 'rejects a negative maximum_grade' do + subject.maximum_grade = -1 + expect(subject).not_to be_valid + expect(subject.errors[:maximum_grade]).to be_present + end + + it 'accepts a zero maximum_grade' do + subject.maximum_grade = 0 + expect(subject).to be_valid + end + end + + describe '.create_for_course!' do + it 'creates the external and its contribution row' do + external = nil + expect do + external = described_class.create_for_course!(course: course, title: 'Final', + maximum_grade: 80.0, weight: 30) + end.to change(Course::Gradebook::Contribution, :count).by(1) + expect(external.course).to eq(course) + expect(external.gradebook_contribution.weight).to eq(30) + end + + it 'does not create any assessment tab or category' do + course # ensure course (and its default tab/category) is created before measuring + expect do + described_class.create_for_course!(course: course, title: 'Final', maximum_grade: 80.0) + end.to not_change(Course::Assessment::Tab, :count).and not_change(Course::Assessment::Category, :count) + end + + it 'raises on duplicate title within the course' do + described_class.create_for_course!(course: course, title: 'Final', maximum_grade: 80.0) + expect do + described_class.create_for_course!(course: course, title: 'Final', maximum_grade: 80.0) + end.to raise_error(ActiveRecord::RecordInvalid) + end + + it 'rolls back the external when contribution creation fails' do + allow(Course::Gradebook::Contribution).to receive(:create!). + and_raise(ActiveRecord::RecordInvalid.new(Course::Gradebook::Contribution.new)) + expect do + expect do + described_class.create_for_course!(course: course, title: 'Final', maximum_grade: 80.0) + end.to raise_error(ActiveRecord::RecordInvalid) + end.to not_change(described_class, :count) + end + end + + describe '#synthetic_tab_id' do + it 'returns the negative of the record id' do + external = create(:course_external_assessment, course: course) + expect(external.synthetic_tab_id).to eq(-external.id) + end + end + + describe '.for_course' do + it 'returns only externals in the course' do + mine = create(:course_external_assessment, course: course) + create(:course_external_assessment, course: create(:course)) + expect(described_class.for_course(course)).to contain_exactly(mine) + end + end + + describe 'grade-bounding defaults' do + it 'defaults floor_at_zero and cap_at_maximum to true' do + external = Course::ExternalAssessment.create_for_course!( + course: course, title: 'Midterm', maximum_grade: 50 + ) + expect(external.floor_at_zero).to be(true) + expect(external.cap_at_maximum).to be(true) + end + + it 'honours explicit bound flags' do + external = Course::ExternalAssessment.create_for_course!( + course: course, title: 'Bonus', maximum_grade: 10, + floor_at_zero: false, cap_at_maximum: false + ) + expect(external.floor_at_zero).to be(false) + expect(external.cap_at_maximum).to be(false) + end + end + end +end