@@ -314,7 +313,7 @@ export function ConfigurationPage() {
{t('location.title')}
}>
- Certifications
+ {t('certification.title')}
diff --git a/apps/backoffice/src/app/features/exam/pages/ExamDetailPage.tsx b/apps/backoffice/src/app/features/exam/pages/ExamDetailPage.tsx
index c9de1a010..2f00a0d25 100644
--- a/apps/backoffice/src/app/features/exam/pages/ExamDetailPage.tsx
+++ b/apps/backoffice/src/app/features/exam/pages/ExamDetailPage.tsx
@@ -177,14 +177,25 @@ export function ExamDetailPage() {
});
} catch { /* logo not available */ }
- const qHtml = (exam.questions ?? []).map((q, i) => `
+ const qMap = new Map(allQuestions.map((qq) => [qq.id, qq]));
+ const qHtml = (exam.questions ?? []).map((q, i) => {
+ const full = qMap.get(q.id);
+ const titleParts = [q.title.en];
+ if (q.title.am) titleParts.push(q.title.am);
+ const titleStr = titleParts.join(' / ');
+ const desc = full?.description;
+ const descParts: string[] = [];
+ if (desc?.en) descParts.push(desc.en);
+ if (desc?.am) descParts.push(desc.am);
+ return `
Question ${i + 1} (${q.points} pts — ${FORM_LABEL[q.form] ?? q.form})
-
${q.title.en}
+
${titleStr}
+ ${descParts.length > 0 ? `
${descParts.join(' / ')}
` : ''}
${q.form === 'ESSAY' ? '
'.repeat(3) : ''}
${q.form === 'CHOICE' ? ['A. ______', 'B. ______', 'C. ______', 'D. ______'].map(l => `
${l}
`).join('') : ''}
-
- `).join('');
+ `;
+ }).join('');
printWindow.document.write(`
${exam.title.en}
@@ -200,13 +211,12 @@ export function ExamDetailPage() {
- ${exam.direction?.en ? `Directions:${exam.direction.en}
` : ''}
+ ${exam.direction?.en || exam.direction?.am ? `Directions:${[exam.direction?.en, exam.direction?.am].filter(Boolean).join(' / ')}
` : ''}
${qHtml}
Generated by EMA — Ethiopian Maritime Authority
diff --git a/apps/backoffice/src/app/features/location/components/LocationDetail.tsx b/apps/backoffice/src/app/features/location/components/LocationDetail.tsx
index f91292497..769137cc6 100644
--- a/apps/backoffice/src/app/features/location/components/LocationDetail.tsx
+++ b/apps/backoffice/src/app/features/location/components/LocationDetail.tsx
@@ -35,7 +35,8 @@ export function LocationDetail({
onEdit,
onDelete,
}: LocationDetailProps) {
- const { t } = useTranslation();
+ const { t, i18n } = useTranslation();
+ const locale = i18n.language as 'en' | 'am';
const typeInfo = locationTypes.find(
(lt) => lt.id === location.locationTypeId,
);
@@ -47,7 +48,7 @@ export function LocationDetail({
return (
- {location.names.en}
+ {location.names[locale]}
@@ -99,15 +100,9 @@ export function LocationDetail({
- {t('location.nameEn')}
+ {t('location.name')}
- {location.names.en}
-
-
-
- {t('location.nameAm')}
-
- {location.names.am}
+ {location.names[locale]}
@@ -120,7 +115,7 @@ export function LocationDetail({
{t('location.type')}
- {typeInfo.names.en} (Level {typeInfo.level})
+ {typeInfo.names[locale]} ({t('location.level')} {typeInfo.level})
)}
diff --git a/apps/backoffice/src/app/features/location/components/LocationForm.tsx b/apps/backoffice/src/app/features/location/components/LocationForm.tsx
index 0cfee89bb..719de957a 100644
--- a/apps/backoffice/src/app/features/location/components/LocationForm.tsx
+++ b/apps/backoffice/src/app/features/location/components/LocationForm.tsx
@@ -44,7 +44,8 @@ export function LocationForm({
onCancel,
isSubmitting,
}: LocationFormProps) {
- const { t } = useTranslation();
+ const { t, i18n } = useTranslation();
+ const locale = i18n.language as 'en' | 'am';
const isEditing = !!editingLocation;
@@ -125,7 +126,7 @@ export function LocationForm({
{parentLocation && !isEditing && (
({
value: lt.id,
- label: lt.names.en,
+ label: lt.names[locale],
}))}
{...form.getInputProps('locationTypeId')}
size="sm"
@@ -153,7 +154,7 @@ export function LocationForm({
{type ? (
- {type.names.en}
+ {type.names[locale]}
) : (
diff --git a/apps/backoffice/src/app/features/location/components/LocationTypeModal.tsx b/apps/backoffice/src/app/features/location/components/LocationTypeModal.tsx
index 4f040d4e6..8db7faa67 100644
--- a/apps/backoffice/src/app/features/location/components/LocationTypeModal.tsx
+++ b/apps/backoffice/src/app/features/location/components/LocationTypeModal.tsx
@@ -32,7 +32,8 @@ interface LocationTypeFormValues {
}
export function LocationTypeModal({ opened, onClose }: { opened: boolean; onClose: () => void }) {
- const { t } = useTranslation();
+ const { t, i18n } = useTranslation();
+ const locale = i18n.language as 'en' | 'am';
const { data: locationTypes, isLoading } = useGetLocationTypesQuery();
const [createType] = useCreateLocationTypeMutation();
const [updateType] = useUpdateLocationTypeMutation();
@@ -49,9 +50,9 @@ export function LocationTypeModal({ opened, onClose }: { opened: boolean; onClos
level: 1,
},
validate: {
- code: (v) => (!v ? 'Code is required' : null),
- namesEn: (v) => (!v ? 'English name is required' : null),
- namesAm: (v) => (!v ? 'Amharic name is required' : null),
+ code: (v) => (!v ? t('location.validation.codeRequired') : null),
+ namesEn: (v) => (!v ? t('location.validation.nameEnRequired') : null),
+ namesAm: (v) => (!v ? t('location.validation.nameAmRequired') : null),
level: (v) => (v < 1 ? 'Level must be at least 1' : null),
},
});
@@ -119,6 +120,7 @@ export function LocationTypeModal({ opened, onClose }: { opened: boolean; onClos
variant="light"
leftSection={}
onClick={() => setShowForm(true)}
+ mt="md"
mb="md"
size="sm"
>
@@ -130,25 +132,25 @@ export function LocationTypeModal({ opened, onClose }: { opened: boolean; onClos