feat: type the plugin host record, move plugin strings out of core and add lint checks

This commit is contained in:
LukeGus committed 2026-09-29 13:08:39 -05:00
1 parent bba06f7ff6
commit b8bbcd2196
626 files changed
+23884 -4590

No files matched your search

+12 -1
View File
@@ -104,6 +104,17 @@
"proxmoxResultFailed": "{{count}} failed",
"proxmoxImportComplete": "Proxmox import complete: {{summary}}",
"proxmoxDiscoveryFailed": "Discovery failed",
"proxmoxImportFailed": "Import failed"
"proxmoxImportFailed": "Import failed",
"docsLink": "View docs",
"hostNotFound": "Host not found",
"loadingHost": "Loading host...",
"none": "None",
"proxmoxGuestsSelected_one": "{{count}} guest — {{selected}} selected",
"proxmoxGuestsSelected_other": "{{count}} guests — {{selected}} selected",
"proxmoxImportButton_one": "Import {{count}} host",
"proxmoxImportButton_other": "Import {{count}} hosts"
},
"terminal": {
"connected": "Connected"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "Minimum 15 sekondes. Hoe gereeld om Proxmox-nodusstatistieke te verfris.",
"proxmoxStatsNodeOverride": "Nodenaam-oorskrywing",
"proxmoxStatsNodeOverrideDesc": "Ignoreer outomatiese opsporing van die Proxmox-nodusnaam (standaard opgespoor via gasheernaam).",
"proxmoxStatsNodeOverridePlaceholder": "Outomaties opgespoor vanaf gasheernaam"
"proxmoxStatsNodeOverridePlaceholder": "Outomaties opgespoor vanaf gasheernaam",
"docsLink": "Bekyk dokumente",
"hostNotFound": "Gasheer nie gevind nie",
"loadingHost": "Laai gasheer...",
"none": "Geen",
"proxmoxGuestsSelected_one": "{{count}} gas — {{selected}} gekies",
"proxmoxGuestsSelected_other": "{{count}} gaste — {{selected}} gekies",
"proxmoxImportButton_one": "Voer {{count}} gasheer in",
"proxmoxImportButton_other": "Voer {{count}} gashere in"
},
"proxmoxStats": {
"tabTitle": "Proxmox-statistieke",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "Geen VM'e of LXC-houers is op hierdie node gevind nie.",
"noGuestsMatch": "Geen gaste stem ooreen met die huidige filters nie."
},
"terminal": {
"connected": "Verbonde"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "الحد الأدنى 15 ثانية. عدد مرات تحديث إحصائيات عقدة Proxmox.",
"proxmoxStatsNodeOverride": "تجاوز اسم العقدة",
"proxmoxStatsNodeOverrideDesc": "تجاوز الكشف التلقائي عن اسم عقدة Proxmox (يتم الكشف عنه عبر اسم المضيف افتراضيًا).",
"proxmoxStatsNodeOverridePlaceholder": "تم اكتشافه تلقائيًا من اسم المضيف"
"proxmoxStatsNodeOverridePlaceholder": "تم اكتشافه تلقائيًا من اسم المضيف",
"docsLink": "عرض المستندات",
"hostNotFound": "المضيف غير موجود",
"loadingHost": "جارٍ تحميل المضيف...",
"none": "لا يوجد",
"proxmoxGuestsSelected_one": "{{count}} جهاز ضيف — {{selected}} مُحدد",
"proxmoxGuestsSelected_other": "{{count}} أجهزة ضيفة — {{selected}} مُحددة",
"proxmoxImportButton_one": "استيراد {{count}} مضيف",
"proxmoxImportButton_other": "استيراد {{count}} مضيفين"
},
"proxmoxStats": {
"tabTitle": "إحصائيات Proxmox",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "لم يتم العثور على أي أجهزة افتراضية أو حاويات LXC على هذه العقدة.",
"noGuestsMatch": "لا يوجد ضيوف يطابقون المعايير الحالية."
},
"terminal": {
"connected": "متصل"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "Минимум 15 секунди. Колко често да се обновяват статистическите данни за възлите на Proxmox.",
"proxmoxStatsNodeOverride": "Замяна на името на възела",
"proxmoxStatsNodeOverrideDesc": "Игнориране на автоматичното откриване на името на възела Proxmox (по подразбиране се открива чрез името на хоста).",
"proxmoxStatsNodeOverridePlaceholder": "Автоматично разпознато от името на хоста"
"proxmoxStatsNodeOverridePlaceholder": "Автоматично разпознато от името на хоста",
"docsLink": "Преглед на документи",
"hostNotFound": "Хостът не е намерен",
"loadingHost": "Зареждане на хоста...",
"none": "Няма",
"proxmoxGuestsSelected_one": "{{count}} гост — {{selected}} избран",
"proxmoxGuestsSelected_other": "{{count}} гости — {{selected}} избрани",
"proxmoxImportButton_one": "Импортиране на хост {{count}}",
"proxmoxImportButton_other": "Импортиране на {{count}} хостове"
},
"proxmoxStats": {
"tabTitle": "Статистика на Proxmox",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "На този възел не са намерени виртуални машини или LXC контейнери.",
"noGuestsMatch": "Няма гости, които да отговарят на текущите филтри."
},
"terminal": {
"connected": "Свързан"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "সর্বনিম্ন ১৫ সেকেন্ড। কত ঘন ঘন প্রক্সমক্স নোড স্ট্যাটস রিফ্রেশ করতে হবে।",
"proxmoxStatsNodeOverride": "নোডের নাম ওভাররাইড",
"proxmoxStatsNodeOverrideDesc": "প্রক্সমক্স নোডের নামের স্বয়ংক্রিয় সনাক্তকরণকে অগ্রাহ্য করুন (যা ডিফল্টরূপে হোস্টনেমের মাধ্যমে সনাক্ত করা হয়)।",
"proxmoxStatsNodeOverridePlaceholder": "হোস্টনেম থেকে স্বয়ংক্রিয়ভাবে শনাক্ত করা হয়েছে"
"proxmoxStatsNodeOverridePlaceholder": "হোস্টনেম থেকে স্বয়ংক্রিয়ভাবে শনাক্ত করা হয়েছে",
"docsLink": "নথি দেখুন",
"hostNotFound": "হোস্ট খুঁজে পাওয়া যায়নি",
"loadingHost": "হোস্ট লোড হচ্ছে...",
"none": "কোনোটিই না",
"proxmoxGuestsSelected_one": "{{count}} অতিথি — {{selected}} নির্বাচিত",
"proxmoxGuestsSelected_other": "{{count}} জন অতিথি — {{selected}} জন নির্বাচিত",
"proxmoxImportButton_one": "{{count}} হোস্ট আমদানি করুন",
"proxmoxImportButton_other": "{{count}} হোস্ট আমদানি করুন"
},
"proxmoxStats": {
"tabTitle": "প্রক্সমক্স পরিসংখ্যান",
@@ -102,5 +110,8 @@
"filterLxc": "এলএক্সসি",
"noGuests": "এই নোডে কোনো ভিএম বা এলএক্সসি কন্টেইনার খুঁজে পাওয়া যায়নি।",
"noGuestsMatch": "বর্তমান ফিল্টারগুলোর সাথে কোনো অতিথি মেলে না।"
},
"terminal": {
"connected": "সংযুক্ত"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "Mínim 15 segons. Amb quina freqüència s'han d'actualitzar les estadístiques del node Proxmox.",
"proxmoxStatsNodeOverride": "Substitució del nom del node",
"proxmoxStatsNodeOverrideDesc": "Anul·la la detecció automàtica del nom del node Proxmox (detectat per defecte mitjançant el nom de l'amfitrió).",
"proxmoxStatsNodeOverridePlaceholder": "Detectat automàticament des del nom d'amfitrió"
"proxmoxStatsNodeOverridePlaceholder": "Detectat automàticament des del nom d'amfitrió",
"docsLink": "Veure documents",
"hostNotFound": "No s'ha trobat l'amfitrió",
"loadingHost": "S'està carregant l'amfitrió...",
"none": "Cap",
"proxmoxGuestsSelected_one": "{{count}} convidat — {{selected}} seleccionat",
"proxmoxGuestsSelected_other": "{{count}} convidats — {{selected}} seleccionats",
"proxmoxImportButton_one": "Importa l'amfitrió {{count}}",
"proxmoxImportButton_other": "Importa els amfitrions {{count}}"
},
"proxmoxStats": {
"tabTitle": "Estadístiques de Proxmox",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "No s'han trobat màquines virtuals ni contenidors LXC en aquest node.",
"noGuestsMatch": "No hi ha convidats que coincideixin amb els filtres actuals."
},
"terminal": {
"connected": "Connectat"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "Minimálně 15 sekund. Jak často aktualizovat statistiky uzlu Proxmox.",
"proxmoxStatsNodeOverride": "Přepsání názvu uzlu",
"proxmoxStatsNodeOverrideDesc": "Přepsat automatickou detekci názvu uzlu Proxmox (ve výchozím nastavení detekováno pomocí názvu hostitele).",
"proxmoxStatsNodeOverridePlaceholder": "Automaticky detekováno z názvu hostitele"
"proxmoxStatsNodeOverridePlaceholder": "Automaticky detekováno z názvu hostitele",
"docsLink": "Zobrazit dokumenty",
"hostNotFound": "Hostitel nenalezen",
"loadingHost": "Načítání hostitele...",
"none": "Žádný",
"proxmoxGuestsSelected_one": "{{count}} host — {{selected}} vybráno",
"proxmoxGuestsSelected_other": "{{count}} hosté — {{selected}} vybráno",
"proxmoxImportButton_one": "Importovat hostitele {{count}}",
"proxmoxImportButton_other": "Importovat hostitele {{count}}"
},
"proxmoxStats": {
"tabTitle": "Statistiky Proxmoxu",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "Na tomto uzlu nebyly nalezeny žádné virtuální počítače ani kontejnery LXC.",
"noGuestsMatch": "Aktuálním filtrům neodpovídají žádní hosté."
},
"terminal": {
"connected": "Připojeno"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "Minimum 15 sekunder. Hvor ofte skal Proxmox-nodestatistikker opdateres.",
"proxmoxStatsNodeOverride": "Tilsidesættelse af nodenavn",
"proxmoxStatsNodeOverrideDesc": "Tilsidesæt automatisk detektion af Proxmox-nodenavnet (registreres som standard via værtsnavn).",
"proxmoxStatsNodeOverridePlaceholder": "Automatisk registreret fra værtsnavn"
"proxmoxStatsNodeOverridePlaceholder": "Automatisk registreret fra værtsnavn",
"docsLink": "Se dokumenter",
"hostNotFound": "Værten blev ikke fundet",
"loadingHost": "Indlæser vært...",
"none": "Ingen",
"proxmoxGuestsSelected_one": "{{count}} gæst — {{selected}} valgt",
"proxmoxGuestsSelected_other": "{{count}} gæster — {{selected}} valgt",
"proxmoxImportButton_one": "Importér {{count}} vært",
"proxmoxImportButton_other": "Importér {{count}} værter"
},
"proxmoxStats": {
"tabTitle": "Proxmox-statistik",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "Der blev ikke fundet nogen VM'er eller LXC-containere på denne node.",
"noGuestsMatch": "Ingen gæster matcher de nuværende filtre."
},
"terminal": {
"connected": "Forbundet"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "Mindestens 15 Sekunden. Wie oft sollen die Proxmox-Knotenstatistiken aktualisiert werden?",
"proxmoxStatsNodeOverride": "Knotennamen überschreiben",
"proxmoxStatsNodeOverrideDesc": "Die automatische Erkennung des Proxmox-Knotennamens (standardmäßig über den Hostnamen ermittelt) kann deaktiviert werden.",
"proxmoxStatsNodeOverridePlaceholder": "Automatisch anhand des Hostnamens erkannt"
"proxmoxStatsNodeOverridePlaceholder": "Automatisch anhand des Hostnamens erkannt",
"docsLink": "Dokumentation anzeigen",
"hostNotFound": "Host nicht gefunden",
"loadingHost": "Host wird geladen...",
"none": "Keine",
"proxmoxGuestsSelected_one": "{{count}} Gast — {{selected}} ausgewählt",
"proxmoxGuestsSelected_other": "{{count}} Gäste — {{selected}} ausgewählt",
"proxmoxImportButton_one": "{{count}} Host importieren",
"proxmoxImportButton_other": "{{count}} Hosts importieren"
},
"proxmoxStats": {
"tabTitle": "Proxmox-Statistiken",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "Auf diesem Knoten wurden keine VMs oder LXC-Container gefunden.",
"noGuestsMatch": "Es gibt keine Gäste, die den aktuellen Filtern entsprechen."
},
"terminal": {
"connected": "Verbunden"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "Ελάχιστο 15 δευτερόλεπτα. Πόσο συχνά θα ανανεώνονται τα στατιστικά στοιχεία του κόμβου Proxmox.",
"proxmoxStatsNodeOverride": "Παράκαμψη ονόματος κόμβου",
"proxmoxStatsNodeOverrideDesc": "Παράκαμψη αυτόματης ανίχνευσης του ονόματος κόμβου Proxmox (εντοπίζεται μέσω του ονόματος κεντρικού υπολογιστή από προεπιλογή).",
"proxmoxStatsNodeOverridePlaceholder": "Αυτόματη ανίχνευση από το όνομα κεντρικού υπολογιστή"
"proxmoxStatsNodeOverridePlaceholder": "Αυτόματη ανίχνευση από το όνομα κεντρικού υπολογιστή",
"docsLink": "Προβολή εγγράφων",
"hostNotFound": "Δεν βρέθηκε κεντρικός υπολογιστής",
"loadingHost": "Φόρτωση κεντρικού υπολογιστή...",
"none": "Κανένας",
"proxmoxGuestsSelected_one": "{{count}} επισκέπτης — {{selected}} επιλεγμένος",
"proxmoxGuestsSelected_other": "{{count}} επισκέπτες — {{selected}} επιλεγμένοι",
"proxmoxImportButton_one": "Εισαγωγή κεντρικού υπολογιστή {{count}}",
"proxmoxImportButton_other": "Εισαγωγή {{count}} κεντρικών υπολογιστών"
},
"proxmoxStats": {
"tabTitle": "Στατιστικά Proxmox",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "Δεν βρέθηκαν εικονικές μηχανές ή κοντέινερ LXC σε αυτόν τον κόμβο.",
"noGuestsMatch": "Δεν υπάρχουν επισκέπτες που να αντιστοιχούν στα τρέχοντα φίλτρα."
},
"terminal": {
"connected": "Συνδεδεμένος"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "Mínimo 15 segundos. Con qué frecuencia se actualizan las estadísticas del nodo Proxmox.",
"proxmoxStatsNodeOverride": "Anulación del nombre del nodo",
"proxmoxStatsNodeOverrideDesc": "Anular la detección automática del nombre del nodo Proxmox (detectado por defecto mediante el nombre de host).",
"proxmoxStatsNodeOverridePlaceholder": "Detectado automáticamente a partir del nombre de host."
"proxmoxStatsNodeOverridePlaceholder": "Detectado automáticamente a partir del nombre de host.",
"docsLink": "Ver documentación",
"hostNotFound": "Host no encontrado",
"loadingHost": "Cargando host...",
"none": "Ninguno",
"proxmoxGuestsSelected_one": "{{count}} invitado — {{selected}} seleccionado",
"proxmoxGuestsSelected_other": "{{count}} invitados — {{selected}} seleccionados",
"proxmoxImportButton_one": "Importar {{count}} host",
"proxmoxImportButton_other": "Importar {{count}} hosts"
},
"proxmoxStats": {
"tabTitle": "Estadísticas de Proxmox",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "No se encontraron máquinas virtuales ni contenedores LXC en este nodo.",
"noGuestsMatch": "No hay huéspedes que coincidan con los filtros actuales."
},
"terminal": {
"connected": "Conectado"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "Vähintään 15 sekuntia. Kuinka usein Proxmox-solmun tilastot päivitetään.",
"proxmoxStatsNodeOverride": "Solmun nimen ohitus",
"proxmoxStatsNodeOverrideDesc": "Ohita Proxmox-solmun nimen automaattinen tunnistus (tunnistetaan oletusarvoisesti isäntänimen kautta).",
"proxmoxStatsNodeOverridePlaceholder": "Automaattisesti tunnistettu isäntänimestä"
"proxmoxStatsNodeOverridePlaceholder": "Automaattisesti tunnistettu isäntänimestä",
"docsLink": "Näytä dokumentit",
"hostNotFound": "Isäntää ei löydy",
"loadingHost": "Ladataan isäntää...",
"none": "Ei mitään",
"proxmoxGuestsSelected_one": "{{count}} vieras — {{selected}} valittu",
"proxmoxGuestsSelected_other": "{{count}} vieraat — {{selected}} valittu",
"proxmoxImportButton_one": "Tuo {{count}} isäntä",
"proxmoxImportButton_other": "Tuo {{count}} isäntiä"
},
"proxmoxStats": {
"tabTitle": "Proxmox-tilastot",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "Tältä solmulta ei löytynyt virtuaalikoneita tai LXC-säilöjä.",
"noGuestsMatch": "Yksikään vieras ei vastaa nykyisiä suodattimia."
},
"terminal": {
"connected": "Yhdistetty"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "Minimum 15 secondes. Fréquence d'actualisation des statistiques du nœud Proxmox.",
"proxmoxStatsNodeOverride": "Remplacement du nom du nœud",
"proxmoxStatsNodeOverrideDesc": "Désactiver la détection automatique du nom du nœud Proxmox (détecté par défaut via le nom d'hôte).",
"proxmoxStatsNodeOverridePlaceholder": "Détection automatique à partir du nom d'hôte"
"proxmoxStatsNodeOverridePlaceholder": "Détection automatique à partir du nom d'hôte",
"docsLink": "Voir la documentation",
"hostNotFound": "Hôte introuvable",
"loadingHost": "Chargement de l'hôte...",
"none": "Aucun",
"proxmoxGuestsSelected_one": "{{count}} invité — {{selected}} sélectionné",
"proxmoxGuestsSelected_other": "{{count}} invités — {{selected}} sélectionnés",
"proxmoxImportButton_one": "Importer {{count}} hôte",
"proxmoxImportButton_other": "Importer {{count}} hôtes"
},
"proxmoxStats": {
"tabTitle": "Statistiques Proxmox",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "Aucune machine virtuelle ni conteneur LXC n'a été trouvé sur ce nœud.",
"noGuestsMatch": "Aucun invité ne correspond aux filtres actuels."
},
"terminal": {
"connected": "Connecté"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "מינימום 15 שניות. באיזו תדירות לרענן את סטטיסטיקות הצומת של Proxmox.",
"proxmoxStatsNodeOverride": "עקיפת שם הצומת",
"proxmoxStatsNodeOverrideDesc": "עקיפת זיהוי אוטומטי של שם הצומת Proxmox (מזוהה דרך שם המארח כברירת מחדל).",
"proxmoxStatsNodeOverridePlaceholder": "זוהה אוטומטית משם המארח"
"proxmoxStatsNodeOverridePlaceholder": "זוהה אוטומטית משם המארח",
"docsLink": "הצג מסמכים",
"hostNotFound": "המארח לא נמצא",
"loadingHost": "טוען מארח...",
"none": "אַף לֹא אֶחָד",
"proxmoxGuestsSelected_one": "{{count}} אורח — {{selected}} נבחר",
"proxmoxGuestsSelected_other": "{{count}} אורחים — {{selected}} נבחרו",
"proxmoxImportButton_one": "ייבוא מארח {{count}}",
"proxmoxImportButton_other": "ייבוא מארחים {{count}}"
},
"proxmoxStats": {
"tabTitle": "סטטיסטיקות פרוקסמוקס",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "לא נמצאו מכונות וירטואליות או מכולות LXC בצומת זה.",
"noGuestsMatch": "אין אורחים התואמים את המסננים הנוכחיים."
},
"terminal": {
"connected": "מְחוּבָּר"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "कम से कम 15 सेकंड। प्रोक्समॉक्स नोड के आंकड़ों को कितनी बार रीफ्रेश करना है?",
"proxmoxStatsNodeOverride": "नोड नाम ओवरराइड",
"proxmoxStatsNodeOverrideDesc": "Proxmox नोड नाम की स्वतः पहचान को ओवरराइड करें (जो डिफ़ॉल्ट रूप से होस्टनाम के माध्यम से पता लगाया जाता है)।",
"proxmoxStatsNodeOverridePlaceholder": "होस्टनाम से स्वतः पता लगाया गया"
"proxmoxStatsNodeOverridePlaceholder": "होस्टनाम से स्वतः पता लगाया गया",
"docsLink": "दस्तावेज़ देखें",
"hostNotFound": "होस्ट नहीं मिला",
"loadingHost": "होस्ट लोड हो रहा है...",
"none": "कोई नहीं",
"proxmoxGuestsSelected_one": "{{count}} अतिथि — {{selected}} चयनित",
"proxmoxGuestsSelected_other": "{{count}} अतिथि — {{selected}} चयनित",
"proxmoxImportButton_one": "{{count}} होस्ट आयात करें",
"proxmoxImportButton_other": "{{count}} होस्ट आयात करें"
},
"proxmoxStats": {
"tabTitle": "प्रॉक्समॉक्स आँकड़े",
@@ -102,5 +110,8 @@
"filterLxc": "एलएक्ससी",
"noGuests": "इस नोड पर कोई वीएम या एलएक्ससी कंटेनर नहीं मिला।",
"noGuestsMatch": "वर्तमान फ़िल्टरों से कोई अतिथि मेल नहीं खाता।"
},
"terminal": {
"connected": "कनेक्टेड"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "Minimum 15 másodperc. A Proxmox csomópont statisztikáinak frissítési gyakorisága.",
"proxmoxStatsNodeOverride": "Csomópont nevének felülbírálása",
"proxmoxStatsNodeOverrideDesc": "A Proxmox csomópont nevének automatikus észlelésének felülbírálása (alapértelmezés szerint a gazdagépnév alapján észlelhető).",
"proxmoxStatsNodeOverridePlaceholder": "Automatikusan felismerve a gazdagépnév alapján"
"proxmoxStatsNodeOverridePlaceholder": "Automatikusan felismerve a gazdagépnév alapján",
"docsLink": "Dokumentumok megtekintése",
"hostNotFound": "Nem található gazdagép",
"loadingHost": "Gazdagép betöltése...",
"none": "Egyik sem",
"proxmoxGuestsSelected_one": "{{count}} vendég — {{selected}} kiválasztva",
"proxmoxGuestsSelected_other": "{{count}} vendégek — {{selected}} kiválasztva",
"proxmoxImportButton_one": "Importálja a {{count}} gazdagépet",
"proxmoxImportButton_other": "{{count}} hosztok importálása"
},
"proxmoxStats": {
"tabTitle": "Proxmox statisztikák",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "Nem találhatók virtuális gépek vagy LXC konténerek ezen a csomóponton.",
"noGuestsMatch": "Egyik vendég sem felel meg a jelenlegi szűrőknek."
},
"terminal": {
"connected": "Csatlakoztatva"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "Minimal 15 detik. Seberapa sering statistik node Proxmox diperbarui.",
"proxmoxStatsNodeOverride": "Penggantian nama node",
"proxmoxStatsNodeOverrideDesc": "Ganti deteksi otomatis nama node Proxmox (yang secara default dideteksi melalui nama host).",
"proxmoxStatsNodeOverridePlaceholder": "Terdeteksi secara otomatis dari nama host"
"proxmoxStatsNodeOverridePlaceholder": "Terdeteksi secara otomatis dari nama host",
"docsLink": "Lihat dokumen",
"hostNotFound": "Host tidak ditemukan",
"loadingHost": "Memuat host...",
"none": "Tidak ada",
"proxmoxGuestsSelected_one": "{{count}} tamu — {{selected}} terpilih",
"proxmoxGuestsSelected_other": "{{count}} tamu — {{selected}} terpilih",
"proxmoxImportButton_one": "Impor {{count}} host",
"proxmoxImportButton_other": "Impor {{count}} host"
},
"proxmoxStats": {
"tabTitle": "Statistik Proxmox",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "Tidak ditemukan VM atau kontainer LXC pada node ini.",
"noGuestsMatch": "Tidak ada tamu yang sesuai dengan filter saat ini."
},
"terminal": {
"connected": "Terhubung"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "Minimo 15 secondi. Frequenza di aggiornamento delle statistiche dei nodi Proxmox.",
"proxmoxStatsNodeOverride": "Sovrascrittura del nome del nodo",
"proxmoxStatsNodeOverrideDesc": "Ignora il rilevamento automatico del nome del nodo Proxmox (rilevato tramite nome host per impostazione predefinita).",
"proxmoxStatsNodeOverridePlaceholder": "Rilevato automaticamente dal nome host"
"proxmoxStatsNodeOverridePlaceholder": "Rilevato automaticamente dal nome host",
"docsLink": "Visualizza documentazione",
"hostNotFound": "Host non trovato",
"loadingHost": "Caricamento host...",
"none": "Nessuna",
"proxmoxGuestsSelected_one": "{{count}} guest — {{selected}} selezionato",
"proxmoxGuestsSelected_other": "{{count}} guest — {{selected}} selezionati",
"proxmoxImportButton_one": "Importa {{count}} host",
"proxmoxImportButton_other": "Importa {{count}} host"
},
"proxmoxStats": {
"tabTitle": "Statistiche di Proxmox",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "Nessuna macchina virtuale o container LXC trovato su questo nodo.",
"noGuestsMatch": "Nessun ospite corrisponde ai filtri attualmente attivi."
},
"terminal": {
"connected": "Connesso"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "最低15秒。Proxmoxノードの統計情報を更新する頻度。",
"proxmoxStatsNodeOverride": "ノード名の上書き",
"proxmoxStatsNodeOverrideDesc": "Proxmoxノード名の自動検出(デフォルトではホスト名で検出)を上書きします。",
"proxmoxStatsNodeOverridePlaceholder": "ホスト名から自動検出"
"proxmoxStatsNodeOverridePlaceholder": "ホスト名から自動検出",
"docsLink": "ドキュメントを表示",
"hostNotFound": "ホストが見つかりません",
"loadingHost": "ホストを読み込み中...",
"none": "なし",
"proxmoxGuestsSelected_one": "{{count}} ゲスト — {{selected}} 選択中",
"proxmoxGuestsSelected_other": "{{count}} ゲスト — {{selected}} 選択中",
"proxmoxImportButton_one": "{{count}} ホストをインポート",
"proxmoxImportButton_other": "{{count}} 台のホストをインポート"
},
"proxmoxStats": {
"tabTitle": "Proxmox統計情報",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "このノード上にはVMまたはLXCコンテナは見つかりませんでした。",
"noGuestsMatch": "現在の検索条件に一致するゲストはいません。"
},
"terminal": {
"connected": "接続中"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "최소 15초. Proxmox 노드 통계를 새로 고치는 빈도.",
"proxmoxStatsNodeOverride": "노드 이름 재정의",
"proxmoxStatsNodeOverrideDesc": "Proxmox 노드 이름 자동 감지 기능을 재정의합니다(기본적으로 호스트 이름을 통해 감지됨).",
"proxmoxStatsNodeOverridePlaceholder": "호스트 이름에서 자동 감지됨"
"proxmoxStatsNodeOverridePlaceholder": "호스트 이름에서 자동 감지됨",
"docsLink": "문서 보기",
"hostNotFound": "호스트를 찾을 수 없습니다",
"loadingHost": "호스트 로드 중...",
"none": "없음",
"proxmoxGuestsSelected_one": "게스트 {{count}}개 — {{selected}}개 선택됨",
"proxmoxGuestsSelected_other": "게스트 {{count}}개 — {{selected}}개 선택됨",
"proxmoxImportButton_one": "호스트 {{count}}개 가져오기",
"proxmoxImportButton_other": "{{count}}개 호스트 가져오기"
},
"proxmoxStats": {
"tabTitle": "프록스목스 통계",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "이 노드에서 VM 또는 LXC 컨테이너를 찾을 수 없습니다.",
"noGuestsMatch": "현재 필터 조건에 맞는 투숙객이 없습니다."
},
"terminal": {
"connected": "연결됨"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "Minimaal 15 seconden. Hoe vaak moeten de Proxmox-node-statistieken worden vernieuwd?",
"proxmoxStatsNodeOverride": "Knooppuntnaam overschrijven",
"proxmoxStatsNodeOverrideDesc": "Schakel de automatische detectie van de Proxmox-knooppuntnaam uit (deze wordt standaard gedetecteerd via de hostnaam).",
"proxmoxStatsNodeOverridePlaceholder": "Automatisch gedetecteerd op basis van hostnaam"
"proxmoxStatsNodeOverridePlaceholder": "Automatisch gedetecteerd op basis van hostnaam",
"docsLink": "Documenten bekijken",
"hostNotFound": "Host niet gevonden",
"loadingHost": "Host wordt geladen...",
"none": "Geen",
"proxmoxGuestsSelected_one": "{{count}} gast — {{selected}} geselecteerd",
"proxmoxGuestsSelected_other": "{{count}} gasten — {{selected}} geselecteerd",
"proxmoxImportButton_one": "Importeer {{count}} host",
"proxmoxImportButton_other": "Importeer {{count}} hosts"
},
"proxmoxStats": {
"tabTitle": "Proxmox-statistieken",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "Er zijn geen VM's of LXC-containers gevonden op dit knooppunt.",
"noGuestsMatch": "Er zijn geen gasten die aan de huidige filters voldoen."
},
"terminal": {
"connected": "Aangesloten"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "Minimum 15 sekunder. Hvor ofte Proxmox-nodestatistikken skal oppdateres.",
"proxmoxStatsNodeOverride": "Overstyring av nodenavn",
"proxmoxStatsNodeOverrideDesc": "Overstyr automatisk deteksjon av Proxmox-nodenavnet (detekteres via vertsnavn som standard).",
"proxmoxStatsNodeOverridePlaceholder": "Automatisk oppdaget fra vertsnavn"
"proxmoxStatsNodeOverridePlaceholder": "Automatisk oppdaget fra vertsnavn",
"docsLink": "Vis dokumenter",
"hostNotFound": "Verten ble ikke funnet",
"loadingHost": "Laster inn vert ...",
"none": "Ingen",
"proxmoxGuestsSelected_one": "{{count}} gjest — {{selected}} valgt",
"proxmoxGuestsSelected_other": "{{count}} gjester — {{selected}} valgt",
"proxmoxImportButton_one": "Importer {{count}} vert",
"proxmoxImportButton_other": "Importer {{count}} verter"
},
"proxmoxStats": {
"tabTitle": "Proxmox-statistikk",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "Ingen virtuelle maskiner eller LXC-containere funnet på denne noden.",
"noGuestsMatch": "Ingen gjester samsvarer med de gjeldende filtrene."
},
"terminal": {
"connected": "Tilkoblet"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "Minimum 15 sekund. Jak często odświeżać statystyki węzła Proxmox.",
"proxmoxStatsNodeOverride": "Nadpisanie nazwy węzła",
"proxmoxStatsNodeOverrideDesc": "Zastąp automatyczne wykrywanie nazwy węzła Proxmox (domyślnie wykrywane za pomocą nazwy hosta).",
"proxmoxStatsNodeOverridePlaceholder": "Automatycznie wykryto na podstawie nazwy hosta"
"proxmoxStatsNodeOverridePlaceholder": "Automatycznie wykryto na podstawie nazwy hosta",
"docsLink": "Zobacz dokumentację",
"hostNotFound": "Nie znaleziono hosta",
"loadingHost": "Ładowanie hosta...",
"none": "Brak",
"proxmoxGuestsSelected_one": "{{count}} gość, wybrano {{selected}}",
"proxmoxGuestsSelected_other": "{{count}} gości, wybrano {{selected}}",
"proxmoxImportButton_one": "Importuj {{count}} host",
"proxmoxImportButton_other": "Importuj {{count}} hostów"
},
"proxmoxStats": {
"tabTitle": "Statystyki Proxmox",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "Nie znaleziono maszyn wirtualnych ani kontenerów LXC na tym węźle.",
"noGuestsMatch": "Żaden gość nie pasuje do bieżących filtrów."
},
"terminal": {
"connected": "Połączono"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "Mínimo de 15 segundos. Com que frequência as estatísticas do nó Proxmox devem ser atualizadas.",
"proxmoxStatsNodeOverride": "Substituição do nome do nó",
"proxmoxStatsNodeOverrideDesc": "Substituir a detecção automática do nome do nó Proxmox (detectado por padrão através do nome do host).",
"proxmoxStatsNodeOverridePlaceholder": "Detectado automaticamente a partir do nome do host"
"proxmoxStatsNodeOverridePlaceholder": "Detectado automaticamente a partir do nome do host",
"docsLink": "Ver documentos",
"hostNotFound": "Host não encontrado",
"loadingHost": "Carregando host...",
"none": "Nenhum",
"proxmoxGuestsSelected_one": "{{count}} convidado — {{selected}} selecionado",
"proxmoxGuestsSelected_other": "{{count}} convidados — {{selected}} selecionados",
"proxmoxImportButton_one": "Importar {{count}} host",
"proxmoxImportButton_other": "Importar {{count}} hosts"
},
"proxmoxStats": {
"tabTitle": "Estatísticas do Proxmox",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "Nenhuma máquina virtual ou contêiner LXC foi encontrado neste nó.",
"noGuestsMatch": "Nenhum hóspede corresponde aos filtros atuais."
},
"terminal": {
"connected": "Conectado"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "Mínimo de 15 segundos. Com que frequência as estatísticas do nó Proxmox devem ser atualizadas.",
"proxmoxStatsNodeOverride": "Substituição do nome do nó",
"proxmoxStatsNodeOverrideDesc": "Substituir a deteção automática do nome do nó Proxmox (detetado por defeito através do nome do host).",
"proxmoxStatsNodeOverridePlaceholder": "Detetado automaticamente a partir do nome do host"
"proxmoxStatsNodeOverridePlaceholder": "Detetado automaticamente a partir do nome do host",
"docsLink": "Ver documentação",
"hostNotFound": "Host não encontrado",
"loadingHost": "A carregar o host...",
"none": "Nenhum",
"proxmoxGuestsSelected_one": "{{count}} convidado — {{selected}} selecionado",
"proxmoxGuestsSelected_other": "{{count}} convidados — {{selected}} selecionados",
"proxmoxImportButton_one": "Importar {{count}} host",
"proxmoxImportButton_other": "Importar {{count}} hosts"
},
"proxmoxStats": {
"tabTitle": "Estatísticas do Proxmox",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "Nenhuma máquina virtual ou contentor LXC foi encontrado neste nó.",
"noGuestsMatch": "Nenhum hóspede corresponde aos filtros atuais."
},
"terminal": {
"connected": "Ligado"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "Minim 15 secunde. Cât de des se actualizează statisticile nodului Proxmox.",
"proxmoxStatsNodeOverride": "Suprascriere nume nod",
"proxmoxStatsNodeOverrideDesc": "Suprascrie detectarea automată a numelui nodului Proxmox (detectat implicit prin numele de gazdă).",
"proxmoxStatsNodeOverridePlaceholder": "Detectat automat de la numele de gazdă"
"proxmoxStatsNodeOverridePlaceholder": "Detectat automat de la numele de gazdă",
"docsLink": "Vizualizați documentele",
"hostNotFound": "Gazdă negăsită",
"loadingHost": "Se încarcă gazda...",
"none": "Nici unul",
"proxmoxGuestsSelected_one": "{{count}} invitat — {{selected}} selectat",
"proxmoxGuestsSelected_other": "{{count}} invitați — {{selected}} selectați",
"proxmoxImportButton_one": "Importați gazda {{count}}",
"proxmoxImportButton_other": "Importați gazde {{count}}"
},
"proxmoxStats": {
"tabTitle": "Statistici Proxmox",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "Nu s-au găsit mașini virtuale sau containere LXC pe acest nod.",
"noGuestsMatch": "Niciun invitat nu corespunde filtrelor actuale."
},
"terminal": {
"connected": "Conectat"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "Минимум 15 секунд. Как часто обновлять статистику узлов Proxmox.",
"proxmoxStatsNodeOverride": "Переопределение имени узла",
"proxmoxStatsNodeOverrideDesc": "Отключить автоматическое определение имени узла Proxmox (по умолчанию определяется по имени хоста).",
"proxmoxStatsNodeOverridePlaceholder": "Автоматически определено по имени хоста"
"proxmoxStatsNodeOverridePlaceholder": "Автоматически определено по имени хоста",
"docsLink": "Документация",
"hostNotFound": "Хост не найден",
"loadingHost": "Загрузка хоста...",
"none": "Нет",
"proxmoxGuestsSelected_one": "{{count}} гость — {{selected}} выбрано",
"proxmoxGuestsSelected_other": "{{count}} гостей — {{selected}} выбрано",
"proxmoxImportButton_one": "Импортировать {{count}} хост",
"proxmoxImportButton_other": "Импортировать {{count}} хостов"
},
"proxmoxStats": {
"tabTitle": "Статистика Proxmox",
@@ -102,5 +110,8 @@
"filterLxc": "ЛХС",
"noGuests": "На этом узле не обнаружено виртуальных машин или контейнеров LXC.",
"noGuestsMatch": "Ни один из гостей не соответствует текущим фильтрам."
},
"terminal": {
"connected": "Подключено"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "Минимум 15 секунди. Колико често освежавати статистику Proxmox чвора.",
"proxmoxStatsNodeOverride": "Замена имена чвора",
"proxmoxStatsNodeOverrideDesc": "Поништи аутоматско откривање имена Proxmox чвора (подразумевано се открива преко имена хоста).",
"proxmoxStatsNodeOverridePlaceholder": "Аутоматски детектовано на основу имена хоста"
"proxmoxStatsNodeOverridePlaceholder": "Аутоматски детектовано на основу имена хоста",
"docsLink": "Прикажи документе",
"hostNotFound": "Хост није пронађен",
"loadingHost": "Учитавање хоста...",
"none": "Ниједан",
"proxmoxGuestsSelected_one": "{{count}} гост — {{selected}} изабрано",
"proxmoxGuestsSelected_other": "{{count}} гости — {{selected}} изабрано",
"proxmoxImportButton_one": "Увоз {{count}} хоста",
"proxmoxImportButton_other": "Увези {{count}} хостова"
},
"proxmoxStats": {
"tabTitle": "Proxmox статистика",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "На овом чвору нису пронађене виртуелне машине или LXC контејнери.",
"noGuestsMatch": "Ниједан гост не одговара тренутним филтерима."
},
"terminal": {
"connected": "Повезано"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "Minst 15 sekunder. Hur ofta Proxmox-nodstatistik ska uppdateras.",
"proxmoxStatsNodeOverride": "Åsidosättning av nodnamn",
"proxmoxStatsNodeOverrideDesc": "Åsidosätt automatisk detektering av Proxmox-nodnamnet (detekteras via värdnamn som standard).",
"proxmoxStatsNodeOverridePlaceholder": "Automatiskt identifierad från värdnamn"
"proxmoxStatsNodeOverridePlaceholder": "Automatiskt identifierad från värdnamn",
"docsLink": "Visa dokument",
"hostNotFound": "Värden hittades inte",
"loadingHost": "Laddar värd...",
"none": "Ingen",
"proxmoxGuestsSelected_one": "{{count}} gäst — {{selected}} vald",
"proxmoxGuestsSelected_other": "{{count}} gäster — {{selected}} vald",
"proxmoxImportButton_one": "Importera {{count}} värd",
"proxmoxImportButton_other": "Importera {{count}} värdar"
},
"proxmoxStats": {
"tabTitle": "Proxmox-statistik",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "Inga virtuella maskiner eller LXC-behållare hittades på den här noden.",
"noGuestsMatch": "Inga gäster matchar de aktuella filtren."
},
"terminal": {
"connected": "Ansluten"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "อย่างน้อย 15 วินาที ความถี่ในการอัปเดตสถิติโหนด Proxmox",
"proxmoxStatsNodeOverride": "การแทนที่ชื่อโหนด",
"proxmoxStatsNodeOverrideDesc": "ยกเลิกการตรวจจับชื่อโหนด Proxmox อัตโนมัติ (โดยค่าเริ่มต้นจะตรวจจับผ่านชื่อโฮสต์)",
"proxmoxStatsNodeOverridePlaceholder": "ตรวจจับอัตโนมัติจากชื่อโฮสต์"
"proxmoxStatsNodeOverridePlaceholder": "ตรวจจับอัตโนมัติจากชื่อโฮสต์",
"docsLink": "ดูเอกสาร",
"hostNotFound": "ไม่พบโฮสต์",
"loadingHost": "กำลังโหลดโฮสต์...",
"none": "ไม่มี",
"proxmoxGuestsSelected_one": "{{count}} แขก — {{selected}} เลือกแล้ว",
"proxmoxGuestsSelected_other": "แขก {{count}} คน — แขก {{selected}} คน ที่เลือก",
"proxmoxImportButton_one": "นำเข้าโฮสต์ {{count}}",
"proxmoxImportButton_other": "นำเข้าโฮสต์ {{count}}"
},
"proxmoxStats": {
"tabTitle": "สถิติ Proxmox",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "ไม่พบเครื่องเสมือน (VM) หรือคอนเทนเนอร์ LXC บนโหนดนี้",
"noGuestsMatch": "ไม่มีแขกท่านใดตรงกับตัวกรองที่มีอยู่ในขณะนี้"
},
"terminal": {
"connected": "เชื่อมต่อแล้ว"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "En az 15 saniye. Proxmox düğüm istatistiklerinin ne sıklıkla yenilenmesi gerektiği.",
"proxmoxStatsNodeOverride": "Düğüm adı geçersiz kılma",
"proxmoxStatsNodeOverrideDesc": "Proxmox düğüm adının otomatik olarak algılanmasını (varsayılan olarak ana bilgisayar adı üzerinden algılanır) geçersiz kılın.",
"proxmoxStatsNodeOverridePlaceholder": "Ana bilgisayar adından otomatik olarak algılandı"
"proxmoxStatsNodeOverridePlaceholder": "Ana bilgisayar adından otomatik olarak algılandı",
"docsLink": "Dokümanları görüntüle",
"hostNotFound": "Host bulunamadı",
"loadingHost": "Host yükleniyor...",
"none": "Hiçbiri",
"proxmoxGuestsSelected_one": "{{count}} misafir — {{selected}} seçili",
"proxmoxGuestsSelected_other": "{{count}} misafir — {{selected}} seçili",
"proxmoxImportButton_one": "{{count}} ana makineyi içe aktar",
"proxmoxImportButton_other": "{{count}} sunucuyu içe aktar"
},
"proxmoxStats": {
"tabTitle": "Proxmox İstatistikleri",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "Bu düğümde hiçbir sanal makine veya LXC kapsayıcısı bulunamadı.",
"noGuestsMatch": "Mevcut filtrelere uyan konuk bulunamadı."
},
"terminal": {
"connected": "Bağlandı"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "Мінімум 15 секунд. Як часто оновлювати статистику вузла Proxmox.",
"proxmoxStatsNodeOverride": "Перевизначення назви вузла",
"proxmoxStatsNodeOverrideDesc": "Перевизначити автоматичне визначення імені вузла Proxmox (за замовчуванням визначається через ім'я хоста).",
"proxmoxStatsNodeOverridePlaceholder": "Автоматично визначено за назвою хоста"
"proxmoxStatsNodeOverridePlaceholder": "Автоматично визначено за назвою хоста",
"docsLink": "Переглянути документи",
"hostNotFound": "Хост не знайдено",
"loadingHost": "Завантаження хоста...",
"none": "Жоден",
"proxmoxGuestsSelected_one": "{{count}} гість — {{selected}} вибрано",
"proxmoxGuestsSelected_other": "{{count}} гостей — {{selected}} вибрано",
"proxmoxImportButton_one": "Імпортувати хост {{count}}",
"proxmoxImportButton_other": "Імпортувати {{count}} хостів"
},
"proxmoxStats": {
"tabTitle": "Статистика Proxmox",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "На цьому вузлі не знайдено віртуальних машин або контейнерів LXC.",
"noGuestsMatch": "Немає гостей, які відповідають поточним фільтрам."
},
"terminal": {
"connected": "Підключено"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "Tối thiểu 15 giây. Tần suất làm mới số liệu thống kê của node Proxmox.",
"proxmoxStatsNodeOverride": "Ghi đè tên nút",
"proxmoxStatsNodeOverrideDesc": "Ghi đè tính năng tự động phát hiện tên nút Proxmox (mặc định được phát hiện thông qua tên máy chủ).",
"proxmoxStatsNodeOverridePlaceholder": "Tự động nhận diện từ tên máy chủ"
"proxmoxStatsNodeOverridePlaceholder": "Tự động nhận diện từ tên máy chủ",
"docsLink": "Xem tài liệu",
"hostNotFound": "Không tìm thấy máy chủ",
"loadingHost": "Đang tải máy chủ...",
"none": "Không có",
"proxmoxGuestsSelected_one": "{{count}} máy khách — đã chọn {{selected}}",
"proxmoxGuestsSelected_other": "{{count}} máy khách — đã chọn {{selected}}",
"proxmoxImportButton_one": "Nhập {{count}} máy chủ",
"proxmoxImportButton_other": "Nhập {{count}} máy chủ"
},
"proxmoxStats": {
"tabTitle": "Thống kê Proxmox",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "Không tìm thấy máy ảo hoặc vùng chứa LXC nào trên nút này.",
"noGuestsMatch": "Hiện không có khách nào phù hợp với bộ lọc hiện tại."
},
"terminal": {
"connected": "Đã kết nối"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "最短间隔 15 秒。Proxmox 节点统计信息刷新频率。",
"proxmoxStatsNodeOverride": "覆盖节点名称",
"proxmoxStatsNodeOverrideDesc": "覆盖自动检测的 Proxmox 节点名称(默认情况下通过主机名检测)。",
"proxmoxStatsNodeOverridePlaceholder": "从主机名自动检测"
"proxmoxStatsNodeOverridePlaceholder": "从主机名自动检测",
"docsLink": "查看文档",
"hostNotFound": "未找到主机",
"loadingHost": "正在加载主机...",
"none": "无",
"proxmoxGuestsSelected_one": "{{count}} 个客户主机 — 已选择 {{selected}} 个",
"proxmoxGuestsSelected_other": "{{count}} 个客户主机 — 已选择 {{selected}} 个",
"proxmoxImportButton_one": "导入 {{count}} 个主机",
"proxmoxImportButton_other": "导入 {{count}} 个主机"
},
"proxmoxStats": {
"tabTitle": "Proxmox 统计数据",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "此节点上未找到虚拟机或 LXC 容器。",
"noGuestsMatch": "没有符合当前筛选条件的客户主机。"
},
"terminal": {
"connected": "已连接"
}
}
+12 -1
View File
@@ -55,7 +55,15 @@
"proxmoxStatsPollIntervalDesc": "最短間隔 15 秒。 Proxmox 節點統計資訊刷新頻率。",
"proxmoxStatsNodeOverride": "節點名稱覆蓋",
"proxmoxStatsNodeOverrideDesc": "覆蓋 Proxmox 節點名稱的自動偵測(預設透過主機名稱偵測)。",
"proxmoxStatsNodeOverridePlaceholder": "從主機名稱自動偵測"
"proxmoxStatsNodeOverridePlaceholder": "從主機名稱自動偵測",
"docsLink": "檢視文件",
"hostNotFound": "找不到主機",
"loadingHost": "正在載入主機...",
"none": "無",
"proxmoxGuestsSelected_one": "{{count}} 個訪客主機 — 已選取 {{selected}}",
"proxmoxGuestsSelected_other": "{{count}} 個訪客主機 — 已選取 {{selected}}",
"proxmoxImportButton_one": "匯入 {{count}} 台主機",
"proxmoxImportButton_other": "匯入 {{count}} 台主機"
},
"proxmoxStats": {
"tabTitle": "Proxmox 統計數據",
@@ -102,5 +110,8 @@
"filterLxc": "LXC",
"noGuests": "此節點上未發現虛擬機器或 LXC 容器。",
"noGuestsMatch": "沒有符合目前篩選條件的客人。"
},
"terminal": {
"connected": "已連線"
}
}
+6 -6
View File
@@ -49,8 +49,8 @@ export function proxmoxSourceKey(source: {
return `${source.sourceHostId}:${source.node}:${source.type}:${source.vmid}`;
}
export interface ImportedGuest {
host: Record<string, unknown>;
export interface ImportedGuest<H = Record<string, unknown>> {
host: H;
config: Record<string, unknown>;
source: ProxmoxSource;
}
@@ -60,13 +60,13 @@ export interface ImportedGuest {
* source lives in each guest's proxmoxConfig host setting, not on the host
* row, so the caller passes both.
*/
export function indexImportedGuests(
hosts: Record<string, unknown>[],
export function indexImportedGuests<H extends { id: unknown }>(
hosts: H[],
configs: Array<{ hostId: number; value: unknown }>,
sourceHostId: number,
): Map<string, ImportedGuest> {
): Map<string, ImportedGuest<H>> {
const configById = new Map(configs.map((c) => [c.hostId, c.value]));
const out = new Map<string, ImportedGuest>();
const out = new Map<string, ImportedGuest<H>>();
for (const host of hosts) {
const config = parseJsonObject(configById.get(Number(host.id)));
const source = getProxmoxSource(config);
@@ -10,8 +10,3 @@ export function parseProxmoxJumpHosts(raw: unknown): unknown[] | null {
return null;
}
}
export function serializeProxmoxJumpHosts(raw: unknown): string | null {
const parsed = parseProxmoxJumpHosts(raw);
return parsed ? JSON.stringify(parsed) : null;
}
+56 -76
View File
@@ -3,16 +3,14 @@ import type { Client as SSHClient } from "ssh2";
import { execElevated } from "@termix/plugin-sdk/host-commands";
import type {
PluginHostCreateInput,
PluginHostRecord,
PluginHostJumpHost,
PluginHostUpdateInput,
PluginSshHost,
} from "@termix/plugin-sdk/backend";
import { connectSsh } from "./ssh.js";
import { pluginCtx } from "./plugin-ctx.js";
import { resolveProxmoxImportAuth } from "./proxmox-import-auth.js";
import {
parseProxmoxJumpHosts,
serializeProxmoxJumpHosts,
} from "./proxmox-jump-hosts.js";
import { parseProxmoxJumpHosts } from "./proxmox-jump-hosts.js";
import { isSafeNodeName } from "./proxmox-shared.js";
import {
indexImportedGuests,
@@ -190,7 +188,7 @@ type ProxmoxGuest = {
};
/** The resolved host ctx.ssh.connect hands back, plus the sudo secret proxmox needs for pvesh. */
type PluginSshHostWithSudo = PluginHostRecord & { sudoPassword?: string };
type PluginSshHostWithSudo = PluginSshHost & { sudoPassword?: string };
type ProxmoxSyncResult = {
created: number;
@@ -215,6 +213,22 @@ function guestTags(guest: ProxmoxGuest): string[] {
];
}
/**
* The switches another plugin keeps for an imported guest. An entry for a
* plugin that is not running is skipped by core.
*/
export function guestPluginSettings(
connectionType: "ssh" | "rdp",
enableDocker: boolean,
): Record<string, Record<string, unknown>> {
return {
...(connectionType === "rdp"
? { "remote-desktop": { enableRdp: true, rdpPort: 3389 } }
: {}),
...(enableDocker ? { docker: { enableDocker: true } } : {}),
};
}
function mergeTags(
existing: unknown,
additions: string[],
@@ -261,7 +275,7 @@ async function discoverProxmoxGuestsForHost(
timeoutMs: 35000,
overrides: { tryKeyboard: false, readyTimeout: 30000 },
});
const hostWithSudo = host as PluginSshHostWithSudo;
const hostWithSudo: PluginSshHostWithSudo = host;
const hostCredentialId = (hostWithSudo.credentialId as number | null) ?? null;
try {
@@ -498,7 +512,7 @@ async function syncProxmoxHost(
try {
const discovery = await discoverProxmoxGuestsForHost(userId, sourceHostId);
const sourceHostName = discovery.host.name || "Proxmox";
const sourceHostName = String(discovery.host.name || "Proxmox");
const defaultCredentialId =
discovery.config.defaultCredentialId ?? discovery.credentialId ?? null;
const importAuth = resolveProxmoxImportAuth(
@@ -507,12 +521,8 @@ async function syncProxmoxHost(
);
const now = new Date().toISOString();
const existingHosts = (await ctx.hosts.listOwned()) as unknown as Record<
string,
unknown
>[];
const existingBySource = indexImportedGuests(
existingHosts,
await ctx.hosts.listOwned(),
await ctx.settings.listHostValues("proxmoxConfig"),
sourceHostId,
);
@@ -560,7 +570,7 @@ async function syncProxmoxHost(
: connectionType === "rdp"
? ""
: "root";
const update: Record<string, unknown> = {
const update: PluginHostUpdateInput = {
name: guest.name,
ip: guest.ip || existing?.ip || "0.0.0.0",
port,
@@ -568,7 +578,7 @@ async function syncProxmoxHost(
connectionType,
folder: existing?.folder || sourceHostName,
tags: mergeTags(existing?.tags, guestTags(guest), ["proxmox-missing"]),
updatedAt: now,
pluginSettings: { [ctx.pluginId]: { proxmoxConfig } },
};
if (existing) {
@@ -576,69 +586,46 @@ async function syncProxmoxHost(
update.credentialId = importAuth.credentialId;
update.overrideCredentialUsername = false;
}
await ctx.hosts.update(
existing.id as number,
update as PluginHostUpdateInput,
);
await ctx.settings.setHost(
existing.id as number,
"proxmoxConfig",
proxmoxConfig,
);
await ctx.hosts.update(existing.id, update);
result.updated++;
continue;
}
Object.assign(update, {
enableDocker: guest.enableDocker,
enableSsh: connectionType === "ssh",
enableRdp: connectionType === "rdp",
});
const created = await ctx.hosts.create({
await ctx.hosts.create({
...update,
createdAt: now,
name: guest.name,
ip: update.ip!,
port,
username,
enableSsh: connectionType === "ssh",
pin: false,
authType: connectionType === "rdp" ? "password" : importAuth.authType,
credentialId: connectionType === "ssh" ? importAuth.credentialId : null,
overrideCredentialUsername: importAuth.overrideCredentialUsername,
password: null,
key: null,
keyPassword: null,
keyType: null,
rdpPort: connectionType === "rdp" ? 3389 : null,
jumpHosts: serializeProxmoxJumpHosts(discovery.jumpHosts),
quickActions: null,
forceKeyboardInteractive: "false",
useSocks5: 0,
socks5Host: null,
socks5Port: null,
socks5Username: null,
socks5Password: null,
socks5ProxyChain: null,
portKnockSequence: null,
} as unknown as PluginHostCreateInput);
await ctx.settings.setHost(
Number(created.id),
"proxmoxConfig",
proxmoxConfig,
);
overrideCredentialUsername: !!importAuth.overrideCredentialUsername,
jumpHosts: (parseProxmoxJumpHosts(discovery.jumpHosts) ??
[]) as PluginHostJumpHost[],
forceKeyboardInteractive: false,
pluginSettings: {
...update.pluginSettings,
...guestPluginSettings(connectionType, guest.enableDocker),
},
});
result.created++;
}
if (discovery.config.markMissingGuests) {
for (const [key, { host, config, source }] of existingBySource) {
if (seen.has(key)) continue;
await ctx.hosts.update(
host.id as number,
{
tags: mergeTags(host.tags, ["proxmox-missing"]),
updatedAt: now,
} as PluginHostUpdateInput,
);
await ctx.settings.setHost(host.id as number, "proxmoxConfig", {
...config,
source: { ...source, missingSince: source.missingSince || now },
await ctx.hosts.update(host.id, {
tags: mergeTags(host.tags, ["proxmox-missing"]),
pluginSettings: {
[ctx.pluginId]: {
proxmoxConfig: {
...config,
source: { ...source, missingSince: source.missingSince || now },
},
},
},
});
result.markedMissing++;
}
@@ -984,22 +971,15 @@ router.post("/import", async (req, res) => {
return res.status(400).json({ error: "No hosts to import" });
}
const result = { success: 0, failed: 0, errors: [] as string[] };
for (const entry of hosts as Array<Record<string, unknown>>) {
const { pluginSettings, ...input } = entry;
for (const entry of hosts as PluginHostCreateInput[]) {
try {
const created = await ctx.hosts.create(
input as unknown as PluginHostCreateInput,
);
const own = (pluginSettings as Record<string, unknown> | undefined)?.[
ctx.pluginId
] as Record<string, unknown> | undefined;
for (const [key, value] of Object.entries(own ?? {})) {
await ctx.settings.setHost(Number(created.id), key, value);
}
// Core refuses any field it does not take, and any host setting its
// plugin does not declare.
await ctx.hosts.create(entry);
result.success++;
} catch (err: unknown) {
result.failed++;
result.errors.push(`${String(input.name)}: ${getErrorMessage(err)}`);
result.errors.push(`${String(entry?.name)}: ${getErrorMessage(err)}`);
}
}
return res.json(result);
@@ -158,8 +158,6 @@ export function ProxmoxDiscoverDialog({
jumpHosts: discoveredJumpHosts ?? undefined,
...importAuth,
enableSsh: g.connectionType !== "rdp",
enableRdp: g.connectionType === "rdp",
enableDocker: g.enableDocker,
connectionType: g.connectionType,
tags: [
"proxmox",
@@ -168,8 +166,13 @@ export function ProxmoxDiscoverDialog({
g.type === "lxc" ? `ct-${g.vmid}` : `vm-${g.vmid}`,
...(g.enableDocker ? ["docker"] : []),
],
// This plugin's host settings travel with the import like an export's.
// Host settings travel with the import like an export's, keyed by
// the plugin that keeps them.
pluginSettings: {
...(g.connectionType === "rdp"
? { "remote-desktop": { enableRdp: true, rdpPort: 3389 } }
: {}),
...(g.enableDocker ? { docker: { enableDocker: true } } : {}),
proxmox: {
proxmoxConfig: {
source: {
+11 -4
View File
@@ -92,6 +92,13 @@ function ProxmoxStatsStandalone({ hostId }: StandaloneViewProps) {
return <ProxmoxStatsApp hostId={hostId} />;
}
/** This plugin's host settings, as they arrive on the host record. */
export function proxmoxSettings(
host: Pick<PluginHostRecord, "pluginSettings">,
): Record<string, unknown> {
return host.pluginSettings?.proxmox ?? {};
}
export function activate(app: TermixApp): void {
setProxmoxApp(app);
app.onDispose(() => setProxmoxApp(null));
@@ -136,7 +143,7 @@ export function activate(app: TermixApp): void {
return (
<DropdownMenuItem
onClick={() => openDiscover({})}
disabled={!hosts.some((host) => host.enableProxmox)}
disabled={!hosts.some((host) => proxmoxSettings(host).enableProxmox)}
>
<Server className="size-3.5 mr-2" />
{t("hosts.proxmoxImportTitle")}
@@ -166,9 +173,9 @@ export function activate(app: TermixApp): void {
icon: Boxes,
kind: "open",
order: 90,
when: (host) => !!host.enableProxmox,
when: (host) => !!proxmoxSettings(host).enableProxmox,
run: (host) => {
const config = host.proxmoxConfig as
const config = proxmoxSettings(host).proxmoxConfig as
| { defaultCredentialId?: number | null; defaultAuthType?: string }
| undefined;
openDiscover({
@@ -205,6 +212,6 @@ export function activate(app: TermixApp): void {
order: 60,
tabType: "proxmox-stats",
copyUrlView: "proxmox-stats",
when: (host) => host.enableProxmoxStats === true,
when: (host) => proxmoxSettings(host).enableProxmoxStats === true,
});
}
@@ -1,26 +1,14 @@
import { describe, expect, it } from "vitest";
import {
parseProxmoxJumpHosts,
serializeProxmoxJumpHosts,
} from "../../src/backend/proxmox-jump-hosts.js";
import { parseProxmoxJumpHosts } from "../../src/backend/proxmox-jump-hosts.js";
describe("Proxmox jump-host persistence", () => {
const jumpHosts = [{ hostId: 7 }, { hostId: 9 }];
it("serializes resolved arrays before inserting a synced guest", () => {
expect(serializeProxmoxJumpHosts(jumpHosts)).toBe(
'[{"hostId":7},{"hostId":9}]',
);
});
it("keeps stored JSON strings stable", () => {
const stored = '[{"hostId":7}]';
expect(serializeProxmoxJumpHosts(stored)).toBe(stored);
expect(parseProxmoxJumpHosts(stored)).toEqual([{ hostId: 7 }]);
it("reads a resolved array or a stored JSON string", () => {
expect(parseProxmoxJumpHosts([{ hostId: 7 }])).toEqual([{ hostId: 7 }]);
expect(parseProxmoxJumpHosts('[{"hostId":7}]')).toEqual([{ hostId: 7 }]);
});
it("turns missing or malformed values into null", () => {
expect(serializeProxmoxJumpHosts(null)).toBeNull();
expect(serializeProxmoxJumpHosts("invalid")).toBeNull();
expect(parseProxmoxJumpHosts(null)).toBeNull();
expect(parseProxmoxJumpHosts("invalid")).toBeNull();
});
});
@@ -0,0 +1,12 @@
import { describe, expect, it } from "vitest";
import { guestPluginSettings } from "../../src/backend/routes.js";
describe("guestPluginSettings", () => {
it("names the plugin that keeps each switch an imported guest needs", () => {
expect(guestPluginSettings("rdp", true)).toEqual({
"remote-desktop": { enableRdp: true, rdpPort: 3389 },
docker: { enableDocker: true },
});
expect(guestPluginSettings("ssh", false)).toEqual({});
});
});
@@ -38,6 +38,25 @@ describe(`${manifest.id} activate`, () => {
}
});
it("reads its switches from its own host settings", async () => {
rendered = await renderWithApp(plugin, { manifest, locales });
const host = (settings: Record<string, unknown>) => ({
id: "1",
name: "pve",
ip: "10.0.0.1",
port: 22,
pluginSettings: { proxmox: settings },
});
const ids = (settings: Record<string, unknown>) =>
rendered!.registered.hostActionsFor(host(settings)).map((a) => a.id);
expect(ids({ enableProxmox: true })).toContain("proxmox-discover");
expect(ids({})).not.toContain("proxmox-discover");
expect(ids({ enableProxmoxStats: true })).toContain("proxmox-stats");
expect(plugin.proxmoxSettings(host({ enableProxmoxStats: true }))).toEqual({
enableProxmoxStats: true,
});
});
it("removes everything it registered on deactivate", async () => {
const app = await renderWithApp(plugin, { manifest, locales });
await app.deactivate();