feat(frontend): Phase 2/3 hardening release
Roadmap P0
- Ship /logo.svg fallback and rewire asset references (superseded later by
the project-manager PNG in a separate commit).
Roadmap P1
- Response envelope alignment ({items,total,page,size}) across services
and query hooks.
- Approval/ticket UX updates tied to the new backend rollback semantics.
Roadmap P2
- React.lazy + Vite manualChunks to split vendor-radix/charts/icons/forms
from the main bundle and cut initial JS.
- Fix the 181 tsc errors (PaginationParams class + per-service generics).
- Auto-refresh flow for JWT refresh tokens wired into api-client.ts.
Roadmap P3
- i18n: i18next + language detector, en/ar locales, RTL auto-switch,
LanguageToggle component in RoleLayout and AdminLmsLayout.
- GDPR: PrivacyCenter page for data export and right-to-erasure, backed
by gdpr.service.ts; logout via AuthContext after erasure.
- Human-in-the-loop exam review UI: admin ExamReviewQueue + ExamReviewDetail
pages, useExamReview hooks, exam-review.service.ts.
- AI quality loop: AIPromptEditor (versioning + render preview),
AIFeedbackButtons for students, AIFeedbackTriage admin page, dedicated
services, hooks, and types.
- Dark mode: ThemeProvider + ThemeToggle + chart color tokens.
- Accessibility: DialogDescription on every DialogContent; alert-dialog
and sheet updates.
- Retire dead pages: ExamPage marketing, Index, ProfilePage import.
- Playwright e2e scaffolding: playwright.config.ts + e2e/login.spec.ts
smoke tests, npm scripts test:e2e / test:e2e:install.
Made-with: Cursor
This commit is contained in:
97
src/i18n/locales/en.ts
Normal file
97
src/i18n/locales/en.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
/** English translations. Keep keys nested by feature area.
|
||||
*
|
||||
* We deliberately annotate the literal with `Translations` (not `as const`)
|
||||
* so sibling locale files can widen their string values without fighting
|
||||
* literal-string type mismatches.
|
||||
*/
|
||||
export interface Translations {
|
||||
common: Record<string, string>;
|
||||
auth: Record<string, string>;
|
||||
nav: Record<string, string>;
|
||||
privacy: Record<string, string>;
|
||||
feedback: Record<string, string>;
|
||||
theme: Record<string, string>;
|
||||
}
|
||||
|
||||
const en: Translations = {
|
||||
common: {
|
||||
cancel: "Cancel",
|
||||
save: "Save",
|
||||
delete: "Delete",
|
||||
edit: "Edit",
|
||||
close: "Close",
|
||||
back: "Back",
|
||||
next: "Next",
|
||||
search: "Search",
|
||||
loading: "Loading…",
|
||||
error: "Error",
|
||||
retry: "Retry",
|
||||
yes: "Yes",
|
||||
no: "No",
|
||||
actions: "Actions",
|
||||
status: "Status",
|
||||
settings: "Settings",
|
||||
signOut: "Sign out",
|
||||
},
|
||||
auth: {
|
||||
signIn: "Sign in",
|
||||
signInTitle: "Sign in to EnCoach",
|
||||
email: "Email",
|
||||
password: "Password",
|
||||
forgotPassword: "Forgot password?",
|
||||
needAccount: "Don't have an account?",
|
||||
signUp: "Sign up",
|
||||
invalidCredentials: "Invalid email or password",
|
||||
},
|
||||
nav: {
|
||||
dashboard: "Dashboard",
|
||||
courses: "Courses",
|
||||
students: "Students",
|
||||
teachers: "Teachers",
|
||||
exams: "Exams",
|
||||
reports: "Reports",
|
||||
settings: "Settings",
|
||||
profile: "Profile",
|
||||
privacy: "Privacy Center",
|
||||
reviewQueue: "Review Queue",
|
||||
aiPrompts: "AI Prompts",
|
||||
aiFeedback: "AI Feedback",
|
||||
},
|
||||
privacy: {
|
||||
title: "Privacy Center",
|
||||
description:
|
||||
"Manage your personal data held by EnCoach under GDPR and equivalent regulations.",
|
||||
exportTitle: "Download your data",
|
||||
exportDescription:
|
||||
"We'll package your profile, entity memberships, exam attempts, answers, AI feedback, and tickets into a single JSON file.",
|
||||
exportButton: "Download my data",
|
||||
exportPreparing: "Preparing export…",
|
||||
exportSuccess: "Data export downloaded",
|
||||
deleteTitle: "Delete my account",
|
||||
deleteDescription:
|
||||
"This anonymises your profile and removes personal fields from our records. Exam attempts are retained (without identifying information) for statistical integrity. This action cannot be undone.",
|
||||
deleteButton: "Erase my account",
|
||||
deleteErasing: "Erasing…",
|
||||
confirmTitle: "Erase your account?",
|
||||
confirmDescription:
|
||||
"We'll anonymise your personal data and deactivate your login. Aggregate analytics will remain but will no longer be linked to you.",
|
||||
confirmTypeDelete: "Type DELETE to confirm",
|
||||
confirmErased: "Your account has been erased. Signing out…",
|
||||
},
|
||||
feedback: {
|
||||
thumbsUp: "Thumbs up",
|
||||
thumbsDown: "Thumbs down",
|
||||
whatWentWrong: "What went wrong?",
|
||||
commentPlaceholder: "e.g. Wrong answer, confusing wording, off-topic…",
|
||||
commentRequired: "Please tell us what was wrong.",
|
||||
submit: "Submit feedback",
|
||||
},
|
||||
theme: {
|
||||
title: "Theme",
|
||||
light: "Light",
|
||||
dark: "Dark",
|
||||
system: "System",
|
||||
},
|
||||
};
|
||||
|
||||
export default en;
|
||||
Reference in New Issue
Block a user