import type { Metadata } from "next" import { getTranslations, getMessages, setRequestLocale } from "next-intl/server" import { Link } from "@/i18n/navigation" import { DocHeader } from "@/components/ui/doc-header" import { Callout } from "@/components/ui/callout" import CopyableCode from "@/components/CopyableCode" export async function generateMetadata({ params, }: { params: Promise<{ locale: string }> }): Promise { const { locale } = await params const t = await getTranslations({ locale, namespace: "docs.diskManager.formatDisk.meta" }) return { title: t("title"), description: t("description"), openGraph: { title: t("ogTitle"), description: t("ogDescription"), type: "article", url: "https://macrimi.github.io/ProxMenux/docs/disk-manager/format-disk", }, } } type StringItem = string type ModeRow = { mode: string; part: string; data: string; useCase: string } type StepData = { title: string; body?: string; bodyRich?: string } type RelatedItem = { href: string; label: string; tail?: string } export default async function FormatDiskPage({ params, }: { params: Promise<{ locale: string }> }) { const { locale } = await params setRequestLocale(locale) const t = await getTranslations({ locale, namespace: "docs.diskManager.formatDisk" }) const messages = (await getMessages({ locale })) as unknown as { docs: { diskManager: { formatDisk: { visibility: { items: StringItem[]; safetyItems: StringItem[] } modes: { rows: ModeRow[]; fullFormatItems: StringItem[] } steps: { list: StepData[] } related: { items: RelatedItem[] } } } } } const visItems = messages.docs.diskManager.formatDisk.visibility.items const safetyItems = messages.docs.diskManager.formatDisk.visibility.safetyItems const modeRows = messages.docs.diskManager.formatDisk.modes.rows const fullFormatItems = messages.docs.diskManager.formatDisk.modes.fullFormatItems const stepList = messages.docs.diskManager.formatDisk.steps.list const relatedItems = messages.docs.diskManager.formatDisk.related.items const code = (chunks: React.ReactNode) => {chunks} const strong = (chunks: React.ReactNode) => {chunks} const em = (chunks: React.ReactNode) => {chunks} return (
{t("danger.body")}

{t("howRuns.heading")}

{t("howRuns.body")}

{`┌─────────────────────────────────────────────┐
│  PHASE 1 — Filter, choose, confirm          │
│  (nothing touched yet)                      │
└──────────────────┬──────────────────────────┘
                   ▼
      Detect disks on host (lsblk)
                   │
                   ▼
      Visibility filter
      ├─ Hidden: root / swap / system-mounted
      ├─ Hidden: active ZFS / LVM / RAID members
      ├─ Hidden: referenced by any VM/LXC config
      └─ Shown: fully free disks (⚠ for stale sigs)
                   │
                   ▼
      User picks a disk
                   │
                   ▼
      Operation mode
      ├─ 1. Wipe all         (partitions + sigs)
      ├─ 2. Remove FS labels (data preserved)
      ├─ 3. Zero all data    (partitions kept)
      └─ 4. Full format      (new GPT + mkfs)
                   │
                   ▼
      Mode = 4? → extra questions
      ├─ Filesystem: ext4 / xfs / exfat / btrfs
      │    └─ if tool missing (mkfs.btrfs,
      │       mkfs.exfat) → abort with hint
      └─ Optional label
                   │
                   ▼
      ╔════════════════════════════════════╗
      ║  Double confirmation gate           ║
      ║  (1) yes/no dialog with summary     ║
      ║  (2) type the full disk path exactly║
      ║      (e.g. /dev/sdc)                ║
      ║  Any mismatch → abort               ║
      ╚══════════════════╤═════════════════╝
                         │
  ┌──────── Cancel   OR   Confirm ────┐
  ▼                                   ▼
Exit, nothing        ┌─────────────────┴─────────────────┐
was changed          │  PHASE 2 — Execute                 │
                     └─────────────────┬─────────────────┘
                                       ▼
                       Pre-execution re-validation
                       (state may have changed since
                        Phase 1 — user just confirmed)
                       ├─ Disk now hosts system mount?
                       │    → hard block, abort
                       ├─ Disk now in root ZFS pool?
                       │    → hard block, abort
                       ├─ Disk has active swap?
                       │    → hard block, abort
                       └─ Data partitions still mounted?
                          → auto-unmount; abort if fails
                                       │
                                       ▼
                       Run the selected mode:
                       ┌─────────────────────────────────┐
                       │ 1. Wipe all                     │
                       │    wipefs -af             │
                       │    sgdisk --zap-all       │
                       ├─────────────────────────────────┤
                       │ 2. Remove FS labels             │
                       │    wipefs -af             │
                       │    + wipefs -af each partition  │
                       │    (partition table PRESERVED)  │
                       ├─────────────────────────────────┤
                       │ 3. Zero all data                │
                       │    For each partition:          │
                       │      dd if=/dev/zero of=  │
                       │         bs=4M                   │
                       │    (partition table PRESERVED)  │
                       ├─────────────────────────────────┤
                       │ 4. Full format                  │
                       │    wipefs -af             │
                       │    sgdisk --zap-all       │
                       │    sgdisk -n 1:0:0 -t 1:8300    │
                       │                           │
                       │    mkfs. [-L 

{t("visibility.heading")}

{t("visibility.intro")}

    {visItems.map((_, idx) => (
  • {t.rich(`visibility.items.${idx}`, { strong, em })}
  • ))}
    {safetyItems.map((_, idx) => (
  • {t.rich(`visibility.safetyItems.${idx}`, { strong, em })}
  • ))}

{t("modes.heading")}

{t("modes.intro")}

{modeRows.map((row) => ( ))}
{t("modes.headerMode")} {t("modes.headerPart")} {t("modes.headerData")} {t("modes.headerUseCase")}
{row.mode} {row.part} {row.data} {row.useCase}

{t.rich("modes.fullFormatOutro", { strong })}

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

{t("steps.heading")}

{stepList.map((step, idx) => (
{t("steps.stepLabel")} {idx + 1}

{step.title}

{step.bodyRich ? (

{t.rich(`steps.list.${idx}.bodyRich`, { strong, code })}

) : step.body &&

{step.body}

}
))}

{t("manual.heading")}

{t("manual.body")}

{t.rich("troubleshoot.notListedBody", { code })} {t.rich("troubleshoot.busyBody", { code })}

{t("related.heading")}

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