diff --git a/docs/work-programmes/master-progress.md b/docs/work-programmes/master-progress.md
index 29c8ce4..1fecc42 100644
--- a/docs/work-programmes/master-progress.md
+++ b/docs/work-programmes/master-progress.md
@@ -32,6 +32,8 @@ Updated: 2026-08-29
- Localized Connected Accounts and the shared email-provider connection controls, validation, OAuth/IMAP feedback, connection states, and accessible form labels without translating provider names or user email addresses.
- Localized the consolidated Job Email hub across provider status, search/filter controls, saved drafts, compose/reply flows, destructive confirmations, send safety states, message metadata, pagination, and failure handling. Persisted subjects, bodies, company names, roles, addresses, and provider names remain unchanged.
- Corrected the Job Email Direction and Link State controls so their visible labels are programmatically associated with the selects, and removed the remaining mojibake separators/loading text from the workflow.
+- Localized the complete public landing experience—hero, previews, feature cards, workflow, plan capabilities, CTAs, accessibility text, and footer—while retaining the server-aligned Free/Pro plan structure and commercial-terms safeguards.
+- Reused the shared EN/NO language control on the unauthenticated landing page, so language can be changed before sign-in and persists through the existing locale mechanism.
### In progress
@@ -82,6 +84,7 @@ Updated: 2026-08-29
- Job Email focused verification: 16/16 passed, including a Bokmål regression that preserves correspondence content; TypeScript passed.
- Full frontend after the Job Email localization batch: 62 suites, 263/263 tests passed.
- Next optimized production build and integrated TypeScript check passed after the Job Email localization batch.
+- Public landing focused verification: 2 suites, 3/3 passed, including live switching to Bokmål and preservation of protected-route sign-in intent; TypeScript passed.
- Backend matcher/intelligence focused verification: 35/35 passed, including detection of a manually created Norwegian advert with no saved translation.
- Full backend: 712/712 tests passed on .NET 9.
- Next optimized production build and TypeScript: passed after the Job Workspace/checklist batch.
diff --git a/job-tracker-ui/src/LandingPage.authRedirect.test.tsx b/job-tracker-ui/src/LandingPage.authRedirect.test.tsx
index ed707f2..2eb3ec9 100644
--- a/job-tracker-ui/src/LandingPage.authRedirect.test.tsx
+++ b/job-tracker-ui/src/LandingPage.authRedirect.test.tsx
@@ -5,6 +5,7 @@ import userEvent from "@testing-library/user-event";
import { MemoryRouter, Route, Routes, useLocation } from "react-router-dom";
import { api } from "./api";
import LandingPage from "./views/LandingPage";
+import { I18nProvider } from "./i18n/I18nProvider";
jest.mock("./api", () => ({
api: {
@@ -33,7 +34,7 @@ describe("LandingPage forwards deep-link intent to /login", () => {
render(
- } />
+ } />
} />
,
diff --git a/job-tracker-ui/src/i18n/translations.ts b/job-tracker-ui/src/i18n/translations.ts
index 4343a20..58037a7 100644
--- a/job-tracker-ui/src/i18n/translations.ts
+++ b/job-tracker-ui/src/i18n/translations.ts
@@ -182,6 +182,74 @@ export const translations = {
languageNorwegianBokmal: "Norsk bokmål",
discoverJobs: "Discover jobs",
discoverJobsSubtitle: "Search official job-board feeds and save opportunities to your tracker.",
+ landingSignIn: "Sign in",
+ landingSignInArrow: "Sign in →",
+ landingEyebrow: "AI-ASSISTED JOB SEARCH WORKSPACE",
+ landingHeroBefore: "Run your job search without losing",
+ landingHeroAccent: "the thread",
+ landingHeroBody: "Import a role, tailor your CV, track every application, and keep recruiter correspondence tied to the right job — all in one focused workspace. Assistive, never autonomous: you approve every draft.",
+ landingGetStarted: "Get started",
+ landingSeeFeatures: "See features",
+ landingPreviewEyebrow: "SEE IT IN ACTION",
+ landingPreviewTitle: "Your whole search, at a glance",
+ landingDashboardAlt: "Jobbjakt dashboard — KPIs, funnel, response trend and follow-ups",
+ landingPipelineAlt: "Drag-and-drop pipeline board",
+ landingWorkspaceAlt: "Per-job workspace with match score, correspondence and attachments",
+ landingPreviewCaption: "Interface preview.",
+ landingFeaturesEyebrow: "WHAT IT DOES",
+ landingFeaturesTitle: "One workspace for the whole search",
+ landingFeaturesBody: "Everything from a single import to the final offer — no more spreadsheets and scattered inboxes.",
+ landingFeaturePipeline: "Centralized pipeline",
+ landingFeaturePipelineBody: "Track every application across Applied, Waiting, Interview, Offer, Rejected and Ghosted — drag to update.",
+ landingFeatureFollowups: "Smart follow-ups",
+ landingFeatureFollowupsBody: "Reminders surface what needs attention next; Pro can help draft a response for you to review.",
+ landingFeatureMatch: "Honest CV match",
+ landingFeatureMatchBody: "A deterministic keyword-coverage score with matched vs missing skills — not an opaque black box.",
+ landingFeatureEmail: "Email correspondence",
+ landingFeatureEmailBody: "Keep linked Gmail and Microsoft messages in the context of the right application.",
+ landingFeatureDocuments: "Attachments & docs",
+ landingFeatureDocumentsBody: "Keep resumes, cover letters and portfolios versioned per application, right where you need them.",
+ landingFeatureInsights: "Dashboard & insights",
+ landingFeatureInsightsBody: "Response rates, funnel, time-in-stage and skill demand across your whole search.",
+ landingHowEyebrow: "HOW IT WORKS",
+ landingHowTitle: "From a link to an offer",
+ landingStepImport: "Import",
+ landingStepImportBody: "Paste a job URL or use the bookmarklet — we parse the role into structured fields.",
+ landingStepMatch: "Match",
+ landingStepMatchBody: "See how your CV covers the role: matched keywords and the gaps to close.",
+ landingStepTailor: "Tailor",
+ landingStepTailorBody: "With Pro, AI can draft a tailored CV and cover letter — you review every word before it goes out.",
+ landingStepTrack: "Track",
+ landingStepTrackBody: "Move it through the pipeline; documents, notes and history stay attached.",
+ landingStepFollowUp: "Follow up",
+ landingStepFollowUpBody: "Linked email threads and reminders keep momentum with grounded replies.",
+ landingStepAnalyze: "Analyze",
+ landingStepAnalyzeBody: "See what's working — response rate, funnel and time-in-stage — and focus your effort.",
+ landingPlansEyebrow: "PLANS",
+ landingPlansTitle: "Two clear plans",
+ landingPlansBody: "Free covers the core job search. Pro adds AI assistance and Pro CV themes.",
+ landingAiAssistance: "AI ASSISTANCE",
+ landingPlanFree: "Free",
+ landingPlanFreeSummary: "Core job-search organisation without AI generation.",
+ landingPlanFreeFeature1: "Track applications in table and Kanban views",
+ landingPlanFreeFeature2: "Keep notes, correspondence and documents with each job",
+ landingPlanFreeFeature3: "Edit your Career Profile and CVs manually",
+ landingPlanFreeFeature4: "Use the deterministic CV-to-job match score",
+ landingPlanFreeFeature5: "Export and retain your own data",
+ landingPlanFreeCta: "Create a Free account",
+ landingPlanPro: "Pro",
+ landingPlanProSummary: "AI assistance and Pro CV themes, with you in control.",
+ landingPlanProFeature1: "Everything in Free",
+ landingPlanProFeature2: "AI-assisted CV and cover-letter drafting",
+ landingPlanProFeature3: "AI job analysis and application strategy",
+ landingPlanProFeature4: "AI interview and follow-up preparation",
+ landingPlanProFeature5: "AI-assisted Career Profile import and rewriting",
+ landingPlanProFeature6: "Pro CV themes",
+ landingPlanProCta: "Sign in to view Pro",
+ landingCommercialTerms: "Commercial terms appear only in configured checkout. Your applications, documents and exports remain accessible if your plan changes.",
+ landingReadyTitle: "Ready to organize your search?",
+ landingReadyBody: "Sign in to start tracking applications, tailoring CVs, and following up with intent.",
+ landingFooter: "© {year} Jobbjakt — a focused workspace for the modern job search.",
jobDiscoveryRoleCompany: "Role or company",
jobDiscoveryMunicipality: "Municipality",
jobDiscoverySearchNav: "Search NAV",
@@ -2199,6 +2267,74 @@ export const translations = {
languageNorwegianBokmal: "Norsk bokmål",
discoverJobs: "Finn jobber",
discoverJobsSubtitle: "Søk i offisielle jobbportaler og lagre muligheter i oversikten din.",
+ landingSignIn: "Logg inn",
+ landingSignInArrow: "Logg inn →",
+ landingEyebrow: "AI-STØTTET ARBEIDSOMRÅDE FOR JOBBSØK",
+ landingHeroBefore: "Hold oversikten gjennom hele",
+ landingHeroAccent: "jobbsøket",
+ landingHeroBody: "Importer en stilling, tilpass CV-en, følg hver søknad og hold korrespondanse med rekrutterere knyttet til riktig jobb — alt i ett fokusert arbeidsområde. Assisterende, aldri autonomt: du godkjenner hvert utkast.",
+ landingGetStarted: "Kom i gang",
+ landingSeeFeatures: "Se funksjoner",
+ landingPreviewEyebrow: "SE DET I BRUK",
+ landingPreviewTitle: "Hele jobbsøket med ett blikk",
+ landingDashboardAlt: "Jobbjakt-oversikt med nøkkeltall, trakt, svartrend og oppfølginger",
+ landingPipelineAlt: "Dra-og-slipp-tavle for søknadsprosessen",
+ landingWorkspaceAlt: "Arbeidsområde per jobb med samsvar, korrespondanse og vedlegg",
+ landingPreviewCaption: "Forhåndsvisning av grensesnittet.",
+ landingFeaturesEyebrow: "DETTE FÅR DU",
+ landingFeaturesTitle: "Ett arbeidsområde for hele jobbsøket",
+ landingFeaturesBody: "Alt fra første import til endelig tilbud — uten regneark og spredte innbokser.",
+ landingFeaturePipeline: "Samlet søknadsprosess",
+ landingFeaturePipelineBody: "Følg alle søknader gjennom Søkt, Venter, Intervju, Tilbud, Avslått og Ingen svar — dra for å oppdatere.",
+ landingFeatureFollowups: "Smarte oppfølginger",
+ landingFeatureFollowupsBody: "Påminnelser viser hva som trenger oppmerksomhet; Pro kan hjelpe med et svarutkast du gjennomgår.",
+ landingFeatureMatch: "Ærlig CV-samsvar",
+ landingFeatureMatchBody: "En deterministisk dekning av nøkkelord med samsvarende og manglende ferdigheter — ikke en ugjennomsiktig svart boks.",
+ landingFeatureEmail: "E-postkorrespondanse",
+ landingFeatureEmailBody: "Behold tilknyttede Gmail- og Microsoft-meldinger i sammenheng med riktig søknad.",
+ landingFeatureDocuments: "Vedlegg og dokumenter",
+ landingFeatureDocumentsBody: "Behold CV-er, søknadsbrev og porteføljer versjonert per søknad, der du trenger dem.",
+ landingFeatureInsights: "Oversikt og innsikt",
+ landingFeatureInsightsBody: "Svarprosent, trakt, tid i status og etterspurte ferdigheter gjennom hele jobbsøket.",
+ landingHowEyebrow: "SLIK FUNGERER DET",
+ landingHowTitle: "Fra lenke til tilbud",
+ landingStepImport: "Importer",
+ landingStepImportBody: "Lim inn en stillingslenke eller bruk bokmerket — vi leser rollen inn i strukturerte felt.",
+ landingStepMatch: "Sammenlign",
+ landingStepMatchBody: "Se hvordan CV-en dekker rollen: samsvarende nøkkelord og hullene du bør lukke.",
+ landingStepTailor: "Tilpass",
+ landingStepTailorBody: "Med Pro kan AI lage utkast til tilpasset CV og søknadsbrev — du gjennomgår hvert ord før det sendes.",
+ landingStepTrack: "Følg opp",
+ landingStepTrackBody: "Flytt søknaden gjennom prosessen; dokumenter, notater og historikk forblir tilknyttet.",
+ landingStepFollowUp: "Hold kontakten",
+ landingStepFollowUpBody: "Tilknyttede e-posttråder og påminnelser holder fremdriften med faktabaserte svar.",
+ landingStepAnalyze: "Analyser",
+ landingStepAnalyzeBody: "Se hva som virker — svarprosent, trakt og tid i status — og fokuser innsatsen.",
+ landingPlansEyebrow: "ABONNEMENTER",
+ landingPlansTitle: "To tydelige alternativer",
+ landingPlansBody: "Free dekker det grunnleggende jobbsøket. Pro legger til AI-støtte og Pro-temaer for CV.",
+ landingAiAssistance: "AI-STØTTE",
+ landingPlanFree: "Free",
+ landingPlanFreeSummary: "Organiser jobbsøket uten AI-generering.",
+ landingPlanFreeFeature1: "Følg søknader i tabell- og Kanban-visning",
+ landingPlanFreeFeature2: "Behold notater, korrespondanse og dokumenter med hver jobb",
+ landingPlanFreeFeature3: "Rediger karriereprofilen og CV-er manuelt",
+ landingPlanFreeFeature4: "Bruk det deterministiske samsvaret mellom CV og jobb",
+ landingPlanFreeFeature5: "Eksporter og behold dine egne data",
+ landingPlanFreeCta: "Opprett en Free-konto",
+ landingPlanPro: "Pro",
+ landingPlanProSummary: "AI-støtte og Pro-temaer for CV, med deg i kontroll.",
+ landingPlanProFeature1: "Alt i Free",
+ landingPlanProFeature2: "AI-støttede utkast til CV og søknadsbrev",
+ landingPlanProFeature3: "AI-analyse av jobber og søknadsstrategi",
+ landingPlanProFeature4: "AI-støtte til intervju og oppfølging",
+ landingPlanProFeature5: "AI-støttet import og omskriving av karriereprofil",
+ landingPlanProFeature6: "Pro-temaer for CV",
+ landingPlanProCta: "Logg inn for å se Pro",
+ landingCommercialTerms: "Kommersielle vilkår vises bare i konfigurert betaling. Søknader, dokumenter og eksporter forblir tilgjengelige hvis abonnementet endres.",
+ landingReadyTitle: "Klar til å organisere jobbsøket?",
+ landingReadyBody: "Logg inn for å følge søknader, tilpasse CV-er og jobbe målrettet med oppfølging.",
+ landingFooter: "© {year} Jobbjakt — et fokusert arbeidsområde for moderne jobbsøk.",
jobDiscoveryRoleCompany: "Rolle eller bedrift",
jobDiscoveryMunicipality: "Kommune",
jobDiscoverySearchNav: "Søk i NAV",
diff --git a/job-tracker-ui/src/landing-page.test.tsx b/job-tracker-ui/src/landing-page.test.tsx
index 12bac2b..3a255ad 100644
--- a/job-tracker-ui/src/landing-page.test.tsx
+++ b/job-tracker-ui/src/landing-page.test.tsx
@@ -4,6 +4,7 @@ import { fireEvent, render, screen } from "@testing-library/react";
import { MemoryRouter } from "react-router-dom";
import { api } from "./api";
+import { I18nProvider } from "./i18n/I18nProvider";
import LandingPage from "./views/LandingPage";
const mockNavigate = jest.fn();
@@ -12,17 +13,18 @@ jest.mock("react-router-dom", () => ({
useNavigate: () => mockNavigate,
}));
-jest.mock("./api", () => ({ api: { get: jest.fn() } }));
+jest.mock("./api", () => ({ api: { get: jest.fn(), put: jest.fn().mockResolvedValue({ data: {} }) } }));
beforeEach(() => {
jest.clearAllMocks();
+ window.localStorage.clear();
(api.get as jest.Mock).mockRejectedValue({ response: { status: 401 } });
});
test("shows exactly Free and Pro without invented commercial terms", async () => {
render(
-
+
,
);
@@ -37,3 +39,11 @@ test("shows exactly Free and Pro without invented commercial terms", async () =>
fireEvent.click(screen.getByRole("button", { name: "Sign in to view Pro" }));
expect(mockNavigate).toHaveBeenCalledWith("/login", { state: { from: "/settings" } });
});
+
+test("switches the public landing page to Norwegian Bokmål", async () => {
+ render();
+
+ fireEvent.click(await screen.findByRole("button", { name: "Norsk" }));
+ expect(await screen.findByRole("heading", { name: "To tydelige alternativer" })).toBeInTheDocument();
+ expect(screen.getByRole("button", { name: "Opprett en Free-konto" })).toBeInTheDocument();
+});
diff --git a/job-tracker-ui/src/layout/AppShell.tsx b/job-tracker-ui/src/layout/AppShell.tsx
index 2cf0b73..25490a6 100644
--- a/job-tracker-ui/src/layout/AppShell.tsx
+++ b/job-tracker-ui/src/layout/AppShell.tsx
@@ -556,7 +556,7 @@ export default function AppShell({
);
}
-function StackLanguageToggle({ language, setLanguage }: { language: "en" | "nb"; setLanguage: (language: "en" | "nb") => void }) {
+export function StackLanguageToggle({ language, setLanguage }: { language: "en" | "nb"; setLanguage: (language: "en" | "nb") => void }) {
return (
diff --git a/job-tracker-ui/src/views/LandingPage.tsx b/job-tracker-ui/src/views/LandingPage.tsx
index 19d87e3..e8bd173 100644
--- a/job-tracker-ui/src/views/LandingPage.tsx
+++ b/job-tracker-ui/src/views/LandingPage.tsx
@@ -14,30 +14,34 @@ import InsightsIcon from "@mui/icons-material/InsightsOutlined";
import { api } from "../api";
import GradientButton from "../components/GradientButton";
import { PUBLIC_PLANS, PublicPlanId } from "../planCatalog";
+import { useI18n } from "../i18n/I18nProvider";
+import type { TranslationKey } from "../i18n/translations";
+import { StackLanguageToggle } from "../layout/AppShell";
const BRAND_DARK = "#0b1020";
const BRAND_PANEL = "#111a33";
-const FEATURES: { icon: React.ReactNode; title: string; body: string }[] = [
- { icon: , title: "Centralized pipeline", body: "Track every application across Applied, Waiting, Interview, Offer, Rejected and Ghosted — drag to update." },
- { icon: , title: "Smart follow-ups", body: "Reminders surface what needs attention next; Pro can help draft a response for you to review." },
- { icon: , title: "Honest CV match", body: "A deterministic keyword-coverage score with matched vs missing skills — not an opaque black box." },
- { icon: , title: "Email correspondence", body: "Keep linked Gmail and Microsoft messages in the context of the right application." },
- { icon: , title: "Attachments & docs", body: "Keep resumes, cover letters and portfolios versioned per application, right where you need them." },
- { icon: , title: "Dashboard & insights", body: "Response rates, funnel, time-in-stage and skill demand across your whole search." },
+const FEATURES: { icon: React.ReactNode; title: TranslationKey; body: TranslationKey }[] = [
+ { icon: , title: "landingFeaturePipeline", body: "landingFeaturePipelineBody" },
+ { icon: , title: "landingFeatureFollowups", body: "landingFeatureFollowupsBody" },
+ { icon: , title: "landingFeatureMatch", body: "landingFeatureMatchBody" },
+ { icon: , title: "landingFeatureEmail", body: "landingFeatureEmailBody" },
+ { icon: , title: "landingFeatureDocuments", body: "landingFeatureDocumentsBody" },
+ { icon: , title: "landingFeatureInsights", body: "landingFeatureInsightsBody" },
];
-const STEPS: { n: number; title: string; body: string }[] = [
- { n: 1, title: "Import", body: "Paste a job URL or use the bookmarklet — we parse the role into structured fields." },
- { n: 2, title: "Match", body: "See how your CV covers the role: matched keywords and the gaps to close." },
- { n: 3, title: "Tailor", body: "With Pro, AI can draft a tailored CV and cover letter — you review every word before it goes out." },
- { n: 4, title: "Track", body: "Move it through the pipeline; documents, notes and history stay attached." },
- { n: 5, title: "Follow up", body: "Linked email threads and reminders keep momentum with grounded replies." },
- { n: 6, title: "Analyze", body: "See what's working — response rate, funnel and time-in-stage — and focus your effort." },
+const STEPS: { n: number; title: TranslationKey; body: TranslationKey }[] = [
+ { n: 1, title: "landingStepImport", body: "landingStepImportBody" },
+ { n: 2, title: "landingStepMatch", body: "landingStepMatchBody" },
+ { n: 3, title: "landingStepTailor", body: "landingStepTailorBody" },
+ { n: 4, title: "landingStepTrack", body: "landingStepTrackBody" },
+ { n: 5, title: "landingStepFollowUp", body: "landingStepFollowUpBody" },
+ { n: 6, title: "landingStepAnalyze", body: "landingStepAnalyzeBody" },
];
export default function LandingPage() {
const navigate = useNavigate();
+ const { language, setLanguage, t } = useI18n();
const location = useLocation() as { state?: { from?: string } };
const [checking, setChecking] = useState(true);
@@ -66,7 +70,7 @@ export default function LandingPage() {
if (checking) {
return (
- Loading…
+ {t("loading")}
);
}
@@ -76,6 +80,13 @@ export default function LandingPage() {
WebkitBackgroundClip: "text",
WebkitTextFillColor: "transparent",
} as const;
+ const plans = PUBLIC_PLANS.map((plan) => ({
+ ...plan,
+ name: t(plan.id === "free" ? "landingPlanFree" : "landingPlanPro"),
+ summary: t(plan.id === "free" ? "landingPlanFreeSummary" : "landingPlanProSummary"),
+ features: plan.features.map((_, index) => t(`landingPlan${plan.id === "free" ? "Free" : "Pro"}Feature${index + 1}` as TranslationKey)),
+ cta: t(plan.id === "free" ? "landingPlanFreeCta" : "landingPlanProCta"),
+ }));
return (
@@ -87,9 +98,12 @@ export default function LandingPage() {
✓
Jobbjakt
-
- Sign in
-
+
+
+
+ {t("landingSignIn")}
+
+
@@ -99,21 +113,20 @@ export default function LandingPage() {
- AI-ASSISTED JOB SEARCH WORKSPACE
+ {t("landingEyebrow")}
- Run your job search without losing the thread.
+ {t("landingHeroBefore")} {t("landingHeroAccent")}.
- Import a role, tailor your CV, track every application, and keep recruiter correspondence tied to the
- right job — all in one focused workspace. Assistive, never autonomous: you approve every draft.
+ {t("landingHeroBody")}
- Get started
+ {t("landingGetStarted")}
@@ -126,38 +139,38 @@ export default function LandingPage() {
{/* Product preview */}
- SEE IT IN ACTION
- Your whole search, at a glance
+ {t("landingPreviewEyebrow")}
+ {t("landingPreviewTitle")}
-
+
-
+
-
+
- Interface preview.
+ {t("landingPreviewCaption")}
{/* Features */}
- WHAT IT DOES
- One workspace for the whole search
+ {t("landingFeaturesEyebrow")}
+ {t("landingFeaturesTitle")}
- Everything from a single import to the final offer — no more spreadsheets and scattered inboxes.
+ {t("landingFeaturesBody")}
{FEATURES.map((f) => (
{f.icon}
- {f.title}
- {f.body}
+ {t(f.title)}
+ {t(f.body)}
))}
@@ -167,15 +180,15 @@ export default function LandingPage() {
- HOW IT WORKS
- From a link to an offer
+ {t("landingHowEyebrow")}
+ {t("landingHowTitle")}
{STEPS.map((s) => (
{s.n}
- {s.title}
- {s.body}
+ {t(s.title)}
+ {t(s.body)}
))}
@@ -185,14 +198,14 @@ export default function LandingPage() {
{/* Plans */}
- PLANS
- Two clear plans
+ {t("landingPlansEyebrow")}
+ {t("landingPlansTitle")}
- Free covers the core job search. Pro adds AI assistance and Pro CV themes.
+ {t("landingPlansBody")}
- {PUBLIC_PLANS.map((plan) => (
+ {plans.map((plan) => (
{plan.id === "pro" && (
- AI ASSISTANCE
+ {t("landingAiAssistance")}
)}
{plan.name}
@@ -237,7 +250,7 @@ export default function LandingPage() {
))}
- Commercial terms appear only in configured checkout. Your applications, documents and exports remain accessible if your plan changes.
+ {t("landingCommercialTerms")}
@@ -245,11 +258,11 @@ export default function LandingPage() {
- Ready to organize your search?
- Sign in to start tracking applications, tailoring CVs, and following up with intent.
+ {t("landingReadyTitle")}
+ {t("landingReadyBody")}
- Sign in →
+ {t("landingSignInArrow")}
@@ -258,8 +271,8 @@ export default function LandingPage() {
- © {new Date().getFullYear()} Jobbjakt — a focused workspace for the modern job search.
-
+ {t("landingFooter", { year: new Date().getFullYear() })}
+