From 89186753937824ab4e9d493b68b1002b76890f95 Mon Sep 17 00:00:00 2001
From: VAIO73 <50487331+Vaso73@users.noreply.github.com>
Date: Sat, 12 Sep 2026 08:12:23 +0200
Subject: [PATCH] =?UTF-8?q?i18n:=20lokalizovan=C3=A9=20kateg=C3=B3rie=20ap?=
=?UTF-8?q?lik=C3=A1ci=C3=AD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
AppImage/components/apps-dashboard.tsx | 19 +++++-----
AppImage/components/custom-link-editor.tsx | 3 +-
AppImage/components/lxc-app-panel.tsx | 7 ++--
AppImage/lib/category-label.ts | 40 ++++++++++++++++++++++
AppImage/messages/de/common.json | 5 ++-
AppImage/messages/en/common.json | 34 ++++++++++++++++--
AppImage/messages/es/common.json | 5 ++-
AppImage/messages/fr/common.json | 5 ++-
AppImage/messages/it/common.json | 5 ++-
AppImage/messages/pt/common.json | 5 ++-
AppImage/messages/sk/common.json | 32 ++++++++++++++++-
AppImage/messages/sv/common.json | 7 ++--
12 files changed, 145 insertions(+), 22 deletions(-)
create mode 100644 AppImage/lib/category-label.ts
diff --git a/AppImage/components/apps-dashboard.tsx b/AppImage/components/apps-dashboard.tsx
index f52c95a6..f3846599 100644
--- a/AppImage/components/apps-dashboard.tsx
+++ b/AppImage/components/apps-dashboard.tsx
@@ -9,6 +9,7 @@ import { ThemeAwareLogo } from "./lxc-app-panel"
import { CustomLinkEditor, type CustomLink, type GuestOption } from "./custom-link-editor"
import { Button } from "./ui/button"
import { categoryChipStyle, useIsLightTheme } from "../lib/category-color"
+import { getCategoryLabel } from "../lib/category-label"
// ─── Local subset of /api/vms shape ─────────────────────────────
// Kept narrow on purpose — this component only needs what feeds a
@@ -248,8 +249,8 @@ export function AppsDashboard() {
return map
}, [links, t])
const sortedCategoryEntries = useMemo(
- () => Array.from(categoryCounts.entries()).sort((a, b) => a[0].localeCompare(b[0])),
- [categoryCounts],
+ () => Array.from(categoryCounts.entries()).sort((a, b) => getCategoryLabel(t, a[0]).localeCompare(getCategoryLabel(t, b[0]))),
+ [categoryCounts, t],
)
// ─── Controls state ────────────────────────────────────────────
@@ -327,7 +328,8 @@ export function AppsDashboard() {
l.appName.toLowerCase().includes(q) ||
(l.ctName || "").toLowerCase().includes(q) ||
(l.vmid != null && String(l.vmid).includes(q)) ||
- (l.category || "").toLowerCase().includes(q)
+ (l.category || "").toLowerCase().includes(q) ||
+ getCategoryLabel(t, l.category || "").toLowerCase().includes(q)
)
}
const sorted = [...filtered]
@@ -344,7 +346,7 @@ export function AppsDashboard() {
// category — grouped alphabetically, then by app name inside
const catA = a.category || uncatKey
const catB = b.category || uncatKey
- const c = catA.localeCompare(catB)
+ const c = getCategoryLabel(t, catA).localeCompare(getCategoryLabel(t, catB))
return c !== 0 ? c : a.appName.localeCompare(b.appName)
})
return sorted
@@ -432,7 +434,7 @@ export function AppsDashboard() {
>
{sortedCategoryEntries.map(([cat, n]) => (
-
+
))}
@@ -532,6 +534,7 @@ function CardsGrid({
editMode: boolean
onEditCustom: (customId: string) => void
}) {
+ const t = useT()
if (!links.length) {
return (
@@ -572,7 +575,7 @@ function CardsGrid({
{groups.map(([cat, items]) => (
- {cat}
+ {getCategoryLabel(t, cat)}
{items.length}
{items.map((link) => (
@@ -715,9 +718,9 @@ function AppCard({
- {link.category}
+ {getCategoryLabel(t, link.category)}
)}
diff --git a/AppImage/components/custom-link-editor.tsx b/AppImage/components/custom-link-editor.tsx
index f32cd455..18f391eb 100644
--- a/AppImage/components/custom-link-editor.tsx
+++ b/AppImage/components/custom-link-editor.tsx
@@ -4,6 +4,7 @@ import { useEffect, useState } from "react"
import { Trash2 } from "lucide-react"
import { fetchApi } from "../lib/api-config"
import { useT } from "../lib/i18n/provider"
+import { getCategoryLabel } from "../lib/category-label"
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "./ui/dialog"
import { Button } from "./ui/button"
import { Input } from "./ui/input"
@@ -237,7 +238,7 @@ export function CustomLinkEditor({
{t("vmLxc.appEditor.portCategoryNone")}
{categoryPresets.map((c) => (
- {c}
+ {getCategoryLabel(t, c)}
))}
{t("vmLxc.appEditor.portCategoryAddNew")}
diff --git a/AppImage/components/lxc-app-panel.tsx b/AppImage/components/lxc-app-panel.tsx
index 3444fc93..3f40048c 100644
--- a/AppImage/components/lxc-app-panel.tsx
+++ b/AppImage/components/lxc-app-panel.tsx
@@ -35,6 +35,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from ".
import { fetchApi } from "../lib/api-config"
import { fetchLxcApps, getLxcAppsCached, setLxcAppsCached, subscribeLxcApps } from "../lib/lxc-apps-cache"
import { categoryChipStyle, useIsLightTheme } from "../lib/category-color"
+import { getCategoryLabel } from "../lib/category-label"
import { useT } from "@/lib/i18n/provider"
// installed_via is optional now — an empty value means "register only,
@@ -1604,7 +1605,7 @@ export function LxcAppPanel({ vmid, ctIp, onChange, managed, initialData }: Prop
{t("vmLxc.appEditor.portCategoryNone")}
{categoryPresets.map((c) => (
- {c}
+ {getCategoryLabel(t, c)}
))}
{t("vmLxc.appEditor.portCategoryAddNew")}
@@ -2649,9 +2650,9 @@ export function LxcAppPanel({ vmid, ctIp, onChange, managed, initialData }: Prop
- {p.category}
+ {getCategoryLabel(t, p.category)}
)}
diff --git a/AppImage/lib/category-label.ts b/AppImage/lib/category-label.ts
new file mode 100644
index 00000000..8b6b4ced
--- /dev/null
+++ b/AppImage/lib/category-label.ts
@@ -0,0 +1,40 @@
+type Translate = (key: string) => string
+
+// Category values come from the community-scripts catalog and are also
+// persisted with application links. Keep those raw values intact for
+// filtering and storage; translate only what is displayed in the UI.
+const CATEGORY_KEY_BY_VALUE: Record = {
+ "*Arr Suite": "arrSuite",
+ "AI / Coding & Dev-Tools": "aiCodingDevTools",
+ "Adblock & DNS": "adblockDns",
+ "Authentication & Security": "authenticationSecurity",
+ "Automation & Scheduling": "automationScheduling",
+ "Backup & Recovery": "backupRecovery",
+ "Business & ERP": "businessErp",
+ "Communication & Community": "communicationCommunity",
+ "Containers & Docker": "containersDocker",
+ "Dashboards & Frontends": "dashboardsFrontends",
+ "Databases": "databases",
+ "Documents & Notes": "documentsNotes",
+ "Files & Downloads": "filesDownloads",
+ "Finance & Budgeting": "financeBudgeting",
+ "Gaming & Leisure": "gamingLeisure",
+ "Host Management": "hostManagement",
+ "IoT & Smart Home": "iotSmartHome",
+ "Media & Streaming": "mediaStreaming",
+ "Messaging & Queues": "messagingQueues",
+ "Miscellaneous": "miscellaneous",
+ "Monitoring & Analytics": "monitoringAnalytics",
+ "NVR & Cameras": "nvrCameras",
+ "Network & Firewall": "networkFirewall",
+ "Operating Systems & Appliances": "operatingSystemsAppliances",
+ "Productivity & Workflows": "productivityWorkflows",
+ "Remote Access & VPN": "remoteAccessVpn",
+ "Webservers & Proxies": "webserversProxies",
+ "ZigBee, Z-Wave & Matter": "zigbeeZwaveMatter",
+}
+
+export function getCategoryLabel(t: Translate, value: string): string {
+ const key = CATEGORY_KEY_BY_VALUE[value.trim()]
+ return key ? t(`apps.categoryLabels.${key}`) : value
+}
diff --git a/AppImage/messages/de/common.json b/AppImage/messages/de/common.json
index cc57df24..86f6f5b8 100644
--- a/AppImage/messages/de/common.json
+++ b/AppImage/messages/de/common.json
@@ -4929,7 +4929,10 @@
"customLinkCancel": "Cancel",
"customLinkDelete": "Delete",
"customLinkSaveError": "Save failed",
- "customLinkDeleteError": "Delete failed"
+ "customLinkDeleteError": "Delete failed",
+ "categoryLabels": {
+ "arrSuite": "*Arr Suite", "aiCodingDevTools": "AI / Coding & Dev-Tools", "adblockDns": "Adblock & DNS", "authenticationSecurity": "Authentication & Security", "automationScheduling": "Automation & Scheduling", "backupRecovery": "Backup & Recovery", "businessErp": "Business & ERP", "communicationCommunity": "Communication & Community", "containersDocker": "Containers & Docker", "dashboardsFrontends": "Dashboards & Frontends", "databases": "Databases", "documentsNotes": "Documents & Notes", "filesDownloads": "Files & Downloads", "financeBudgeting": "Finance & Budgeting", "gamingLeisure": "Gaming & Leisure", "hostManagement": "Host Management", "iotSmartHome": "IoT & Smart Home", "mediaStreaming": "Media & Streaming", "messagingQueues": "Messaging & Queues", "miscellaneous": "Miscellaneous", "monitoringAnalytics": "Monitoring & Analytics", "nvrCameras": "NVR & Cameras", "networkFirewall": "Network & Firewall", "operatingSystemsAppliances": "Operating Systems & Appliances", "productivityWorkflows": "Productivity & Workflows", "remoteAccessVpn": "Remote Access & VPN", "webserversProxies": "Webservers & Proxies", "zigbeeZwaveMatter": "ZigBee, Z-Wave & Matter"
+ }
},
"audit": {
"presentation": {
diff --git a/AppImage/messages/en/common.json b/AppImage/messages/en/common.json
index c6791134..51ca198d 100644
--- a/AppImage/messages/en/common.json
+++ b/AppImage/messages/en/common.json
@@ -4994,7 +4994,37 @@
"customLinkCancel": "Cancel",
"customLinkDelete": "Delete",
"customLinkSaveError": "Save failed",
- "customLinkDeleteError": "Delete failed"
+ "customLinkDeleteError": "Delete failed",
+ "categoryLabels": {
+ "arrSuite": "*Arr Suite",
+ "aiCodingDevTools": "AI / Coding & Dev-Tools",
+ "adblockDns": "Adblock & DNS",
+ "authenticationSecurity": "Authentication & Security",
+ "automationScheduling": "Automation & Scheduling",
+ "backupRecovery": "Backup & Recovery",
+ "businessErp": "Business & ERP",
+ "communicationCommunity": "Communication & Community",
+ "containersDocker": "Containers & Docker",
+ "dashboardsFrontends": "Dashboards & Frontends",
+ "databases": "Databases",
+ "documentsNotes": "Documents & Notes",
+ "filesDownloads": "Files & Downloads",
+ "financeBudgeting": "Finance & Budgeting",
+ "gamingLeisure": "Gaming & Leisure",
+ "hostManagement": "Host Management",
+ "iotSmartHome": "IoT & Smart Home",
+ "mediaStreaming": "Media & Streaming",
+ "messagingQueues": "Messaging & Queues",
+ "miscellaneous": "Miscellaneous",
+ "monitoringAnalytics": "Monitoring & Analytics",
+ "nvrCameras": "NVR & Cameras",
+ "networkFirewall": "Network & Firewall",
+ "operatingSystemsAppliances": "Operating Systems & Appliances",
+ "productivityWorkflows": "Productivity & Workflows",
+ "remoteAccessVpn": "Remote Access & VPN",
+ "webserversProxies": "Webservers & Proxies",
+ "zigbeeZwaveMatter": "ZigBee, Z-Wave & Matter"
+ }
},
"audit": {
"presentation": {
@@ -6054,4 +6084,4 @@
"cancel": "Cancel"
}
}
-}
\ No newline at end of file
+}
diff --git a/AppImage/messages/es/common.json b/AppImage/messages/es/common.json
index fa8ffbc4..e2b1dee5 100644
--- a/AppImage/messages/es/common.json
+++ b/AppImage/messages/es/common.json
@@ -4929,7 +4929,10 @@
"customLinkCancel": "Cancelar",
"customLinkDelete": "Eliminar",
"customLinkSaveError": "Error al guardar",
- "customLinkDeleteError": "Error al eliminar"
+ "customLinkDeleteError": "Error al eliminar",
+ "categoryLabels": {
+ "arrSuite": "*Arr Suite", "aiCodingDevTools": "AI / Coding & Dev-Tools", "adblockDns": "Adblock & DNS", "authenticationSecurity": "Authentication & Security", "automationScheduling": "Automation & Scheduling", "backupRecovery": "Backup & Recovery", "businessErp": "Business & ERP", "communicationCommunity": "Communication & Community", "containersDocker": "Containers & Docker", "dashboardsFrontends": "Dashboards & Frontends", "databases": "Databases", "documentsNotes": "Documents & Notes", "filesDownloads": "Files & Downloads", "financeBudgeting": "Finance & Budgeting", "gamingLeisure": "Gaming & Leisure", "hostManagement": "Host Management", "iotSmartHome": "IoT & Smart Home", "mediaStreaming": "Media & Streaming", "messagingQueues": "Messaging & Queues", "miscellaneous": "Miscellaneous", "monitoringAnalytics": "Monitoring & Analytics", "nvrCameras": "NVR & Cameras", "networkFirewall": "Network & Firewall", "operatingSystemsAppliances": "Operating Systems & Appliances", "productivityWorkflows": "Productivity & Workflows", "remoteAccessVpn": "Remote Access & VPN", "webserversProxies": "Webservers & Proxies", "zigbeeZwaveMatter": "ZigBee, Z-Wave & Matter"
+ }
},
"audit": {
"presentation": {
diff --git a/AppImage/messages/fr/common.json b/AppImage/messages/fr/common.json
index 351f3638..2bd92044 100644
--- a/AppImage/messages/fr/common.json
+++ b/AppImage/messages/fr/common.json
@@ -4929,7 +4929,10 @@
"customLinkCancel": "Cancel",
"customLinkDelete": "Delete",
"customLinkSaveError": "Save failed",
- "customLinkDeleteError": "Delete failed"
+ "customLinkDeleteError": "Delete failed",
+ "categoryLabels": {
+ "arrSuite": "*Arr Suite", "aiCodingDevTools": "AI / Coding & Dev-Tools", "adblockDns": "Adblock & DNS", "authenticationSecurity": "Authentication & Security", "automationScheduling": "Automation & Scheduling", "backupRecovery": "Backup & Recovery", "businessErp": "Business & ERP", "communicationCommunity": "Communication & Community", "containersDocker": "Containers & Docker", "dashboardsFrontends": "Dashboards & Frontends", "databases": "Databases", "documentsNotes": "Documents & Notes", "filesDownloads": "Files & Downloads", "financeBudgeting": "Finance & Budgeting", "gamingLeisure": "Gaming & Leisure", "hostManagement": "Host Management", "iotSmartHome": "IoT & Smart Home", "mediaStreaming": "Media & Streaming", "messagingQueues": "Messaging & Queues", "miscellaneous": "Miscellaneous", "monitoringAnalytics": "Monitoring & Analytics", "nvrCameras": "NVR & Cameras", "networkFirewall": "Network & Firewall", "operatingSystemsAppliances": "Operating Systems & Appliances", "productivityWorkflows": "Productivity & Workflows", "remoteAccessVpn": "Remote Access & VPN", "webserversProxies": "Webservers & Proxies", "zigbeeZwaveMatter": "ZigBee, Z-Wave & Matter"
+ }
},
"audit": {
"presentation": {
diff --git a/AppImage/messages/it/common.json b/AppImage/messages/it/common.json
index 918e19bc..61114411 100644
--- a/AppImage/messages/it/common.json
+++ b/AppImage/messages/it/common.json
@@ -4929,7 +4929,10 @@
"customLinkCancel": "Cancel",
"customLinkDelete": "Delete",
"customLinkSaveError": "Save failed",
- "customLinkDeleteError": "Delete failed"
+ "customLinkDeleteError": "Delete failed",
+ "categoryLabels": {
+ "arrSuite": "*Arr Suite", "aiCodingDevTools": "AI / Coding & Dev-Tools", "adblockDns": "Adblock & DNS", "authenticationSecurity": "Authentication & Security", "automationScheduling": "Automation & Scheduling", "backupRecovery": "Backup & Recovery", "businessErp": "Business & ERP", "communicationCommunity": "Communication & Community", "containersDocker": "Containers & Docker", "dashboardsFrontends": "Dashboards & Frontends", "databases": "Databases", "documentsNotes": "Documents & Notes", "filesDownloads": "Files & Downloads", "financeBudgeting": "Finance & Budgeting", "gamingLeisure": "Gaming & Leisure", "hostManagement": "Host Management", "iotSmartHome": "IoT & Smart Home", "mediaStreaming": "Media & Streaming", "messagingQueues": "Messaging & Queues", "miscellaneous": "Miscellaneous", "monitoringAnalytics": "Monitoring & Analytics", "nvrCameras": "NVR & Cameras", "networkFirewall": "Network & Firewall", "operatingSystemsAppliances": "Operating Systems & Appliances", "productivityWorkflows": "Productivity & Workflows", "remoteAccessVpn": "Remote Access & VPN", "webserversProxies": "Webservers & Proxies", "zigbeeZwaveMatter": "ZigBee, Z-Wave & Matter"
+ }
},
"audit": {
"presentation": {
diff --git a/AppImage/messages/pt/common.json b/AppImage/messages/pt/common.json
index c00319df..99f8572a 100644
--- a/AppImage/messages/pt/common.json
+++ b/AppImage/messages/pt/common.json
@@ -4930,7 +4930,10 @@
"customLinkCancel": "Cancel",
"customLinkDelete": "Delete",
"customLinkSaveError": "Save failed",
- "customLinkDeleteError": "Delete failed"
+ "customLinkDeleteError": "Delete failed",
+ "categoryLabels": {
+ "arrSuite": "*Arr Suite", "aiCodingDevTools": "AI / Coding & Dev-Tools", "adblockDns": "Adblock & DNS", "authenticationSecurity": "Authentication & Security", "automationScheduling": "Automation & Scheduling", "backupRecovery": "Backup & Recovery", "businessErp": "Business & ERP", "communicationCommunity": "Communication & Community", "containersDocker": "Containers & Docker", "dashboardsFrontends": "Dashboards & Frontends", "databases": "Databases", "documentsNotes": "Documents & Notes", "filesDownloads": "Files & Downloads", "financeBudgeting": "Finance & Budgeting", "gamingLeisure": "Gaming & Leisure", "hostManagement": "Host Management", "iotSmartHome": "IoT & Smart Home", "mediaStreaming": "Media & Streaming", "messagingQueues": "Messaging & Queues", "miscellaneous": "Miscellaneous", "monitoringAnalytics": "Monitoring & Analytics", "nvrCameras": "NVR & Cameras", "networkFirewall": "Network & Firewall", "operatingSystemsAppliances": "Operating Systems & Appliances", "productivityWorkflows": "Productivity & Workflows", "remoteAccessVpn": "Remote Access & VPN", "webserversProxies": "Webservers & Proxies", "zigbeeZwaveMatter": "ZigBee, Z-Wave & Matter"
+ }
},
"audit": {
"presentation": {
diff --git a/AppImage/messages/sk/common.json b/AppImage/messages/sk/common.json
index dc7a6887..993f39f0 100644
--- a/AppImage/messages/sk/common.json
+++ b/AppImage/messages/sk/common.json
@@ -4994,7 +4994,37 @@
"customLinkCancel": "Zrušiť",
"customLinkDelete": "Odstrániť",
"customLinkSaveError": "Odkaz sa nepodarilo uložiť",
- "customLinkDeleteError": "Odkaz sa nepodarilo odstrániť"
+ "customLinkDeleteError": "Odkaz sa nepodarilo odstrániť",
+ "categoryLabels": {
+ "arrSuite": "Sada *Arr",
+ "aiCodingDevTools": "AI, programovanie a vývojárske nástroje",
+ "adblockDns": "Blokovanie reklám a DNS",
+ "authenticationSecurity": "Overovanie a bezpečnosť",
+ "automationScheduling": "Automatizácia a plánovanie",
+ "backupRecovery": "Zálohovanie a obnova",
+ "businessErp": "Podnikové aplikácie a ERP",
+ "communicationCommunity": "Komunikácia a komunita",
+ "containersDocker": "Kontajnery a Docker",
+ "dashboardsFrontends": "Prehľady a webové rozhrania",
+ "databases": "Databázy",
+ "documentsNotes": "Dokumenty a poznámky",
+ "filesDownloads": "Súbory a sťahovanie",
+ "financeBudgeting": "Financie a rozpočet",
+ "gamingLeisure": "Hry a voľný čas",
+ "hostManagement": "Správa servera",
+ "iotSmartHome": "IoT a inteligentná domácnosť",
+ "mediaStreaming": "Médiá a streamovanie",
+ "messagingQueues": "Správy a fronty",
+ "miscellaneous": "Ostatné",
+ "monitoringAnalytics": "Monitorovanie a analýza",
+ "nvrCameras": "NVR a kamery",
+ "networkFirewall": "Sieť a firewall",
+ "operatingSystemsAppliances": "Operačné systémy a zariadenia",
+ "productivityWorkflows": "Produktivita a pracovné postupy",
+ "remoteAccessVpn": "Vzdialený prístup a VPN",
+ "webserversProxies": "Webové servery a proxy",
+ "zigbeeZwaveMatter": "Zigbee, Z-Wave a Matter"
+ }
},
"audit": {
"presentation": {
diff --git a/AppImage/messages/sv/common.json b/AppImage/messages/sv/common.json
index 4fbccd0c..4012c26c 100644
--- a/AppImage/messages/sv/common.json
+++ b/AppImage/messages/sv/common.json
@@ -4929,7 +4929,10 @@
"customLinkCancel": "Cancel",
"customLinkDelete": "Delete",
"customLinkSaveError": "Save failed",
- "customLinkDeleteError": "Delete failed"
+ "customLinkDeleteError": "Delete failed",
+ "categoryLabels": {
+ "arrSuite": "*Arr Suite", "aiCodingDevTools": "AI / Coding & Dev-Tools", "adblockDns": "Adblock & DNS", "authenticationSecurity": "Authentication & Security", "automationScheduling": "Automation & Scheduling", "backupRecovery": "Backup & Recovery", "businessErp": "Business & ERP", "communicationCommunity": "Communication & Community", "containersDocker": "Containers & Docker", "dashboardsFrontends": "Dashboards & Frontends", "databases": "Databases", "documentsNotes": "Documents & Notes", "filesDownloads": "Files & Downloads", "financeBudgeting": "Finance & Budgeting", "gamingLeisure": "Gaming & Leisure", "hostManagement": "Host Management", "iotSmartHome": "IoT & Smart Home", "mediaStreaming": "Media & Streaming", "messagingQueues": "Messaging & Queues", "miscellaneous": "Miscellaneous", "monitoringAnalytics": "Monitoring & Analytics", "nvrCameras": "NVR & Cameras", "networkFirewall": "Network & Firewall", "operatingSystemsAppliances": "Operating Systems & Appliances", "productivityWorkflows": "Productivity & Workflows", "remoteAccessVpn": "Remote Access & VPN", "webserversProxies": "Webservers & Proxies", "zigbeeZwaveMatter": "ZigBee, Z-Wave & Matter"
+ }
},
"audit": {
"presentation": {
@@ -5989,4 +5992,4 @@
"cancel": "Cancel"
}
}
-}
\ No newline at end of file
+}