Add complete internationalization (i18n) translations for the entire courses feature in both English and Arabic. This ensures all user-facing text in courses pages uses t() calls instead of hardcoded strings, and that the Arabic experience is fully translated.
{
"courses": {
"list": {
"title": "Courses",
"myCourses": "My Courses",
"publicCourses": "Public Courses",
"createButton": "Create Course",
"emptyMine": "You're not enrolled in any courses yet",
"emptyPublic": "No public courses available",
"browsePublic": "Browse public courses to get started",
"loading": "Loading courses...",
"errorLoading": "Failed to load courses",
"titleColumn": "Title",
"subjectColumn": "Subject",
"languageColumn": "Language",
"visibilityColumn": "Visibility",
"membersColumn": "Members",
"startDateColumn": "Start Date",
"showing": "Showing {{start}}-{{end}} of {{total}}",
"pageOf": "Page {{current}} of {{total}}"
},
"detail": {
"title": "Course Details",
"outline": "Outline",
"subject": "Subject",
"language": "Language",
"country": "Country",
"visibility": "Visibility",
"startDate": "Start Date",
"endDate": "End Date",
"duration": "Duration",
"members": "Members",
"modules": "Modules",
"memberCount": "{{count}} member",
"memberCount_plural": "{{count}} members",
"editCourse": "Edit Course",
"deleteCourse": "Delete Course",
"deleteConfirmTitle": "Delete Course",
"deleteConfirmMessage": "Are you sure you want to delete \"{{title}}\"? This will remove all modules, memberships, and chat rooms. This action cannot be undone.",
"deleteConfirmButton": "Delete Course"
},
"form": {
"createTitle": "Create Course",
"editTitle": "Edit Course",
"titleLabel": "Title",
"titlePlaceholder": "Enter course title",
"outlineLabel": "Outline",
"outlinePlaceholder": "Describe what this course covers...",
"subjectLabel": "Subject",
"languageLabel": "Language",
"countryLabel": "Country",
"visibilityLabel": "Visibility",
"startDateLabel": "Start Date",
"endDateLabel": "End Date",
"allowJoinRequests": "Allow Join Requests",
"allowJoinRequestsHint": "Students can request to join this restricted course",
"saveButton": "Save Changes",
"createButton": "Create Course",
"draftRecovered": "Draft recovered from {{time}}",
"validationTitleRequired": "Course title is required",
"validationDateOrder": "Start date must be before end date"
},
"enrollment": {
"joinCourse": "Join Course",
"leaveCourse": "Leave Course",
"requestToJoin": "Request to Join",
"cancelRequest": "Cancel Request",
"acceptInvite": "Accept Invitation",
"declineInvite": "Decline Invitation",
"enrolled": "Enrolled",
"pending": "Request Pending",
"invited": "Invited",
"notEnrolled": "Not Enrolled",
"leaveConfirmTitle": "Leave Course",
"leaveConfirmMessage": "Are you sure you want to leave \"{{title}}\"?",
"enrollSuccess": "Successfully enrolled in course",
"enrollPending": "Join request submitted — awaiting approval",
"leaveSuccess": "Successfully left course",
"alreadyEnrolled": "You are already enrolled in this course",
"cannotJoin": "This course is not accepting new members",
"lastTeacher": "Cannot leave — you are the only teacher in this course"
},
"members": {
"title": "Members",
"inviteMember": "Invite Member",
"removeMember": "Remove Member",
"changeRole": "Change Role",
"approveRequest": "Approve",
"denyRequest": "Deny",
"removeConfirmTitle": "Remove Member",
"removeConfirmMessage": "Are you sure you want to remove {{name}} from this course?",
"inviteSuccess": "Invitation sent to {{name}}",
"removeSuccess": "{{name}} removed from course",
"alreadyMember": "This user is already a member",
"lastTeacherRemove": "Cannot remove the only teacher",
"lastTeacherDemote": "Cannot change role — this is the only teacher"
},
"modules": {
"title": "Modules",
"addModule": "Add Module",
"editModule": "Edit Module",
"deleteModule": "Delete Module",
"moduleTitle": "Module Title",
"contentType": "Content Type",
"order": "Order",
"deleteConfirmTitle": "Delete Module",
"deleteConfirmMessage": "Are you sure you want to delete this module?"
},
"roles": {
"teacher": "Teacher",
"student": "Student",
"assistant": "Assistant"
},
"visibility": {
"public": "Public",
"restricted": "Restricted",
"private": "Private",
"publicDesc": "Anyone can view and join",
"restrictedDesc": "Visible but requires approval to join",
"privateDesc": "Only visible to members"
},
"profile": {
"emptyTitle": "No courses yet",
"emptyMessage": "You're not enrolled in any courses",
"browseCourses": "Browse Courses",
"memberCount": "{{count}} members"
}
}
}
This ensures EduLite's courses feature is accessible to Arabic-speaking users from day one. Internationalization is core to our mission of serving areas with limited resources — language should never be a barrier. The contributor will learn how i18n works in a real React app with react-i18next.
Claiming This Task
Before you start working, check the Assignees section. If no one is assigned, leave a comment claiming the issue and assign it to yourself. This prevents duplicate work.
See the Community Wiki for contributing guidelines and git workflow.
Goal
Add complete internationalization (i18n) translations for the entire courses feature in both English and Arabic. This ensures all user-facing text in courses pages uses
t()calls instead of hardcoded strings, and that the Arabic experience is fully translated.Task Description
Frontend/EduLiteFrontend/src/i18n/locales/en.json"courses"section covering all courses UI text (see structure below)Frontend/EduLiteFrontend/src/i18n/locales/ar.jsont()callsTranslation Keys to Add
{ "courses": { "list": { "title": "Courses", "myCourses": "My Courses", "publicCourses": "Public Courses", "createButton": "Create Course", "emptyMine": "You're not enrolled in any courses yet", "emptyPublic": "No public courses available", "browsePublic": "Browse public courses to get started", "loading": "Loading courses...", "errorLoading": "Failed to load courses", "titleColumn": "Title", "subjectColumn": "Subject", "languageColumn": "Language", "visibilityColumn": "Visibility", "membersColumn": "Members", "startDateColumn": "Start Date", "showing": "Showing {{start}}-{{end}} of {{total}}", "pageOf": "Page {{current}} of {{total}}" }, "detail": { "title": "Course Details", "outline": "Outline", "subject": "Subject", "language": "Language", "country": "Country", "visibility": "Visibility", "startDate": "Start Date", "endDate": "End Date", "duration": "Duration", "members": "Members", "modules": "Modules", "memberCount": "{{count}} member", "memberCount_plural": "{{count}} members", "editCourse": "Edit Course", "deleteCourse": "Delete Course", "deleteConfirmTitle": "Delete Course", "deleteConfirmMessage": "Are you sure you want to delete \"{{title}}\"? This will remove all modules, memberships, and chat rooms. This action cannot be undone.", "deleteConfirmButton": "Delete Course" }, "form": { "createTitle": "Create Course", "editTitle": "Edit Course", "titleLabel": "Title", "titlePlaceholder": "Enter course title", "outlineLabel": "Outline", "outlinePlaceholder": "Describe what this course covers...", "subjectLabel": "Subject", "languageLabel": "Language", "countryLabel": "Country", "visibilityLabel": "Visibility", "startDateLabel": "Start Date", "endDateLabel": "End Date", "allowJoinRequests": "Allow Join Requests", "allowJoinRequestsHint": "Students can request to join this restricted course", "saveButton": "Save Changes", "createButton": "Create Course", "draftRecovered": "Draft recovered from {{time}}", "validationTitleRequired": "Course title is required", "validationDateOrder": "Start date must be before end date" }, "enrollment": { "joinCourse": "Join Course", "leaveCourse": "Leave Course", "requestToJoin": "Request to Join", "cancelRequest": "Cancel Request", "acceptInvite": "Accept Invitation", "declineInvite": "Decline Invitation", "enrolled": "Enrolled", "pending": "Request Pending", "invited": "Invited", "notEnrolled": "Not Enrolled", "leaveConfirmTitle": "Leave Course", "leaveConfirmMessage": "Are you sure you want to leave \"{{title}}\"?", "enrollSuccess": "Successfully enrolled in course", "enrollPending": "Join request submitted — awaiting approval", "leaveSuccess": "Successfully left course", "alreadyEnrolled": "You are already enrolled in this course", "cannotJoin": "This course is not accepting new members", "lastTeacher": "Cannot leave — you are the only teacher in this course" }, "members": { "title": "Members", "inviteMember": "Invite Member", "removeMember": "Remove Member", "changeRole": "Change Role", "approveRequest": "Approve", "denyRequest": "Deny", "removeConfirmTitle": "Remove Member", "removeConfirmMessage": "Are you sure you want to remove {{name}} from this course?", "inviteSuccess": "Invitation sent to {{name}}", "removeSuccess": "{{name}} removed from course", "alreadyMember": "This user is already a member", "lastTeacherRemove": "Cannot remove the only teacher", "lastTeacherDemote": "Cannot change role — this is the only teacher" }, "modules": { "title": "Modules", "addModule": "Add Module", "editModule": "Edit Module", "deleteModule": "Delete Module", "moduleTitle": "Module Title", "contentType": "Content Type", "order": "Order", "deleteConfirmTitle": "Delete Module", "deleteConfirmMessage": "Are you sure you want to delete this module?" }, "roles": { "teacher": "Teacher", "student": "Student", "assistant": "Assistant" }, "visibility": { "public": "Public", "restricted": "Restricted", "private": "Private", "publicDesc": "Anyone can view and join", "restrictedDesc": "Visible but requires approval to join", "privateDesc": "Only visible to members" }, "profile": { "emptyTitle": "No courses yet", "emptyMessage": "You're not enrolled in any courses", "browseCourses": "Browse Courses", "memberCount": "{{count}} members" } } }ar.json.Definition of Done
t("courses....")callsen.jsonandar.jsonhave the complete"courses"sectionBenefits
This ensures EduLite's courses feature is accessible to Arabic-speaking users from day one. Internationalization is core to our mission of serving areas with limited resources — language should never be a barrier. The contributor will learn how i18n works in a real React app with react-i18next.
Skills You'll Practice
t()function usage{{variable}})_pluralsuffix)Files to be Altered
Frontend/EduLiteFrontend/src/i18n/locales/en.json— addcoursessectionFrontend/EduLiteFrontend/src/i18n/locales/ar.json— addcoursessection with Arabic translationsTesting
Tips
"slideshow"section in both JSON files as a reference for structure and patterns_pluralsuffix which covers the "other" formTODOcomment and note it in the PR — the team will reviewGetting started? These wiki pages will help you get set up:
This is a beginner-friendly task. Ask questions in Discord — we're here to help!