import type { Metadata } from "next" import { getTranslations, getMessages, setRequestLocale } from "next-intl/server" import { Info, CalendarClock } from "lucide-react" import { Link } from "@/i18n/navigation" import { DocHeader } from "@/components/ui/doc-header" import { Callout } from "@/components/ui/callout" export async function generateMetadata({ params, }: { params: Promise<{ locale: string }> }): Promise { const { locale } = await params const t = await getTranslations({ locale, namespace: "docs.backupRestore.scheduledJobs.meta" }) return { title: t("title"), description: t("description"), keywords: [ "proxmox scheduled backup", "proxmenux backup job", "systemd timer backup", "vzdump attach hook", "keep-last keep-daily", "backup retention proxmox", ], alternates: { canonical: "https://proxmenux.com/docs/backup-restore/scheduled-jobs" }, openGraph: { title: t("ogTitle"), description: t("ogDescription"), type: "article", url: "https://proxmenux.com/docs/backup-restore/scheduled-jobs", }, twitter: { card: "summary_large_image", title: t("twitterTitle"), description: t("twitterDescription"), }, } } type ModeRow = { mode: string; backends: string; schedule: string; retention: string } type StepRow = { step: string; detail: string } type LayoutRow = { path: string; content: string } type MgmtRow = { action: string; detail: string } type WhereNextItem = { label: string; href: string; tail: string } export default async function ScheduledJobsPage({ params, }: { params: Promise<{ locale: string }> }) { const { locale } = await params setRequestLocale(locale) const t = await getTranslations({ locale, namespace: "docs.backupRestore.scheduledJobs" }) const messages = (await getMessages({ locale })) as unknown as { docs: { backupRestore: { scheduledJobs: { intro: { modelsList: string[] } modes: { rows: ModeRow[] } attachDetail: { steps: StepRow[] } storageLayout: { rows: LayoutRow[] } runner: { steps: string[] } management: { rows: MgmtRow[] } whereNext: { items: WhereNextItem[] } } } } } const sj = messages.docs.backupRestore.scheduledJobs const modelsList = sj.intro.modelsList const modeRows = sj.modes.rows const attachSteps = sj.attachDetail.steps const layoutRows = sj.storageLayout.rows const runnerSteps = sj.runner.steps const mgmtRows = sj.management.rows const whereNextItems = sj.whereNext.items const code = (chunks: React.ReactNode) => {chunks} const strong = (chunks: React.ReactNode) => {chunks} const em = (chunks: React.ReactNode) => {chunks} return (

{t("intro.title")}

{t("intro.body")}

    {modelsList.map((_, idx) => (
  • {t.rich(`intro.modelsList.${idx}`, { code, strong })}
  • ))}

{t("modes.heading")}

{modeRows.map((row, idx) => ( ))}
Mode Backends Schedule Retention
{row.mode} {row.backends} {t.rich(`modes.rows.${idx}.schedule`, { code })} {t.rich(`modes.rows.${idx}.retention`, { code })}

{t("attachDetail.heading")}

{t.rich("attachDetail.intro", { code })}

{attachSteps.map((row, idx) => ( ))}
# Detail
{row.step} {t.rich(`attachDetail.steps.${idx}.detail`, { code })}

{t.rich("attachDetail.outroBody", { code })}

{t("storageLayout.heading")}

{t("storageLayout.intro")}

{layoutRows.map((row, idx) => ( ))}
Path Content
{row.path} {t.rich(`storageLayout.rows.${idx}.content`, { code })}

{t.rich("runner.heading", { code })}

{t("runner.intro")}

    {runnerSteps.map((_, idx) => (
  1. {t.rich(`runner.steps.${idx}`, { code, strong })}
  2. ))}

{t("management.heading")}

{t("management.intro")}

{mgmtRows.map((row, idx) => ( ))}
Action Detail
{row.action} {t.rich(`management.rows.${idx}.detail`, { code })}

{t("notifications.heading")}

{t.rich("notifications.body", { code })}

{t("whereNext.heading")}

    {whereNextItems.map((item) => (
  • {item.label} {item.tail}
  • ))}
) }