From 6a7ffad9b8ba572cd378e43b2686d6d233817d77 Mon Sep 17 00:00:00 2001
From: martino <32328813+f3rs3n@users.noreply.github.com>
Date: Mon, 21 Sep 2026 19:49:43 +0200
Subject: [PATCH 1/4] fix(backup): use complete messages for archives and
destinations
---
.../tests/test_command_descriptions.py | 14 +++
AppImage/components/host-backup.tsx | 6 +-
AppImage/messages/README.md | 18 ++++
AppImage/messages/en/common.json | 3 +
tests/test_backup_archives_empty.cjs | 91 +++++++++++++++++++
tests/test_backup_destination_messages.cjs | 56 ++++++++++++
6 files changed, 185 insertions(+), 3 deletions(-)
create mode 100644 tests/test_backup_archives_empty.cjs
create mode 100644 tests/test_backup_destination_messages.cjs
diff --git a/.github/scripts/tests/test_command_descriptions.py b/.github/scripts/tests/test_command_descriptions.py
index 30d9b38e..b3e8518c 100644
--- a/.github/scripts/tests/test_command_descriptions.py
+++ b/.github/scripts/tests/test_command_descriptions.py
@@ -90,6 +90,20 @@ class CommandDescriptionsTests(unittest.TestCase):
path = root / lang / "common.json"
path.parent.mkdir()
shutil.copyfile(ROOT / f"AppImage/messages/{lang}/common.json", path)
+ # This steady-state fixture assumes generation already finished.
+ # Seed only the three new backup messages in temporary locale
+ # copies; keep recovered command arrays and repo catalogs exact.
+ # Actual missing-key fallback is tested by the JSX seam tests.
+ if lang != "en":
+ temporary = json.loads(path.read_text())
+ for section, key in (
+ ("archives", "emptyMessage"),
+ ("destinations", "backupsKeptMessage"),
+ ("destinations", "localAttachHelpMessage"),
+ ):
+ temporary["backup"][section].setdefault(
+ key, catalog("en")["backup"][section][key])
+ path.write_text(json.dumps(temporary, ensure_ascii=False))
before = {p: p.read_bytes() for p in root.glob("*/common.json")}
argv = [str(SCRIPT), "--source", str(root / "en/common.json"),
"--messages-dir", str(root), "--languages", languages, "--sleep", "0"]
diff --git a/AppImage/components/host-backup.tsx b/AppImage/components/host-backup.tsx
index 2e455cd5..1a2f5e6c 100644
--- a/AppImage/components/host-backup.tsx
+++ b/AppImage/components/host-backup.tsx
@@ -1300,7 +1300,7 @@ export function HostBackup() {
) : unifiedArchives.length === 0 ? (
- {t("backup.archives.emptyBefore")} {t("backup.manual.run")} {t("backup.archives.emptyAfter")}
+ {t("backup.archives.emptyMessage")}
) : (
@@ -4089,7 +4089,7 @@ function CreateJobDialog({
className="font-mono"
/>
- {t("backup.destinations.localAttachHelpBefore")} /dump {t("backup.destinations.localAttachHelpMiddle")} /var/lib/vz/dump.
+ {t("backup.destinations.localAttachHelpMessage")}
>
) : (
@@ -5709,7 +5709,7 @@ function DestinationsSection({
)}
{backups > 0 && (
- {t("backup.destinations.backupsKeptBefore", { count: backups })} {t("backup.destinations.kept")}.
+ {t("backup.destinations.backupsKeptMessage")}
)}
diff --git a/AppImage/messages/README.md b/AppImage/messages/README.md
index 68e100f7..dd726e3d 100644
--- a/AppImage/messages/README.md
+++ b/AppImage/messages/README.md
@@ -7,4 +7,22 @@ The ProxMenux Monitor dashboard uses a small client-side i18n layer.
To improve a translation, edit the values in your locale's `common.json` — keep placeholders such as `{uptime}`, `{vmid}` or `{count}` unchanged, and don't translate brand or product names (`ProxMenux Monitor`, `Proxmox Backup Server`, `Secure Gateway`, `Tailscale`, etc.). Missing keys fall back to English at runtime, so a partial refresh is always safe to merge.
+## Backup message composition regressions
+
+From the repository root, run:
+
+```sh
+node tests/test_backup_archives_empty.cjs
+node tests/test_backup_destination_messages.cjs
+```
+
+Prerequisites: Node.js and the `typescript` development dependency from
+`AppImage/package.json` must be installed/resolvable (normally in
+`AppImage/node_modules`). These tests compile actual JSX message branches and
+pure i18n lookup functions without importing the component or calling a backend.
+They cover whole English messages, missing-key locale fallback, loading/error
+branches, nonempty lists, the removal notice at zero/one/multiple archives,
+local-attach help, and unchanged shared labels. They do not replace browser or
+real-host acceptance. Keep literal paths in the local-attach help unchanged.
+
To add a new locale, see [§11 → Adding a new locale](../../CONTRIBUTING.md#adding-a-new-locale) in the Contributing Guide.
diff --git a/AppImage/messages/en/common.json b/AppImage/messages/en/common.json
index 20a9af22..eac3b591 100644
--- a/AppImage/messages/en/common.json
+++ b/AppImage/messages/en/common.json
@@ -3828,6 +3828,7 @@
"downloadTitle": "Download this backup",
"emptyAfter": "backups yet.",
"emptyBefore": "No",
+ "emptyMessage": "No backup archives found.",
"encrypted": "Encrypted",
"encryptedTitle": "This backup is encrypted",
"filesInBackup": "Files in backup",
@@ -3903,6 +3904,7 @@
"addPbsRepository": "Add PBS repository",
"appendAuthorizedKeyBefore": "Append the generated public key to",
"backupsKeptBefore": "Existing backups are kept in",
+ "backupsKeptMessage": "Existing backup archives are not deleted.",
"borgEncryptionInherited": "Borg encryption is controlled by the repository.",
"builtIn": "Built-in",
"builtInDefault": "Built-in default",
@@ -3923,6 +3925,7 @@
"leavePassphraseBlank": "Leave blank to keep the saved passphrase.",
"leavePasswordBlank": "Leave blank to keep the saved password.",
"localAttachHelpBefore": "Use a mounted local path. For USB drives, mount them first in",
+ "localAttachHelpMessage": "Mount USB drives first. Leave blank to use the PVE storage path + /dump (fallback: /var/lib/vz/dump).",
"localAttachHelpMiddle": "USB drives",
"localManualPickHelp": "Pick a local path for one-shot backup output.",
"localPathHelpAfter": "or another mounted path.",
diff --git a/tests/test_backup_archives_empty.cjs b/tests/test_backup_archives_empty.cjs
new file mode 100644
index 00000000..c78c5797
--- /dev/null
+++ b/tests/test_backup_archives_empty.cjs
@@ -0,0 +1,91 @@
+// Offline JSX seam, following the TypeScript compiler harness in adjacent tests.
+// No component imports, React effects, API calls or host-management execution.
+// Run from the repository root: node tests/test_backup_archives_empty.cjs
+const assert = require('node:assert/strict');
+const fs = require('node:fs');
+const path = require('node:path');
+const { createRequire } = require('node:module');
+const app = path.resolve(__dirname, '../AppImage');
+const ts = createRequire(path.join(app, 'package.json'))('typescript');
+const read = file => fs.readFileSync(path.join(app, file), 'utf8');
+const parse = file => ts.createSourceFile(file, read(file), ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
+const compile = text => ts.transpileModule(text, {
+ compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020, jsx: ts.JsxEmit.React },
+}).outputText;
+const printer = ts.createPrinter();
+const provider = parse('lib/i18n/provider.tsx');
+const pure = provider.statements.filter(node => ts.isFunctionDeclaration(node) &&
+ ['getMessage', 'interpolate'].includes(node.name?.text));
+assert.equal(pure.length, 2);
+let lookup;
+function visitLookup(node) {
+ if (ts.isVariableDeclaration(node) && node.name.getText(provider) === 't' &&
+ node.initializer && ts.isCallExpression(node.initializer) &&
+ node.initializer.expression.getText(provider) === 'useCallback') lookup = node.initializer.arguments[0];
+ ts.forEachChild(node, visitLookup);
+}
+visitLookup(provider);
+assert.ok(lookup, 'real provider lookup callback');
+const lookupCode = pure.map(node => printer.printNode(ts.EmitHint.Unspecified, node, provider)).join('\n') +
+ '\nconst t = ' + printer.printNode(ts.EmitHint.Expression, lookup, provider) + ';';
+const catalogs = Object.fromEntries(fs.readdirSync(path.join(app, 'messages')).filter(locale =>
+ fs.existsSync(path.join(app, 'messages', locale, 'common.json'))).map(locale =>
+ [locale, JSON.parse(read(`messages/${locale}/common.json`))]));
+// Compile only trusted, checked-out source; no catalog/input strings enter code.
+const translator = (language, messages = catalogs) =>
+ new Function('MESSAGE_CATALOG', 'language', compile(lookupCode) + '\nreturn t;')(messages, language);
+
+const source = parse('components/host-backup.tsx');
+let branch;
+function visitBranch(node) {
+ if (ts.isConditionalExpression(node) && node.condition.getText(source) === 'archivesErr && remoteArchivesErr') branch = node;
+ ts.forEachChild(node, visitBranch);
+}
+visitBranch(source);
+assert.ok(branch, 'real archives loading/error/empty decision');
+// Keep the actual guards and JSX messages. Only replace the nonempty archive
+// list with a sentinel: rendering its controls is outside this message test.
+const transformed = ts.transform(branch, [context => root => {
+ const visit = node => {
+ if (ts.isConditionalExpression(node) && node.condition.getText(source) === 'unifiedArchives.length === 0') {
+ return ts.factory.updateConditionalExpression(node, node.condition, node.questionToken,
+ node.whenTrue, node.colonToken, ts.factory.createStringLiteral('NONEMPTY_ARCHIVES'));
+ }
+ return ts.visitEachChild(node, visit, context);
+ };
+ return ts.visitNode(root, visit);
+}]);
+const expression = printer.printNode(ts.EmitHint.Expression, transformed.transformed[0], source);
+transformed.dispose();
+const render = new Function('React', 'Loader2', 't', 'archivesErr', 'remoteArchivesErr',
+ 'archivesResp', 'remoteArchivesResp', 'unifiedArchives', compile(`const result = ${expression};`) + '\nreturn result;');
+// Text-only JSX sink: TypeScript performs the real JSX whitespace conversion.
+const React = { createElement: (tag, props, ...children) => children.flat(Infinity).filter(x => x != null && x !== false).join('') };
+const text = (locale = 'en', overrides = {}, messages = catalogs) => {
+ const state = { archivesErr: null, remoteArchivesErr: null, archivesResp: { archives: [] },
+ remoteArchivesResp: { snapshots: [] }, unifiedArchives: [], ...overrides };
+ return render(React, 'spinner', translator(locale, messages), state.archivesErr, state.remoteArchivesErr,
+ state.archivesResp, state.remoteArchivesResp, state.unifiedArchives);
+};
+
+assert.equal(text(), 'No backup archives found.');
+assert.equal(text('it'), 'No backup archives found.', 'Italian catalog uses English fallback');
+// Keep fallback coverage even after all shipped locales gain the new key.
+assert.equal(text('missing', {}, { ...catalogs, missing: {} }), 'No backup archives found.');
+for (const locale of Object.keys(catalogs)) {
+ // Existing catalogs intentionally have no new key; actual provider falls back.
+ if (catalogs[locale].backup?.archives?.emptyMessage === undefined) {
+ assert.equal(text(locale), 'No backup archives found.', `${locale}: missing-key fallback`);
+ }
+}
+for (const count of [1, 3]) assert.equal(text('en', { unifiedArchives: Array(count).fill({}) }), 'NONEMPTY_ARCHIVES');
+assert.equal(text('en', { archivesResp: undefined, remoteArchivesResp: undefined }), translator('en')('backup.common.loading'));
+assert.equal(text('en', { archivesErr: true, remoteArchivesErr: true }), translator('en')('backup.archives.loadFailed'));
+// Preserve existing partial-source semantics; no claim that every source was queried.
+assert.equal(text('en', { archivesErr: true, archivesResp: undefined }), 'No backup archives found.');
+assert.equal(text('en', { remoteArchivesErr: true, remoteArchivesResp: undefined }), 'No backup archives found.');
+assert.equal(translator('en')('backup.manual.run'), 'Run');
+assert.ok(read('components/host-backup.tsx').includes('{t("backup.manual.run")}'), 'manual action remains');
+console.log('PASS: actual archives JSX seam, zero/one/multiple, loading/errors, locale fallback, Run unchanged');
+// Export only test seams for separate, unapplied linguistic proposal checks.
+module.exports = { text, translator, catalogs };
diff --git a/tests/test_backup_destination_messages.cjs b/tests/test_backup_destination_messages.cjs
new file mode 100644
index 00000000..c1cc8e92
--- /dev/null
+++ b/tests/test_backup_destination_messages.cjs
@@ -0,0 +1,56 @@
+// Offline actual JSX/provider seams; no component/backend imports or effects.
+const assert = require('node:assert/strict');
+const fs = require('node:fs');
+const path = require('node:path');
+const { createRequire } = require('node:module');
+const { translator, catalogs } = require('./test_backup_archives_empty.cjs');
+const app = path.resolve(__dirname, '../AppImage');
+const ts = createRequire(path.join(app, 'package.json'))('typescript');
+const source = ts.createSourceFile('host-backup.tsx', fs.readFileSync(path.join(app, 'components/host-backup.tsx'), 'utf8'), ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
+const printer = ts.createPrinter();
+const React = { createElement: (tag, props, ...children) => children.flat(Infinity).filter(x => x != null && x !== false).join('') };
+function find(predicate) {
+ const found = [];
+ function visit(node) { if (predicate(node)) found.push(node); ts.forEachChild(node, visit); }
+ visit(source);
+ assert.equal(found.length, 1, 'unique actual message seam');
+ return found[0];
+}
+function render(node, locale, backups = 1, messages = catalogs) {
+ const code = ts.transpileModule(`const result = ${printer.printNode(ts.EmitHint.Expression, node, source)};`, {
+ compilerOptions: { target: ts.ScriptTarget.ES2020, jsx: ts.JsxEmit.React },
+ }).outputText;
+ // Only trusted checked-out AST enters executable code, never catalog values.
+ return new Function('React', 't', 'backups', code + '\nreturn result;')(React, translator(locale, messages), backups);
+}
+const kept = find(node => ts.isBinaryExpression(node) && node.left.getText(source) === 'backups > 0');
+const keptMessage = 'Existing backup archives are not deleted.';
+for (const count of [1, 3]) assert.equal(render(kept, 'it', count), keptMessage, 'Italian catalog uses English fallback');
+assert.equal(render(kept, 'en', 0), false);
+for (const locale of Object.keys(catalogs)) {
+ if (catalogs[locale].backup?.destinations?.backupsKeptMessage !== undefined && locale !== 'en') continue;
+ for (const count of [1, 3]) assert.equal(render(kept, locale, count), keptMessage, `${locale}: kept whole-message fallback`);
+}
+console.log('PASS: destination removal JSX guard 0/1/N and whole-message locale fallback');
+// Select the actual help paragraph, keeping its literal paths/JSX whitespace.
+const help = find(node => ts.isJsxElement(node) && node.openingElement.tagName.getText(source) === 'p' &&
+ /backup\.destinations\.localAttachHelp(?:Before|Message)/.test(node.getText(source)));
+const helpMessage = 'Mount USB drives first. Leave blank to use the PVE storage path + /dump (fallback: /var/lib/vz/dump).';
+assert.equal(render(help, 'it'), helpMessage, 'Italian catalog uses English fallback');
+for (const locale of Object.keys(catalogs)) {
+ if (catalogs[locale].backup?.destinations?.localAttachHelpMessage !== undefined && locale !== 'en') continue;
+ assert.equal(render(help, locale), helpMessage, `${locale}: local attach help fallback`);
+}
+// Missing-key fallback must remain covered after shipped catalogs are complete.
+const missing = { ...catalogs, missing: {} };
+assert.equal(render(kept, 'missing', 1, missing), keptMessage);
+assert.equal(render(help, 'missing', 1, missing), helpMessage);
+// Synthetic locale proves complete messages are translatable, not hardcoded.
+const synthetic = { ...catalogs, fixture: { backup: { destinations: {
+ backupsKeptMessage: 'Fixture kept.', localAttachHelpMessage: 'Fixture help.',
+} } } };
+assert.equal(render(kept, 'fixture', 1, synthetic), 'Fixture kept.');
+assert.equal(render(help, 'fixture', 1, synthetic), 'Fixture help.');
+assert.equal(catalogs.en.backup.destinations.kept, 'kept');
+assert.equal(catalogs.en.backup.destinations.localAttachHelpMiddle, 'USB drives');
+console.log('PASS: local attach JSX whole-message fallback and literal paths');
From db8cc2267aeac1808e448456eed154ab0c66b29b Mon Sep 17 00:00:00 2001
From: martino <32328813+f3rs3n@users.noreply.github.com>
Date: Mon, 21 Sep 2026 20:37:01 +0200
Subject: [PATCH 2/4] fix(tui): use complete messages for device, path and
package counts
---
scripts/backup_restore/backup_host.sh | 14 +-
scripts/storage/add_controller_nvme_vm.sh | 9 +-
tests/test_tui_count_messages.py | 206 ++++++++++++++++++++++
3 files changed, 226 insertions(+), 3 deletions(-)
create mode 100644 tests/test_tui_count_messages.py
diff --git a/scripts/backup_restore/backup_host.sh b/scripts/backup_restore/backup_host.sh
index f86783ad..35b82d60 100755
--- a/scripts/backup_restore/backup_host.sh
+++ b/scripts/backup_restore/backup_host.sh
@@ -919,7 +919,11 @@ _bk_manage_extra_paths() {
if (( count == 0 )); then
preview="$(hb_translate "You haven't added any custom paths yet.")"
else
- preview="$(hb_translate "Currently"): \Zb\Z4${count}\Zn $(hb_translate "custom path(s) saved.")"
+ preview="$(hb_translate "Custom paths currently saved: {count}.")"
+ if [[ "$preview" != *'{count}'* ]]; then
+ preview="Custom paths currently saved: {count}."
+ fi
+ preview="${preview//\{count\}/"\Zb\Z4${count}\Zn"}"
fi
preview+=$'\n\n'"$(hb_translate "Custom paths are included in BOTH default and custom backup profiles.")"
@@ -3878,7 +3882,13 @@ _rs_run_complete_extras() {
"${installable[@]}" >>"$apt_log" 2>&1
local apt_rc=$?
if (( apt_rc == 0 )); then
- msg_ok "$(translate "Installed:") ${#installable[@]} $(translate "packages.")"
+ local installed_message
+ installed_message="$(translate "Packages installed: {count}.")"
+ if [[ "$installed_message" != *'{count}'* ]]; then
+ installed_message="Packages installed: {count}."
+ fi
+ installed_message="${installed_message//\{count\}/${#installable[@]}}"
+ msg_ok "$installed_message"
else
msg_warn "$(translate "apt-get exited") ${apt_rc} — $(translate "see log:") $apt_log"
fi
diff --git a/scripts/storage/add_controller_nvme_vm.sh b/scripts/storage/add_controller_nvme_vm.sh
index d249bd17..b8e8186f 100644
--- a/scripts/storage/add_controller_nvme_vm.sh
+++ b/scripts/storage/add_controller_nvme_vm.sh
@@ -694,7 +694,14 @@ apply_assignment() {
echo -e "${TAB}${BL}Log: ${LOG_FILE}${CL}"
if [[ "$assigned_count" -gt 0 ]]; then
- msg_ok "$(translate "Completed.") $assigned_count $(translate "device(s) added to VM") ${SELECTED_VMID}."
+ local completed_message
+ completed_message="$(translate "Completed. Devices added to VM {vmid}: {count}.")"
+ if [[ "$completed_message" != *'{vmid}'* || "$completed_message" != *'{count}'* ]]; then
+ completed_message="Completed. Devices added to VM {vmid}: {count}."
+ fi
+ completed_message="${completed_message//\{vmid\}/$SELECTED_VMID}"
+ completed_message="${completed_message//\{count\}/$assigned_count}"
+ msg_ok "$completed_message"
else
msg_warn "$(translate "No new Controller/NVMe entries were added.")"
fi
diff --git a/tests/test_tui_count_messages.py b/tests/test_tui_count_messages.py
new file mode 100644
index 00000000..2335aaa6
--- /dev/null
+++ b/tests/test_tui_count_messages.py
@@ -0,0 +1,206 @@
+"""Offline message seams: no full administrative script is sourced or run.
+
+Run: python3 -m unittest discover -s tests -p test_tui_count_messages.py -v
+Requires Bash and jq. Only extracted translation functions and bounded message
+consumers execute. PATH contains jq only; VM/disk/backup commands are unavailable.
+"""
+import importlib.util
+import json
+from pathlib import Path
+import re
+import shutil
+import subprocess
+import tempfile
+import unittest
+
+ROOT = Path(__file__).resolve().parents[1]
+VM = "scripts/storage/add_controller_nvme_vm.sh"
+BACKUP = "scripts/backup_restore/backup_host.sh"
+
+
+def between(path, start, end):
+ text = (ROOT / path).read_text()
+ assert text.count(start) == 1, (path, start)
+ tail = text.split(start, 1)[1]
+ assert end in tail, (path, end)
+ return start + tail.split(end, 1)[0]
+
+
+def function(path, name):
+ # These two small functions have no unindented nested closing braces.
+ text = (ROOT / path).read_text()
+ match = re.search(r"^" + re.escape(name) + r"\(\) \{\n.*?^\}", text, re.M | re.S)
+ assert match, (path, name)
+ return match[0]
+
+
+def lookup(catalog, text):
+ return (catalog or {}).get(text) or text
+
+
+class CountMessages(unittest.TestCase):
+ def locales(self, key, translated):
+ return (("en", None), ("it", {}), ("zz", None),
+ ("it", json.loads((ROOT / "lang/it.json").read_text())),
+ ("xx", {key: translated}),
+ # Presence is the bounded contract: repeated tokens are replaced
+ # everywhere; unrelated braces remain literal, not a format DSL.
+ ("repeat", {key: translated + " / again " + key}),
+ ("extra", {key: translated + " / {unknown} $(literal) %s"})
+ ) + self.malformed_locales(key)
+
+ def malformed_locales(self, key):
+ required = ("{count}", "{vmid}") if "{vmid}" in key else ("{count}",)
+ # These cached values must fall back as a whole, not lose a value.
+ malformed = ["Translated without values."]
+ for token in required:
+ malformed.extend((key.replace(token, ""),
+ key.replace(token, "{renamed}"),
+ key.replace(token, token.upper())))
+ return tuple(("bad", {key: text}) for text in malformed)
+
+ def test_new_messages_are_discovered_by_cache_builder(self):
+ spec = importlib.util.spec_from_file_location(
+ "translation_cache", ROOT / ".github/scripts/build_translation_cache.py")
+ module = importlib.util.module_from_spec(spec)
+ spec.loader.exec_module(module)
+ keys = module.extract_translate_texts(ROOT / "scripts")
+ for key in ("Completed. Devices added to VM {vmid}: {count}.",
+ "Custom paths currently saved: {count}.", "Packages installed: {count}."):
+ self.assertIn(key, keys)
+
+ def render(self, seam, setup, language="en", catalog=None):
+ jq = shutil.which("jq")
+ self.assertIsNotNone(jq, "jq is required for actual translation lookup")
+ with tempfile.TemporaryDirectory(prefix="pmx-count-messages-") as tmp:
+ tmp = Path(tmp)
+ (tmp / "bin").mkdir()
+ (tmp / "bin" / "jq").symlink_to(jq)
+ (tmp / "lang").mkdir()
+ if catalog is not None:
+ (tmp / "lang" / f"{language}.json").write_text(json.dumps(catalog))
+ shell = function("scripts/utils.sh", "translate") + "\n"
+ shell += function("scripts/backup_restore/lib_host_backup_common.sh", "hb_translate")
+ shell += '''
+msg_ok() { printf 'OK:%s\\n' "$1"; }
+msg_warn() { printf 'WARN:%s\\n' "$1"; }
+consumer() {
+'''
+ shell += setup + "\n" + seam + "\n}\nconsumer\n"
+ env = {"PATH": str(tmp / "bin"), "LANGUAGE": language,
+ "LANG_DIR": str(tmp / "lang"), "LC_ALL": "C"}
+ result = subprocess.run(["/bin/bash", "--noprofile", "--norc", "-c", shell],
+ env=env, text=True, capture_output=True, timeout=10)
+ self.assertEqual(result.returncode, 0, result.stderr)
+ self.assertEqual(result.stderr, "")
+ return result.stdout.rstrip("\n")
+
+ def test_vm_devices_zero_one_many_and_translation(self):
+ seam = between(VM, ' if [[ "$assigned_count" -gt 0 ]]; then',
+ ' if [[ "${IOMMU_ALREADY_ACTIVE:-0}" == "1" ]]; then')
+ key = "Completed. Devices added to VM {vmid}: {count}."
+ translated = "Devices: {count} / VM {vmid} / done 100%."
+ for count in (0, 1, 3):
+ for vmid in (101, 987654):
+ for language, catalog in self.locales(key, translated):
+ with self.subTest(count=count, vmid=vmid, language=language):
+ actual = self.render(seam, f"assigned_count={count}; SELECTED_VMID={vmid}",
+ language, catalog)
+ if count == 0:
+ expected = "WARN:" + lookup(catalog, "No new Controller/NVMe entries were added.")
+ elif language == "xx":
+ expected = f"OK:Devices: {count} / VM {vmid} / done 100%."
+ elif language == "bad":
+ expected = f"OK:Completed. Devices added to VM {vmid}: {count}."
+ else:
+ expected = "OK:" + lookup(catalog, key).replace("{vmid}", str(vmid)).replace("{count}", str(count))
+ self.assertEqual(actual, expected)
+
+ def test_vm_summary_counts_successful_new_assignments_only(self):
+ seam = between(VM, ' local pci bdf assigned_count=0',
+ ' if [[ "${IOMMU_ALREADY_ACTIVE:-0}" == "1" ]]; then')
+ for devices, expected_count in (([], 0), (["ok1"], 1),
+ (["ok1", "ok2", "ok3"], 3),
+ (["existing", "failed"], 0),
+ (["existing", "ok1", "failed", "ok2"], 2)):
+ with self.subTest(devices=devices):
+ setup = 'SELECTED_CONTROLLER_PCIS=(' + ' '.join(devices) + ')\n'
+ setup += '''SELECTED_VMID=101; hostpci_idx=0; LOG_FILE="$LANG_DIR/vm.log"
+msg_info() { :; }
+msg_error() { printf 'ERROR:%s\\n' "$1"; }
+_pci_function_assigned_to_vm() { [[ "$1" == existing ]]; }
+_pci_storage_display_name() { printf '%s' "$1"; }
+qm() {
+ [[ "$1 $2" == 'set 101' && "$3" == "--hostpci${hostpci_idx}" ]] || return 99
+ [[ "$4" != 'failed,pcie=1' ]]
+}
+'''
+ actual = self.render(seam, setup).splitlines()[-1]
+ expected = (f"OK:Completed. Devices added to VM 101: {expected_count}." if expected_count
+ else "WARN:No new Controller/NVMe entries were added.")
+ self.assertEqual(actual, expected)
+
+ def test_custom_paths_zero_one_many_and_translation(self):
+ seam = between(BACKUP, ' local -a paths=()', ' local choice')
+ seam += '\n printf "%s" "$preview"\n'
+ key = "Custom paths currently saved: {count}."
+ translated = "Saved 100%: {count} custom paths."
+ suffix = "Custom paths are included in BOTH default and custom backup profiles."
+ for count in (0, 1, 3):
+ setup = 'hb_load_extra_paths() {\n'
+ setup += ''.join(f"printf '%s\\n' '/fixture/path {i}'\n" for i in range(count))
+ setup += ':;\n}\n'
+ for language, catalog in self.locales(key, translated):
+ with self.subTest(count=count, language=language):
+ actual = self.render(seam, setup, language, catalog)
+ colored_count = rf"\Zb\Z4{count}\Zn"
+ if count == 0:
+ expected = lookup(catalog, "You haven't added any custom paths yet.")
+ elif language == "xx":
+ expected = f"Saved 100%: {colored_count} custom paths."
+ elif language == "bad":
+ expected = f"Custom paths currently saved: {colored_count}."
+ else:
+ expected = lookup(catalog, key).replace("{count}", colored_count)
+ self.assertEqual(actual, expected + "\n\n" + lookup(catalog, suffix))
+
+ def test_installed_packages_zero_one_many_success_and_failure(self):
+ # Keep the actual nonempty guard and apt return-code consumer; omit
+ # unrelated preview/cache/log setup. apt-get is a function stub only.
+ guard = ' if (( ${#installable[@]} > 0 )); then\n'
+ self.assertEqual((ROOT / BACKUP).read_text().count(guard), 1)
+ seam = guard + between(BACKUP, ' DEBIAN_FRONTEND=noninteractive \\\n',
+ ' if (( ${#unknown[@]} > 0 )); then')
+ key = "Packages installed: {count}."
+ translated = "Done 100% / {count} installed packages."
+ for count in (0, 1, 3):
+ for status in (0, 100):
+ for language, catalog in self.locales(key, translated):
+ with self.subTest(count=count, status=status, language=language):
+ setup = f'installable=({" ".join("pkg" + str(i) for i in range(count))}); apt_status={status}\n'
+ setup += '''apt_log="$LANG_DIR/apt.log"
+apt-get() {
+ [[ "$DEBIAN_FRONTEND" == noninteractive ]] || return 99
+ [[ "$1 $2 $3 $4 $5 $6" == 'install -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confold' ]] || return 99
+ shift 6
+ [[ "$*" == "${installable[*]}" ]] || return 99
+ printf 'CALLED\\n' > "$LANG_DIR/calls"
+ return "$apt_status"
+}
+'''
+ check_call = '\nif [[ -f "$LANG_DIR/calls" ]]; then printf "CALLED\\n"; fi\n'
+ actual = self.render(seam + check_call, setup, language, catalog)
+ if count == 0:
+ self.assertEqual(actual, "")
+ elif status:
+ prefix = "WARN:" + lookup(catalog, "apt-get exited") + " 100 — " + lookup(catalog, "see log:")
+ self.assertRegex(actual, "^" + re.escape(prefix) + r" .*/lang/apt.log\nCALLED$")
+ else:
+ message = (f"Done 100% / {count} installed packages." if language == "xx"
+ else f"Packages installed: {count}." if language == "bad"
+ else lookup(catalog, key).replace("{count}", str(count)))
+ self.assertEqual(actual, f"OK:{message}\nCALLED")
+
+
+if __name__ == "__main__":
+ unittest.main()
From 4d4828e7c853f1498d7e72ea76b7110855072cc8 Mon Sep 17 00:00:00 2001
From: ProxMenuxBot
Date: Tue, 22 Sep 2026 14:40:45 +0000
Subject: [PATCH 3/4] chore(i18n): auto-fill missing translations in
messages/{locale}/common.json
Source: 3b18e3e
Triggered by: push
---
AppImage/messages/de/common.json | 7 +-
AppImage/messages/es/common.json | 7 +-
AppImage/messages/fr/common.json | 7 +-
AppImage/messages/it/common.json | 7 +-
AppImage/messages/pt/common.json | 7 +-
AppImage/messages/sk/common.json | 740 ++++++++++++++++++++++++++++++-
AppImage/messages/sv/common.json | 7 +-
7 files changed, 767 insertions(+), 15 deletions(-)
diff --git a/AppImage/messages/de/common.json b/AppImage/messages/de/common.json
index 84272238..bda71206 100644
--- a/AppImage/messages/de/common.json
+++ b/AppImage/messages/de/common.json
@@ -3845,7 +3845,8 @@
"restoreTitle": "Von diesem Backup wiederherstellen",
"startingExport": "Download wird vorbereitet...",
"title": "Backups",
- "viewContentsTitle": "Sicherungsinhalte anzeigen"
+ "viewContentsTitle": "Sicherungsinhalte anzeigen",
+ "emptyMessage": "Keine Sicherungsarchive gefunden."
},
"backends": {
"borgDescription": "Borg-Repository für deduplizierte Host-Backups.",
@@ -3961,7 +3962,9 @@
"sshUserHelpBefore": "Benutzer auf dem Remote-Host,",
"title": "Reiseziele",
"unmountTitle": "Hängen Sie dieses Ziel aus",
- "whereIsBorgRepo": "Wo ist das Borg-Repository?"
+ "whereIsBorgRepo": "Wo ist das Borg-Repository?",
+ "backupsKeptMessage": "Vorhandene Backup-Archive werden nicht gelöscht.",
+ "localAttachHelpMessage": "Mounten Sie zuerst USB-Laufwerke.Lassen Sie das Feld leer, um den PVE-Speicherpfad + /dump zu verwenden (Fallback: /var/lib/vz/dump)."
},
"encryption": {
"autoDetectedFromPveStorage": "Aus PVE-Speicher erkannt",
diff --git a/AppImage/messages/es/common.json b/AppImage/messages/es/common.json
index bd81573b..3d66d6c2 100644
--- a/AppImage/messages/es/common.json
+++ b/AppImage/messages/es/common.json
@@ -3845,7 +3845,8 @@
"restoreTitle": "Restaurar desde esta copia de seguridad",
"startingExport": "Preparando descarga...",
"title": "Copias de seguridad",
- "viewContentsTitle": "Ver contenidos de la copia de seguridad"
+ "viewContentsTitle": "Ver contenidos de la copia de seguridad",
+ "emptyMessage": "No se encontraron archivos de respaldo."
},
"backends": {
"borgDescription": "Repositorio Borg para copias de seguridad de host deduplicadas.",
@@ -3961,7 +3962,9 @@
"sshUserHelpBefore": "Usuario en el host remoto,",
"title": "Destinos",
"unmountTitle": "Desmontar este destino",
- "whereIsBorgRepo": "¿Dónde está el repositorio Borg?"
+ "whereIsBorgRepo": "¿Dónde está el repositorio Borg?",
+ "backupsKeptMessage": "los archivos de copia de seguridad existentes no se eliminan.",
+ "localAttachHelpMessage": "Monte primero las unidades USB.Déjelo en blanco para usar la ruta de almacenamiento PVE + /dump (alternativa: /var/lib/vz/dump)."
},
"encryption": {
"autoDetectedFromPveStorage": "Detectado desde el almacenamiento PVE",
diff --git a/AppImage/messages/fr/common.json b/AppImage/messages/fr/common.json
index b3169f51..c27ad791 100644
--- a/AppImage/messages/fr/common.json
+++ b/AppImage/messages/fr/common.json
@@ -3845,7 +3845,8 @@
"restoreTitle": "Restaurer à partir de cette sauvegarde",
"startingExport": "Préparation du téléchargement...",
"title": "Sauvegardes",
- "viewContentsTitle": "Afficher le contenu de la sauvegarde"
+ "viewContentsTitle": "Afficher le contenu de la sauvegarde",
+ "emptyMessage": "Aucune archive de sauvegarde trouvée."
},
"backends": {
"borgDescription": "Référentiel Borg pour les sauvegardes d'hôtes dédupliquées.",
@@ -3961,7 +3962,9 @@
"sshUserHelpBefore": "Utilisateur sur l'hôte distant,",
"title": "Destinations",
"unmountTitle": "Démonter cette destination",
- "whereIsBorgRepo": "Où se trouve le référentiel Borg ?"
+ "whereIsBorgRepo": "Où se trouve le référentiel Borg ?",
+ "backupsKeptMessage": "Les archives de sauvegarde existantes ne sont pas supprimées.",
+ "localAttachHelpMessage": "Montez d’abord les clés USB.Laissez vide pour utiliser le chemin de stockage PVE + /dump (repli : /var/lib/vz/dump)."
},
"encryption": {
"autoDetectedFromPveStorage": "Détecté depuis le stockage PVE",
diff --git a/AppImage/messages/it/common.json b/AppImage/messages/it/common.json
index eaab50b4..c812e8ca 100644
--- a/AppImage/messages/it/common.json
+++ b/AppImage/messages/it/common.json
@@ -3845,7 +3845,8 @@
"restoreTitle": "Ripristina da questo backup",
"startingExport": "Preparazione download...",
"title": "Backup",
- "viewContentsTitle": "Visualizza i contenuti del backup"
+ "viewContentsTitle": "Visualizza i contenuti del backup",
+ "emptyMessage": "nessun archivio di backup trovato."
},
"backends": {
"borgDescription": "Repository Borg per backup host deduplicati.",
@@ -3961,7 +3962,9 @@
"sshUserHelpBefore": "Utente sull'host remoto,",
"title": "Destinazioni",
"unmountTitle": "Smonta questa destinazione",
- "whereIsBorgRepo": "Dov'è il deposito Borg?"
+ "whereIsBorgRepo": "Dov'è il deposito Borg?",
+ "backupsKeptMessage": "gli archivi di backup esistenti non vengono eliminati.",
+ "localAttachHelpMessage": "monta prima le unità USB.Lascia vuoto per utilizzare il percorso di archiviazione PVE + /dump (fallback: /var/lib/vz/dump)."
},
"encryption": {
"autoDetectedFromPveStorage": "Rilevato dall'archivio PVE",
diff --git a/AppImage/messages/pt/common.json b/AppImage/messages/pt/common.json
index 13f1e7de..c54ed25c 100644
--- a/AppImage/messages/pt/common.json
+++ b/AppImage/messages/pt/common.json
@@ -3845,7 +3845,8 @@
"restoreTitle": "Restaurar deste backup",
"startingExport": "Preparando download...",
"title": "Cópias de segurança",
- "viewContentsTitle": "Ver o conteúdo do backup"
+ "viewContentsTitle": "Ver o conteúdo do backup",
+ "emptyMessage": "Nenhum arquivo de backup encontrado."
},
"backends": {
"borgDescription": "Repositório Borg para backups de host desduplicados.",
@@ -3961,7 +3962,9 @@
"sshUserHelpBefore": "Usuário no host remoto,",
"title": "Destinos",
"unmountTitle": "Desmontar este destino",
- "whereIsBorgRepo": "Onde está o repositório Borg?"
+ "whereIsBorgRepo": "Onde está o repositório Borg?",
+ "backupsKeptMessage": "os arquivos de backup existentes não são excluídos.",
+ "localAttachHelpMessage": "Monte as unidades USB primeiro.Deixe em branco para usar o caminho de armazenamento PVE + /dump (fallback: /var/lib/vz/dump)."
},
"encryption": {
"autoDetectedFromPveStorage": "Detectado no armazenamento PVE",
diff --git a/AppImage/messages/sk/common.json b/AppImage/messages/sk/common.json
index 64ed0903..b241c561 100644
--- a/AppImage/messages/sk/common.json
+++ b/AppImage/messages/sk/common.json
@@ -3844,7 +3844,8 @@
"restoreTitle": "Obnoviť z tejto zálohy",
"startingExport": "Pripravujem stiahnutie...",
"title": "Zálohy",
- "viewContentsTitle": "Zobraziť obsah zálohy"
+ "viewContentsTitle": "Zobraziť obsah zálohy",
+ "emptyMessage": "Nenašli sa žiadne zálohy."
},
"backends": {
"borgDescription": "Borg repozitár pre deduplikované zálohy servera.",
@@ -3960,7 +3961,9 @@
"sshUserHelpBefore": "Používateľ na vzdialenom serveri,",
"title": "Ciele",
"unmountTitle": "Odpojiť tento cieľ",
- "whereIsBorgRepo": "Kde je Borg repozitár?"
+ "whereIsBorgRepo": "Kde je Borg repozitár?",
+ "backupsKeptMessage": "Existujúce zálohy sa neodstránia.",
+ "localAttachHelpMessage": "Najprv pripojte jednotky USB.Ak chcete použiť cestu k úložisku PVE + /dump, nechajte pole prázdne (záložný: /var/lib/vz/dump)."
},
"encryption": {
"autoDetectedFromPveStorage": "Zistené z PVE úložiska",
@@ -6095,5 +6098,736 @@
"cancel": "Zrušiť"
}
},
- "runtime": {"notifications":{"templates":{"state_change":{"title":"{hostname}: {category} sa zmenilo na {current}{entity_suffix}","body":"Stav kategórie {category} sa zmenil z {previous} na {current}.\n{reason}","label":"Zmena stavu kontroly"},"new_error":{"title":"{hostname}: Nový {severity} - {category}{entity_suffix}","body":"{reason}","label":"Nový problém so stavom"},"error_resolved":{"title":"{hostname}: Vyriešené - {category}{entity_suffix}","body":"Problém v kategórii {category} bol vyriešený.\n{reason}\n🚦 Predchádzajúca závažnosť: {original_severity}\n⏱️ Trvanie: {duration}","label":"Problém bol vyriešený"},"error_escalated":{"title":"{hostname}: Zvýšené na {severity} - {category}{entity_suffix}","body":"{reason}","label":"Problém sa zhoršil"},"health_degraded":{"title":"{title_or_default}","body":"{reason}","label":"Zhoršený stav kontroly"},"lxc_updates_available":{"title":"{hostname}: Aktualizácie balíkov sú dostupné pre {count} LXC","body":"📊 Čakajúce aktualizácie balíkov má {count} LXC (📦 spolu {total_packages}, 🔒 bezpečnostné {security_count}):\n\n{ct_list}","label":"Dostupné aktualizácie LXC (experimentálne)"},"lxc_update_applied":{"title":"{hostname}: LXC {ct_name} ({vmid}) aktualizácia {result}","body":"{details}","label":"Aktualizácia LXC použitá"},"app_update_available":{"title":"{hostname}: Pre {app_name} je na CT {vmid} dostupná aktualizácia","body":"Aplikácia {app_name} na CT {vmid} ({ct_name}) má novú verziu:\n {installed} → {latest}","label":"K dispozícii je aktualizácia aplikácie"},"docker_stack_update_available":{"title":"{hostname}: Na CT {vmid} sú dostupné aktualizácie Docker","body":"Kontajner {ct_name} (CT {vmid}) má {count} aktualizácií Docker:\n{details}","label":"Dostupné aktualizácie Docker"},"vm_start":{"title":"{hostname}: VM {vmname} ({vmid}) spustený","body":"Virtuálny stroj {vmname} (ID: {vmid}) je spustený.","label":"VM bola spustená"},"vm_start_warning":{"title":"{hostname}: VM {vmname} ({vmid}) spustený s upozorneniami","body":"Virtuálny stroj {vmname} (ID: {vmid}) sa úspešne spustil, ale obsahuje upozornenia.\nUpozornenia: {reason}","label":"VM bola spustená s upozorneniami"},"vm_stop":{"title":"{hostname}: VM {vmname} ({vmid}) zastavený","body":"Virtuálny stroj {vmname} (ID: {vmid}) bol zastavený.","label":"VM bola zastavená"},"vm_shutdown":{"title":"{hostname}: VM {vmname} ({vmid}) vypnutý","body":"Virtuálny stroj {vmname} (ID: {vmid}) bol korektne vypnutý.","label":"VM bola vypnutá"},"vm_fail":{"title":"{hostname}: VM {vmname} ({vmid}) ZLYHAL","body":"Virtuálny stroj {vmname} (ID: {vmid}) zlyhal alebo sa ho nepodarilo spustiť.\nDôvod: {reason}","label":"Spustenie VM zlyhalo"},"vm_restart":{"title":"{hostname}: VM {vmname} ({vmid}) reštartovaný","body":"Virtuálny stroj {vmname} (ID: {vmid}) bol reštartovaný.","label":"VM bola reštartovaná"},"ct_start":{"title":"{hostname}: CT {vmname} ({vmid}) spustený","body":"Kontajner {vmname} (ID: {vmid}) je spustený.","label":"Kontajner bol spustený"},"ct_start_warning":{"title":"{hostname}: CT {vmname} ({vmid}) spustený s upozorneniami","body":"Kontajner {vmname} (ID: {vmid}) sa úspešne spustil, ale obsahuje upozornenia.\nUpozornenia: {reason}","label":"Kontajner bol spustený s upozorneniami"},"ct_stop":{"title":"{hostname}: CT {vmname} ({vmid}) zastavený","body":"Kontajner {vmname} (ID: {vmid}) bol zastavený.","label":"Kontajner bol zastavený"},"ct_shutdown":{"title":"{hostname}: CT {vmname} ({vmid}) vypnutý","body":"Kontajner {vmname} (ID: {vmid}) bol korektne vypnutý.","label":"Kontajner bol vypnutý"},"ct_restart":{"title":"{hostname}: CT {vmname} ({vmid}) reštartovaný","body":"Kontajner {vmname} (ID: {vmid}) bol reštartovaný.","label":"Kontajner bol reštartovaný"},"ct_fail":{"title":"{hostname}: CT {vmname} ({vmid}) ZLYHAL","body":"Kontajner {vmname} (ID: {vmid}) zlyhal alebo sa ho nepodarilo spustiť.\nDôvod: {reason}","label":"Spustenie kontajnera zlyhalo"},"migration_start":{"title":"{hostname}: Migrácia spustená — {vmname} ({vmid})","body":"Živá migrácia VM alebo LXC {vmname} (ID: {vmid}) na uzol {target_node} sa začala.","label":"Migrácia sa začala"},"migration_complete":{"title":"{hostname}: Migrácia dokončená — {vmname} ({vmid})","body":"{vmname} (ID: {vmid}) bol úspešne presunutý na uzol {target_node}.","label":"Migrácia bola dokončená"},"migration_warning":{"title":"{hostname}: Migrácia dokončená s upozorneniami — {vmname} ({vmid})","body":"VM alebo LXC {vmname} (ID: {vmid}) bol presunutý na uzol {target_node}, ale vyskytli sa upozornenia.\nUpozornenia: {reason}","label":"Migrácia skončila s upozorneniami"},"migration_fail":{"title":"{hostname}: Migrácia ZLYHALA — {vmname} ({vmid})","body":"Migrácia VM alebo LXC {vmname} (ID: {vmid}) na uzol {target_node} zlyhala.\nDôvod: {reason}","label":"Migrácia zlyhala"},"replication_fail":{"title":"{hostname}: Replikácia ZLYHALA — {vmname} ({vmid})","body":"Replikácia VM alebo LXC {vmname} (ID: {vmid}) zlyhala.\nDôvod: {reason}","label":"Replikácia zlyhala"},"replication_complete":{"title":"{hostname}: Replikácia dokončená — {vmname} ({vmid})","body":"Replikácia VM alebo LXC {vmname} (ID: {vmid}) bola úspešne dokončená.","label":"Replikácia bola dokončená"},"backup_start":{"title":"{hostname}: Záloha na úložisko {storage} spustená","body":"Úloha zálohovania na úložisko {storage} sa začala.\n{reason}","label":"Zálohovanie sa začalo"},"backup_complete":{"title":"{hostname} → {storage}: Záloha dokončená — {vmname} ({vmid})","body":"Záloha {vmname} (ID: {vmid}) na úložisku {storage} bola úspešne dokončená.\nVeľkosť: {size}","label":"Záloha bola dokončená"},"backup_warning":{"title":"{hostname} → {storage}: Záloha dokončená s upozorneniami — {vmname} ({vmid})","body":"Záloha {vmname} (ID: {vmid}) na úložisku {storage} bola dokončená, ale vyskytli sa upozornenia.\nUpozornenia: {reason}","label":"Záloha skončila s upozorneniami"},"backup_fail":{"title":"{hostname} → {storage}: Záloha ZLYHALA — {vmname} ({vmid})","body":"Záloha {vmname} (ID: {vmid}) na úložisku {storage} zlyhala.\nDôvod: {reason}","label":"Zálohovanie zlyhalo"},"host_backup_start":{"title":"{hostname}: Záloha servera spustená → {backend_label}","body":"Úloha: {job_id}\nBackend: {backend_label}\nCieľ: {destination}\nProfil: {profile_mode}","label":"Zálohovanie servera sa začalo"},"host_backup_complete":{"title":"{hostname}: Záloha servera dokončená → {backend_label}","body":"Úloha: {job_id}\nBackend: {backend_label}\nCieľ: {destination}\nVeľkosť dát: {data_size}\nVeľkosť archívu: {archive_size}\nTrvanie: {duration}","label":"Záloha servera bola dokončená"},"host_backup_fail":{"title":"{hostname}: Záloha servera ZLYHALA → {backend_label}","body":"Úloha: {job_id}\nBackend: {backend_label}\nCieľ: {destination}\nTrvanie pred zlyhaním: {duration}\nDôvod: {reason}\nZáznam: {log_file}","label":"Zálohovanie servera zlyhalo"},"snapshot_complete":{"title":"{hostname}: Snímka vytvorená — {vmname} ({vmid})","body":"Snímka „{snapshot_name}“ bola vytvorená pre {vmname} (ID: {vmid}).","label":"Snapshot bol vytvorený"},"snapshot_fail":{"title":"{hostname}: Vytvorenie snímky ZLYHALO — {vmname} ({vmid})","body":"Vytvorenie snímky pre {vmname} (ID: {vmid}) zlyhalo.\nDôvod: {reason}","label":"Vytvorenie snapshotu zlyhalo"},"cpu_high":{"title":"{hostname}: Vysoké využitie CPU — {value}%","body":"Využitie CPU dosiahlo {value}% na {cores} jadrách.\n{details}","label":"Vysoké využitie CPU"},"ram_high":{"title":"{hostname}: Vysoké využitie pamäte — {value}%","body":"Využitie pamäte: {used} / {total} ({value}%).\n{details}","label":"Vysoké využitie pamäte"},"temp_high":{"title":"{hostname}: Vysoká teplota CPU — {value}°C","body":"Teplota CPU dosiahla {value}°C (prahová hodnota: {threshold}°C).\n{details}","label":"Vysoká teplota"},"disk_space_low":{"title":"{hostname}: Málo miesta na disku {mount}","body":"Súborový systém {mount}: {used}% využité ({available} voľných).\nUvoľnite miesto na disku, aby ste predišli výpadku služieb.","label":"Málo miesta na disku"},"disk_io_error":{"title":"{hostname}: Zistené zlyhanie disku — {device}","body":"Na zariadení bola zistená chyba I/O alebo zlyhanie disku {device}.\n{reason}","label":"Chyba disku alebo I/O"},"storage_unavailable":{"title":"{hostname}: Úložisko nedostupné — {storage_name}","body":"Úložisko PVE „{storage_name}“ (typ: {storage_type}) nie je dostupné.\nDôvod: {reason}","label":"Úložisko nie je dostupné"},"smart_test_complete":{"title":"{hostname}: Test SMART dokončený — {device}","body":"Test SMART typu {test_type} na /dev/{device} bol dokončený.\nVýsledok: {result}\nTrvanie: {duration}","label":"SMART test bol dokončený"},"smart_test_failed":{"title":"{hostname}: Test SMART ZLYHAL — {device}","body":"Test SMART typu {test_type} na /dev/{device} zlyhal.\nVýsledok: {result}\nDôvod: {reason}","label":"SMART test zlyhal"},"gpu_mode_switch":{"title":"{hostname}: Režim GPU zmenený na {new_mode}","body":"Režim priameho priradenia GPU bol zmenený.\nGPU: {gpu_name} ({gpu_pci})\nPredchádzajúci režim: {old_mode}\nNový režim: {new_mode}\n{details}","label":"Režim GPU bol zmenený"},"gpu_passthrough_blocked":{"title":"{hostname}: {guest_type} {guest_id} zablokovaný pri spustení","body":"Ochrana priameho priradenia PCIe zabránila spusteniu {guest_type} {guest_id} ({guest_name}).\nDôvod: {reason}\n{details}","label":"GPU passthrough bol zablokovaný"},"pci_passthrough_conflict":{"title":"{hostname}: Zistený konflikt zariadenia PCIe — {device_pci}","body":"Zariadenie PCIe je priradené viacerým VM alebo LXC.\nZariadenie: {device_pci}\nKonfliktné VM a LXC: {guest_list}\nVyžaduje sa zásah: zastavte jednu z VM alebo LXC alebo zmeňte priradenie zariadenia.","label":"Konflikt PCIe zariadenia"},"load_high":{"title":"{hostname}: Vysoká záťaž systému — {value}","body":"Priemerná záťaž systému je {value} na {cores} jadrách.\n{details}","label":"Vysoká záťaž systému"},"network_down":{"title":"{hostname}: Sieťové pripojenie prerušené{entity_suffix}","body":"Uzol stratil sieťové pripojenie.\nDôvod: {reason}","label":"Sieťové pripojenie bolo prerušené"},"network_latency":{"title":"{hostname}: Vysoká latencia siete — {value}ms","body":"Latencia k bráne: {value}ms (prahová hodnota: {threshold}ms).\nMôže to znamenať preťaženie siete alebo problém s hardvérom.","label":"Vysoká odozva siete"},"auth_fail":{"title":"{hostname}: Zlyhanie overenia","body":"Bol zistený neúspešný pokus o prihlásenie.\nZdrojová IP: {source_ip}\nPoužívateľ: {username}\nSlužba: {service}","label":"Neúspešné prihlásenie"},"ip_block":{"title":"{hostname}: IP zablokovaná cez Fail2Ban","body":"IP adresa {source_ip} bola zablokovaná.\nJail: {jail}\nNeúspešné pokusy: {failures}","label":"Fail2Ban zablokoval IP adresu"},"firewall_issue":{"title":"{hostname}: Zistený problém firewallu{entity_suffix}","body":"Bol zistený problém v konfigurácii firewallu.\nDôvod: {reason}","label":"Zistený problém s firewallom"},"user_permission_change":{"title":"{hostname}: Zmenené oprávnenie používateľa","body":"Používateľ: {username}\nZmena: {change_details}","label":"Zmena oprávnení používateľa"},"split_brain":{"title":"{hostname}: Zistený SPLIT-BRAIN","body":"V klastri bol zistený stav split-brain. Kvórum môže byť stratené.\nStav kvóra: {quorum}","label":"Zistený split-brain"},"node_disconnect":{"title":"{hostname}: Uzol {node_name} odpojený","body":"Uzol {node_name} sa odpojil od klastra.","label":"Server sa odpojil"},"node_reconnect":{"title":"{hostname}: Uzol {node_name} znovu pripojený","body":"Uzol {node_name} sa úspešne znovu pripojil ku klastru.","label":"Server sa znova pripojil"},"system_startup":{"title":"{hostname}: {reason}","body":"{summary}","label":"Súhrn po spustení systému"},"system_shutdown":{"title":"{hostname}: Systém sa vypína","body":"Uzol sa vypína.\n{reason}","label":"Systém sa vypína"},"system_reboot":{"title":"{hostname}: Systém sa reštartuje","body":"Uzol sa reštartuje.\n{reason}","label":"Systém sa reštartuje"},"system_restore_completed":{"title":"{hostname}: Obnova servera dokončená","body":"Úlohy po obnove boli dokončené na pozadí.\n\nPoužité VM a LXC: {guests}\nZástupné priečinky bind mountov: {stubs}\nOdstránené zastarané priečinky uzlov: {stale_nodes}\nPreinštalované súčasti: {components}\nTrvanie: {duration}\n{warnings_block}\nUzol je teraz úplne pripravený na použitie.","label":"Obnova servera bola dokončená"},"system_problem":{"title":"{hostname}: Zistený systémový problém{entity_suffix}","body":"Bol zistený problém na úrovni systému.\nDôvod: {reason}","label":"Zistený problém so systémom"},"service_fail":{"title":"{hostname}: Služba zlyhala — {service_name}","body":"Systémová služba \"{service_name}\" zlyhala.\nDôvod: {reason}","label":"Služba zlyhala"},"oom_kill":{"title":"{hostname}: Ukončenie pri nedostatku pamäte — {process}","body":"Proces „{process}“ bol ukončený správcom pri nedostatku pamäte.\n{reason}","label":"Proces bol ukončený pre nedostatok pamäte"},"service_fail_batch":{"title":"{hostname}: {service_count} zlyhaných služieb{entity_suffix}","body":"{reason}","label":"Zlyhanie viacerých služieb"},"cron_output":{"title":"{hostname}: {pve_title}","body":"{reason}","label":"Výstup úlohy cron"},"system_mail":{"title":"{hostname}: {pve_title}","body":"{reason}","label":"Správy Smartd a systému"},"apt_listchanges":{"title":"{hostname}: {pve_title}","body":"Informácie o balíkoch od ich tvorcov preposlané systémom Proxmox VE cez apt-listchanges. Nasledujúci text pochádza od správcu balíka a nie je odporúčaním ProxMenux.\n\n{reason}","label":"Oznámenia o balíkoch apt-listchanges"},"webhook_test":{"title":"{hostname}: Prijatý test webhooku","body":"Test pripojenia webhooku PVE bol úspešný.\n{reason}","label":"Test webhooku"},"update_available":{"title":"{hostname}: Dostupné aktualizácie","body":"Aktualizácie spolu: {total_count}\nBezpečnostné: {security_count}\nProxmox: {pve_count}\nJadro: {kernel_count}\nDôležité balíky:\n{important_list}","label":"Dostupné aktualizácie (starší typ)"},"unknown_persistent":{"title":"{hostname}: Kontrola nedostupná - {category}{entity_suffix}","body":"Kontrola stavu pre kategóriu {category} je nedostupná aspoň 3 cykly.\n{reason}","label":"Kontrola nie je dostupná"},"health_persistent":{"title":"{hostname}: {count} aktívnych problémov so stavom{entity_suffix}","body":"Nasledujúce problémy so stavom systému zostávajú nevyriešené:\n{issue_list}\n\nTento súhrn sa odosiela raz za 24 hodín, kým problémy pretrvávajú.","label":"Aktívne problémy so stavom (denne)"},"health_issue_new":{"title":"{hostname}: Nový problém so stavom systému — {category}{entity_suffix}","body":"Nový {severity} problém zistený v kategórii: {category}\nPodrobnosti: {reason}","label":"Nový problém so stavom"},"health_issue_resolved":{"title":"{hostname}: Vyriešené - {category}{entity_suffix}","body":"Problém v kategórii {category} bol vyriešený.\n{reason}\nTrvanie: {duration}","label":"Problém bol vyriešený"},"update_summary":{"title":"{hostname}: Dostupné aktualizácie","body":"Aktualizácie spolu: {total_count}\nBezpečnostné aktualizácie: {security_count}\nAktualizácie súvisiace s Proxmoxom: {pve_count}\nAktualizácie jadra: {kernel_count}\nDôležité balíky:\n{important_list}","label":"Dostupné aktualizácie"},"pve_update":{"title":"{hostname}: Dostupný Proxmox VE {new_version}","body":"Je dostupná nová verzia Proxmox VE.\nAktuálna: {current_version}\nNová: {new_version}\n{details}","label":"Dostupná aktualizácia Proxmox VE"},"update_complete":{"title":"{hostname}: Aktualizácia systému dokončená","body":"Systémové balíky boli úspešne aktualizované.\n{details}","label":"Aktualizácia bola dokončená"},"ai_model_migrated":{"title":"{hostname}: Model AI aktualizovaný","body":"Model AI pre notifikácie bol automaticky aktualizovaný.\nPoskytovateľ: {provider}\nPredchádzajúci model: {old_model}\nNový model: {new_model}\n\n{message}","label":"AI model bol automaticky aktualizovaný"},"proxmenux_update":{"title":"{hostname}: Dostupný ProxMenux {new_version}","body":"Je dostupná nová verzia ProxMenux.\nAktuálna: {current_version}\nNová: {new_version}","label":"Dostupná aktualizácia ProxMenux"},"mount_stale":{"title":"{hostname}: nereagujúce vzdialené pripojenie {mount_target}","body":"Vzdialené pripojenie {mount_target} ({fstype}) zo zdroja {mount_source} nereaguje{lxc_scope}.\nKontrola stat vypršala alebo vrátila chybu: {error}\n\nAplikácie zapisujúce do tejto cesty môžu nepozorovane zapisovať na podkladový súborový systém a zaplniť disk. Pripojenie obnovte alebo čo najskôr opravte konektivitu.","label":"Vzdialené pripojenie neodpovedá"},"mount_readonly":{"title":"{hostname}: vzdialené pripojenie {mount_target} je iba na čítanie","body":"Vzdialené pripojenie {mount_target} ({fstype}) zo zdroja {mount_source} je pripojené iba na čítanie{lxc_scope}. Zápisy zlyhajú. Ak to nebolo zámerné, pripojte ho znova s voľbou rw.","label":"Vzdialené pripojenie je iba na čítanie"},"lxc_disk_low":{"title":"{hostname}: CT {vmid} koreňový systém na {usage_percent}%","body":"Koreňový súborový systém CT {vmid} ({name}) je zaplnený na {usage_percent}% ({disk_bytes_human} / {maxdisk_bytes_human}).\n\nPlný rootfs LXC bráni korektnému spusteniu kontajnera. Zväčšite rootfs (pct resize {vmid} rootfs +1G) alebo uvoľnite miesto v kontajneri.","label":"Rootfs LXC je takmer plný"},"vm_disk_low":{"title":"{hostname}: VM {vmid} súborové systémy na {usage_percent}%","body":"Súborové systémy VM {vmid} ({name}) sú zaplnené na {usage_percent}% ({disk_bytes_human} / {maxdisk_bytes_human}).\n\nÚdaje poskytol QEMU Guest Agent. Zahŕňajú každý trvalý súborový systém pripojený z blokového zariadenia vrátane virtuálnych diskov a diskov priamo priradených cez PCI. Uvoľnite miesto vo VM alebo zväčšite dotknuté úložisko skôr, než začnú zlyhávať zápisy.","label":"Súborové systémy VM sú takmer plné"},"lxc_mount_low":{"title":"{hostname}: Pripojenie {mount} v CT {vmid} je zaplnené na {usage_percent}%","body":"Pripojenie {mount} v CT {vmid} ({name}) je využité na {usage_percent}%.\nTyp súborového systému: {fstype}\n\nPlné pripojenie v kontajneri často nepozorovane zablokuje aplikáciu — zápisy zlyhajú alebo skončia na rootfs a vyvolajú ďalšie upozornenie. Uvoľnite miesto alebo pripojenie zväčšite.","label":"Pripojenie LXC je takmer plné"},"pve_storage_full":{"title":"{hostname}: Úložisko PVE {storage_name} je zaplnené na {usage_percent}%","body":"Úložisko Proxmox „{storage_name}“ (typ: {storage_type}) je využité na {usage_percent}%.\n\nPo zaplnení nebude možné vytvárať nové VM/CT a existujúcim VM a LXC môžu zlyhať zápisy. Presuňte alebo odstráňte nepoužívané zväzky, prípadne zväčšite podkladový pool/LV/RBD obraz.","label":"Úložisko PVE je takmer plné"},"zfs_pool_full":{"title":"{hostname}: Fond ZFS {pool_name} je zaplnený na {usage_percent}%","body":"Fond ZFS „{pool_name}“ je zaplnený na {usage_percent}%.\n\nVýkon a spoľahlivosť zápisu ZFS sa nad približne 80 % výrazne zhoršujú, pretože CoW potrebuje voľné miesto pre nové bloky. Uvoľnite snímky, odstráňte staré datasety alebo pridajte do fondu ďalšie vdevy.","label":"ZFS pool je takmer plný"},"post_install_update":{"title":"{hostname}: {count} ProxMenux dostupných aktualizácií optimalizácií","body":"Na tomto serveri je dostupných {count} aktualizácií optimalizácií ProxMenux.\n\n🛠️ Dostupné verzie:\n{tool_list}\n\n💡 Použiť cez:\n • ProxMenux Monitor → Nastavenia → Optimalizácie ProxMenux\n • Alebo spustite ponuku po inštalácii (možnosť 2) → „Použiť dostupné aktualizácie“","label":"Dostupné aktualizácie optimalizácií ProxMenux"},"secure_gateway_update_available":{"title":"{hostname}: {app_name} dostupná aktualizácia{update_title_suffix}","body":"Aplikácia {app_name} (spravovaná cez ProxMenux) má vo svojom kontajneri 📦 {package_count} čakajúcich aktualizácií balíkov.\n{version_line}\n\n💡 Otvorte ProxMenux Monitor > Nastavenia > Secure Gateway a kliknite na „Aktualizovať“.\n\n🗂️ Balíky:\n{package_list}","label":"K dispozícii je aktualizácia Secure Gateway"},"nvidia_driver_update_available":{"title":"{hostname}: NVIDIA dostupná aktualizácia ovládača — v{latest_version}","body":"Pre nainštalovaný rad ovládača NVIDIA je dostupná novšia údržbová verzia.\n🔹 Aktuálne nainštalovaná: v{current_version}\n🟢 Najnovšia dostupná: v{latest_version}\n\n{upgrade_reason}\n\n💡 Preinštalovanie:\n • V ponuke ProxMenux po inštalácii: {menu_label}\n\nPreinštalovanie zostaví modul DKMS pre aktuálne jadro a načítanie nového ovládača vyžaduje reštart.","label":"Dostupná aktualizácia ovládača NVIDIA"},"coral_driver_update_available":{"title":"{hostname}: Coral TPU dostupná aktualizácia ovládača — {latest_version}","body":"Je dostupná novšia verzia {variant_label}.\n🔹 Aktuálne nainštalovaná: {current_version}\n🟢 Najnovšia dostupná: {latest_version}\n\n{upgrade_reason}\n\n💡 Preinštalovanie:\n • V ponuke ProxMenux po inštalácii: {menu_label}\n\n{reboot_note}","label":"Dostupná aktualizácia ovládača Coral TPU"},"burst_auth_fail":{"title":"{hostname}: Ďalšie zlyhania overenia za {window}: +{count}","body":"Za {window} bolo zistených ďalších {count} zlyhaní overenia (spolu {total_count}).\nZdroje: {entity_list}","label":"Veľa neúspešných prihlásení"},"burst_ip_block":{"title":"{hostname}: Fail2Ban zablokoval za {window} ďalšie IP: +{count}","body":"Fail2Ban zablokoval za {window} ďalších {count} IP (spolu {total_count}).\nIP adresy: {entity_list}","label":"Veľa zablokovaných IP adries"},"burst_disk_io":{"title":"{hostname}: +{count} ďalších chýb I/O disku na {entity_list}","body":"Za {window} bolo zistených ďalších {count} chýb I/O (spolu {total_count}).\nZariadenia: {entity_list}","label":"Viacero diskových I/O chýb"},"burst_cluster":{"title":"{hostname}: Zistené kolísanie stavu klastra (+{count} ďalších zmien)","body":"Stav klastra sa za {window} zmenil ešte {count}-krát (spolu {total_count}).\nUzly: {entity_list}","label":"Nestabilné spojenie clustra"},"burst_service_fail":{"title":"{hostname}: Za {window} zlyhali ďalšie služby: +{count}","body":"Za {window} bolo zistených ďalších {count} zlyhaní služieb (spolu {total_count}).\nZvyčajne to znamená reštart uzla alebo služby PVE.\n\nĎalšie zlyhania:\n{details}","label":"Zlyhanie viacerých služieb"},"burst_system":{"title":"{hostname}: Ďalšie systémové problémy za {window}: +{count}","body":"Za {window} bolo zistených ďalších {count} systémových problémov (spolu {total_count}).\n\nĎalšie problémy:\n{details}","label":"Viacero systémových problémov"},"burst_generic":{"title":"{hostname}: Ďalšie udalosti {event_type} za {window}: +{count}","body":"Za {window} bolo zaznamenaných ďalších {count} udalostí typu {event_type} (spolu {total_count}).\n\nĎalšie udalosti:\n{details}","label":"Viacero súvisiacich udalostí"},"kernel_warning":{"title":"{hostname}: Zaznamenaná diagnostická udalosť jadra","body":"Jadro zaznamenalo diagnostickú udalosť: {kernel_details}","label":"Upozornenia jadra a diagnostické záznamy"}},"lxcUpdate":{"status":{"success":"úspešne dokončená","failure":"zlyhala","partial":"dokončená čiastočne","deferred":"odložená","skipped":"preskočená"},"source":{"scheduled":"Plánovane","manual":"Manuálne"},"sourceLabel":"Zdroj","targets":"Ciele","osPending":"Čakajúce aktualizácie OS: {before} → {after}","osUnverified":"Balíky OS: príkaz na aktualizáciu bol spustený, výsledok sa nepodarilo overiť","applications":"Aplikácie: {items}","applicationsUnverified":"Aplikácie: aktualizátor bol spustený, nezistila sa však zmena sledovanej verzie","dockerEngineChange":"Docker Engine: {before} → {after}","dockerEngineVerified":"Docker Engine: overený vo verzii {version}","dockerEngineUnverified":"Docker Engine: príkaz na aktualizáciu bol spustený, verziu sa nepodarilo overiť","dockerImagesPending":"Čakajúce aktualizácie Docker obrazov: {before} → {after}","dockerImagesChanged":"Zmenené Docker obrazy: {images}","deferredTargets":"Odložené ciele: {targets}","reason":"Dôvod: {reason}","restartRequired":"Vyžaduje sa reštart: {value}","yes":"áno","no":"nie","verificationPending":"Overenie bude pokračovať po spustení kontajnera","verificationWarning":"Upozornenie pri overení: {error}","duration":"Trvanie: {duration}"},"fallback":{"unknownTitle":"{hostname}: {event_type}","healthCheckDegraded":"Zhoršený stav kontroly","none":"žiadne"},"fields":{"vmid":"VM/CT","name":"Názov","device":"Zariadenie","sourceIp":"Zdrojová IP","node":"Uzol","category":"Kategória","service":"Služba","jail":"Jail","user":"Používateľ","count":"Počet","window":"Obdobie","affected":"Ovplyvnené"},"vzdump":{"size":"Veľkosť: {value}","duration":"Trvanie: {value}","file":"Súbor","backups":"Počet záloh: {count}","failed":"Zlyhalo: {count}","total":"Spolu: {value}","time":"Čas: {value}"},"startup":{"issuesTitle":"{hostname}: Spustenie systému – zistených problémov: {count}","completeTitle":"{hostname}: Spustenie systému dokončené","operational":"Všetky systémy sú funkčné.","vmCountOne":"{count} VM","vmCountMany":"Počet VM: {count}","ctCountOne":"{count} CT","ctCountMany":"Počet CT: {count}","started":"✅ Spustené: {counts}","vmFailed":"❌ VM {name} zlyhal – {reason}","ctFailed":"❌ CT {name} zlyhal – {reason}","unknownError":"neznáma chyba","storageUnavailable":"⚠️ Nedostupné úložiská: {count} ({names})","servicesFailed":"⚠️ Zlyhané služby: {count} ({names})","duration":"⏱️ Spustenie dokončené za {minutes} min"},"appUpdates":{"singleTitle":"{hostname}: Pre {app_name} je na CT {vmid} dostupná aktualizácia","singleBody":"Aplikácia {app_name} na CT {vmid} ({ct_name}) má novú verziu:\n {installed} → {latest}","emptyTitle":"{hostname}: Dostupné aktualizácie aplikácií","emptyBody":"Sú dostupné aktualizácie aplikácií.","batchTitle":"{hostname}: Dostupné aktualizácie aplikácií: {count}","batchLeadOneContainer":"Aplikácie s dostupnou novšou verziou: {count} v {container_count} kontajneri LXC:","batchLeadManyContainers":"Aplikácie s dostupnou novšou verziou: {count} v {container_count} kontajneroch LXC:","additional":"… ďalšie aplikácie: {count}","app":"aplikácia","unknown":"neznáme"},"healthDegraded":{"categories":{"cpu":"Využitie CPU a teplota","memory":"Pamäť a swap","storage":"Pripojené úložiská a miesto","disks":"I/O disku a chyby","network":"Sieťové rozhrania","vms":"VM a kontajnery","services":"Služby PVE","logs":"Systémové záznamy","updates":"Systémové aktualizácie","security":"Bezpečnosť"},"severity":{"critical":"Kritický","warning":"Upozornenie"},"singleTitle":"{hostname}: {severity} stav – {category}","multipleTitle":"{hostname}: Zhoršené kontroly stavu: {count}","multipleLine":"• {severity}: {category}\n {reason}","reasons":{"cpuSustained":"CPU je nad {threshold} % už {duration} s."}},"digest":{"title":"{hostname}: Súhrn za 24 hodín ({timestamp})","readFailed":"načítanie súhrnu zlyhalo: {error}","empty":"Pre toto obdobie súhrnu nie sú uložené žiadne udalosti INFO.","lead":"{count} udalostí INFO zoskupených podľa kategórie:\n","more":" • … a ďalšie: {count}","footer":"(Kritické udalosti a upozornenia boli doručené ihneď, nie v tomto súhrne.)","quietTitle":"{hostname}: Udalosti uložené počas tichých hodín: {count}","groups":{"vm_ct":"VM a CT","backup":"Zálohy","resources":"Zdroje","storage":"Úložisko","network":"Sieť","security":"Bezpečnosť","cluster":"Klaster","services":"Služby","health":"Stav systému","updates":"Aktualizácie","hardware":"Hardvér","system":"Systém","other":"Ostatné"}},"test":{"title":"Test ProxMenux","welcome":"Vitajte v ProxMenux Monitor!","verify":"Toto je testovacia správa na overenie správneho fungovania notifikačného kanála.","configuration":"Nastavenie kanála:","iconsEnabled":"Ikony: zapnuté","iconsDisabled":"Ikony: vypnuté","aiEnabled":"AI: zapnutá ({info})","aiDisabled":"AI: vypnutá","alerts":"Budete dostávať upozornenia na systémové udalosti, zmeny stavu a bezpečnostné incidenty.","photoCaption":"Tento obrázok môžete použiť ako profilovú fotografiu svojho notifikačného bota."},"channels":{"discord":{"category":"Kategória","host":"Server","severity":"Závažnosť"},"email":{"report":"Prehľad: {group}","details":"Podrobnosti","host":"Server","footer":"Notifikačná služba ProxMenux","severity":{"critical":"Kritické","warning":"Upozornenie","info":"Informácia","ok":"Vyriešené","default":"Oznámenie"},"groups":{"vm_ct":"Virtuálny stroj / kontajner","backup":"Záloha a snímka","resources":"Systémové zdroje","storage":"Úložisko","network":"Sieť","security":"Bezpečnosť","cluster":"Klaster","services":"Systémové služby","health":"Stav systému","updates":"Systémové aktualizácie","system":"Systém","hardware":"Hardvér","other":"Systémová notifikácia"},"fields":{"vmCtId":"ID VM/CT","name":"Názov","action":"Akcia","targetNode":"Cieľový uzol","reason":"Dôvod","storage":"Úložisko","status":"Stav","size":"Veľkosť","duration":"Trvanie","snapshot":"Snímka","metric":"Metrika","currentValue":"Aktuálna hodnota","threshold":"Prahová hodnota","cpuCores":"Jadrá CPU","memory":"Pamäť","temperature":"Teplota","mountPoint":"Bod pripojenia","usage":"Využitie","available":"Voľné","device":"Zariadenie","severity":"Závažnosť","storageName":"Názov úložiska","type":"Typ","interface":"Rozhranie","latency":"Latencia","event":"Udalosť","sourceIp":"Zdrojová IP","username":"Používateľ","service":"Služba","jail":"Jail","failures":"Zlyhania","change":"Zmena","node":"Uzol","quorum":"Kvórum","nodesAffected":"Ovplyvnené uzly","process":"Proces","category":"Kategória","previousSeverity":"Predchádzajúca závažnosť","activeIssues":"Aktívne problémy","totalUpdates":"Aktualizácie spolu","securityUpdates":"Bezpečnostné aktualizácie","proxmoxUpdates":"Aktualizácie Proxmox","kernelUpdates":"Aktualizácie jadra","importantPackages":"Dôležité balíky","currentVersion":"Aktuálna verzia","newVersion":"Nová verzia"},"status":{"failed":"Zlyhalo","completed":"Dokončené","started":"Spustené"}}}}}
+ "runtime": {
+ "notifications": {
+ "templates": {
+ "state_change": {
+ "title": "{hostname}: {category} sa zmenilo na {current}{entity_suffix}",
+ "body": "Stav kategórie {category} sa zmenil z {previous} na {current}.\n{reason}",
+ "label": "Zmena stavu kontroly"
+ },
+ "new_error": {
+ "title": "{hostname}: Nový {severity} - {category}{entity_suffix}",
+ "body": "{reason}",
+ "label": "Nový problém so stavom"
+ },
+ "error_resolved": {
+ "title": "{hostname}: Vyriešené - {category}{entity_suffix}",
+ "body": "Problém v kategórii {category} bol vyriešený.\n{reason}\n🚦 Predchádzajúca závažnosť: {original_severity}\n⏱️ Trvanie: {duration}",
+ "label": "Problém bol vyriešený"
+ },
+ "error_escalated": {
+ "title": "{hostname}: Zvýšené na {severity} - {category}{entity_suffix}",
+ "body": "{reason}",
+ "label": "Problém sa zhoršil"
+ },
+ "health_degraded": {
+ "title": "{title_or_default}",
+ "body": "{reason}",
+ "label": "Zhoršený stav kontroly"
+ },
+ "lxc_updates_available": {
+ "title": "{hostname}: Aktualizácie balíkov sú dostupné pre {count} LXC",
+ "body": "📊 Čakajúce aktualizácie balíkov má {count} LXC (📦 spolu {total_packages}, 🔒 bezpečnostné {security_count}):\n\n{ct_list}",
+ "label": "Dostupné aktualizácie LXC (experimentálne)"
+ },
+ "lxc_update_applied": {
+ "title": "{hostname}: LXC {ct_name} ({vmid}) aktualizácia {result}",
+ "body": "{details}",
+ "label": "Aktualizácia LXC použitá"
+ },
+ "app_update_available": {
+ "title": "{hostname}: Pre {app_name} je na CT {vmid} dostupná aktualizácia",
+ "body": "Aplikácia {app_name} na CT {vmid} ({ct_name}) má novú verziu:\n {installed} → {latest}",
+ "label": "K dispozícii je aktualizácia aplikácie"
+ },
+ "docker_stack_update_available": {
+ "title": "{hostname}: Na CT {vmid} sú dostupné aktualizácie Docker",
+ "body": "Kontajner {ct_name} (CT {vmid}) má {count} aktualizácií Docker:\n{details}",
+ "label": "Dostupné aktualizácie Docker"
+ },
+ "vm_start": {
+ "title": "{hostname}: VM {vmname} ({vmid}) spustený",
+ "body": "Virtuálny stroj {vmname} (ID: {vmid}) je spustený.",
+ "label": "VM bola spustená"
+ },
+ "vm_start_warning": {
+ "title": "{hostname}: VM {vmname} ({vmid}) spustený s upozorneniami",
+ "body": "Virtuálny stroj {vmname} (ID: {vmid}) sa úspešne spustil, ale obsahuje upozornenia.\nUpozornenia: {reason}",
+ "label": "VM bola spustená s upozorneniami"
+ },
+ "vm_stop": {
+ "title": "{hostname}: VM {vmname} ({vmid}) zastavený",
+ "body": "Virtuálny stroj {vmname} (ID: {vmid}) bol zastavený.",
+ "label": "VM bola zastavená"
+ },
+ "vm_shutdown": {
+ "title": "{hostname}: VM {vmname} ({vmid}) vypnutý",
+ "body": "Virtuálny stroj {vmname} (ID: {vmid}) bol korektne vypnutý.",
+ "label": "VM bola vypnutá"
+ },
+ "vm_fail": {
+ "title": "{hostname}: VM {vmname} ({vmid}) ZLYHAL",
+ "body": "Virtuálny stroj {vmname} (ID: {vmid}) zlyhal alebo sa ho nepodarilo spustiť.\nDôvod: {reason}",
+ "label": "Spustenie VM zlyhalo"
+ },
+ "vm_restart": {
+ "title": "{hostname}: VM {vmname} ({vmid}) reštartovaný",
+ "body": "Virtuálny stroj {vmname} (ID: {vmid}) bol reštartovaný.",
+ "label": "VM bola reštartovaná"
+ },
+ "ct_start": {
+ "title": "{hostname}: CT {vmname} ({vmid}) spustený",
+ "body": "Kontajner {vmname} (ID: {vmid}) je spustený.",
+ "label": "Kontajner bol spustený"
+ },
+ "ct_start_warning": {
+ "title": "{hostname}: CT {vmname} ({vmid}) spustený s upozorneniami",
+ "body": "Kontajner {vmname} (ID: {vmid}) sa úspešne spustil, ale obsahuje upozornenia.\nUpozornenia: {reason}",
+ "label": "Kontajner bol spustený s upozorneniami"
+ },
+ "ct_stop": {
+ "title": "{hostname}: CT {vmname} ({vmid}) zastavený",
+ "body": "Kontajner {vmname} (ID: {vmid}) bol zastavený.",
+ "label": "Kontajner bol zastavený"
+ },
+ "ct_shutdown": {
+ "title": "{hostname}: CT {vmname} ({vmid}) vypnutý",
+ "body": "Kontajner {vmname} (ID: {vmid}) bol korektne vypnutý.",
+ "label": "Kontajner bol vypnutý"
+ },
+ "ct_restart": {
+ "title": "{hostname}: CT {vmname} ({vmid}) reštartovaný",
+ "body": "Kontajner {vmname} (ID: {vmid}) bol reštartovaný.",
+ "label": "Kontajner bol reštartovaný"
+ },
+ "ct_fail": {
+ "title": "{hostname}: CT {vmname} ({vmid}) ZLYHAL",
+ "body": "Kontajner {vmname} (ID: {vmid}) zlyhal alebo sa ho nepodarilo spustiť.\nDôvod: {reason}",
+ "label": "Spustenie kontajnera zlyhalo"
+ },
+ "migration_start": {
+ "title": "{hostname}: Migrácia spustená — {vmname} ({vmid})",
+ "body": "Živá migrácia VM alebo LXC {vmname} (ID: {vmid}) na uzol {target_node} sa začala.",
+ "label": "Migrácia sa začala"
+ },
+ "migration_complete": {
+ "title": "{hostname}: Migrácia dokončená — {vmname} ({vmid})",
+ "body": "{vmname} (ID: {vmid}) bol úspešne presunutý na uzol {target_node}.",
+ "label": "Migrácia bola dokončená"
+ },
+ "migration_warning": {
+ "title": "{hostname}: Migrácia dokončená s upozorneniami — {vmname} ({vmid})",
+ "body": "VM alebo LXC {vmname} (ID: {vmid}) bol presunutý na uzol {target_node}, ale vyskytli sa upozornenia.\nUpozornenia: {reason}",
+ "label": "Migrácia skončila s upozorneniami"
+ },
+ "migration_fail": {
+ "title": "{hostname}: Migrácia ZLYHALA — {vmname} ({vmid})",
+ "body": "Migrácia VM alebo LXC {vmname} (ID: {vmid}) na uzol {target_node} zlyhala.\nDôvod: {reason}",
+ "label": "Migrácia zlyhala"
+ },
+ "replication_fail": {
+ "title": "{hostname}: Replikácia ZLYHALA — {vmname} ({vmid})",
+ "body": "Replikácia VM alebo LXC {vmname} (ID: {vmid}) zlyhala.\nDôvod: {reason}",
+ "label": "Replikácia zlyhala"
+ },
+ "replication_complete": {
+ "title": "{hostname}: Replikácia dokončená — {vmname} ({vmid})",
+ "body": "Replikácia VM alebo LXC {vmname} (ID: {vmid}) bola úspešne dokončená.",
+ "label": "Replikácia bola dokončená"
+ },
+ "backup_start": {
+ "title": "{hostname}: Záloha na úložisko {storage} spustená",
+ "body": "Úloha zálohovania na úložisko {storage} sa začala.\n{reason}",
+ "label": "Zálohovanie sa začalo"
+ },
+ "backup_complete": {
+ "title": "{hostname} → {storage}: Záloha dokončená — {vmname} ({vmid})",
+ "body": "Záloha {vmname} (ID: {vmid}) na úložisku {storage} bola úspešne dokončená.\nVeľkosť: {size}",
+ "label": "Záloha bola dokončená"
+ },
+ "backup_warning": {
+ "title": "{hostname} → {storage}: Záloha dokončená s upozorneniami — {vmname} ({vmid})",
+ "body": "Záloha {vmname} (ID: {vmid}) na úložisku {storage} bola dokončená, ale vyskytli sa upozornenia.\nUpozornenia: {reason}",
+ "label": "Záloha skončila s upozorneniami"
+ },
+ "backup_fail": {
+ "title": "{hostname} → {storage}: Záloha ZLYHALA — {vmname} ({vmid})",
+ "body": "Záloha {vmname} (ID: {vmid}) na úložisku {storage} zlyhala.\nDôvod: {reason}",
+ "label": "Zálohovanie zlyhalo"
+ },
+ "host_backup_start": {
+ "title": "{hostname}: Záloha servera spustená → {backend_label}",
+ "body": "Úloha: {job_id}\nBackend: {backend_label}\nCieľ: {destination}\nProfil: {profile_mode}",
+ "label": "Zálohovanie servera sa začalo"
+ },
+ "host_backup_complete": {
+ "title": "{hostname}: Záloha servera dokončená → {backend_label}",
+ "body": "Úloha: {job_id}\nBackend: {backend_label}\nCieľ: {destination}\nVeľkosť dát: {data_size}\nVeľkosť archívu: {archive_size}\nTrvanie: {duration}",
+ "label": "Záloha servera bola dokončená"
+ },
+ "host_backup_fail": {
+ "title": "{hostname}: Záloha servera ZLYHALA → {backend_label}",
+ "body": "Úloha: {job_id}\nBackend: {backend_label}\nCieľ: {destination}\nTrvanie pred zlyhaním: {duration}\nDôvod: {reason}\nZáznam: {log_file}",
+ "label": "Zálohovanie servera zlyhalo"
+ },
+ "snapshot_complete": {
+ "title": "{hostname}: Snímka vytvorená — {vmname} ({vmid})",
+ "body": "Snímka „{snapshot_name}“ bola vytvorená pre {vmname} (ID: {vmid}).",
+ "label": "Snapshot bol vytvorený"
+ },
+ "snapshot_fail": {
+ "title": "{hostname}: Vytvorenie snímky ZLYHALO — {vmname} ({vmid})",
+ "body": "Vytvorenie snímky pre {vmname} (ID: {vmid}) zlyhalo.\nDôvod: {reason}",
+ "label": "Vytvorenie snapshotu zlyhalo"
+ },
+ "cpu_high": {
+ "title": "{hostname}: Vysoké využitie CPU — {value}%",
+ "body": "Využitie CPU dosiahlo {value}% na {cores} jadrách.\n{details}",
+ "label": "Vysoké využitie CPU"
+ },
+ "ram_high": {
+ "title": "{hostname}: Vysoké využitie pamäte — {value}%",
+ "body": "Využitie pamäte: {used} / {total} ({value}%).\n{details}",
+ "label": "Vysoké využitie pamäte"
+ },
+ "temp_high": {
+ "title": "{hostname}: Vysoká teplota CPU — {value}°C",
+ "body": "Teplota CPU dosiahla {value}°C (prahová hodnota: {threshold}°C).\n{details}",
+ "label": "Vysoká teplota"
+ },
+ "disk_space_low": {
+ "title": "{hostname}: Málo miesta na disku {mount}",
+ "body": "Súborový systém {mount}: {used}% využité ({available} voľných).\nUvoľnite miesto na disku, aby ste predišli výpadku služieb.",
+ "label": "Málo miesta na disku"
+ },
+ "disk_io_error": {
+ "title": "{hostname}: Zistené zlyhanie disku — {device}",
+ "body": "Na zariadení bola zistená chyba I/O alebo zlyhanie disku {device}.\n{reason}",
+ "label": "Chyba disku alebo I/O"
+ },
+ "storage_unavailable": {
+ "title": "{hostname}: Úložisko nedostupné — {storage_name}",
+ "body": "Úložisko PVE „{storage_name}“ (typ: {storage_type}) nie je dostupné.\nDôvod: {reason}",
+ "label": "Úložisko nie je dostupné"
+ },
+ "smart_test_complete": {
+ "title": "{hostname}: Test SMART dokončený — {device}",
+ "body": "Test SMART typu {test_type} na /dev/{device} bol dokončený.\nVýsledok: {result}\nTrvanie: {duration}",
+ "label": "SMART test bol dokončený"
+ },
+ "smart_test_failed": {
+ "title": "{hostname}: Test SMART ZLYHAL — {device}",
+ "body": "Test SMART typu {test_type} na /dev/{device} zlyhal.\nVýsledok: {result}\nDôvod: {reason}",
+ "label": "SMART test zlyhal"
+ },
+ "gpu_mode_switch": {
+ "title": "{hostname}: Režim GPU zmenený na {new_mode}",
+ "body": "Režim priameho priradenia GPU bol zmenený.\nGPU: {gpu_name} ({gpu_pci})\nPredchádzajúci režim: {old_mode}\nNový režim: {new_mode}\n{details}",
+ "label": "Režim GPU bol zmenený"
+ },
+ "gpu_passthrough_blocked": {
+ "title": "{hostname}: {guest_type} {guest_id} zablokovaný pri spustení",
+ "body": "Ochrana priameho priradenia PCIe zabránila spusteniu {guest_type} {guest_id} ({guest_name}).\nDôvod: {reason}\n{details}",
+ "label": "GPU passthrough bol zablokovaný"
+ },
+ "pci_passthrough_conflict": {
+ "title": "{hostname}: Zistený konflikt zariadenia PCIe — {device_pci}",
+ "body": "Zariadenie PCIe je priradené viacerým VM alebo LXC.\nZariadenie: {device_pci}\nKonfliktné VM a LXC: {guest_list}\nVyžaduje sa zásah: zastavte jednu z VM alebo LXC alebo zmeňte priradenie zariadenia.",
+ "label": "Konflikt PCIe zariadenia"
+ },
+ "load_high": {
+ "title": "{hostname}: Vysoká záťaž systému — {value}",
+ "body": "Priemerná záťaž systému je {value} na {cores} jadrách.\n{details}",
+ "label": "Vysoká záťaž systému"
+ },
+ "network_down": {
+ "title": "{hostname}: Sieťové pripojenie prerušené{entity_suffix}",
+ "body": "Uzol stratil sieťové pripojenie.\nDôvod: {reason}",
+ "label": "Sieťové pripojenie bolo prerušené"
+ },
+ "network_latency": {
+ "title": "{hostname}: Vysoká latencia siete — {value}ms",
+ "body": "Latencia k bráne: {value}ms (prahová hodnota: {threshold}ms).\nMôže to znamenať preťaženie siete alebo problém s hardvérom.",
+ "label": "Vysoká odozva siete"
+ },
+ "auth_fail": {
+ "title": "{hostname}: Zlyhanie overenia",
+ "body": "Bol zistený neúspešný pokus o prihlásenie.\nZdrojová IP: {source_ip}\nPoužívateľ: {username}\nSlužba: {service}",
+ "label": "Neúspešné prihlásenie"
+ },
+ "ip_block": {
+ "title": "{hostname}: IP zablokovaná cez Fail2Ban",
+ "body": "IP adresa {source_ip} bola zablokovaná.\nJail: {jail}\nNeúspešné pokusy: {failures}",
+ "label": "Fail2Ban zablokoval IP adresu"
+ },
+ "firewall_issue": {
+ "title": "{hostname}: Zistený problém firewallu{entity_suffix}",
+ "body": "Bol zistený problém v konfigurácii firewallu.\nDôvod: {reason}",
+ "label": "Zistený problém s firewallom"
+ },
+ "user_permission_change": {
+ "title": "{hostname}: Zmenené oprávnenie používateľa",
+ "body": "Používateľ: {username}\nZmena: {change_details}",
+ "label": "Zmena oprávnení používateľa"
+ },
+ "split_brain": {
+ "title": "{hostname}: Zistený SPLIT-BRAIN",
+ "body": "V klastri bol zistený stav split-brain. Kvórum môže byť stratené.\nStav kvóra: {quorum}",
+ "label": "Zistený split-brain"
+ },
+ "node_disconnect": {
+ "title": "{hostname}: Uzol {node_name} odpojený",
+ "body": "Uzol {node_name} sa odpojil od klastra.",
+ "label": "Server sa odpojil"
+ },
+ "node_reconnect": {
+ "title": "{hostname}: Uzol {node_name} znovu pripojený",
+ "body": "Uzol {node_name} sa úspešne znovu pripojil ku klastru.",
+ "label": "Server sa znova pripojil"
+ },
+ "system_startup": {
+ "title": "{hostname}: {reason}",
+ "body": "{summary}",
+ "label": "Súhrn po spustení systému"
+ },
+ "system_shutdown": {
+ "title": "{hostname}: Systém sa vypína",
+ "body": "Uzol sa vypína.\n{reason}",
+ "label": "Systém sa vypína"
+ },
+ "system_reboot": {
+ "title": "{hostname}: Systém sa reštartuje",
+ "body": "Uzol sa reštartuje.\n{reason}",
+ "label": "Systém sa reštartuje"
+ },
+ "system_restore_completed": {
+ "title": "{hostname}: Obnova servera dokončená",
+ "body": "Úlohy po obnove boli dokončené na pozadí.\n\nPoužité VM a LXC: {guests}\nZástupné priečinky bind mountov: {stubs}\nOdstránené zastarané priečinky uzlov: {stale_nodes}\nPreinštalované súčasti: {components}\nTrvanie: {duration}\n{warnings_block}\nUzol je teraz úplne pripravený na použitie.",
+ "label": "Obnova servera bola dokončená"
+ },
+ "system_problem": {
+ "title": "{hostname}: Zistený systémový problém{entity_suffix}",
+ "body": "Bol zistený problém na úrovni systému.\nDôvod: {reason}",
+ "label": "Zistený problém so systémom"
+ },
+ "service_fail": {
+ "title": "{hostname}: Služba zlyhala — {service_name}",
+ "body": "Systémová služba \"{service_name}\" zlyhala.\nDôvod: {reason}",
+ "label": "Služba zlyhala"
+ },
+ "oom_kill": {
+ "title": "{hostname}: Ukončenie pri nedostatku pamäte — {process}",
+ "body": "Proces „{process}“ bol ukončený správcom pri nedostatku pamäte.\n{reason}",
+ "label": "Proces bol ukončený pre nedostatok pamäte"
+ },
+ "service_fail_batch": {
+ "title": "{hostname}: {service_count} zlyhaných služieb{entity_suffix}",
+ "body": "{reason}",
+ "label": "Zlyhanie viacerých služieb"
+ },
+ "cron_output": {
+ "title": "{hostname}: {pve_title}",
+ "body": "{reason}",
+ "label": "Výstup úlohy cron"
+ },
+ "system_mail": {
+ "title": "{hostname}: {pve_title}",
+ "body": "{reason}",
+ "label": "Správy Smartd a systému"
+ },
+ "apt_listchanges": {
+ "title": "{hostname}: {pve_title}",
+ "body": "Informácie o balíkoch od ich tvorcov preposlané systémom Proxmox VE cez apt-listchanges. Nasledujúci text pochádza od správcu balíka a nie je odporúčaním ProxMenux.\n\n{reason}",
+ "label": "Oznámenia o balíkoch apt-listchanges"
+ },
+ "webhook_test": {
+ "title": "{hostname}: Prijatý test webhooku",
+ "body": "Test pripojenia webhooku PVE bol úspešný.\n{reason}",
+ "label": "Test webhooku"
+ },
+ "update_available": {
+ "title": "{hostname}: Dostupné aktualizácie",
+ "body": "Aktualizácie spolu: {total_count}\nBezpečnostné: {security_count}\nProxmox: {pve_count}\nJadro: {kernel_count}\nDôležité balíky:\n{important_list}",
+ "label": "Dostupné aktualizácie (starší typ)"
+ },
+ "unknown_persistent": {
+ "title": "{hostname}: Kontrola nedostupná - {category}{entity_suffix}",
+ "body": "Kontrola stavu pre kategóriu {category} je nedostupná aspoň 3 cykly.\n{reason}",
+ "label": "Kontrola nie je dostupná"
+ },
+ "health_persistent": {
+ "title": "{hostname}: {count} aktívnych problémov so stavom{entity_suffix}",
+ "body": "Nasledujúce problémy so stavom systému zostávajú nevyriešené:\n{issue_list}\n\nTento súhrn sa odosiela raz za 24 hodín, kým problémy pretrvávajú.",
+ "label": "Aktívne problémy so stavom (denne)"
+ },
+ "health_issue_new": {
+ "title": "{hostname}: Nový problém so stavom systému — {category}{entity_suffix}",
+ "body": "Nový {severity} problém zistený v kategórii: {category}\nPodrobnosti: {reason}",
+ "label": "Nový problém so stavom"
+ },
+ "health_issue_resolved": {
+ "title": "{hostname}: Vyriešené - {category}{entity_suffix}",
+ "body": "Problém v kategórii {category} bol vyriešený.\n{reason}\nTrvanie: {duration}",
+ "label": "Problém bol vyriešený"
+ },
+ "update_summary": {
+ "title": "{hostname}: Dostupné aktualizácie",
+ "body": "Aktualizácie spolu: {total_count}\nBezpečnostné aktualizácie: {security_count}\nAktualizácie súvisiace s Proxmoxom: {pve_count}\nAktualizácie jadra: {kernel_count}\nDôležité balíky:\n{important_list}",
+ "label": "Dostupné aktualizácie"
+ },
+ "pve_update": {
+ "title": "{hostname}: Dostupný Proxmox VE {new_version}",
+ "body": "Je dostupná nová verzia Proxmox VE.\nAktuálna: {current_version}\nNová: {new_version}\n{details}",
+ "label": "Dostupná aktualizácia Proxmox VE"
+ },
+ "update_complete": {
+ "title": "{hostname}: Aktualizácia systému dokončená",
+ "body": "Systémové balíky boli úspešne aktualizované.\n{details}",
+ "label": "Aktualizácia bola dokončená"
+ },
+ "ai_model_migrated": {
+ "title": "{hostname}: Model AI aktualizovaný",
+ "body": "Model AI pre notifikácie bol automaticky aktualizovaný.\nPoskytovateľ: {provider}\nPredchádzajúci model: {old_model}\nNový model: {new_model}\n\n{message}",
+ "label": "AI model bol automaticky aktualizovaný"
+ },
+ "proxmenux_update": {
+ "title": "{hostname}: Dostupný ProxMenux {new_version}",
+ "body": "Je dostupná nová verzia ProxMenux.\nAktuálna: {current_version}\nNová: {new_version}",
+ "label": "Dostupná aktualizácia ProxMenux"
+ },
+ "mount_stale": {
+ "title": "{hostname}: nereagujúce vzdialené pripojenie {mount_target}",
+ "body": "Vzdialené pripojenie {mount_target} ({fstype}) zo zdroja {mount_source} nereaguje{lxc_scope}.\nKontrola stat vypršala alebo vrátila chybu: {error}\n\nAplikácie zapisujúce do tejto cesty môžu nepozorovane zapisovať na podkladový súborový systém a zaplniť disk. Pripojenie obnovte alebo čo najskôr opravte konektivitu.",
+ "label": "Vzdialené pripojenie neodpovedá"
+ },
+ "mount_readonly": {
+ "title": "{hostname}: vzdialené pripojenie {mount_target} je iba na čítanie",
+ "body": "Vzdialené pripojenie {mount_target} ({fstype}) zo zdroja {mount_source} je pripojené iba na čítanie{lxc_scope}. Zápisy zlyhajú. Ak to nebolo zámerné, pripojte ho znova s voľbou rw.",
+ "label": "Vzdialené pripojenie je iba na čítanie"
+ },
+ "lxc_disk_low": {
+ "title": "{hostname}: CT {vmid} koreňový systém na {usage_percent}%",
+ "body": "Koreňový súborový systém CT {vmid} ({name}) je zaplnený na {usage_percent}% ({disk_bytes_human} / {maxdisk_bytes_human}).\n\nPlný rootfs LXC bráni korektnému spusteniu kontajnera. Zväčšite rootfs (pct resize {vmid} rootfs +1G) alebo uvoľnite miesto v kontajneri.",
+ "label": "Rootfs LXC je takmer plný"
+ },
+ "vm_disk_low": {
+ "title": "{hostname}: VM {vmid} súborové systémy na {usage_percent}%",
+ "body": "Súborové systémy VM {vmid} ({name}) sú zaplnené na {usage_percent}% ({disk_bytes_human} / {maxdisk_bytes_human}).\n\nÚdaje poskytol QEMU Guest Agent. Zahŕňajú každý trvalý súborový systém pripojený z blokového zariadenia vrátane virtuálnych diskov a diskov priamo priradených cez PCI. Uvoľnite miesto vo VM alebo zväčšite dotknuté úložisko skôr, než začnú zlyhávať zápisy.",
+ "label": "Súborové systémy VM sú takmer plné"
+ },
+ "lxc_mount_low": {
+ "title": "{hostname}: Pripojenie {mount} v CT {vmid} je zaplnené na {usage_percent}%",
+ "body": "Pripojenie {mount} v CT {vmid} ({name}) je využité na {usage_percent}%.\nTyp súborového systému: {fstype}\n\nPlné pripojenie v kontajneri často nepozorovane zablokuje aplikáciu — zápisy zlyhajú alebo skončia na rootfs a vyvolajú ďalšie upozornenie. Uvoľnite miesto alebo pripojenie zväčšite.",
+ "label": "Pripojenie LXC je takmer plné"
+ },
+ "pve_storage_full": {
+ "title": "{hostname}: Úložisko PVE {storage_name} je zaplnené na {usage_percent}%",
+ "body": "Úložisko Proxmox „{storage_name}“ (typ: {storage_type}) je využité na {usage_percent}%.\n\nPo zaplnení nebude možné vytvárať nové VM/CT a existujúcim VM a LXC môžu zlyhať zápisy. Presuňte alebo odstráňte nepoužívané zväzky, prípadne zväčšite podkladový pool/LV/RBD obraz.",
+ "label": "Úložisko PVE je takmer plné"
+ },
+ "zfs_pool_full": {
+ "title": "{hostname}: Fond ZFS {pool_name} je zaplnený na {usage_percent}%",
+ "body": "Fond ZFS „{pool_name}“ je zaplnený na {usage_percent}%.\n\nVýkon a spoľahlivosť zápisu ZFS sa nad približne 80 % výrazne zhoršujú, pretože CoW potrebuje voľné miesto pre nové bloky. Uvoľnite snímky, odstráňte staré datasety alebo pridajte do fondu ďalšie vdevy.",
+ "label": "ZFS pool je takmer plný"
+ },
+ "post_install_update": {
+ "title": "{hostname}: {count} ProxMenux dostupných aktualizácií optimalizácií",
+ "body": "Na tomto serveri je dostupných {count} aktualizácií optimalizácií ProxMenux.\n\n🛠️ Dostupné verzie:\n{tool_list}\n\n💡 Použiť cez:\n • ProxMenux Monitor → Nastavenia → Optimalizácie ProxMenux\n • Alebo spustite ponuku po inštalácii (možnosť 2) → „Použiť dostupné aktualizácie“",
+ "label": "Dostupné aktualizácie optimalizácií ProxMenux"
+ },
+ "secure_gateway_update_available": {
+ "title": "{hostname}: {app_name} dostupná aktualizácia{update_title_suffix}",
+ "body": "Aplikácia {app_name} (spravovaná cez ProxMenux) má vo svojom kontajneri 📦 {package_count} čakajúcich aktualizácií balíkov.\n{version_line}\n\n💡 Otvorte ProxMenux Monitor > Nastavenia > Secure Gateway a kliknite na „Aktualizovať“.\n\n🗂️ Balíky:\n{package_list}",
+ "label": "K dispozícii je aktualizácia Secure Gateway"
+ },
+ "nvidia_driver_update_available": {
+ "title": "{hostname}: NVIDIA dostupná aktualizácia ovládača — v{latest_version}",
+ "body": "Pre nainštalovaný rad ovládača NVIDIA je dostupná novšia údržbová verzia.\n🔹 Aktuálne nainštalovaná: v{current_version}\n🟢 Najnovšia dostupná: v{latest_version}\n\n{upgrade_reason}\n\n💡 Preinštalovanie:\n • V ponuke ProxMenux po inštalácii: {menu_label}\n\nPreinštalovanie zostaví modul DKMS pre aktuálne jadro a načítanie nového ovládača vyžaduje reštart.",
+ "label": "Dostupná aktualizácia ovládača NVIDIA"
+ },
+ "coral_driver_update_available": {
+ "title": "{hostname}: Coral TPU dostupná aktualizácia ovládača — {latest_version}",
+ "body": "Je dostupná novšia verzia {variant_label}.\n🔹 Aktuálne nainštalovaná: {current_version}\n🟢 Najnovšia dostupná: {latest_version}\n\n{upgrade_reason}\n\n💡 Preinštalovanie:\n • V ponuke ProxMenux po inštalácii: {menu_label}\n\n{reboot_note}",
+ "label": "Dostupná aktualizácia ovládača Coral TPU"
+ },
+ "burst_auth_fail": {
+ "title": "{hostname}: Ďalšie zlyhania overenia za {window}: +{count}",
+ "body": "Za {window} bolo zistených ďalších {count} zlyhaní overenia (spolu {total_count}).\nZdroje: {entity_list}",
+ "label": "Veľa neúspešných prihlásení"
+ },
+ "burst_ip_block": {
+ "title": "{hostname}: Fail2Ban zablokoval za {window} ďalšie IP: +{count}",
+ "body": "Fail2Ban zablokoval za {window} ďalších {count} IP (spolu {total_count}).\nIP adresy: {entity_list}",
+ "label": "Veľa zablokovaných IP adries"
+ },
+ "burst_disk_io": {
+ "title": "{hostname}: +{count} ďalších chýb I/O disku na {entity_list}",
+ "body": "Za {window} bolo zistených ďalších {count} chýb I/O (spolu {total_count}).\nZariadenia: {entity_list}",
+ "label": "Viacero diskových I/O chýb"
+ },
+ "burst_cluster": {
+ "title": "{hostname}: Zistené kolísanie stavu klastra (+{count} ďalších zmien)",
+ "body": "Stav klastra sa za {window} zmenil ešte {count}-krát (spolu {total_count}).\nUzly: {entity_list}",
+ "label": "Nestabilné spojenie clustra"
+ },
+ "burst_service_fail": {
+ "title": "{hostname}: Za {window} zlyhali ďalšie služby: +{count}",
+ "body": "Za {window} bolo zistených ďalších {count} zlyhaní služieb (spolu {total_count}).\nZvyčajne to znamená reštart uzla alebo služby PVE.\n\nĎalšie zlyhania:\n{details}",
+ "label": "Zlyhanie viacerých služieb"
+ },
+ "burst_system": {
+ "title": "{hostname}: Ďalšie systémové problémy za {window}: +{count}",
+ "body": "Za {window} bolo zistených ďalších {count} systémových problémov (spolu {total_count}).\n\nĎalšie problémy:\n{details}",
+ "label": "Viacero systémových problémov"
+ },
+ "burst_generic": {
+ "title": "{hostname}: Ďalšie udalosti {event_type} za {window}: +{count}",
+ "body": "Za {window} bolo zaznamenaných ďalších {count} udalostí typu {event_type} (spolu {total_count}).\n\nĎalšie udalosti:\n{details}",
+ "label": "Viacero súvisiacich udalostí"
+ },
+ "kernel_warning": {
+ "title": "{hostname}: Zaznamenaná diagnostická udalosť jadra",
+ "body": "Jadro zaznamenalo diagnostickú udalosť: {kernel_details}",
+ "label": "Upozornenia jadra a diagnostické záznamy"
+ }
+ },
+ "lxcUpdate": {
+ "status": {
+ "success": "úspešne dokončená",
+ "failure": "zlyhala",
+ "partial": "dokončená čiastočne",
+ "deferred": "odložená",
+ "skipped": "preskočená"
+ },
+ "source": {
+ "scheduled": "Plánovane",
+ "manual": "Manuálne"
+ },
+ "sourceLabel": "Zdroj",
+ "targets": "Ciele",
+ "osPending": "Čakajúce aktualizácie OS: {before} → {after}",
+ "osUnverified": "Balíky OS: príkaz na aktualizáciu bol spustený, výsledok sa nepodarilo overiť",
+ "applications": "Aplikácie: {items}",
+ "applicationsUnverified": "Aplikácie: aktualizátor bol spustený, nezistila sa však zmena sledovanej verzie",
+ "dockerEngineChange": "Docker Engine: {before} → {after}",
+ "dockerEngineVerified": "Docker Engine: overený vo verzii {version}",
+ "dockerEngineUnverified": "Docker Engine: príkaz na aktualizáciu bol spustený, verziu sa nepodarilo overiť",
+ "dockerImagesPending": "Čakajúce aktualizácie Docker obrazov: {before} → {after}",
+ "dockerImagesChanged": "Zmenené Docker obrazy: {images}",
+ "deferredTargets": "Odložené ciele: {targets}",
+ "reason": "Dôvod: {reason}",
+ "restartRequired": "Vyžaduje sa reštart: {value}",
+ "yes": "áno",
+ "no": "nie",
+ "verificationPending": "Overenie bude pokračovať po spustení kontajnera",
+ "verificationWarning": "Upozornenie pri overení: {error}",
+ "duration": "Trvanie: {duration}"
+ },
+ "fallback": {
+ "unknownTitle": "{hostname}: {event_type}",
+ "healthCheckDegraded": "Zhoršený stav kontroly",
+ "none": "žiadne"
+ },
+ "fields": {
+ "vmid": "VM/CT",
+ "name": "Názov",
+ "device": "Zariadenie",
+ "sourceIp": "Zdrojová IP",
+ "node": "Uzol",
+ "category": "Kategória",
+ "service": "Služba",
+ "jail": "Jail",
+ "user": "Používateľ",
+ "count": "Počet",
+ "window": "Obdobie",
+ "affected": "Ovplyvnené"
+ },
+ "vzdump": {
+ "size": "Veľkosť: {value}",
+ "duration": "Trvanie: {value}",
+ "file": "Súbor",
+ "backups": "Počet záloh: {count}",
+ "failed": "Zlyhalo: {count}",
+ "total": "Spolu: {value}",
+ "time": "Čas: {value}"
+ },
+ "startup": {
+ "issuesTitle": "{hostname}: Spustenie systému – zistených problémov: {count}",
+ "completeTitle": "{hostname}: Spustenie systému dokončené",
+ "operational": "Všetky systémy sú funkčné.",
+ "vmCountOne": "{count} VM",
+ "vmCountMany": "Počet VM: {count}",
+ "ctCountOne": "{count} CT",
+ "ctCountMany": "Počet CT: {count}",
+ "started": "✅ Spustené: {counts}",
+ "vmFailed": "❌ VM {name} zlyhal – {reason}",
+ "ctFailed": "❌ CT {name} zlyhal – {reason}",
+ "unknownError": "neznáma chyba",
+ "storageUnavailable": "⚠️ Nedostupné úložiská: {count} ({names})",
+ "servicesFailed": "⚠️ Zlyhané služby: {count} ({names})",
+ "duration": "⏱️ Spustenie dokončené za {minutes} min"
+ },
+ "appUpdates": {
+ "singleTitle": "{hostname}: Pre {app_name} je na CT {vmid} dostupná aktualizácia",
+ "singleBody": "Aplikácia {app_name} na CT {vmid} ({ct_name}) má novú verziu:\n {installed} → {latest}",
+ "emptyTitle": "{hostname}: Dostupné aktualizácie aplikácií",
+ "emptyBody": "Sú dostupné aktualizácie aplikácií.",
+ "batchTitle": "{hostname}: Dostupné aktualizácie aplikácií: {count}",
+ "batchLeadOneContainer": "Aplikácie s dostupnou novšou verziou: {count} v {container_count} kontajneri LXC:",
+ "batchLeadManyContainers": "Aplikácie s dostupnou novšou verziou: {count} v {container_count} kontajneroch LXC:",
+ "additional": "… ďalšie aplikácie: {count}",
+ "app": "aplikácia",
+ "unknown": "neznáme"
+ },
+ "healthDegraded": {
+ "categories": {
+ "cpu": "Využitie CPU a teplota",
+ "memory": "Pamäť a swap",
+ "storage": "Pripojené úložiská a miesto",
+ "disks": "I/O disku a chyby",
+ "network": "Sieťové rozhrania",
+ "vms": "VM a kontajnery",
+ "services": "Služby PVE",
+ "logs": "Systémové záznamy",
+ "updates": "Systémové aktualizácie",
+ "security": "Bezpečnosť"
+ },
+ "severity": {
+ "critical": "Kritický",
+ "warning": "Upozornenie"
+ },
+ "singleTitle": "{hostname}: {severity} stav – {category}",
+ "multipleTitle": "{hostname}: Zhoršené kontroly stavu: {count}",
+ "multipleLine": "• {severity}: {category}\n {reason}",
+ "reasons": {
+ "cpuSustained": "CPU je nad {threshold} % už {duration} s."
+ }
+ },
+ "digest": {
+ "title": "{hostname}: Súhrn za 24 hodín ({timestamp})",
+ "readFailed": "načítanie súhrnu zlyhalo: {error}",
+ "empty": "Pre toto obdobie súhrnu nie sú uložené žiadne udalosti INFO.",
+ "lead": "{count} udalostí INFO zoskupených podľa kategórie:\n",
+ "more": " • … a ďalšie: {count}",
+ "footer": "(Kritické udalosti a upozornenia boli doručené ihneď, nie v tomto súhrne.)",
+ "quietTitle": "{hostname}: Udalosti uložené počas tichých hodín: {count}",
+ "groups": {
+ "vm_ct": "VM a CT",
+ "backup": "Zálohy",
+ "resources": "Zdroje",
+ "storage": "Úložisko",
+ "network": "Sieť",
+ "security": "Bezpečnosť",
+ "cluster": "Klaster",
+ "services": "Služby",
+ "health": "Stav systému",
+ "updates": "Aktualizácie",
+ "hardware": "Hardvér",
+ "system": "Systém",
+ "other": "Ostatné"
+ }
+ },
+ "test": {
+ "title": "Test ProxMenux",
+ "welcome": "Vitajte v ProxMenux Monitor!",
+ "verify": "Toto je testovacia správa na overenie správneho fungovania notifikačného kanála.",
+ "configuration": "Nastavenie kanála:",
+ "iconsEnabled": "Ikony: zapnuté",
+ "iconsDisabled": "Ikony: vypnuté",
+ "aiEnabled": "AI: zapnutá ({info})",
+ "aiDisabled": "AI: vypnutá",
+ "alerts": "Budete dostávať upozornenia na systémové udalosti, zmeny stavu a bezpečnostné incidenty.",
+ "photoCaption": "Tento obrázok môžete použiť ako profilovú fotografiu svojho notifikačného bota."
+ },
+ "channels": {
+ "discord": {
+ "category": "Kategória",
+ "host": "Server",
+ "severity": "Závažnosť"
+ },
+ "email": {
+ "report": "Prehľad: {group}",
+ "details": "Podrobnosti",
+ "host": "Server",
+ "footer": "Notifikačná služba ProxMenux",
+ "severity": {
+ "critical": "Kritické",
+ "warning": "Upozornenie",
+ "info": "Informácia",
+ "ok": "Vyriešené",
+ "default": "Oznámenie"
+ },
+ "groups": {
+ "vm_ct": "Virtuálny stroj / kontajner",
+ "backup": "Záloha a snímka",
+ "resources": "Systémové zdroje",
+ "storage": "Úložisko",
+ "network": "Sieť",
+ "security": "Bezpečnosť",
+ "cluster": "Klaster",
+ "services": "Systémové služby",
+ "health": "Stav systému",
+ "updates": "Systémové aktualizácie",
+ "system": "Systém",
+ "hardware": "Hardvér",
+ "other": "Systémová notifikácia"
+ },
+ "fields": {
+ "vmCtId": "ID VM/CT",
+ "name": "Názov",
+ "action": "Akcia",
+ "targetNode": "Cieľový uzol",
+ "reason": "Dôvod",
+ "storage": "Úložisko",
+ "status": "Stav",
+ "size": "Veľkosť",
+ "duration": "Trvanie",
+ "snapshot": "Snímka",
+ "metric": "Metrika",
+ "currentValue": "Aktuálna hodnota",
+ "threshold": "Prahová hodnota",
+ "cpuCores": "Jadrá CPU",
+ "memory": "Pamäť",
+ "temperature": "Teplota",
+ "mountPoint": "Bod pripojenia",
+ "usage": "Využitie",
+ "available": "Voľné",
+ "device": "Zariadenie",
+ "severity": "Závažnosť",
+ "storageName": "Názov úložiska",
+ "type": "Typ",
+ "interface": "Rozhranie",
+ "latency": "Latencia",
+ "event": "Udalosť",
+ "sourceIp": "Zdrojová IP",
+ "username": "Používateľ",
+ "service": "Služba",
+ "jail": "Jail",
+ "failures": "Zlyhania",
+ "change": "Zmena",
+ "node": "Uzol",
+ "quorum": "Kvórum",
+ "nodesAffected": "Ovplyvnené uzly",
+ "process": "Proces",
+ "category": "Kategória",
+ "previousSeverity": "Predchádzajúca závažnosť",
+ "activeIssues": "Aktívne problémy",
+ "totalUpdates": "Aktualizácie spolu",
+ "securityUpdates": "Bezpečnostné aktualizácie",
+ "proxmoxUpdates": "Aktualizácie Proxmox",
+ "kernelUpdates": "Aktualizácie jadra",
+ "importantPackages": "Dôležité balíky",
+ "currentVersion": "Aktuálna verzia",
+ "newVersion": "Nová verzia"
+ },
+ "status": {
+ "failed": "Zlyhalo",
+ "completed": "Dokončené",
+ "started": "Spustené"
+ }
+ }
+ }
+ }
+ }
}
diff --git a/AppImage/messages/sv/common.json b/AppImage/messages/sv/common.json
index 849f4dd4..4d573709 100644
--- a/AppImage/messages/sv/common.json
+++ b/AppImage/messages/sv/common.json
@@ -3845,7 +3845,8 @@
"startingExport": "Förbereder nedladdning...",
"title": "Säkerhetskopieringar",
"viewContentsTitle": "Visa säkerhetskopieringsinnehåll",
- "descriptionAfter": ""
+ "descriptionAfter": "",
+ "emptyMessage": "Inga backup-arkiv hittades."
},
"backends": {
"borgDescription": "Borg-arkiv för deduplicerade värdsäkerhetskopior.",
@@ -3961,7 +3962,9 @@
"sshUserHelpBefore": "Användare på fjärrvärden,",
"title": "Destinationer",
"unmountTitle": "Avmontera denna destination",
- "whereIsBorgRepo": "Var finns Borgarkivet?"
+ "whereIsBorgRepo": "Var finns Borgarkivet?",
+ "backupsKeptMessage": "Befintliga säkerhetskopieringsarkiv tas inte bort.",
+ "localAttachHelpMessage": "Montera USB-enheter först.Lämna tomt för att använda PVE-lagringssökvägen + /dump (fallback: /var/lib/vz/dump)."
},
"encryption": {
"autoDetectedFromPveStorage": "Upptäckt från PVE-lagring",
From f63362b460ff5d98390ca92c151d95feb66c5ca3 Mon Sep 17 00:00:00 2001
From: ProxMenuxBot
Date: Tue, 22 Sep 2026 14:41:16 +0000
Subject: [PATCH 4/4] chore(lang): auto-rebuild translation cache
Source: a6ca3d4
Triggered by: push
---
lang/de.json | 8 +++-----
lang/es.json | 8 +++-----
lang/fr.json | 8 +++-----
lang/it.json | 8 +++-----
lang/pt.json | 8 +++-----
lang/sk.json | 8 +++-----
lang/sv.json | 8 +++-----
7 files changed, 21 insertions(+), 35 deletions(-)
diff --git a/lang/de.json b/lang/de.json
index 2a7cb744..382217dc 100644
--- a/lang/de.json
+++ b/lang/de.json
@@ -644,6 +644,7 @@
"Completed Successfully!": "Erfolgreich abgeschlossen!",
"Completed with errors —": "Mit Fehlern abgeschlossen –",
"Completed.": "Vollendet.",
+ "Completed. Devices added to VM {vmid}: {count}.": "Abgeschlossen. Zur VM {vmid} hinzugefügte Geräte: {count}.",
"Completed. Press Enter to return to menu...": "Vollendet. Drücken Sie die Eingabetaste, um zum Menü zurückzukehren...",
"Completing pending package configurations...": "Ausstehende Paketkonfigurationen werden abgeschlossen...",
"Compliance checking (PCI-DSS, HIPAA, etc.)": "Konformitätsprüfung (PCI-DSS, HIPAA usw.)",
@@ -1045,7 +1046,6 @@
"Current user": "Aktueller Benutzer",
"Current user UID, GID and groups": "Aktuelle Benutzer-UID, GID und Gruppen",
"Current version:": "Aktuelle Version:",
- "Currently": "Momentan",
"Currently Mounted:": "Derzeit montiert:",
"Currently configured target:": "Derzeit konfiguriertes Ziel:",
"Currently mounted:": "Derzeit montiert:",
@@ -1068,6 +1068,7 @@
"Custom path": "Benutzerdefinierter Pfad",
"Custom path...": "Benutzerdefinierter Pfad...",
"Custom paths are included in BOTH default and custom backup profiles.": "Benutzerdefinierte Pfade sind SOWOHL in den Standard- als auch in den benutzerdefinierten Sicherungsprofilen enthalten.",
+ "Custom paths currently saved: {count}.": "Derzeit gespeicherte benutzerdefinierte Pfade: {count}.",
"Custom restore by components": "Benutzerdefinierte Wiederherstellung nach Komponenten",
"Custom restore by paths": "Benutzerdefinierte Wiederherstellung nach Pfaden",
"Custom scripts and ProxMenux files": "Benutzerdefinierte Skripte und ProxMenux-Dateien",
@@ -2220,7 +2221,6 @@
"Installed": "Installiert",
"Installed at:": "Installiert unter:",
"Installed components:": "Installierte Komponenten:",
- "Installed:": "Installiert:",
"Installer already downloaded and verified.": "Das Installationsprogramm wurde bereits heruntergeladen und überprüft.",
"Installer copied to container.": "Installer in Container kopiert.",
"Installer downloaded.": "Installer heruntergeladen.",
@@ -3178,6 +3178,7 @@
"Package update completed with warnings, continuing...": "Paketaktualisierung mit Warnungen abgeschlossen, Fortsetzung ...",
"Package update had issues, checking details...": "Bei der Paketaktualisierung gab es Probleme, beim Überprüfen der Details ...",
"Packages from backup to install:": "Pakete vom Backup zur Installation:",
+ "Packages installed: {count}.": "Installierte Pakete: {count}.",
"Packages upgrade successfull": "Paketaktualisierung erfolgreich",
"Packages upgraded": "Pakete aktualisiert",
"Packages:": "Pakete:",
@@ -5057,12 +5058,10 @@
"chown/chmod failed — likely unprivileged CT against host bind mount. Falling back to ACL.": "chown/chmod fehlgeschlagen – wahrscheinlich unprivilegierter CT gegen Host-Bind-Mount. Zurückgreifen auf ACL.",
"content:": "Inhalt:",
"could not be compiled for kernel": "konnte nicht für den Kernel kompiliert werden",
- "custom path(s) saved.": "Benutzerdefinierte(r) Pfad(e) gespeichert.",
"default": "Standard",
"delete the credentials file (if any)": "Löschen Sie die Anmeldeinformationsdatei (falls vorhanden).",
"delete the matching line from /etc/fstab": "Löschen Sie die entsprechende Zeile aus /etc/fstab",
"descriptor + VMDK files": "Deskriptor + VMDK-Dateien",
- "device(s) added to VM": "Gerät(e) zur VM hinzugefügt",
"devices": "Geräte",
"did not become ready. Skipping.": "nicht fertig geworden. Überspringen.",
"disk(s) added to CT": "Festplatte(n) zu CT hinzugefügt",
@@ -5238,7 +5237,6 @@
"orphan iface lines, no impact on restore": "Verwaiste Iface-Zeilen, keine Auswirkung auf die Wiederherstellung",
"other .tar archive(s) — not ProxMenux host backups (e.g. PVE vzdump or unrelated tarballs).": "andere .tar-Archive – keine ProxMenux-Host-Backups (z. B. PVE vzdump oder nicht verwandte Tarballs).",
"packages (this may take a few minutes)...": "Pakete (dies kann einige Minuten dauern)...",
- "packages.": "Pakete.",
"parent PF:": "Eltern-PF:",
"partition(s). Partition table preserved.": "Partition(en). Partitionstabelle bleibt erhalten.",
"paths for next boot (/etc/pve, guests, drivers, ...)": "Pfade für den nächsten Start (/etc/pve, Gäste, Treiber, ...)",
diff --git a/lang/es.json b/lang/es.json
index 97cd2810..03a319d2 100644
--- a/lang/es.json
+++ b/lang/es.json
@@ -644,6 +644,7 @@
"Completed Successfully!": "¡Completado con éxito!",
"Completed with errors —": "Completado con errores.",
"Completed.": "Terminado.",
+ "Completed. Devices added to VM {vmid}: {count}.": "Completado. Dispositivos agregados a la VM {vmid}: {count}.",
"Completed. Press Enter to return to menu...": "Terminado. Presione Enter para regresar al menú...",
"Completing pending package configurations...": "Completando las configuraciones de paquetes pendientes...",
"Compliance checking (PCI-DSS, HIPAA, etc.)": "Comprobación de cumplimiento (PCI-DSS, HIPAA, etc.)",
@@ -1045,7 +1046,6 @@
"Current user": "Usuario actual",
"Current user UID, GID and groups": "UID, GID y grupos del usuario actual",
"Current version:": "Versión actual:",
- "Currently": "actualmente",
"Currently Mounted:": "Actualmente montado:",
"Currently configured target:": "Destino actualmente configurado:",
"Currently mounted:": "Actualmente montado:",
@@ -1068,6 +1068,7 @@
"Custom path": "Ruta personalizada",
"Custom path...": "Ruta personalizada...",
"Custom paths are included in BOTH default and custom backup profiles.": "Las rutas personalizadas se incluyen tanto en los perfiles de copia de seguridad predeterminados como en los personalizados.",
+ "Custom paths currently saved: {count}.": "Rutas personalizadas guardadas actualmente: {count}.",
"Custom restore by components": "Restauración personalizada por componentes",
"Custom restore by paths": "restauración personalizada por rutas",
"Custom scripts and ProxMenux files": "Scripts personalizados y archivos ProxMenux",
@@ -2220,7 +2221,6 @@
"Installed": "Instalado",
"Installed at:": "Instalado en:",
"Installed components:": "Componentes instalados:",
- "Installed:": "Instalado:",
"Installer already downloaded and verified.": "Instalador ya descargado y verificado.",
"Installer copied to container.": "Instalador copiado al contenedor.",
"Installer downloaded.": "Instalador descargado.",
@@ -3178,6 +3178,7 @@
"Package update completed with warnings, continuing...": "Actualización del paquete completada con advertencias, continúa...",
"Package update had issues, checking details...": "La actualización del paquete tuvo problemas, comprobando detalles...",
"Packages from backup to install:": "Paquetes de copia de seguridad para instalar:",
+ "Packages installed: {count}.": "Paquetes instalados: {count}.",
"Packages upgrade successfull": "Actualización de paquetes exitosa",
"Packages upgraded": "Paquetes actualizados",
"Packages:": "Paquetes:",
@@ -5057,12 +5058,10 @@
"chown/chmod failed — likely unprivileged CT against host bind mount. Falling back to ACL.": "chown/chmod falló: probablemente CT sin privilegios contra el montaje de enlace del host. Regresando a ACL.",
"content:": "contenido:",
"could not be compiled for kernel": "no se pudo compilar para el kernel",
- "custom path(s) saved.": "rutas personalizadas guardadas.",
"default": "por defecto",
"delete the credentials file (if any)": "eliminar el archivo de credenciales (si corresponde)",
"delete the matching line from /etc/fstab": "elimine la línea coincidente de /etc/fstab",
"descriptor + VMDK files": "descriptor + archivos VMDK",
- "device(s) added to VM": "Dispositivo(s) agregado(s) a la VM",
"devices": "dispositivos",
"did not become ready. Skipping.": "no estuvo listo. Salto a la comba.",
"disk(s) added to CT": "disco(s) agregado(s) a CT",
@@ -5238,7 +5237,6 @@
"orphan iface lines, no impact on restore": "líneas de iface huérfanas, sin impacto en la restauración",
"other .tar archive(s) — not ProxMenux host backups (e.g. PVE vzdump or unrelated tarballs).": "otros archivos .tar, no copias de seguridad del host ProxMenux (por ejemplo, PVE vzdump o archivos tar no relacionados).",
"packages (this may take a few minutes)...": "paquetes (esto puede tardar unos minutos)...",
- "packages.": "paquetes.",
"parent PF:": "padre PF:",
"partition(s). Partition table preserved.": "partición(es). Se conserva la tabla de particiones.",
"paths for next boot (/etc/pve, guests, drivers, ...)": "rutas para el próximo arranque (/etc/pve, invitados, controladores, ...)",
diff --git a/lang/fr.json b/lang/fr.json
index f4a9f3cd..01cf3f3b 100644
--- a/lang/fr.json
+++ b/lang/fr.json
@@ -644,6 +644,7 @@
"Completed Successfully!": "Terminé avec succès !",
"Completed with errors —": "Complété avec des erreurs —",
"Completed.": "Complété.",
+ "Completed. Devices added to VM {vmid}: {count}.": "Terminé. Appareils ajoutés à la VM {vmid} : {count}.",
"Completed. Press Enter to return to menu...": "Complété. Appuyez sur Entrée pour revenir au menu...",
"Completing pending package configurations...": "Finalisation des configurations de packages en attente...",
"Compliance checking (PCI-DSS, HIPAA, etc.)": "Vérification de la conformité (PCI-DSS, HIPAA, etc.)",
@@ -1045,7 +1046,6 @@
"Current user": "Utilisateur actuel",
"Current user UID, GID and groups": "UID, GID et groupes de l'utilisateur actuel",
"Current version:": "Version actuelle :",
- "Currently": "Actuellement",
"Currently Mounted:": "Actuellement monté :",
"Currently configured target:": "cible actuellement configurée :",
"Currently mounted:": "Actuellement monté :",
@@ -1068,6 +1068,7 @@
"Custom path": "Chemin personnalisé",
"Custom path...": "Chemin personnalisé...",
"Custom paths are included in BOTH default and custom backup profiles.": "Les chemins personnalisés sont inclus dans les profils de sauvegarde par défaut et personnalisés.",
+ "Custom paths currently saved: {count}.": "Chemins personnalisés actuellement enregistrés : {count}.",
"Custom restore by components": "Restauration personnalisée par composants",
"Custom restore by paths": "Restauration personnalisée par chemins",
"Custom scripts and ProxMenux files": "Scripts personnalisés et fichiers ProxMenux",
@@ -2220,7 +2221,6 @@
"Installed": "Installé",
"Installed at:": "Installé à :",
"Installed components:": "Composants installés :",
- "Installed:": "Installé:",
"Installer already downloaded and verified.": "Installateur déjà téléchargé et vérifié.",
"Installer copied to container.": "Programme d'installation copié dans le conteneur.",
"Installer downloaded.": "Installateur téléchargé.",
@@ -3178,6 +3178,7 @@
"Package update completed with warnings, continuing...": "Mise à jour du package terminée avec des avertissements, suite...",
"Package update had issues, checking details...": "La mise à jour du package a rencontré des problèmes, vérification des détails...",
"Packages from backup to install:": "Packages de la sauvegarde à installer :",
+ "Packages installed: {count}.": "Packages installés : {count}.",
"Packages upgrade successfull": "Mise à jour des packages réussie",
"Packages upgraded": "Forfaits mis à niveau",
"Packages:": "Forfaits :",
@@ -5057,12 +5058,10 @@
"chown/chmod failed — likely unprivileged CT against host bind mount. Falling back to ACL.": "chown/chmod a échoué - CT probablement non privilégié contre le montage de liaison de l'hôte. Revenir à ACL.",
"content:": "contenu:",
"could not be compiled for kernel": "n'a pas pu être compilé pour le noyau",
- "custom path(s) saved.": "chemin(s) personnalisé(s) enregistré(s).",
"default": "défaut",
"delete the credentials file (if any)": "supprimer le fichier d'informations d'identification (le cas échéant)",
"delete the matching line from /etc/fstab": "supprimez la ligne correspondante de /etc/fstab",
"descriptor + VMDK files": "descripteur + fichiers VMDK",
- "device(s) added to VM": "périphérique(s) ajouté(s) à la VM",
"devices": "appareils",
"did not become ready. Skipping.": "n'est pas devenu prêt. Saut.",
"disk(s) added to CT": "disque(s) ajouté(s) à CT",
@@ -5238,7 +5237,6 @@
"orphan iface lines, no impact on restore": "lignes iface orphelines, aucun impact sur la restauration",
"other .tar archive(s) — not ProxMenux host backups (e.g. PVE vzdump or unrelated tarballs).": "autres archives .tar - pas les sauvegardes de l'hôte ProxMenux (par exemple, vzdump PVE ou archives tar sans rapport).",
"packages (this may take a few minutes)...": "packages (cela peut prendre quelques minutes)...",
- "packages.": "paquets.",
"parent PF:": "PF parent :",
"partition(s). Partition table preserved.": "partition(s). Table de partition conservée.",
"paths for next boot (/etc/pve, guests, drivers, ...)": "chemins pour le prochain démarrage (/etc/pve, invités, pilotes, ...)",
diff --git a/lang/it.json b/lang/it.json
index cf276b33..eea682d5 100644
--- a/lang/it.json
+++ b/lang/it.json
@@ -644,6 +644,7 @@
"Completed Successfully!": "Completato con successo!",
"Completed with errors —": "Completato con errori —",
"Completed.": "Completato.",
+ "Completed. Devices added to VM {vmid}: {count}.": "completato. Dispositivi aggiunti alla VM {vmid}: {count}.",
"Completed. Press Enter to return to menu...": "Completato. Premere Invio per tornare al menu...",
"Completing pending package configurations...": "completamento delle configurazioni dei pacchetti in sospeso...",
"Compliance checking (PCI-DSS, HIPAA, etc.)": "Controllo della conformità (PCI-DSS, HIPAA, ecc.)",
@@ -1045,7 +1046,6 @@
"Current user": "Utente attuale",
"Current user UID, GID and groups": "UID, GID e gruppi dell'utente corrente",
"Current version:": "Versione attuale:",
- "Currently": "Attualmente",
"Currently Mounted:": "Attualmente montato:",
"Currently configured target:": "destinazione attualmente configurata:",
"Currently mounted:": "Attualmente montato:",
@@ -1068,6 +1068,7 @@
"Custom path": "Percorso personalizzato",
"Custom path...": "Percorso personalizzato...",
"Custom paths are included in BOTH default and custom backup profiles.": "I percorsi personalizzati sono inclusi SIA nei profili di backup predefiniti che in quelli personalizzati.",
+ "Custom paths currently saved: {count}.": "percorsi personalizzati attualmente salvati: {count}.",
"Custom restore by components": "Ripristino personalizzato per componenti",
"Custom restore by paths": "ripristino personalizzato per percorsi",
"Custom scripts and ProxMenux files": "Script personalizzati e file ProxMenux",
@@ -2220,7 +2221,6 @@
"Installed": "Installato",
"Installed at:": "Installato presso:",
"Installed components:": "Componenti installati:",
- "Installed:": "Installato:",
"Installer already downloaded and verified.": "Programma di installazione già scaricato e verificato.",
"Installer copied to container.": "Programma di installazione copiato nel contenitore.",
"Installer downloaded.": "Programma di installazione scaricato.",
@@ -3178,6 +3178,7 @@
"Package update completed with warnings, continuing...": "Aggiornamento del pacchetto completato con avvisi, continuando...",
"Package update had issues, checking details...": "L'aggiornamento del pacchetto presentava problemi, verifica dei dettagli...",
"Packages from backup to install:": "pacchetti dal backup all'installazione:",
+ "Packages installed: {count}.": "pacchetti installati: {count}.",
"Packages upgrade successfull": "Aggiornamento dei pacchetti riuscito",
"Packages upgraded": "Pacchetti aggiornati",
"Packages:": "Pacchetti:",
@@ -5057,12 +5058,10 @@
"chown/chmod failed — likely unprivileged CT against host bind mount. Falling back to ACL.": "chown/chmod non è riuscito: probabilmente CT non privilegiato contro il montaggio del collegamento dell'host. Ritornando all'ACL.",
"content:": "contenuto:",
"could not be compiled for kernel": "non può essere compilato per il kernel",
- "custom path(s) saved.": "percorsi personalizzati salvati.",
"default": "predefinito",
"delete the credentials file (if any)": "eliminare il file delle credenziali (se presente)",
"delete the matching line from /etc/fstab": "elimina la riga corrispondente da /etc/fstab",
"descriptor + VMDK files": "descrittore + file VMDK",
- "device(s) added to VM": "dispositivi aggiunti alla VM",
"devices": "dispositivi",
"did not become ready. Skipping.": "non è diventato pronto. Saltare.",
"disk(s) added to CT": "disco(i) aggiunto(i) a CT",
@@ -5238,7 +5237,6 @@
"orphan iface lines, no impact on restore": "Linee iface orfane, nessun impatto sul ripristino",
"other .tar archive(s) — not ProxMenux host backups (e.g. PVE vzdump or unrelated tarballs).": "altri archivi .tar — non backup dell'host ProxMenux (ad esempio PVE vzdump o tarball non correlati).",
"packages (this may take a few minutes)...": "pacchetti (l'operazione potrebbe richiedere alcuni minuti)...",
- "packages.": "pacchetti.",
"parent PF:": "PF genitore:",
"partition(s). Partition table preserved.": "partizione(i). Tabella delle partizioni conservata.",
"paths for next boot (/etc/pve, guests, drivers, ...)": "percorsi per l'avvio successivo (/etc/pve, guest, driver, ...)",
diff --git a/lang/pt.json b/lang/pt.json
index c13957d6..c29e9276 100644
--- a/lang/pt.json
+++ b/lang/pt.json
@@ -644,6 +644,7 @@
"Completed Successfully!": "Concluído com sucesso!",
"Completed with errors —": "Concluído com erros -",
"Completed.": "Concluído.",
+ "Completed. Devices added to VM {vmid}: {count}.": "Concluído. Dispositivos adicionados à VM {vmid}: {count}.",
"Completed. Press Enter to return to menu...": "Concluído. Pressione Enter para retornar ao menu...",
"Completing pending package configurations...": "Concluindo configurações de pacotes pendentes...",
"Compliance checking (PCI-DSS, HIPAA, etc.)": "Verificação de conformidade (PCI-DSS, HIPAA, etc.)",
@@ -1045,7 +1046,6 @@
"Current user": "Usuário atual",
"Current user UID, GID and groups": "UID, GID e grupos do usuário atual",
"Current version:": "Versão atual:",
- "Currently": "Atualmente",
"Currently Mounted:": "Atualmente montado:",
"Currently configured target:": "destino atualmente configurado:",
"Currently mounted:": "Atualmente montado:",
@@ -1068,6 +1068,7 @@
"Custom path": "Caminho personalizado",
"Custom path...": "Caminho personalizado...",
"Custom paths are included in BOTH default and custom backup profiles.": "Os caminhos personalizados estão incluídos em AMBOS os perfis de backup padrão e personalizados.",
+ "Custom paths currently saved: {count}.": "caminhos personalizados salvos atualmente: {count}.",
"Custom restore by components": "Restauração personalizada por componentes",
"Custom restore by paths": "restauração personalizada por caminhos",
"Custom scripts and ProxMenux files": "Scripts personalizados e arquivos ProxMenux",
@@ -2220,7 +2221,6 @@
"Installed": "Instalado",
"Installed at:": "Instalado em:",
"Installed components:": "Componentes instalados:",
- "Installed:": "Instalado:",
"Installer already downloaded and verified.": "Instalador já baixado e verificado.",
"Installer copied to container.": "Instalador copiado para contêiner.",
"Installer downloaded.": "Instalador baixado.",
@@ -3178,6 +3178,7 @@
"Package update completed with warnings, continuing...": "Atualização do pacote concluída com avisos, continuando...",
"Package update had issues, checking details...": "A atualização do pacote teve problemas, verificando detalhes...",
"Packages from backup to install:": "Pacotes do backup para instalação:",
+ "Packages installed: {count}.": "Pacotes instalados: {count}.",
"Packages upgrade successfull": "Atualização de pacotes bem-sucedida",
"Packages upgraded": "Pacotes atualizados",
"Packages:": "Pacotes:",
@@ -5057,12 +5058,10 @@
"chown/chmod failed — likely unprivileged CT against host bind mount. Falling back to ACL.": "chown/chmod falhou — provavelmente CT sem privilégios contra montagem de ligação do host. Voltando ao ACL.",
"content:": "contente:",
"could not be compiled for kernel": "não foi possível compilar para o kernel",
- "custom path(s) saved.": "caminhos personalizados salvos.",
"default": "padrão",
"delete the credentials file (if any)": "exclua o arquivo de credenciais (se houver)",
"delete the matching line from /etc/fstab": "exclua a linha correspondente de /etc/fstab",
"descriptor + VMDK files": "descritor + arquivos VMDK",
- "device(s) added to VM": "dispositivos adicionados à VM",
"devices": "dispositivos",
"did not become ready. Skipping.": "não ficou pronto. Pulando.",
"disk(s) added to CT": "disco(s) adicionado(s) ao CT",
@@ -5238,7 +5237,6 @@
"orphan iface lines, no impact on restore": "linhas iface órfãs, sem impacto na restauração",
"other .tar archive(s) — not ProxMenux host backups (e.g. PVE vzdump or unrelated tarballs).": "outros arquivos .tar — não backups de host ProxMenux (por exemplo, PVE vzdump ou tarballs não relacionados).",
"packages (this may take a few minutes)...": "pacotes (isso pode levar alguns minutos)...",
- "packages.": "pacotes.",
"parent PF:": "pai PF:",
"partition(s). Partition table preserved.": "partição(ões). Tabela de partição preservada.",
"paths for next boot (/etc/pve, guests, drivers, ...)": "caminhos para a próxima inicialização (/etc/pve, convidados, drivers, ...)",
diff --git a/lang/sk.json b/lang/sk.json
index 3b26488a..f19561d0 100644
--- a/lang/sk.json
+++ b/lang/sk.json
@@ -644,6 +644,7 @@
"Completed Successfully!": "Úspešne dokončené.",
"Completed with errors —": "Dokončené s chybami -",
"Completed.": "Dokončené.",
+ "Completed. Devices added to VM {vmid}: {count}.": "Dokončené. Zariadenia pridané do VM {vmid}: {count}.",
"Completed. Press Enter to return to menu...": "Dokončené. Stlačte Enter pre návrat do menu...",
"Completing pending package configurations...": "Dokončenie čakajúcich konfigurácií balíka...",
"Compliance checking (PCI-DSS, HIPAA, etc.)": "kontroly súladu (PCI-DSS, HIPAA atď.)",
@@ -1045,7 +1046,6 @@
"Current user": "Aktuálny používateľ",
"Current user UID, GID and groups": "UID, GID a skupiny aktuálneho používateľa",
"Current version:": "Aktuálna verzia:",
- "Currently": "Aktuálne",
"Currently Mounted:": "Aktuálne pripojené:",
"Currently configured target:": "Aktuálne nastavený cieľ:",
"Currently mounted:": "Aktuálne pripojené:",
@@ -1068,6 +1068,7 @@
"Custom path": "Vlastná cesta",
"Custom path...": "Vlastná cesta...",
"Custom paths are included in BOTH default and custom backup profiles.": "Vlastné cesty sú zahrnuté v predvolenom aj vlastnom profile zálohy.",
+ "Custom paths currently saved: {count}.": "Aktuálne uložené vlastné cesty: {count}.",
"Custom restore by components": "Vlastná obnova podľa súčastí",
"Custom restore by paths": "Vlastná obnova podľa ciest",
"Custom scripts and ProxMenux files": "Vlastné skripty a súbory ProxMenux",
@@ -2220,7 +2221,6 @@
"Installed": "Nainštalované",
"Installed at:": "Nainštalované v:",
"Installed components:": "Nainštalované súčasti:",
- "Installed:": "Nainštalované:",
"Installer already downloaded and verified.": "Inštalátor už je stiahnutý a overený.",
"Installer copied to container.": "Inštalátor skopírovaný do kontajnera.",
"Installer downloaded.": "Inštalátor bol stiahnutý.",
@@ -3178,6 +3178,7 @@
"Package update completed with warnings, continuing...": "Aktualizácia balíkov skončila s upozorneniami, pokračujem...",
"Package update had issues, checking details...": "Pri aktualizácii balíkov nastali problémy, kontrolujem podrobnosti...",
"Packages from backup to install:": "Balíky zo zálohy na inštaláciu:",
+ "Packages installed: {count}.": "Nainštalované balíky: {count}.",
"Packages upgrade successfull": "Aktualizácia balíkov bola úspešná",
"Packages upgraded": "Aktualizované balíky",
"Packages:": "Balíky:",
@@ -5057,12 +5058,10 @@
"chown/chmod failed — likely unprivileged CT against host bind mount. Falling back to ACL.": "chown/chmod zlyhalo - pravdepodobne ide o neprivilegovaný CT nad bind mountom z hosta. Skúšam náhradné riešenie cez ACL.",
"content:": "obsah:",
"could not be compiled for kernel": "nepodarilo sa skompilovať pre jadro",
- "custom path(s) saved.": "uložených vlastných ciest.",
"default": "predvolené",
"delete the credentials file (if any)": "vymazať súbor s prihlasovacími údajmi (ak existuje)",
"delete the matching line from /etc/fstab": "odstrániť zodpovedajúci riadok z /etc/fstab",
"descriptor + VMDK files": "popisovač + VMDK súbory",
- "device(s) added to VM": "zariadení pridaných do VM",
"devices": "zariadenia",
"did not become ready. Skipping.": "nebol pripravený. Preskakujem.",
"disk(s) added to CT": "diskov pridaných do CT",
@@ -5238,7 +5237,6 @@
"orphan iface lines, no impact on restore": "osirelé iface riadky, bez vplyvu na obnovu",
"other .tar archive(s) — not ProxMenux host backups (e.g. PVE vzdump or unrelated tarballs).": "iné .tar archívy - nie sú to ProxMenux zálohy hosta (napr. PVE vzdump alebo nesúvisiace tar archívy).",
"packages (this may take a few minutes)...": "balíkov (môže to trvať pár minút)...",
- "packages.": "balíkov.",
"parent PF:": "rodičovská PF:",
"partition(s). Partition table preserved.": "oddielov. Tabuľka oddielov zostala zachovaná.",
"paths for next boot (/etc/pve, guests, drivers, ...)": "cesty na najbližší štart (/etc/pve, hostia, ovládače, ...)",
diff --git a/lang/sv.json b/lang/sv.json
index b7d80896..3480aee4 100644
--- a/lang/sv.json
+++ b/lang/sv.json
@@ -644,6 +644,7 @@
"Completed Successfully!": "Avslutad framgångsrikt!",
"Completed with errors —": "Kompletterad med fel —",
"Completed.": "Avslutad.",
+ "Completed. Devices added to VM {vmid}: {count}.": "Klar. Enheter som har lagts till VM {vmid}: {count}.",
"Completed. Press Enter to return to menu...": "Avslutad. Tryck på Enter för att återgå till menyn...",
"Completing pending package configurations...": "Slutför väntande paketkonfigurationer...",
"Compliance checking (PCI-DSS, HIPAA, etc.)": "Överensstämmelsekontroll (PCI-DSS, HIPAA, etc.)",
@@ -1045,7 +1046,6 @@
"Current user": "Nuvarande användare",
"Current user UID, GID and groups": "Aktuell användar-UID, GID och grupper",
"Current version:": "Aktuell version:",
- "Currently": "För närvarande",
"Currently Mounted:": "För närvarande monterad:",
"Currently configured target:": "För närvarande konfigurerat mål:",
"Currently mounted:": "För närvarande monterad:",
@@ -1068,6 +1068,7 @@
"Custom path": "Anpassad sökväg",
"Custom path...": "Anpassad sökväg...",
"Custom paths are included in BOTH default and custom backup profiles.": "Anpassade sökvägar ingår i BÅDE standard- och anpassade säkerhetskopieringsprofiler.",
+ "Custom paths currently saved: {count}.": "Anpassade sökvägar sparade för närvarande: {count}.",
"Custom restore by components": "Anpassad återställning av komponenter",
"Custom restore by paths": "Anpassad återställning av sökvägar",
"Custom scripts and ProxMenux files": "Anpassade skript och ProxMenux-filer",
@@ -2220,7 +2221,6 @@
"Installed": "Installerad",
"Installed at:": "Installerad på:",
"Installed components:": "Installerade komponenter:",
- "Installed:": "Installerat:",
"Installer already downloaded and verified.": "Installationsprogrammet har redan laddats ner och verifierats.",
"Installer copied to container.": "Installatören kopierad till behållaren.",
"Installer downloaded.": "Installationsprogrammet nedladdat.",
@@ -3178,6 +3178,7 @@
"Package update completed with warnings, continuing...": "Paketuppdateringen slutförd med varningar, fortsätter...",
"Package update had issues, checking details...": "Paketuppdateringen hade problem, kontrollerade detaljer...",
"Packages from backup to install:": "Paket från säkerhetskopia till installation:",
+ "Packages installed: {count}.": "Paket installerade: {count}.",
"Packages upgrade successfull": "Paketuppgraderingen lyckades",
"Packages upgraded": "Paketen har uppgraderats",
"Packages:": "Paket:",
@@ -5057,12 +5058,10 @@
"chown/chmod failed — likely unprivileged CT against host bind mount. Falling back to ACL.": "chown/chmod misslyckades — sannolikt oprivilegierad CT mot värdbindningsmontering. Faller tillbaka till ACL.",
"content:": "innehåll:",
"could not be compiled for kernel": "kunde inte kompileras för kärnan",
- "custom path(s) saved.": "anpassade sökvägar har sparats.",
"default": "standard",
"delete the credentials file (if any)": "radera autentiseringsfilen (om någon)",
"delete the matching line from /etc/fstab": "ta bort den matchande raden från /etc/fstab",
"descriptor + VMDK files": "descriptor + VMDK-filer",
- "device(s) added to VM": "enhet(er) har lagts till i VM",
"devices": "enheter",
"did not become ready. Skipping.": "blev inte redo. Hoppa över.",
"disk(s) added to CT": "disk(ar) har lagts till i CT",
@@ -5238,7 +5237,6 @@
"orphan iface lines, no impact on restore": "föräldralösa iface-linjer, ingen inverkan på återställning",
"other .tar archive(s) — not ProxMenux host backups (e.g. PVE vzdump or unrelated tarballs).": "andra .tar-arkiv – inte ProxMenux-värdsäkerhetskopior (t.ex. PVE vzdump eller orelaterade tarballs).",
"packages (this may take a few minutes)...": "paket (detta kan ta några minuter)...",
- "packages.": "paket.",
"parent PF:": "förälder PF:",
"partition(s). Partition table preserved.": "partition(er). Partitionstabell bevarad.",
"paths for next boot (/etc/pve, guests, drivers, ...)": "sökvägar för nästa start (/etc/pve, gäster, drivrutin, ...)",