Skip to content

[NEWBIE-FRONTEND] Add Complete i18n Translations for Courses Feature #252

@smattymatty

Description

@smattymatty

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

  1. Open Frontend/EduLiteFrontend/src/i18n/locales/en.json
  2. Add a complete "courses" section covering all courses UI text (see structure below)
  3. Open Frontend/EduLiteFrontend/src/i18n/locales/ar.json
  4. Add the Arabic translations for every key
  5. Search all courses-related components for any hardcoded strings and replace them with t() calls
  6. Test in both English and Arabic, and verify RTL layout doesn't break

Translation 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"
    }
  }
}
  1. For each key above, provide the Arabic translation in ar.json.

Definition of Done

  • Every user-facing string in courses components uses t("courses....") calls
  • Both en.json and ar.json have the complete "courses" section
  • Switching language to Arabic shows fully translated courses UI
  • RTL layout is not broken by any of the new text
  • No hardcoded English strings remain in courses components
  • No console warnings about missing translation keys

Benefits

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

  • Working with JSON translation files
  • react-i18next t() function usage
  • String interpolation in translations ({{variable}})
  • Plural forms (_plural suffix)
  • RTL layout awareness
  • Searching codebases for hardcoded strings

Files to be Altered

  • Frontend/EduLiteFrontend/src/i18n/locales/en.json — add courses section
  • Frontend/EduLiteFrontend/src/i18n/locales/ar.json — add courses section with Arabic translations
  • Any courses component files with hardcoded strings (search for them)

Testing

  • Run the dev server and navigate to each courses page
  • Switch language to Arabic — verify all text is translated
  • Switch language back to English — verify nothing is broken
  • Check browser console for missing translation key warnings
  • Verify RTL layout on Arabic: text alignment, button positions, form labels

Tips

  • Use the existing "slideshow" section in both JSON files as a reference for structure and patterns
  • For Arabic translations, use formal Modern Standard Arabic (MSA)
  • Plural forms in Arabic are complex — for simplicity, use _plural suffix which covers the "other" form
  • If you're not confident in Arabic, mark uncertain translations with a TODO comment and note it in the PR — the team will review

Getting 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!

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions