diff --git a/job-tracker-ui/src/i18n/translations.ts b/job-tracker-ui/src/i18n/translations.ts index 1b93e92..e7ba77b 100644 --- a/job-tracker-ui/src/i18n/translations.ts +++ b/job-tracker-ui/src/i18n/translations.ts @@ -184,6 +184,51 @@ export const translations = { assetsCoverPlaceholder: "Write it yourself, start from the template, or generate a tailored draft.", assetsDiscardChanges: "Discard changes", assetsStartTemplate: "Start from template", + cvEditorBack: "Back to CVs", + cvEditorName: "CV name", + cvEditorNameRequired: "Enter a name before saving.", + cvEditorUndo: "Undo", + cvEditorRedo: "Redo", + cvEditorEdit: "Edit", + cvEditorPreview: "Preview", + cvEditorDuplicate: "Duplicate", + cvEditorUpdating: "Updating…", + cvEditorPublic: "Public", + cvEditorPrivate: "Private", + cvEditorCopyLink: "Copy link", + cvEditorExporting: "Exporting…", + cvEditorDownloadPdf: "Download PDF", + cvEditorContent: "Content", + cvEditorTemplate: "Template", + cvEditorDesign: "Design", + cvEditorLayout: "Layout", + cvEditorHistory: "History", + cvEditorLivePreview: "Live preview", + cvEditorUpdatingPreview: "updating…", + cvEditorPreviewUnavailable: "Preview unavailable", + cvEditorRetryPreview: "Retry preview", + cvEditorPrevious: "Previous", + cvEditorNext: "Next", + cvEditorPageOf: "Page {page} of {pages}", + cvEditorZoomOut: "Zoom out", + cvEditorZoom: "Zoom", + cvEditorZoomIn: "Zoom in", + cvEditorFit: "Fit", + cvEditorOverflowWarning: "The preview reported horizontal overflow. Shorten an unbroken value or retry after the latest render.", + cvEditorLongDocument: "This CV is {pages} pages. Content remains readable, but consider hiding less relevant entries for a more focused application.", + cvEditorPreviewTitle: "CV preview", + cvEditorPage: "Page {page}", + cvEditorPreviewPage: "CV preview page {page}", + cvEditorUnsaved: "Unsaved", + cvEditorSaving: "Saving…", + cvEditorSaved: "Saved", + cvEditorSaveFailed: "Save failed", + cvEditorSaveNow: "Save now", + cvEditorNoVersions: "No saved versions yet. Edits autosave and appear here.", + cvEditorVersionCount: "{count} saved version(s). Restoring keeps history — it adds a new version.", + cvEditorVersion: "Version {version}", + cvEditorCurrent: "current", + cvEditorRestore: "Restore", richTextBold: "Bold", richTextBoldPlaceholder: "bold text", richTextItalic: "Italic", @@ -1567,6 +1612,51 @@ export const translations = { assetsCoverPlaceholder: "Skriv selv, start fra malen eller generer et tilpasset utkast.", assetsDiscardChanges: "Forkast endringer", assetsStartTemplate: "Start fra mal", + cvEditorBack: "Tilbake til CV-er", + cvEditorName: "CV-navn", + cvEditorNameRequired: "Skriv inn et navn før du lagrer.", + cvEditorUndo: "Angre", + cvEditorRedo: "Gjør om", + cvEditorEdit: "Rediger", + cvEditorPreview: "Forhåndsvis", + cvEditorDuplicate: "Dupliser", + cvEditorUpdating: "Oppdaterer…", + cvEditorPublic: "Offentlig", + cvEditorPrivate: "Privat", + cvEditorCopyLink: "Kopier lenke", + cvEditorExporting: "Eksporterer…", + cvEditorDownloadPdf: "Last ned PDF", + cvEditorContent: "Innhold", + cvEditorTemplate: "Mal", + cvEditorDesign: "Design", + cvEditorLayout: "Oppsett", + cvEditorHistory: "Historikk", + cvEditorLivePreview: "Direkte forhåndsvisning", + cvEditorUpdatingPreview: "oppdaterer…", + cvEditorPreviewUnavailable: "Forhåndsvisning utilgjengelig", + cvEditorRetryPreview: "Prøv forhåndsvisning på nytt", + cvEditorPrevious: "Forrige", + cvEditorNext: "Neste", + cvEditorPageOf: "Side {page} av {pages}", + cvEditorZoomOut: "Zoom ut", + cvEditorZoom: "Zoom", + cvEditorZoomIn: "Zoom inn", + cvEditorFit: "Tilpass", + cvEditorOverflowWarning: "Forhåndsvisningen rapporterte vannrett overflyt. Forkort en ubrutt verdi, eller prøv igjen etter siste gjengivelse.", + cvEditorLongDocument: "Denne CV-en er på {pages} sider. Innholdet er lesbart, men vurder å skjule mindre relevante oppføringer for en mer fokusert søknad.", + cvEditorPreviewTitle: "CV-forhåndsvisning", + cvEditorPage: "Side {page}", + cvEditorPreviewPage: "CV-forhåndsvisning side {page}", + cvEditorUnsaved: "Ikke lagret", + cvEditorSaving: "Lagrer…", + cvEditorSaved: "Lagret", + cvEditorSaveFailed: "Lagring mislyktes", + cvEditorSaveNow: "Lagre nå", + cvEditorNoVersions: "Ingen lagrede versjoner ennå. Endringer lagres automatisk og vises her.", + cvEditorVersionCount: "{count} lagret(e) versjon(er). Gjenoppretting beholder historikken og legger til en ny versjon.", + cvEditorVersion: "Versjon {version}", + cvEditorCurrent: "gjeldende", + cvEditorRestore: "Gjenopprett", richTextBold: "Fet", richTextBoldPlaceholder: "fet tekst", richTextItalic: "Kursiv", diff --git a/job-tracker-ui/src/views/CvBuilderEditor.tsx b/job-tracker-ui/src/views/CvBuilderEditor.tsx index dd39aca..354282a 100644 --- a/job-tracker-ui/src/views/CvBuilderEditor.tsx +++ b/job-tracker-ui/src/views/CvBuilderEditor.tsx @@ -35,6 +35,7 @@ import { cvBuilderApi, getCvPageCount, getCvPageMetrics, moveItem, } from "../cvBuilder"; import { useDialogActions } from "../dialogs"; +import { useI18n } from "../i18n/I18nProvider"; const FONTS = [ "'Segoe UI', Roboto, Arial, sans-serif", @@ -65,6 +66,7 @@ export default function CvBuilderEditor() { const variantId = Number(id); const navigate = useNavigate(); const { toast } = useToast(); + const { t } = useI18n(); const { confirmAction } = useDialogActions(); const compactEditor = useMediaQuery("(max-width:899.95px)"); @@ -410,7 +412,7 @@ export default function CvBuilderEditor() { if (loadError) { return ( - + {loadError} ); @@ -424,26 +426,26 @@ export default function CvBuilderEditor() { - navigate("/career/builder")}> + navigate("/career/builder")}> renameVariant(e.target.value)} - error={!name.trim()} helperText={!name.trim() ? "Enter a name before saving." : undefined} + error={!name.trim()} helperText={!name.trim() ? t("cvEditorNameRequired") : undefined} sx={{ minWidth: { xs: 150, sm: 220 }, flex: "1 1 240px", maxWidth: 420 }} - slotProps={{ input: { style: { fontWeight: 800, fontSize: "1.05rem" } }, htmlInput: { "aria-label": "CV name" } }} /> + slotProps={{ input: { style: { fontWeight: 800, fontSize: "1.05rem" } }, htmlInput: { "aria-label": t("cvEditorName") } }} /> void retrySave()} /> - - + + {compactEditor && - - + + } - + - {isPublic && } - + {isPublic && } + @@ -451,11 +453,11 @@ export default function CvBuilderEditor() { { setTab(v); if (v === 4) loadVersions(); }} variant="scrollable" scrollButtons="auto" allowScrollButtonsMobile sx={{ mb: 1.5, minHeight: 38 }}> - - - - - + + + + + {tab === 0 && } @@ -467,35 +469,35 @@ export default function CvBuilderEditor() { - Live preview - {previewing && } - {previewError && } - {previewError && } + {t("cvEditorLivePreview")} + {previewing && } + {previewError && } + {previewError && } {pages >= 3 && } - - Page {page} of {pages} - + + {t("cvEditorPageOf", { page, pages })} + - setZoom((z) => Math.max(MIN_PREVIEW_ZOOM, +(z - 0.1).toFixed(2)))}> - setZoom(v as number)} sx={{ width: 90 }} aria-label="Zoom" /> - setZoom((z) => Math.min(1, +(z + 0.1).toFixed(2)))}> + setZoom((z) => Math.max(MIN_PREVIEW_ZOOM, +(z - 0.1).toFixed(2)))}> + setZoom(v as number)} sx={{ width: 90 }} aria-label={t("cvEditorZoom")} /> + setZoom((z) => Math.min(1, +(z + 0.1).toFixed(2)))}> {Math.round(zoom * 100)}% - + - {previewOverflow && The preview reported horizontal overflow. Shorten an unbroken value or retry after the latest render.} - {pages >= 3 && This CV is {pages} pages. Content remains readable, but consider hiding less relevant entries for a more focused application.} -