import type { Metadata } from "next" import { getTranslations, getMessages, setRequestLocale } from "next-intl/server" import { AlertTriangle } 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.crossKernel.meta" }) return { title: t("title"), description: t("description"), keywords: [ "proxmox cross-kernel restore", "bk_older bk_newer safe subset", "IOMMU VFIO hydration", "kernel-agnostic restore", "hb_unsafe_paths_cross_version", "HB_HYDRATION_APPLIED", ], alternates: { canonical: "https://proxmenux.com/docs/backup-restore/cross-kernel" }, openGraph: { title: t("ogTitle"), description: t("ogDescription"), type: "article", url: "https://proxmenux.com/docs/backup-restore/cross-kernel", }, twitter: { card: "summary_large_image", title: t("twitterTitle"), description: t("twitterDescription"), }, } } type DirectionRow = { direction: string; condition: string; behavior: string } type CategoryRow = { category: string; paths: string; reason: string } type PhaseRow = { phase: string; detail: string } type ScenarioRow = { scenario: string; detail: string } type CodeRefRow = { component: string; location: string } type WhereNextItem = { label: string; href: string; tail: string } export default async function CrossKernelPage({ params, }: { params: Promise<{ locale: string }> }) { const { locale } = await params setRequestLocale(locale) const t = await getTranslations({ locale, namespace: "docs.backupRestore.crossKernel" }) const messages = (await getMessages({ locale })) as unknown as { docs: { backupRestore: { crossKernel: { directionCheck: { rows: DirectionRow[] } safeSubsetFilter: { categoryRows: CategoryRow[] } hydration: { phaseRows: PhaseRow[] } concreteExamples: { rows: ScenarioRow[] } codeReference: { rows: CodeRefRow[] } whereNext: { items: WhereNextItem[] } } } } } const ck = messages.docs.backupRestore.crossKernel const directionRows = ck.directionCheck.rows const categoryRows = ck.safeSubsetFilter.categoryRows const phaseRows = ck.hydration.phaseRows const scenarioRows = ck.concreteExamples.rows const codeRefRows = ck.codeReference.rows const whereNextItems = ck.whereNext.items const code = (chunks: React.ReactNode) => {chunks} const strong = (chunks: React.ReactNode) => {chunks} const em = (chunks: React.ReactNode) => {chunks} return (
{t.rich("intro.body", { code, strong, em })}

{t("directionCheck.heading")}

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

{directionRows.map((row, idx) => ( ))}
Direction Condition Behaviour
{row.direction} {t.rich(`directionCheck.rows.${idx}.condition`, { code })} {t.rich(`directionCheck.rows.${idx}.behavior`, { code, em })}

{t("whyBkNewerIsSafe.heading")}

{t.rich("whyBkNewerIsSafe.body", { code, em })}

{t("safeSubsetFilter.heading")}

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

{categoryRows.map((row, idx) => ( ))}
Category Paths Why they are skipped
{row.category} {t.rich(`safeSubsetFilter.categoryRows.${idx}.paths`, { code })} {t.rich(`safeSubsetFilter.categoryRows.${idx}.reason`, { code })}

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

{t("hydration.heading")}

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

{phaseRows.map((row, idx) => ( ))}
Phase Detail
{row.phase} {t.rich(`hydration.phaseRows.${idx}.detail`, { code })}

{t("planCommit.heading")}

{t.rich("planCommit.body", { code, em })}

{t("flowDiagram.heading")}

{t("flowDiagram.intro")}

        {t("flowDiagram.diagram")}
      

{t("concreteExamples.heading")}

{t("concreteExamples.intro")}

{scenarioRows.map((row, idx) => ( ))}
Scenario What hydration does
{row.scenario} {t.rich(`concreteExamples.rows.${idx}.detail`, { code })}

{t("codeReference.heading")}

{t("codeReference.intro")}

{codeRefRows.map((row, idx) => ( ))}
Component Location
{row.component} {t.rich(`codeReference.rows.${idx}.location`, { code })}

{t("whereNext.heading")}

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