import type { Metadata } from "next" import { getTranslations, getMessages, setRequestLocale } from "next-intl/server" import { Link } from "@/i18n/navigation" import { ExternalLink } from "lucide-react" 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.glossary.meta" }) return { title: t("title"), description: t("description"), openGraph: { title: t("ogTitle"), description: t("ogDescription"), type: "article", url: "https://macrimi.github.io/ProxMenux/docs/glossary", }, } } type Category = "Proxmox" | "Virtualization" | "Storage" | "Network" | "Linux" | "ProxMenux" type SeeAlso = { label: string; href: string } type GlossaryEntry = { term: string aliases?: string[] category: Category definitionRich: string seeAlso?: SeeAlso[] } const categoryColor: Record = { Proxmox: "bg-red-50 text-red-700 border-red-200", Virtualization: "bg-blue-50 text-blue-700 border-blue-200", Storage: "bg-amber-50 text-amber-700 border-amber-200", Network: "bg-emerald-50 text-emerald-700 border-emerald-200", Linux: "bg-purple-50 text-purple-700 border-purple-200", ProxMenux: "bg-gray-100 text-gray-700 border-gray-300", } function CategoryBadge({ category }: { category: Category }) { return ( {category} ) } export default async function GlossaryPage({ params, }: { params: Promise<{ locale: string }> }) { const { locale } = await params setRequestLocale(locale) const t = await getTranslations({ locale, namespace: "docs.glossary" }) const messages = (await getMessages({ locale })) as unknown as { docs: { glossary: { entries: GlossaryEntry[] } } } const entries = messages.docs.glossary.entries const sortedEntries = [...entries].sort((a, b) => a.term.localeCompare(b.term, "en", { sensitivity: "base" }) ) const lettersInUse = Array.from( new Set(sortedEntries.map((e) => e.term[0].toUpperCase())) ).sort() const code = (chunks: React.ReactNode) => {chunks} const strong = (chunks: React.ReactNode) => {chunks} const em = (chunks: React.ReactNode) => {chunks} const ext = (chunks: React.ReactNode) => ( {chunks} ) return (
{t.rich("callout.bodyRich", { em })}

{t("jumpHeading")}

{lettersInUse.map((letter) => ( {letter} ))}
{sortedEntries.map((entry, i) => { const letter = entry.term[0].toUpperCase() const prevLetter = i > 0 ? sortedEntries[i - 1].term[0].toUpperCase() : null const isFirstOfLetter = letter !== prevLetter const entryIdx = entries.findIndex((e) => e.term === entry.term) return (
{isFirstOfLetter && (

{letter}

)}

{entry.term}

{entry.aliases && entry.aliases.length > 0 && ( {t("aliasesLabel")} {entry.aliases.join(" · ")} )}

{t.rich(`entries.${entryIdx}.definitionRich`, { code, strong, em })}

{entry.seeAlso && entry.seeAlso.length > 0 && (

{t("seeAlsoLabel")}{" "} {entry.seeAlso.map((s, idx) => ( {s.label} {idx < entry.seeAlso!.length - 1 && " · "} ))}

)}
) })}
{t.rich("missingCallout.leadRich", { ext, code })}
) }