fix(i18n): localize generated labels without changing saved content

This commit is contained in:
cesnimda
2026-10-20 20:27:42 +02:00
parent d8c0187305
commit ab89b6984c
17 changed files with 1106 additions and 31 deletions
@@ -12,6 +12,33 @@ import { useI18n } from "../i18n/I18nProvider";
import { useViewResource, type ViewResourceError } from "../hooks/useViewResource";
import { PageHeader } from "../layout/PageLayout";
import { statusLabel } from "../pipeline";
import type { TranslationKey } from "../i18n/translations";
const generatedReasons = new Map<string, TranslationKey>([
["Interview stage reached but prep notes are still missing.", "reminderReasonInterview"],
["Tailored CV and saved application answers still need work.", "reminderReasonCvAndAnswers"],
["Tailored CV missing for this role.", "reminderReasonCv"],
["Saved application answers still need work.", "reminderReasonAnswers"],
["No response yet and no follow-up is scheduled.", "reminderReasonUnscheduled"],
["Follow-up is due for this role.", "reminderReasonDue"],
["No urgent workflow gaps are blocking this job right now.", "reminderReasonNoGaps"],
]);
const generatedDayReasons: [RegExp, TranslationKey][] = [
[/^No reply after (\d+)d$/, "reminderReasonNoReplyDays"],
[/^Stalled after (\d+)d$/, "reminderReasonStalledDays"],
[/^Feedback requested (\d+)d ago$/, "reminderReasonFeedbackDays"],
[/^Waiting (\d+)d$/, "reminderReasonWaitingDays"],
];
function reminderReason(reason: string, t: ReturnType<typeof useI18n>["t"]) {
const key = generatedReasons.get(reason);
if (key) return t(key);
for (const [pattern, dayKey] of generatedDayReasons) {
const match = pattern.exec(reason);
if (match) return t(dayKey, { days: match[1] });
}
return reason;
}
type FollowUpFailure = {
job: Pick<JobApplication, "id" | "jobTitle">;
@@ -62,7 +89,7 @@ function ReminderSection({ title, items, disabled, onOpen, onSetFollowUp }: { ti
</Typography>
<Box sx={{ display: "flex", gap: 1, mt: 0.5, flexWrap: "wrap", minWidth: 0, "& .MuiChip-root": { maxWidth: "100%", height: "auto", minHeight: 24 }, "& .MuiChip-label": { whiteSpace: "normal", overflowWrap: "anywhere", py: 0.5 } }}>
{j.needsFollowUp ? <Chip size="small" color="warning" label={t("remindersFollowUpLabel")} /> : null}
{(j.workflowSignal?.reason ?? j.followUpReason) ? <Chip size="small" label={j.workflowSignal?.reason ?? j.followUpReason} variant="outlined" /> : null}
{(j.workflowSignal?.reason ?? j.followUpReason) ? <Chip size="small" label={reminderReason((j.workflowSignal?.reason ?? j.followUpReason)!, t)} variant="outlined" /> : null}
{j.followUpAt ? <Chip size="small" label={t("remindersFollowUpDate", { date: new Date(j.followUpAt).toLocaleDateString(language === "nb" ? "nb-NO" : "en") })} variant="outlined" /> : null}
<Chip size="small" label={statusLabel(t, j.status)} variant="outlined" />
</Box>