Servers.tsx i18n

This commit is contained in:
headlessdev 2025-04-29 16:20:34 +02:00
parent 58e2466875
commit c4f3b47fc7
2 changed files with 342 additions and 272 deletions

View File

@ -28,6 +28,8 @@ import {
Copy,
History,
Thermometer,
ChevronLeft,
ChevronRight,
} from "lucide-react"
import { Card, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import {
@ -124,7 +126,7 @@ interface MonitoringData {
}
export default function Servers() {
const t = useTranslations('Servers')
const t = useTranslations()
const [host, setHost] = useState<boolean>(false)
const [hostServer, setHostServer] = useState<number>(0)
const [name, setName] = useState<string>("")
@ -527,11 +529,11 @@ export default function Servers() {
</BreadcrumbItem>
<BreadcrumbSeparator className="hidden md:block" />
<BreadcrumbItem>
<BreadcrumbPage>{t('MyInfrastructure')}</BreadcrumbPage>
<BreadcrumbPage>{t('Servers.MyInfrastructure')}</BreadcrumbPage>
</BreadcrumbItem>
<BreadcrumbSeparator className="hidden md:block" />
<BreadcrumbItem>
<BreadcrumbPage>{t('Servers')}</BreadcrumbPage>
<BreadcrumbPage>{t('Servers.Title')}</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
@ -540,11 +542,11 @@ export default function Servers() {
<Toaster />
<div className="p-6">
<div className="flex justify-between items-center">
<span className="text-3xl font-bold">{t('YourServers')}</span>
<span className="text-3xl font-bold">{t('Servers.YourServers')}</span>
<div className="flex gap-2">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" size="icon" title={t('ChangeView')}>
<Button variant="outline" size="icon" title={t('Common.ChangeView')}>
{isGridLayout ? (
<LayoutGrid className="h-4 w-4" />
) : (
@ -554,10 +556,10 @@ export default function Servers() {
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem onClick={() => toggleLayout(false)}>
<List className="h-4 w-4 mr-2" /> {t('ListView')}
<List className="h-4 w-4 mr-2" /> {t('Common.ListView')}
</DropdownMenuItem>
<DropdownMenuItem onClick={() => toggleLayout(true)}>
<LayoutGrid className="h-4 w-4 mr-2" /> {t('GridView')}
<LayoutGrid className="h-4 w-4 mr-2" /> {t('Common.GridView')}
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
@ -573,23 +575,23 @@ export default function Servers() {
>
<SelectTrigger className="w-[140px]">
<SelectValue>
{itemsPerPage} {itemsPerPage === 1 ? t('ItemsPerPage.item') : t('ItemsPerPage.items')}
{itemsPerPage} {itemsPerPage === 1 ? t('Common.ItemsPerPage.item') : t('Common.ItemsPerPage.items')}
</SelectValue>
</SelectTrigger>
<SelectContent>
{![4, 6, 10, 15, 20, 25].includes(itemsPerPage) ? (
<SelectItem value={String(itemsPerPage)}>
{itemsPerPage} {itemsPerPage === 1 ? t('ItemsPerPage.item') : t('ItemsPerPage.items')} ({t('ItemsPerPage.Custom')})
{itemsPerPage} {itemsPerPage === 1 ? t('Common.ItemsPerPage.item') : t('Common.ItemsPerPage.items')} ({t('Common.ItemsPerPage.Custom')})
</SelectItem>
) : null}
<SelectItem value="4">{t('4')}</SelectItem>
<SelectItem value="6">{t('6')}</SelectItem>
<SelectItem value="10">{t('10')}</SelectItem>
<SelectItem value="15">{t('15')}</SelectItem>
<SelectItem value="20">{t('20')}</SelectItem>
<SelectItem value="25">{t('25')}</SelectItem>
<SelectItem value="4">{t('Common.ItemsPerPage.4')}</SelectItem>
<SelectItem value="6">{t('Common.ItemsPerPage.6')}</SelectItem>
<SelectItem value="10">{t('Common.ItemsPerPage.10')}</SelectItem>
<SelectItem value="15">{t('Common.ItemsPerPage.15')}</SelectItem>
<SelectItem value="20">{t('Common.ItemsPerPage.20')}</SelectItem>
<SelectItem value="25">{t('Common.ItemsPerPage.25')}</SelectItem>
<div className="p-2 border-t mt-1">
<Label htmlFor="custom-items" className="text-xs font-medium">{t('ItemsPerPage.Custom')}</Label>
<Label htmlFor="custom-items" className="text-xs font-medium">{t('Common.ItemsPerPage.Custom')}</Label>
<div className="flex items-center gap-2 mt-1">
<Input
id="custom-items"
@ -640,7 +642,7 @@ export default function Servers() {
}}
onClick={(e) => e.stopPropagation()}
/>
<span className="text-xs text-muted-foreground whitespace-nowrap">{t('ItemsPerPage.items')}</span>
<span className="text-xs text-muted-foreground whitespace-nowrap">{t('Common.ItemsPerPage.items')}</span>
</div>
</div>
</SelectContent>
@ -655,7 +657,7 @@ export default function Servers() {
<AlertDialogContent className="max-w-[95vw] w-[600px] max-h-[90vh] overflow-y-auto">
<AlertDialogHeader>
<AlertDialogTitle className="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-4">
<span>{t('AddServer.Title')}</span>
<span>{t('Servers.AddServer.Title')}</span>
<Select
onValueChange={(value) => {
if (!value) return;
@ -696,7 +698,7 @@ export default function Servers() {
<SelectTrigger className="w-[140px] h-8 text-xs">
<div className="flex items-center gap-1.5">
<Copy className="h-3 w-3 text-muted-foreground" />
<SelectValue placeholder="Copy server" />
<SelectValue placeholder={t('Servers.AddServer.General.CopyServer')} />
</div>
</SelectTrigger>
<SelectContent>
@ -711,20 +713,20 @@ export default function Servers() {
<AlertDialogDescription>
<Tabs defaultValue="general" className="w-full">
<TabsList className="w-full">
<TabsTrigger value="general">{t('Tabs.General')}</TabsTrigger>
<TabsTrigger value="hardware">{t('Tabs.Hardware')}</TabsTrigger>
<TabsTrigger value="virtualization">{t('Tabs.Host')}</TabsTrigger>
<TabsTrigger value="monitoring">{t('Tabs.Monitoring')}</TabsTrigger>
<TabsTrigger value="general">{t('Common.Server.Tabs.General')}</TabsTrigger>
<TabsTrigger value="hardware">{t('Common.Server.Tabs.Hardware')}</TabsTrigger>
<TabsTrigger value="virtualization">{t('Common.Server.Tabs.Host')}</TabsTrigger>
<TabsTrigger value="monitoring">{t('Common.Server.Tabs.Monitoring')}</TabsTrigger>
</TabsList>
<TabsContent value="general">
<div className="space-y-4 pt-4">
<div className="flex flex-col sm:flex-row items-start sm:items-center gap-4">
<div className="grid w-full sm:w-[calc(100%-52px)] items-center gap-1.5">
<Label htmlFor="icon">{t('AddServer.General.Icon')}</Label>
<Label htmlFor="icon">{t('Servers.AddServer.General.Icon')}</Label>
<div className="space-y-2">
<Select value={icon} onValueChange={(value) => setIcon(value)}>
<SelectTrigger className="w-full">
<SelectValue placeholder={t('AddServer.General.IconPlaceholder')}>
<SelectValue placeholder={t('Servers.AddServer.General.IconPlaceholder')}>
{icon && (
<div className="flex items-center gap-2">
<DynamicIcon name={icon as any} size={18} />
@ -735,7 +737,7 @@ export default function Servers() {
</SelectTrigger>
<SelectContent className="max-h-[300px]">
<Input
placeholder={t('AddServer.General.IconSearchPlaceholder')}
placeholder={t('Servers.AddServer.General.IconSearchPlaceholder')}
className="mb-2"
onChange={(e) => {
const iconElements = document.querySelectorAll("[data-icon-item]")
@ -776,14 +778,14 @@ export default function Servers() {
</div>
</div>
<div className="grid w-[52px] items-center gap-1.5">
<Label htmlFor="icon">{t('AddServer.General.Preview')}</Label>
<Label htmlFor="icon">{t('Servers.AddServer.General.Preview')}</Label>
<div className="flex items-center justify-center">
{icon && <DynamicIcon name={icon as any} size={36} />}
</div>
</div>
</div>
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="name">{t('AddServer.General.Name')}</Label>
<Label htmlFor="name">{t('Servers.AddServer.General.Name')}</Label>
<Input
id="name"
type="text"
@ -794,11 +796,11 @@ export default function Servers() {
</div>
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="description">
{t('AddServer.General.OperatingSystem')} <span className="text-stone-600">({t('optional')})</span>
{t('Servers.AddServer.General.OperatingSystem')} <span className="text-stone-600">({t('Common.optional')})</span>
</Label>
<Select value={os} onValueChange={(value) => setOs(value)}>
<SelectTrigger className="w-full">
<SelectValue placeholder={t('AddServer.General.OperatingSystemPlaceholder')} />
<SelectValue placeholder={t('Servers.AddServer.General.OperatingSystemPlaceholder')} />
</SelectTrigger>
<SelectContent>
<SelectItem value="Windows">Windows</SelectItem>
@ -809,7 +811,7 @@ export default function Servers() {
</div>
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="ip">
{t('AddServer.General.IPAdress')} <span className="text-stone-600">({t('optional')})</span>
{t('Servers.AddServer.General.IPAdress')} <span className="text-stone-600">({t('Common.optional')})</span>
</Label>
<Input
id="ip"
@ -824,11 +826,11 @@ export default function Servers() {
<Tooltip>
<TooltipTrigger>
<Label htmlFor="publicURL">
{t('AddServer.General.ManagementURL')} <span className="text-stone-600">({t('optional')})</span>
{t('Servers.AddServer.General.ManagementURL')} <span className="text-stone-600">({t('Common.optional')})</span>
</Label>
</TooltipTrigger>
<TooltipContent>
{t('AddServer.General.ManagementURLTooltip')}
{t('Servers.AddServer.General.ManagementURLTooltip')}
</TooltipContent>
</Tooltip>
</TooltipProvider>
@ -846,7 +848,7 @@ export default function Servers() {
<div className="space-y-4 pt-4">
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="cpu">
{t('AddServer.Hardware.CPU')} <span className="text-stone-600">({t('optional')})</span>
{t('Common.Server.CPU')} <span className="text-stone-600">({t('Common.optional')})</span>
</Label>
<Input
id="cpu"
@ -858,7 +860,7 @@ export default function Servers() {
</div>
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="gpu">
{t('AddServer.Hardware.GPU')} <span className="text-stone-600">({t('optional')})</span>
{t('Common.Server.GPU')} <span className="text-stone-600">({t('Common.optional')})</span>
</Label>
<Input
id="gpu"
@ -870,7 +872,7 @@ export default function Servers() {
</div>
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="ram">
{t('AddServer.Hardware.RAM')} <span className="text-stone-600">({t('optional')})</span>
{t('Common.Server.RAM')} <span className="text-stone-600">({t('Common.optional')})</span>
</Label>
<Input
id="ram"
@ -882,7 +884,7 @@ export default function Servers() {
</div>
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="disk">
{t('AddServer.Hardware.Disk')} <span className="text-stone-600">({t('optional')})</span>
{t('Common.Server.Disk')} <span className="text-stone-600">({t('Common.optional')})</span>
</Label>
<Input
id="disk"
@ -902,11 +904,11 @@ export default function Servers() {
checked={host}
onCheckedChange={(checked) => setHost(checked === true)}
/>
<Label htmlFor="hostCheckbox">{t('AddServer.Host.MarkAsHostServer')}</Label>
<Label htmlFor="hostCheckbox">{t('Servers.AddServer.Host.MarkAsHostServer')}</Label>
</div>
{!host && (
<div className="grid w-full items-center gap-1.5">
<Label>{t('AddServer.Host.SelectHostServer')}</Label>
<Label>{t('Servers.AddServer.Host.SelectHostServer')}</Label>
<Select
value={hostServer?.toString()}
onValueChange={(value) => {
@ -918,10 +920,10 @@ export default function Servers() {
}}
>
<SelectTrigger>
<SelectValue placeholder={t('AddServer.Host.SelectHostServerPlaceholder')} />
<SelectValue placeholder={t('Servers.AddServer.Host.SelectHostServerPlaceholder')} />
</SelectTrigger>
<SelectContent>
<SelectItem value="0">{t('AddServer.Host.NoHostServer')}</SelectItem>
<SelectItem value="0">{t('Servers.AddServer.Host.NoHostServer')}</SelectItem>
{hostServers.map((server) => (
<SelectItem key={server.id} value={server.id.toString()}>
{server.name}
@ -941,12 +943,12 @@ export default function Servers() {
checked={monitoring}
onCheckedChange={(checked) => setMonitoring(checked === true)}
/>
<Label htmlFor="monitoringCheckbox">{t('AddServer.Monitoring.Enable')}</Label>
<Label htmlFor="monitoringCheckbox">{t('Servers.AddServer.Monitoring.Enable')}</Label>
</div>
{monitoring && (
<>
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="monitoringURL">{t('AddServer.Monitoring.URL')}</Label>
<Label htmlFor="monitoringURL">{t('Servers.AddServer.Monitoring.URL')}</Label>
<Input
id="monitoringURL"
type="text"
@ -956,9 +958,9 @@ export default function Servers() {
/>
</div>
<div className="mt-4 p-4 border rounded-lg bg-muted">
<h4 className="text-sm font-semibold mb-2">{t('AddServer.Monitoring.SetupTitle')}</h4>
<h4 className="text-sm font-semibold mb-2">{t('Servers.AddServer.Monitoring.SetupTitle')}</h4>
<p className="text-sm text-muted-foreground mb-3">
{t('AddServer.Monitoring.SetupDescription')}
{t('Servers.AddServer.Monitoring.SetupDescription')}
</p>
<pre className="bg-background p-4 rounded-md text-sm overflow-x-auto">
<code>{`services:
@ -983,8 +985,8 @@ export default function Servers() {
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>{t('cancel')}</AlertDialogCancel>
<AlertDialogAction onClick={add}>{t('add')}</AlertDialogAction>
<AlertDialogCancel>{t('Common.cancel')}</AlertDialogCancel>
<AlertDialogAction onClick={add}>{t('Common.add')}</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
@ -993,7 +995,7 @@ export default function Servers() {
<div className="flex flex-col gap-2 mb-4 pt-2">
<Input
id="application-search"
placeholder="Type to search..."
placeholder={t('Servers.Search.Placeholder')}
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
@ -1016,7 +1018,7 @@ export default function Servers() {
<StatusIndicator isOnline={server.online} />
{server.online && server.uptime && (
<span className="text-xs text-muted-foreground mt-1">
since {server.uptime}
{t('Common.since', { date: server.uptime })}
</span>
)}
</div>
@ -1045,13 +1047,13 @@ export default function Servers() {
<div className="flex items-center gap-2 text-foreground/80">
<MonitorCog className="h-4 w-4 text-muted-foreground" />
<span>
<b>OS:</b> {server.os || "-"}
<b>{t('Common.Server.OS')}:</b> {server.os || "-"}
</span>
</div>
<div className="flex items-center gap-2 text-foreground/80">
<FileDigit className="h-4 w-4 text-muted-foreground" />
<span>
<b>IP:</b> {server.ip || "Not set"}
<b>{t('Common.Server.IP')}:</b> {server.ip || t('Common.notSet')}
</span>
</div>
@ -1059,7 +1061,7 @@ export default function Servers() {
<div className="flex items-center gap-2 text-foreground/80">
<LucideServer className="h-4 w-4 text-muted-foreground" />
<span>
<b>Host:</b> {getHostServerName(server.hostServer)}
<b>{t('Common.Server.Host')}:</b> {getHostServerName(server.hostServer)}
</span>
</div>
)}
@ -1069,31 +1071,31 @@ export default function Servers() {
</div>
<div className="col-span-full mb-2">
<h4 className="text-sm font-semibold">Hardware Information</h4>
<h4 className="text-sm font-semibold">{t('Servers.ServerCard.HardwareInformation')}</h4>
</div>
<div className="flex items-center gap-2 text-foreground/80">
<Cpu className="h-4 w-4 text-muted-foreground" />
<span>
<b>CPU:</b> {server.cpu || "-"}
<b>{t('Common.Server.CPU')}:</b> {server.cpu || "-"}
</span>
</div>
<div className="flex items-center gap-2 text-foreground/80">
<Microchip className="h-4 w-4 text-muted-foreground" />
<span>
<b>GPU:</b> {server.gpu || "-"}
<b>{t('Common.Server.GPU')}:</b> {server.gpu || "-"}
</span>
</div>
<div className="flex items-center gap-2 text-foreground/80">
<MemoryStick className="h-4 w-4 text-muted-foreground" />
<span>
<b>RAM:</b> {server.ram || "-"}
<b>{t('Common.Server.RAM')}:</b> {server.ram || "-"}
</span>
</div>
<div className="flex items-center gap-2 text-foreground/80">
<HardDrive className="h-4 w-4 text-muted-foreground" />
<span>
<b>Disk:</b> {server.disk || "-"}
<b>{t('Common.Server.Disk')}:</b> {server.disk || "-"}
</span>
</div>
@ -1104,15 +1106,15 @@ export default function Servers() {
</div>
<div className="col-span-full">
<h4 className="text-sm font-semibold mb-3">Resource Usage</h4>
<h4 className="text-sm font-semibold mb-3">{t('Servers.ServerCard.ResourceUsage')}</h4>
<div className="grid grid-cols-2 gap-4">
<div>
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<Cpu className="h-4 w-4 text-muted-foreground" />
<span className="text-sm font-medium">CPU</span>
<span className="text-sm font-medium">{t('Common.Server.CPU')}</span>
</div>
<span className="text-xs font-medium">{server.cpuUsage !== null && server.cpuUsage !== undefined ? `${server.cpuUsage}%` : "NO DATA"}</span>
<span className="text-xs font-medium">{server.cpuUsage !== null && server.cpuUsage !== undefined ? `${server.cpuUsage}%` : t('Common.noData')}</span>
</div>
<div className="h-2 w-full overflow-hidden rounded-full bg-secondary mt-1">
<div
@ -1126,9 +1128,9 @@ export default function Servers() {
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<MemoryStick className="h-4 w-4 text-muted-foreground" />
<span className="text-sm font-medium">RAM</span>
<span className="text-sm font-medium">{t('Common.Server.RAM')}</span>
</div>
<span className="text-xs font-medium">{server.ramUsage !== null && server.ramUsage !== undefined ? `${server.ramUsage}%` : "NO DATA"}</span>
<span className="text-xs font-medium">{server.ramUsage !== null && server.ramUsage !== undefined ? `${server.ramUsage}%` : t('Common.noData')}</span>
</div>
<div className="h-2 w-full overflow-hidden rounded-full bg-secondary mt-1">
<div
@ -1142,9 +1144,9 @@ export default function Servers() {
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<HardDrive className="h-4 w-4 text-muted-foreground" />
<span className="text-sm font-medium">Disk</span>
<span className="text-sm font-medium">{t('Common.Server.Disk')}</span>
</div>
<span className="text-xs font-medium">{server.diskUsage !== null && server.diskUsage !== undefined ? `${server.diskUsage}%` : "NO DATA"}</span>
<span className="text-xs font-medium">{server.diskUsage !== null && server.diskUsage !== undefined ? `${server.diskUsage}%` : t('Common.noData')}</span>
</div>
<div className="h-2 w-full overflow-hidden rounded-full bg-secondary mt-1">
<div
@ -1155,21 +1157,21 @@ export default function Servers() {
</div>
<div>
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<Microchip className="h-4 w-4 text-muted-foreground" />
<span className="text-sm font-medium">GPU</span>
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<Microchip className="h-4 w-4 text-muted-foreground" />
<span className="text-sm font-medium">{t('Common.Server.GPU')}</span>
</div>
<span className="text-xs font-medium">
{server.online &&
server.gpuUsage &&
server.gpuUsage !== null &&
server.gpuUsage !== undefined &&
server.gpuUsage.toString() !== "0"
? `${server.gpuUsage}%`
: t('Common.noData')}
</span>
</div>
<span className="text-xs font-medium">
{server.online &&
server.gpuUsage &&
server.gpuUsage !== null &&
server.gpuUsage !== undefined &&
server.gpuUsage.toString() !== "0"
? `${server.gpuUsage}%`
: "NO DATA"}
</span>
</div>
<div className="h-2 w-full overflow-hidden rounded-full bg-secondary mt-1">
<div
className={`h-full ${server.gpuUsage && server.gpuUsage > 80 ? "bg-destructive" : server.gpuUsage && server.gpuUsage > 60 ? "bg-amber-500" : "bg-emerald-500"}`}
@ -1180,20 +1182,20 @@ export default function Servers() {
</div>
<div className="mt-4">
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<Thermometer className="h-4 w-4 text-muted-foreground" />
<span className="text-sm font-medium">Temp</span>
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<Thermometer className="h-4 w-4 text-muted-foreground" />
<span className="text-sm font-medium">{t('Common.Server.Temperature')}</span>
</div>
<span className="text-xs font-medium">
{server.online &&
server.temp !== null &&
server.temp !== undefined &&
server.temp.toString() !== "0"
? `${server.temp}°C`
: t('Common.noData')}
</span>
</div>
<span className="text-xs font-medium">
{server.online &&
server.temp !== null &&
server.temp !== undefined &&
server.temp.toString() !== "0"
? `${server.temp}°C`
: "NO DATA"}
</span>
</div>
<div className="h-2 w-full overflow-hidden rounded-full bg-secondary mt-1">
<div
className={`h-full ${server.temp && server.temp > 80 ? "bg-destructive" : server.temp && server.temp > 60 ? "bg-amber-500" : "bg-emerald-500"}`}
@ -1214,7 +1216,7 @@ export default function Servers() {
<NextLink href={`/dashboard/servers/${server.id}`} className="flex-1">
<Button variant="outline" className="w-full">
<History className="h-4 w-4 mr-2" />
View Details
{t('Servers.ServerCard.ViewDetails')}
</Button>
</NextLink>
@ -1230,7 +1232,7 @@ export default function Servers() {
<LinkIcon className="h-4 w-4" />
</Button>
</TooltipTrigger>
<TooltipContent>Open Management URL</TooltipContent>
<TooltipContent>{t('Servers.ServerCard.OpenManagementURL')}</TooltipContent>
</Tooltip>
</TooltipProvider>
)}
@ -1254,7 +1256,7 @@ export default function Servers() {
<Pencil className="h-4 w-4" />
</Button>
</TooltipTrigger>
<TooltipContent>Edit server</TooltipContent>
<TooltipContent>{t('Servers.ServerCard.EditServer')}</TooltipContent>
</Tooltip>
</TooltipProvider>
@ -1270,7 +1272,7 @@ export default function Servers() {
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Hosted VMs</AlertDialogTitle>
<AlertDialogTitle>{t('Servers.ServerCard.HostedVMs')}</AlertDialogTitle>
<AlertDialogDescription>
{server.host && (
<div className="mt-4">
@ -1325,21 +1327,21 @@ export default function Servers() {
</AlertDialogTrigger>
<AlertDialogContent className="max-w-[95vw] w-[600px] max-h-[90vh] overflow-y-auto">
<AlertDialogHeader>
<AlertDialogTitle>Edit VM</AlertDialogTitle>
<AlertDialogTitle>{t('Servers.EditServer.Title', { name: hostedVM.name })}</AlertDialogTitle>
<AlertDialogDescription>
<Tabs defaultValue="general" className="w-full">
<TabsList className="w-full">
<TabsTrigger value="general">General</TabsTrigger>
<TabsTrigger value="hardware">Hardware</TabsTrigger>
<TabsTrigger value="general">{t('Common.Server.Tabs.General')}</TabsTrigger>
<TabsTrigger value="hardware">{t('Common.Server.Tabs.Hardware')}</TabsTrigger>
<TabsTrigger value="virtualization">
Host
{t('Common.Server.Tabs.Host')}
</TabsTrigger>
</TabsList>
<TabsContent value="general">
<div className="space-y-4 pt-4">
<div className="flex items-center gap-2">
<div className="grid w-[calc(100%-52px)] items-center gap-1.5">
<Label htmlFor="editIcon">Icon</Label>
<Label htmlFor="editIcon">{t('Servers.EditServer.General.Icon')}</Label>
<div className="space-y-2">
<Select
value={editIcon}
@ -1348,7 +1350,7 @@ export default function Servers() {
}
>
<SelectTrigger className="w-full">
<SelectValue placeholder="Select an icon">
<SelectValue placeholder={t('Servers.AddServer.General.IconPlaceholder')}>
{editIcon && (
<div className="flex items-center gap-2">
<DynamicIcon
@ -1362,7 +1364,7 @@ export default function Servers() {
</SelectTrigger>
<SelectContent className="max-h-[300px]">
<Input
placeholder="Search icons..."
placeholder={t('Servers.AddServer.General.IconSearchPlaceholder')}
className="mb-2"
onChange={(e) => {
const iconElements =
@ -1426,7 +1428,7 @@ export default function Servers() {
</div>
</div>
<div className="grid w-[52px] items-center gap-1.5">
<Label htmlFor="editIcon">Preview</Label>
<Label htmlFor="editIcon">{t('Servers.AddServer.General.Preview')}</Label>
<div className="flex items-center justify-center">
{editIcon && (
<DynamicIcon
@ -1438,7 +1440,7 @@ export default function Servers() {
</div>
</div>
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="editName">Name</Label>
<Label htmlFor="editName">{t('Servers.EditServer.General.Name')}</Label>
<Input
id="editName"
type="text"
@ -1448,13 +1450,13 @@ export default function Servers() {
/>
</div>
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="editOs">Operating System</Label>
<Label htmlFor="editOs">{t('Servers.EditServer.General.OperatingSystem')}</Label>
<Select
value={editOs}
onValueChange={setEditOs}
>
<SelectTrigger className="w-full">
<SelectValue placeholder="Select OS" />
<SelectValue placeholder={t('Servers.AddServer.General.OperatingSystemPlaceholder')} />
</SelectTrigger>
<SelectContent>
<SelectItem value="Windows">
@ -1466,7 +1468,7 @@ export default function Servers() {
</Select>
</div>
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="editIp">IP Adress</Label>
<Label htmlFor="editIp">{t('Servers.EditServer.General.IPAddress')}</Label>
<Input
id="editIp"
type="text"
@ -1476,7 +1478,7 @@ export default function Servers() {
/>
</div>
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="editUrl">Management URL</Label>
<Label htmlFor="editUrl">{t('Servers.EditServer.General.ManagementURL')}</Label>
<Input
id="editUrl"
type="text"
@ -1491,7 +1493,7 @@ export default function Servers() {
<TabsContent value="hardware">
<div className="space-y-4 pt-4">
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="editCpu">CPU</Label>
<Label htmlFor="editCpu">{t('Servers.EditServer.Hardware.CPU')}</Label>
<Input
id="editCpu"
value={editCpu}
@ -1499,7 +1501,7 @@ export default function Servers() {
/>
</div>
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="editGpu">GPU</Label>
<Label htmlFor="editGpu">{t('Servers.EditServer.Hardware.GPU')}</Label>
<Input
id="editGpu"
value={editGpu}
@ -1507,7 +1509,7 @@ export default function Servers() {
/>
</div>
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="editRam">RAM</Label>
<Label htmlFor="editRam">{t('Servers.EditServer.Hardware.RAM')}</Label>
<Input
id="editRam"
value={editRam}
@ -1515,7 +1517,7 @@ export default function Servers() {
/>
</div>
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="editDisk">Disk</Label>
<Label htmlFor="editDisk">{t('Servers.EditServer.Hardware.Disk')}</Label>
<Input
id="editDisk"
value={editDisk}
@ -1539,18 +1541,18 @@ export default function Servers() {
}
/>
<Label htmlFor="editHostCheckbox">
Mark as host server
{t('Servers.EditServer.Host.MarkAsHostServer')}
{server.hostedVMs &&
server.hostedVMs.length > 0 && (
<span className="text-muted-foreground text-sm ml-2">
(Cannot be disabled while hosting VMs)
({t('Servers.EditServer.Host.CannotDisableHost')})
</span>
)}
</Label>
</div>
{!editHost && (
<div className="grid w-full items-center gap-1.5">
<Label>Host Server</Label>
<Label>{t('Servers.EditServer.Host.SelectHostServer')}</Label>
<Select
value={editHostServer?.toString()}
onValueChange={(value) => {
@ -1562,10 +1564,10 @@ export default function Servers() {
}}
>
<SelectTrigger>
<SelectValue placeholder="Select a host server" />
<SelectValue placeholder={t('Servers.AddServer.Host.SelectHostServerPlaceholder')} />
</SelectTrigger>
<SelectContent>
<SelectItem value="0">No host server</SelectItem>
<SelectItem value="0">{t('Servers.AddServer.Host.NoHostServer')}</SelectItem>
{hostServers
.filter(
(server) => server.id !== editId,
@ -1585,8 +1587,8 @@ export default function Servers() {
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<Button onClick={edit}>Save</Button>
<AlertDialogCancel>{t('Common.cancel')}</AlertDialogCancel>
<Button onClick={edit}>{t('Servers.EditServer.Save')}</Button>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
@ -1601,43 +1603,43 @@ export default function Servers() {
<div className="flex items-center gap-2 text-foreground/80">
<MonitorCog className="h-4 w-4 text-muted-foreground" />
<span>
<b>OS:</b> {hostedVM.os || "-"}
<b>{t('Common.Server.OS')}:</b> {hostedVM.os || "-"}
</span>
</div>
<div className="flex items-center gap-2 text-foreground/80">
<FileDigit className="h-4 w-4 text-muted-foreground" />
<span>
<b>IP:</b> {hostedVM.ip || "Not set"}
<b>{t('Common.Server.IP')}:</b> {hostedVM.ip || t('Common.notSet')}
</span>
</div>
</div>
<div className="col-span-full mb-2">
<h4 className="text-sm font-semibold">Hardware Information</h4>
<h4 className="text-sm font-semibold">{t('Servers.ServerCard.HardwareInformation')}</h4>
</div>
<div className="flex items-center gap-2 text-foreground/80">
<Cpu className="h-4 w-4 text-muted-foreground" />
<span>
<b>CPU:</b> {hostedVM.cpu || "-"}
<b>{t('Common.Server.CPU')}:</b> {hostedVM.cpu || "-"}
</span>
</div>
<div className="flex items-center gap-2 text-foreground/80">
<Microchip className="h-4 w-4 text-muted-foreground" />
<span>
<b>GPU:</b> {hostedVM.gpu || "-"}
<b>{t('Common.Server.GPU')}:</b> {hostedVM.gpu || "-"}
</span>
</div>
<div className="flex items-center gap-2 text-foreground/80">
<MemoryStick className="h-4 w-4 text-muted-foreground" />
<span>
<b>RAM:</b> {hostedVM.ram || "-"}
<b>{t('Common.Server.RAM')}:</b> {hostedVM.ram || "-"}
</span>
</div>
<div className="flex items-center gap-2 text-foreground/80">
<HardDrive className="h-4 w-4 text-muted-foreground" />
<span>
<b>Disk:</b> {hostedVM.disk || "-"}
<b>{t('Common.Server.Disk')}:</b> {hostedVM.disk || "-"}
</span>
</div>
@ -1652,7 +1654,7 @@ export default function Servers() {
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<Cpu className="h-4 w-4 text-muted-foreground" />
<span className="text-sm font-medium">CPU</span>
<span className="text-sm font-medium">{t('Common.Server.CPU')}</span>
</div>
<span className="text-xs font-medium">
{hostedVM.cpuUsage || 0}%
@ -1670,7 +1672,7 @@ export default function Servers() {
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<MemoryStick className="h-4 w-4 text-muted-foreground" />
<span className="text-sm font-medium">RAM</span>
<span className="text-sm font-medium">{t('Common.Server.RAM')}</span>
</div>
<span className="text-xs font-medium">
{hostedVM.ramUsage || 0}%
@ -1688,7 +1690,7 @@ export default function Servers() {
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<HardDrive className="h-4 w-4 text-muted-foreground" />
<span className="text-sm font-medium">Disk</span>
<span className="text-sm font-medium">{t('Common.Server.Disk')}</span>
</div>
<span className="text-xs font-medium">
{hostedVM.diskUsage || 0}%
@ -1713,12 +1715,12 @@ export default function Servers() {
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Close</AlertDialogCancel>
<AlertDialogCancel>{t('Common.cancel')}</AlertDialogCancel>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</TooltipTrigger>
<TooltipContent>View VMs ({server.hostedVMs.length})</TooltipContent>
<TooltipContent>{t('Servers.ServerCard.HostedVMs')} ({server.hostedVMs.length})</TooltipContent>
</Tooltip>
</TooltipProvider>
)}
@ -1734,27 +1736,27 @@ export default function Servers() {
</AlertDialogTrigger>
<AlertDialogContent className="max-w-[95vw] w-[600px] max-h-[90vh] overflow-y-auto">
<AlertDialogHeader>
<AlertDialogTitle>Edit {server.name}</AlertDialogTitle>
<AlertDialogTitle>{t('Servers.EditServer.Title', { name: server.name })}</AlertDialogTitle>
<AlertDialogDescription>
<Tabs defaultValue="general" className="w-full">
<TabsList className="w-full">
<TabsTrigger value="general">General</TabsTrigger>
<TabsTrigger value="hardware">Hardware</TabsTrigger>
<TabsTrigger value="virtualization">Host</TabsTrigger>
<TabsTrigger value="monitoring">Monitoring</TabsTrigger>
<TabsTrigger value="general">{t('Common.Server.Tabs.General')}</TabsTrigger>
<TabsTrigger value="hardware">{t('Common.Server.Tabs.Hardware')}</TabsTrigger>
<TabsTrigger value="virtualization">{t('Common.Server.Tabs.Host')}</TabsTrigger>
<TabsTrigger value="monitoring">{t('Common.Server.Tabs.Monitoring')}</TabsTrigger>
</TabsList>
<TabsContent value="general">
<div className="space-y-4 pt-4">
<div className="flex items-center gap-2">
<div className="grid w-[calc(100%-52px)] items-center gap-1.5">
<Label htmlFor="editIcon">Icon</Label>
<Label htmlFor="editIcon">{t('Servers.EditServer.General.Icon')}</Label>
<div className="space-y-2">
<Select
value={editIcon}
onValueChange={(value) => setEditIcon(value)}
>
<SelectTrigger className="w-full">
<SelectValue placeholder="Select an icon">
<SelectValue placeholder={t('Servers.AddServer.General.IconPlaceholder')}>
{editIcon && (
<div className="flex items-center gap-2">
<DynamicIcon name={editIcon as any} size={18} />
@ -1765,7 +1767,7 @@ export default function Servers() {
</SelectTrigger>
<SelectContent className="max-h-[300px]">
<Input
placeholder="Search icons..."
placeholder={t('Servers.AddServer.General.IconSearchPlaceholder')}
className="mb-2"
onChange={(e) => {
const iconElements = document.querySelectorAll(
@ -1811,14 +1813,14 @@ export default function Servers() {
</div>
</div>
<div className="grid w-[52px] items-center gap-1.5">
<Label htmlFor="editIcon">Preview</Label>
<Label htmlFor="editIcon">{t('Servers.AddServer.General.Preview')}</Label>
<div className="flex items-center justify-center">
{editIcon && <DynamicIcon name={editIcon as any} size={36} />}
</div>
</div>
</div>
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="editName">Name</Label>
<Label htmlFor="editName">{t('Servers.EditServer.General.Name')}</Label>
<Input
id="editName"
type="text"
@ -1828,11 +1830,11 @@ export default function Servers() {
</div>
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="editOs">
Operating System <span className="text-stone-600">(optional)</span>
{t('Servers.EditServer.General.OperatingSystem')} <span className="text-stone-600">({t('Common.optional')})</span>
</Label>
<Select value={editOs} onValueChange={(value) => setEditOs(value)}>
<SelectTrigger className="w-full">
<SelectValue placeholder="Select OS" />
<SelectValue placeholder={t('Servers.AddServer.General.OperatingSystemPlaceholder')} />
</SelectTrigger>
<SelectContent>
<SelectItem value="Windows">Windows</SelectItem>
@ -1843,7 +1845,7 @@ export default function Servers() {
</div>
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="editIp">
IP Address <span className="text-stone-600">(optional)</span>
{t('Servers.EditServer.General.IPAddress')} <span className="text-stone-600">({t('Common.optional')})</span>
</Label>
<Input
id="editIp"
@ -1854,7 +1856,7 @@ export default function Servers() {
</div>
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="editUrl">
Management URL <span className="text-stone-600">(optional)</span>
{t('Servers.EditServer.General.ManagementURL')} <span className="text-stone-600">({t('Common.optional')})</span>
</Label>
<Input
id="editUrl"
@ -1868,7 +1870,7 @@ export default function Servers() {
<TabsContent value="hardware">
<div className="space-y-4 pt-4">
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="editCpu">CPU</Label>
<Label htmlFor="editCpu">{t('Servers.EditServer.Hardware.CPU')}</Label>
<Input
id="editCpu"
value={editCpu}
@ -1876,7 +1878,7 @@ export default function Servers() {
/>
</div>
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="editGpu">GPU</Label>
<Label htmlFor="editGpu">{t('Servers.EditServer.Hardware.GPU')}</Label>
<Input
id="editGpu"
value={editGpu}
@ -1884,7 +1886,7 @@ export default function Servers() {
/>
</div>
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="editRam">RAM</Label>
<Label htmlFor="editRam">{t('Servers.EditServer.Hardware.RAM')}</Label>
<Input
id="editRam"
value={editRam}
@ -1892,7 +1894,7 @@ export default function Servers() {
/>
</div>
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="editDisk">Disk</Label>
<Label htmlFor="editDisk">{t('Servers.EditServer.Hardware.Disk')}</Label>
<Input
id="editDisk"
value={editDisk}
@ -1911,11 +1913,11 @@ export default function Servers() {
setEditHost(checked === true)
}
/>
<Label htmlFor="editHostCheckbox">Mark as host server</Label>
<Label htmlFor="editHostCheckbox">{t('Servers.EditServer.Host.MarkAsHostServer')}</Label>
</div>
{!editHost && (
<div className="grid w-full items-center gap-1.5">
<Label>Host Server</Label>
<Label>{t('Servers.EditServer.Host.SelectHostServer')}</Label>
<Select
value={editHostServer?.toString()}
onValueChange={(value) => {
@ -1927,10 +1929,10 @@ export default function Servers() {
}}
>
<SelectTrigger>
<SelectValue placeholder="Select a host server" />
<SelectValue placeholder={t('Servers.AddServer.Host.SelectHostServerPlaceholder')} />
</SelectTrigger>
<SelectContent>
<SelectItem value="0">No host server</SelectItem>
<SelectItem value="0">{t('Servers.AddServer.Host.NoHostServer')}</SelectItem>
{hostServers
.filter(
(server) => server.id !== editId,
@ -1954,12 +1956,12 @@ export default function Servers() {
checked={editMonitoring}
onCheckedChange={(checked) => setEditMonitoring(checked === true)}
/>
<Label htmlFor="editMonitoringCheckbox">Enable monitoring</Label>
<Label htmlFor="editMonitoringCheckbox">{t('Servers.EditServer.Monitoring.Enable')}</Label>
</div>
{editMonitoring && (
<>
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="editMonitoringURL">Monitoring URL</Label>
<Label htmlFor="editMonitoringURL">{t('Servers.EditServer.Monitoring.URL')}</Label>
<Input
id="editMonitoringURL"
type="text"
@ -1969,9 +1971,9 @@ export default function Servers() {
/>
</div>
<div className="mt-4 p-4 border rounded-lg bg-muted">
<h4 className="text-sm font-semibold mb-2">Required Server Setup</h4>
<h4 className="text-sm font-semibold mb-2">{t('Servers.EditServer.Monitoring.SetupTitle')}</h4>
<p className="text-sm text-muted-foreground mb-3">
To enable monitoring, you need to install Glances on your server. Here's an example Docker Compose configuration:
{t('Servers.EditServer.Monitoring.SetupDescription')}
</p>
<pre className="bg-background p-4 rounded-md text-sm">
<code>{`services:
@ -1996,8 +1998,8 @@ export default function Servers() {
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<Button onClick={edit}>Save</Button>
<AlertDialogCancel>{t('Common.cancel')}</AlertDialogCancel>
<Button onClick={edit}>{t('Servers.EditServer.Save')}</Button>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
@ -2013,24 +2015,24 @@ export default function Servers() {
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Delete {server.name}</AlertDialogTitle>
<AlertDialogTitle>{t('Servers.ServerCard.DeleteConfirmation.Title', { name: server.name })}</AlertDialogTitle>
<AlertDialogDescription>
Are you sure you want to delete this server? This action cannot be undone.
{t('Servers.ServerCard.DeleteConfirmation.Description')}
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogCancel>{t('Servers.ServerCard.DeleteConfirmation.Cancel')}</AlertDialogCancel>
<AlertDialogAction
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
onClick={() => deleteApplication(server.id)}
>
Delete
{t('Servers.ServerCard.DeleteConfirmation.Delete')}
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</TooltipTrigger>
<TooltipContent>Delete server</TooltipContent>
<TooltipContent>{t('Servers.ServerCard.DeleteServer')}</TooltipContent>
</Tooltip>
</TooltipProvider>
</div>
@ -2071,8 +2073,12 @@ export default function Servers() {
<div className="flex justify-between items-center mb-2">
<div className="text-sm text-muted-foreground">
{totalItems > 0
? `Showing ${((currentPage - 1) * itemsPerPage) + 1}-${Math.min(currentPage * itemsPerPage, totalItems)} of ${totalItems} servers`
: "No servers found"}
? t('Servers.Pagination.Showing', {
start: ((currentPage - 1) * itemsPerPage) + 1,
end: Math.min(currentPage * itemsPerPage, totalItems),
total: totalItems
})
: t('Servers.Pagination.NoServers')}
</div>
</div>
<Pagination>

View File

@ -1,114 +1,178 @@
{
"Sidebar": {
"Main Navigation": "Main Navigation",
"Dashboard": "Dashboard",
"My Infrastructure": "My Infrastructure",
"Servers": "Servers",
"Applications": "Applications",
"Uptime": "Uptime",
"Network": "Network",
"Settings": "Settings",
"Logout": "Logout"
},
"Home": {
"TitleUnder": "Dashboard to manage your entire server infrastructure",
"LoginCardTitle": "Login",
"LoginCardDescription": "Enter your credentials to continue",
"AuthenticationError": "Authentication Error",
"Email": "Email",
"Password": "Password",
"SigninButton": "Sign in",
"SigninButtonSigningIn": "Signing in..."
},
"Dashboard": {
"Title": "Dashboard",
"Servers": {
"Title": "Servers",
"Description": "Physical and virtual servers overview",
"PhysicalServers": "Physical Servers",
"VirtualServers": "Virtual Servers",
"ManageServers": "Manage Servers"
},
"Applications": {
"Title": "Applications",
"Description": "Manage your deployed applications",
"OnlineApplications": "Running Applications",
"ViewAllApplications": "View all applications"
},
"Uptime": {
"Title": "Uptime",
"Description": "Monitor your service availability",
"OnlineApplications": "Online Applications",
"ViewUptimeMetrics": "View uptime metrics"
},
"Network": {
"Title": "Network",
"Description": "Manage network configuration",
"ActiveConnections": "Active Connections",
"ViewNetworkDetails": "View network details"
}
},
"Servers": {
"MyInfrastructure": "My Infrastructure",
"Title": "Servers",
"YourServers": "Your Servers",
"ChangeView": "Change View",
"ListView": "List View",
"GridView": "Grid View",
"ItemsPerPage": {
"items": "items",
"item": "item",
"4": "4 items",
"6": "6 items",
"10": "10 items",
"15": "15 items",
"20": "20 items",
"25": "25 items",
"Custom": "Custom (1-100)"
},
"Common": {
"ChangeView": "Change View",
"ListView": "List View",
"GridView": "Grid View",
"optional": "optional",
"cancel": "Cancel",
"add": "Add",
"since": "since {date}",
"notSet": "Not set",
"noData": "No data",
"ItemsPerPage": {
"items": "items",
"item": "item",
"4": "4 items",
"6": "6 items",
"10": "10 items",
"15": "15 items",
"20": "20 items",
"25": "25 items",
"Custom": "Custom (1-100)"
},
"Server": {
"CPU": "CPU",
"GPU": "GPU",
"RAM": "RAM",
"Disk": "Disk",
"OS": "OS",
"IP": "IP",
"Host": "Host",
"Temperature": "Temperature",
"Tabs": {
"General": "General",
"Hardware": "Hardware",
"Host": "Host",
"Monitoring": "Monitoring"
},
"optional": "optional",
"cancel": "Cancel",
"add": "Add",
"AddServer": {
"Title": "Add a server",
"General": {
"Title": "Add a server",
"CopyServer": "Copy server",
"Icon": "Icon",
"IconPlaceholder": "Select an icon",
"IconSearchPlaceholder": "Search icons...",
"Preview": "Preview",
"Name": "Name",
"OperatingSystem": "Operating System",
"OperatingSystemPlaceholder": "Select OS",
"IPAdress": "IP Adress",
"ManagementURL": "Management URL",
"ManagementURLTooltip": "Link to a web interface (e.g. Proxmox or Portainer) with which the server can be managed"
},
"Hardware": {
"CPU": "CPU",
"GPU": "GPU",
"RAM": "RAM",
"Storage": "Storage"
},
"Host": {
"MarkAsHostServer": "Mark as host server",
"SelectHostServer": "Select a host server",
"SelectHostServerPlaceholder": "Select a host server",
"NoHostServer": "No host server"
},
"Monitoring": {
"Enable": "Enable monitoring",
"URL": "Monitoring URL",
"SetupTitle": "Required Server Setup",
"SetupDescription": "To enable monitoring, you need to install Glances on your server. Here's an example Docker Compose configuration:"
}
}
}
},
"Sidebar": {
"Main Navigation": "Main Navigation",
"Dashboard": "Dashboard",
"My Infrastructure": "My Infrastructure",
"Servers": "Servers",
"Applications": "Applications",
"Uptime": "Uptime",
"Network": "Network",
"Settings": "Settings",
"Logout": "Logout"
},
"Home": {
"TitleUnder": "Dashboard to manage your entire server infrastructure",
"LoginCardTitle": "Login",
"LoginCardDescription": "Enter your credentials to continue",
"AuthenticationError": "Authentication Error",
"Email": "Email",
"Password": "Password",
"SigninButton": "Sign in",
"SigninButtonSigningIn": "Signing in..."
},
"Dashboard": {
"Title": "Dashboard",
"Servers": {
"Title": "Servers",
"Description": "Physical and virtual servers overview",
"PhysicalServers": "Physical Servers",
"VirtualServers": "Virtual Servers",
"ManageServers": "Manage Servers"
},
"Applications": {
"Title": "Applications",
"Description": "Manage your deployed applications",
"OnlineApplications": "Running Applications",
"ViewAllApplications": "View all applications"
},
"Uptime": {
"Title": "Uptime",
"Description": "Monitor your service availability",
"OnlineApplications": "Online Applications",
"ViewUptimeMetrics": "View uptime metrics"
},
"Network": {
"Title": "Network",
"Description": "Manage network configuration",
"ActiveConnections": "Active Connections",
"ViewNetworkDetails": "View network details"
}
},
"Servers": {
"Title": "Servers",
"MyInfrastructure": "My Infrastructure",
"YourServers": "Your Servers",
"AddServer": {
"Title": "Add a server",
"General": {
"Title": "Add a server",
"CopyServer": "Copy server",
"Icon": "Icon",
"IconPlaceholder": "Select an icon",
"IconSearchPlaceholder": "Search icons...",
"Preview": "Preview",
"Name": "Name",
"OperatingSystem": "Operating System",
"OperatingSystemPlaceholder": "Select OS",
"IPAdress": "IP Adress",
"ManagementURL": "Management URL",
"ManagementURLTooltip": "Link to a web interface (e.g. Proxmox or Portainer) with which the server can be managed"
},
"Host": {
"MarkAsHostServer": "Mark as host server",
"SelectHostServer": "Select a host server",
"SelectHostServerPlaceholder": "Select a host server",
"NoHostServer": "No host server"
},
"Monitoring": {
"Enable": "Enable monitoring",
"URL": "Monitoring URL",
"SetupTitle": "Required Server Setup",
"SetupDescription": "To enable monitoring, you need to install Glances on your server. Here's an example Docker Compose configuration:"
}
},
"ServerCard": {
"HardwareInformation": "Hardware Information",
"ViewDetails": "View Details",
"OpenManagementURL": "Open Management URL",
"EditServer": "Edit Server",
"DeleteServer": "Delete Server",
"HostedVMs": "Hosted VMs",
"ResourceUsage": "Resource Usage",
"DeleteConfirmation": {
"Title": "Delete {name}",
"Description": "Are you sure you want to delete this server? This action cannot be undone.",
"Cancel": "Cancel",
"Delete": "Delete"
}
},
"EditServer": {
"Title": "Edit {name}",
"Save": "Save",
"General": {
"Title": "General",
"Icon": "Icon",
"Name": "Name",
"OperatingSystem": "Operating System",
"IPAddress": "IP Address",
"ManagementURL": "Management URL"
},
"Hardware": {
"Title": "Hardware",
"CPU": "CPU",
"GPU": "GPU",
"RAM": "RAM",
"Disk": "Disk"
},
"Host": {
"Title": "Host",
"MarkAsHostServer": "Mark as host server",
"CannotDisableHost": "Cannot be disabled while hosting VMs",
"SelectHostServer": "Select a host server"
},
"Monitoring": {
"Title": "Monitoring",
"Enable": "Enable monitoring",
"URL": "Monitoring URL",
"SetupTitle": "Required Server Setup",
"SetupDescription": "To enable monitoring, you need to install Glances on your server. Here's an example Docker Compose configuration:"
}
},
"Pagination": {
"Showing": "Showing {start}-{end} of {total} servers",
"NoServers": "No servers found"
},
"Search": {
"Placeholder": "Type to search..."
}
}
}
}