mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-09-29 10:06:41 +00:00
Merge pull request #388 from MacRimi/beta/1.2.6.2
ProxMenux pre 1.2.6.2-beta: OCI containers in the Monitor, docs and fixes
This commit is contained in:
@@ -116,7 +116,9 @@ def protect_placeholders(text: str) -> tuple[str, list[str]]:
|
||||
|
||||
def _swap(match: re.Match) -> str:
|
||||
placeholders.append(match.group(0))
|
||||
return f"__PMX_PH_{len(placeholders) - 1}__"
|
||||
# No underscores: a local model splits on them and returns
|
||||
# "PMX PH 0", so the placeholder never comes back.
|
||||
return f"PMXPH{len(placeholders) - 1:03d}"
|
||||
|
||||
return PLACEHOLDER_RE.sub(_swap, text), placeholders
|
||||
|
||||
@@ -127,7 +129,7 @@ def restore_placeholders(text: str, placeholders: list[str]) -> str:
|
||||
fallback assignment (target = existing or EN) upstream catches
|
||||
the worst case."""
|
||||
for i, original in enumerate(placeholders):
|
||||
text = text.replace(f"__PMX_PH_{i}__", original)
|
||||
text = text.replace(f"PMXPH{i:03d}", original)
|
||||
return text
|
||||
|
||||
|
||||
@@ -241,9 +243,16 @@ def build_arg_parser() -> argparse.ArgumentParser:
|
||||
"--refresh",
|
||||
action="store_true",
|
||||
help=(
|
||||
"Re-translate EVERY key, ignoring existing translations. "
|
||||
"Dangerous: this DOES overwrite human-curated strings. "
|
||||
"Use only when you know what you are doing."
|
||||
"Retranslate the keys named by --refresh-keys. On its own it has "
|
||||
"no effect: an existing translation is never replaced."
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--refresh-keys",
|
||||
type=Path,
|
||||
help=(
|
||||
"File with one dotted message key per line. Only these may be "
|
||||
"retranslated over an existing value, and only with --refresh."
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
@@ -283,6 +292,21 @@ def main() -> int:
|
||||
print(f"Provider: {args.provider}", flush=True)
|
||||
print(f"Sleep between calls: {args.sleep}s", flush=True)
|
||||
|
||||
refresh_keys: set[str] = set()
|
||||
if args.refresh_keys is not None:
|
||||
if not args.refresh:
|
||||
print("--refresh-keys needs --refresh.", file=sys.stderr)
|
||||
return 1
|
||||
refresh_keys = {
|
||||
line.strip()
|
||||
for line in args.refresh_keys.read_text(encoding="utf-8").splitlines()
|
||||
if line.strip()
|
||||
}
|
||||
print(f"Refreshing {len(refresh_keys)} named keys.", flush=True)
|
||||
elif args.refresh:
|
||||
print("--refresh without --refresh-keys: existing translations are kept.",
|
||||
flush=True)
|
||||
|
||||
total_failures: list[tuple[str, CatalogPath, str]] = []
|
||||
|
||||
# Preflight every locale before any provider call or write. Serialized
|
||||
@@ -331,8 +355,9 @@ def main() -> int:
|
||||
# 3. Auto-fills from prior runs whose output happened to
|
||||
# match EN — leaving them alone is the intended
|
||||
# steady-state, not a bug.
|
||||
# When someone genuinely wants to redo everything, --refresh
|
||||
# is still available (and is destructive by design).
|
||||
# An existing translation is never replaced. --refresh only reaches
|
||||
# the keys named in --refresh-keys, so an overwrite is always one
|
||||
# somebody asked for by name rather than a side effect of a run.
|
||||
# Seed structural nodes and non-text leaves before any checkpoint.
|
||||
# Only strings are sent to a translation provider.
|
||||
original_flat = target_flat.copy()
|
||||
@@ -348,7 +373,7 @@ def main() -> int:
|
||||
if not isinstance(en_value, str) or not en_value:
|
||||
continue
|
||||
existing = target_flat.get(key, "")
|
||||
if args.refresh or not existing:
|
||||
if not existing or ".".join(str(part) for part in key) in refresh_keys:
|
||||
missing.append(key)
|
||||
|
||||
if args.limit > 0:
|
||||
|
||||
@@ -104,6 +104,15 @@ PROTECTED_TECHNICAL_TERMS = (
|
||||
"OCI manager Apps",
|
||||
"OCI",
|
||||
"beta",
|
||||
# Debian release names. "Bookworm" is a bird and a reader of books, and
|
||||
# came back as "el libro de Debian"; the others are equally ordinary
|
||||
# words in the languages that borrowed them.
|
||||
"Bookworm",
|
||||
"Trixie",
|
||||
"Bullseye",
|
||||
"Buster",
|
||||
"Noble",
|
||||
"Jammy",
|
||||
)
|
||||
TECHNICAL_TERM_RE = re.compile(
|
||||
"|".join(
|
||||
@@ -127,9 +136,37 @@ STRUCTURAL_LITERAL_RE = re.compile(
|
||||
r"""
|
||||
/(?:dev|etc|usr|var|opt|srv|proc|sys|run|boot|tmp)/[\w./+-]*[\w/+-]
|
||||
| (?<![\w-])--[A-Za-z][\w-]*
|
||||
# Angle-bracket placeholders a reader substitutes: <CTID> came back as
|
||||
# "■CTID confiar", with the closing bracket translated as a verb.
|
||||
| <[A-Za-z][\w-]*>
|
||||
# Shell operators. "&&" became the HTML entity "'" in Spanish, and
|
||||
# the command it joined stopped being one command; a lone pipe came back
|
||||
# as the word "Silencio".
|
||||
| &&|\|\||(?<!\|)\|(?!\|)
|
||||
# Environment variable names. THELOUNGE_HOME lost its underscore and
|
||||
# became two words, so the command no longer set anything.
|
||||
| \b[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)+\b
|
||||
| \b[\w.-]+\.(?:sh|py|json|yml|yaml|conf|service|timer|func|cfg|list|log)\b
|
||||
| \b(?:pct|qm|pvesm|pveam|pveum|pvecm|apt-get|dpkg|systemctl|journalctl
|
||||
|zpool|smartctl|modprobe|blkid|lsblk|mkfs)\s+[a-z][\w-]*
|
||||
# Reverse-DNS identifiers: org.opencontainers.image.version came back as
|
||||
# "org.open containers.image.version" — a label name with a space in it.
|
||||
| \b[a-z][a-z0-9-]*(?:\.[a-z][a-z0-9-]*){2,}\b
|
||||
# A command plus a real subcommand. An allowlist, not "any word": with
|
||||
# a wildcard, "pvesm command not found" and "apt-get exited" were read as
|
||||
# invocations, and the strings a contributor had already translated by
|
||||
# hand were discarded as damaged.
|
||||
| \b(?:pct|qm)\s+(?:config|start|stop|shutdown|reboot|destroy|create|clone
|
||||
|enter|exec|push|pull|set|list|status|snapshot|rollback|resize|migrate
|
||||
|template|unlock|mount|unmount|df|fsck|restore|suspend|resume|monitor)\b
|
||||
| \bpvesm\s+(?:path|status|list|alloc|free|add|remove|set|scan|export|import)\b
|
||||
| \b(?:pveam|pveum|pvecm)\s+(?:available|download|list|update|remove|add|create
|
||||
|delete|status|nodes|keygen|expected|modify|set|useradd|userdel|passwd)\b
|
||||
| \bapt-get\s+(?:install|update|upgrade|remove|purge|autoremove|dist-upgrade|clean)\b
|
||||
| \bdpkg\s+(?:-l|-i|-r|-P|--configure|--get-selections)\b
|
||||
| \b(?:systemctl|journalctl)\s+(?:start|stop|restart|reload|enable|disable|status
|
||||
|daemon-reload|mask|unmask|is-active|is-enabled|list-units|-u|-f|-b)\b
|
||||
| \bzpool\s+(?:status|list|import|export|scrub|trim|get|set|history)\b
|
||||
| \bsmartctl\s+(?:-a|-A|-H|-i|-t|-l|-x|--all|--health|--info)\b
|
||||
| \b(?:modprobe|blkid|lsblk|mkfs)\s+(?:-a|-r|-n|-o|-f|-t|\.[a-z0-9]+)\b
|
||||
""",
|
||||
re.VERBOSE,
|
||||
)
|
||||
@@ -551,14 +588,17 @@ def load_language_cache(path: Path) -> dict[str, str]:
|
||||
|
||||
|
||||
def is_fully_protected(source: str) -> bool:
|
||||
"""Whether the string is glossary terms and punctuation, nothing else.
|
||||
"""Whether the string is protected material and punctuation, nothing else.
|
||||
|
||||
"Docker Volume Backup" and "NVIDIA (NVDEC/CUDA)" are product and API
|
||||
names from end to end. Coming back unchanged is the right answer for
|
||||
them, so the guard below must not read it as a silent failure and throw
|
||||
the result away.
|
||||
names from end to end, and "apt-get exited" is a command with a word
|
||||
the command itself supplies. Coming back unchanged is the right answer
|
||||
for all of them, so the guard below must not read it as a silent
|
||||
failure and throw the result away. Both kinds of protection count:
|
||||
the glossary catches the names, the structural pattern the rest.
|
||||
"""
|
||||
return not re.search(r"[A-Za-z]{2,}", TECHNICAL_TERM_RE.sub(" ", source))
|
||||
remainder = STRUCTURAL_LITERAL_RE.sub(" ", source)
|
||||
return not re.search(r"[A-Za-z]{2,}", TECHNICAL_TERM_RE.sub(" ", remainder))
|
||||
|
||||
|
||||
def looks_untranslated(source: str, result: str) -> bool:
|
||||
@@ -667,7 +707,14 @@ def build_arg_parser() -> argparse.ArgumentParser:
|
||||
parser.add_argument(
|
||||
"--refresh",
|
||||
action="store_true",
|
||||
help="Translate all entries again instead of reusing existing cache values.",
|
||||
help="Retranslate the strings named by --refresh-keys. On its own it has "
|
||||
"no effect: an existing translation is never replaced.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--refresh-keys",
|
||||
type=Path,
|
||||
help="File with one source string per line. Only these may be "
|
||||
"retranslated over an existing value, and only with --refresh.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--extract-only",
|
||||
@@ -730,6 +777,21 @@ def main() -> int:
|
||||
print(f"Output directory: {output_dir}", flush=True)
|
||||
print(f"Languages: {', '.join(languages)}", flush=True)
|
||||
|
||||
refresh_keys: set[str] = set()
|
||||
if args.refresh_keys is not None:
|
||||
if not args.refresh:
|
||||
print("--refresh-keys needs --refresh.", file=sys.stderr)
|
||||
return 1
|
||||
refresh_keys = {
|
||||
line.rstrip("\n")
|
||||
for line in args.refresh_keys.read_text(encoding="utf-8").splitlines()
|
||||
if line.strip()
|
||||
}
|
||||
print(f"Refreshing {len(refresh_keys)} named strings.", flush=True)
|
||||
elif args.refresh:
|
||||
print("--refresh without --refresh-keys: existing translations are kept.",
|
||||
flush=True)
|
||||
|
||||
failures: list[tuple[str, str, str]] = []
|
||||
total = len(texts) * len(languages)
|
||||
done = 0
|
||||
@@ -740,7 +802,13 @@ def main() -> int:
|
||||
|
||||
for index, text in enumerate(texts, start=1):
|
||||
done += 1
|
||||
if not args.refresh and existing.get(text):
|
||||
# A translation that is already there is never replaced. Most of
|
||||
# this catalogue is hand-written by the people who speak the
|
||||
# language, and a machine pass over it trades their wording for
|
||||
# something worse without anyone seeing the swap. Only a string
|
||||
# named in --refresh-keys may be overwritten, so every overwrite
|
||||
# is one somebody asked for by name.
|
||||
if existing.get(text) and text not in refresh_keys:
|
||||
next_by_lang[lang][text] = existing[text]
|
||||
continue
|
||||
if args.extract_only:
|
||||
|
||||
@@ -18,6 +18,7 @@ sys.path.insert(0, str(Path(__file__).parent))
|
||||
from build_translation_cache import ( # noqa: E402
|
||||
clean_translation,
|
||||
translate_appimage,
|
||||
translate_argos,
|
||||
translate_google_web,
|
||||
translate_googletrans,
|
||||
)
|
||||
@@ -86,6 +87,7 @@ PROTECTED_PATTERNS = (
|
||||
re.compile(r"(?<![\w-])--[A-Za-z0-9][A-Za-z0-9_-]*"),
|
||||
re.compile(r"(?<![A-Za-z0-9<])/(?:[A-Za-z0-9._~:@%+=-]+/)*[A-Za-z0-9._~:@%+=-]+"),
|
||||
re.compile(r"\b[A-Za-z0-9_.-]+\.(?:json|ya?ml|toml|conf|service|socket|sh|py|tsx?|jsx?|md)\b"),
|
||||
re.compile(r"(?<![\w.@])@[A-Za-z_][A-Za-z0-9_]*"),
|
||||
)
|
||||
LITERAL_TAG_RE = re.compile(
|
||||
r"<(code|kbd|pre)\b[^>]*>.*?</\1>",
|
||||
@@ -100,6 +102,11 @@ TERM_RE = re.compile(
|
||||
re.IGNORECASE,
|
||||
)
|
||||
TAG_RE = re.compile(r"</?([A-Za-z][A-Za-z0-9]*)>")
|
||||
# Every tag as written, attributes and self-closing slash included.
|
||||
ANY_TAG_RE = re.compile(r"</?[A-Za-z][^<>]*>")
|
||||
# Set from --provider: a local model rewrites bracketed sentinels, a remote
|
||||
# one drops bare ones beside inline markup. See protect_text.
|
||||
BARE_SENTINELS = False
|
||||
PLACEHOLDER_RE = re.compile(r"\{[A-Za-z_][A-Za-z0-9_.-]*\}")
|
||||
NON_TRANSLATABLE_KEYS = {
|
||||
"command",
|
||||
@@ -206,13 +213,13 @@ def needs_translation(
|
||||
source: str,
|
||||
target: Any,
|
||||
path: tuple[str | int, ...],
|
||||
refresh: bool,
|
||||
forced_tokens: set[str] | None = None,
|
||||
) -> bool:
|
||||
if should_copy(source, path):
|
||||
return False
|
||||
if refresh:
|
||||
return True
|
||||
# An existing translation is never replaced. Only a leaf whose token was
|
||||
# named on the command line may be retranslated over a real value, so an
|
||||
# overwrite is always one somebody asked for rather than a side effect.
|
||||
if forced_tokens and leaf_token(path) in forced_tokens:
|
||||
return True
|
||||
return not isinstance(target, str) or not target.strip() or target == source
|
||||
@@ -279,6 +286,17 @@ def protect_text(text: str) -> tuple[str, dict[str, str]]:
|
||||
for match in TERM_RE.finditer(text)
|
||||
if not overlaps_literal(match.start(), match.end())
|
||||
)
|
||||
if BARE_SENTINELS:
|
||||
# A remote provider carries inline tags through untouched, so they are
|
||||
# only validated afterwards. A local model rewrites them — dropping a
|
||||
# </code>, merging two <em> — and the whole file is then discarded for
|
||||
# a broken contract. Protecting them costs the translator the tag as
|
||||
# context and saves the paragraph.
|
||||
candidates.extend((match.start(), match.end()) for match in ANY_TAG_RE.finditer(text))
|
||||
# A local model also rewrites what a literal block holds: it drops the
|
||||
# underscores of an identifier, translates a subcommand and turns a
|
||||
# pipe into punctuation. The whole block is one opaque token instead.
|
||||
candidates.extend(literal_ranges)
|
||||
candidates.sort(key=lambda item: (item[0], -(item[1] - item[0])))
|
||||
|
||||
selected: list[tuple[int, int]] = []
|
||||
@@ -296,7 +314,12 @@ def protect_text(text: str) -> tuple[str, dict[str, str]]:
|
||||
# sit directly beside inline markup (for example an opening <em>
|
||||
# token followed by translated prose). Triple brackets remain opaque
|
||||
# in that position and preserve the complete rich-text contract.
|
||||
token = f"[[[PMXDOC{index:04d}]]]"
|
||||
#
|
||||
# A local model treats the brackets as punctuation instead, and
|
||||
# rewrites them: argos returns [PMXDOC0000] in German, [[PMXDOC0000]]
|
||||
# in Slovak and [[[[PMXDOC0000]]]]] in Italian. The bare identifier
|
||||
# survives every provider tried, so it is what a local run uses.
|
||||
token = f"PMXDOC{index:04d}" if BARE_SENTINELS else f"[[[PMXDOC{index:04d}]]]"
|
||||
chunks.append(text[cursor:start])
|
||||
chunks.append(token)
|
||||
mapping[token] = text[start:end]
|
||||
@@ -317,13 +340,20 @@ def restore_text(text: str, mapping: dict[str, str]) -> str:
|
||||
def validate_contract(source: str, target: str) -> None:
|
||||
if sorted(TAG_RE.findall(source)) != sorted(TAG_RE.findall(target)):
|
||||
raise ValueError("rich-text tag contract changed")
|
||||
if sorted(ANY_TAG_RE.findall(source)) != sorted(ANY_TAG_RE.findall(target)):
|
||||
raise ValueError("markup changed")
|
||||
literal = lambda text: sorted(match.group(0) for match in LITERAL_TAG_RE.finditer(text))
|
||||
if literal(source) != literal(target):
|
||||
raise ValueError("literal code changed")
|
||||
if sorted(PLACEHOLDER_RE.findall(source)) != sorted(PLACEHOLDER_RE.findall(target)):
|
||||
raise ValueError("placeholder contract changed")
|
||||
|
||||
|
||||
def provider_function(args: argparse.Namespace) -> Callable[[str, str], str]:
|
||||
def translate(text: str, language: str) -> str:
|
||||
if args.provider == "googletrans":
|
||||
if args.provider == "argos":
|
||||
raw = translate_argos(text, language)
|
||||
elif args.provider == "googletrans":
|
||||
raw = translate_googletrans(text, language, args.context)
|
||||
elif args.provider == "google-web":
|
||||
raw = translate_google_web(text, language, args.context, args.timeout)
|
||||
@@ -446,7 +476,6 @@ def collect_memory(source_root: Path, messages_root: Path, language: str) -> dic
|
||||
def pending_leaves(
|
||||
source: Any,
|
||||
target: Any,
|
||||
refresh: bool,
|
||||
forced_tokens: set[str] | None = None,
|
||||
) -> list[Leaf]:
|
||||
return [
|
||||
@@ -456,7 +485,6 @@ def pending_leaves(
|
||||
leaf.source,
|
||||
get_at_path(target, leaf.path),
|
||||
leaf.path,
|
||||
refresh,
|
||||
forced_tokens,
|
||||
)
|
||||
]
|
||||
@@ -533,13 +561,14 @@ def translate_file(
|
||||
memory: dict[str, str],
|
||||
translate: Callable[[str, str], str],
|
||||
args: argparse.Namespace,
|
||||
) -> tuple[Any | None, list[str], int]:
|
||||
) -> tuple[Any | None, list[str], int, set[str]]:
|
||||
resolved: dict[tuple[str | int, ...], str] = {}
|
||||
failures: list[str] = []
|
||||
failed_tokens: set[str] = set()
|
||||
jobs: dict[str, list[tuple[str | int, ...]]] = {}
|
||||
|
||||
for leaf in leaves:
|
||||
if not args.refresh and leaf.source in memory:
|
||||
if leaf.source in memory:
|
||||
resolved[leaf.path] = memory[leaf.source]
|
||||
continue
|
||||
jobs.setdefault(leaf.source, []).append(leaf.path)
|
||||
@@ -566,12 +595,17 @@ def translate_file(
|
||||
resolved[path] = translated
|
||||
except Exception as exc:
|
||||
failures.append(f"{text[:90]}: {exc}")
|
||||
failed_tokens.update(leaf_token(path) for path in jobs[text])
|
||||
if args.sleep:
|
||||
time.sleep(args.sleep)
|
||||
|
||||
if failures:
|
||||
return None, failures, len(jobs)
|
||||
return merge_tree(source, target, resolved), [], len(jobs)
|
||||
# What did translate is kept. merge_tree leaves a string it has no
|
||||
# translation for as whatever the locale already held, or as the English
|
||||
# source, so a file is written with the strings that worked rather than
|
||||
# discarded whole: a dense paragraph that a provider cannot carry its
|
||||
# protected tokens through used to take the other hundred and seventy
|
||||
# strings of its file with it.
|
||||
return merge_tree(source, target, resolved), failures, len(jobs), failed_tokens
|
||||
|
||||
|
||||
def build_parser() -> argparse.ArgumentParser:
|
||||
@@ -586,8 +620,12 @@ def build_parser() -> argparse.ArgumentParser:
|
||||
)
|
||||
parser.add_argument(
|
||||
"--provider",
|
||||
choices=("google-web", "googletrans", "appimage"),
|
||||
choices=("argos", "google-web", "googletrans", "appimage"),
|
||||
default="googletrans",
|
||||
help=(
|
||||
"Translation provider. The default is what CI uses; `argos` runs "
|
||||
"locally with no quota, which is what a corpus this size needs."
|
||||
),
|
||||
)
|
||||
parser.add_argument("--appimage-path", type=Path, default=Path("ProxMenux-Monitor.AppImage"))
|
||||
parser.add_argument(
|
||||
@@ -623,7 +661,9 @@ def build_parser() -> argparse.ArgumentParser:
|
||||
|
||||
|
||||
def main() -> int:
|
||||
global BARE_SENTINELS
|
||||
args = build_parser().parse_args()
|
||||
BARE_SENTINELS = args.provider == "argos"
|
||||
if args.workers < 1 or args.retries < 0 or args.max_files < 0:
|
||||
print("workers must be positive; retries and max-files cannot be negative", file=sys.stderr)
|
||||
return 2
|
||||
@@ -646,7 +686,8 @@ def main() -> int:
|
||||
print("No target languages selected.", file=sys.stderr)
|
||||
return 2
|
||||
if args.refresh:
|
||||
print("WARNING: --refresh overwrites existing translations in the selected scope.")
|
||||
print("--refresh no longer overwrites existing translations; "
|
||||
"name the leaves with --tokens instead.")
|
||||
|
||||
translate = provider_function(args)
|
||||
state = load_source_state(source_state_path)
|
||||
@@ -716,7 +757,7 @@ def main() -> int:
|
||||
pending_tokens.update(changed_tokens)
|
||||
pending_tokens.update(
|
||||
leaf_token(leaf.path)
|
||||
for leaf in pending_leaves(source, target, args.refresh)
|
||||
for leaf in pending_leaves(source, target)
|
||||
)
|
||||
set_state_pending_tokens(state, language, relative, pending_tokens)
|
||||
|
||||
@@ -742,6 +783,11 @@ def main() -> int:
|
||||
|
||||
total_failures = 0
|
||||
total_written = 0
|
||||
# The provider decides the sentinel format, so a run that cannot be
|
||||
# attributed to one cannot be diagnosed afterwards: a night of failures
|
||||
# reading "translation provider changed protected token" left no way to
|
||||
# tell whether the provider was the one the tokens were shaped for.
|
||||
print(f"Provider: {args.provider} | bare sentinels: {BARE_SENTINELS}")
|
||||
print(f"English files: {len(files)} | locales: {', '.join(languages)}")
|
||||
|
||||
for language in languages:
|
||||
@@ -773,7 +819,7 @@ def main() -> int:
|
||||
source = file_info[relative_key][1]
|
||||
target = read_json(target_path)
|
||||
queued_tokens = state_pending_tokens(state, language, relative_key)
|
||||
leaves = pending_leaves(source, target, args.refresh, queued_tokens)
|
||||
leaves = pending_leaves(source, target, queued_tokens)
|
||||
total_strings += len(iter_leaves(source))
|
||||
missing_strings += len(leaves)
|
||||
schema_changed = not schema_matches(source, target)
|
||||
@@ -816,7 +862,7 @@ def main() -> int:
|
||||
f"({len(leaves)} strings{suffix})",
|
||||
flush=True,
|
||||
)
|
||||
built, failures, calls = translate_file(
|
||||
built, failures, calls, failed_tokens = translate_file(
|
||||
source,
|
||||
target,
|
||||
leaves,
|
||||
@@ -827,18 +873,18 @@ def main() -> int:
|
||||
)
|
||||
if failures:
|
||||
total_failures += len(failures)
|
||||
set_state_pending_tokens(state, language, relative_key, queued_tokens)
|
||||
write_json(source_state_path, state)
|
||||
print(
|
||||
f" skipped atomically after {len(failures)} failures "
|
||||
f"({calls} calls)",
|
||||
f" {len(failures)} strings left untranslated ({calls} calls)",
|
||||
file=sys.stderr,
|
||||
)
|
||||
for failure in failures[:5]:
|
||||
print(f" - {failure}", file=sys.stderr)
|
||||
continue
|
||||
write_json(target_path, built)
|
||||
set_state_pending_tokens(state, language, relative_key, set())
|
||||
# The strings that failed stay pending, so the next run comes back
|
||||
# for them and leaves the ones that translated alone.
|
||||
set_state_pending_tokens(state, language, relative_key, failed_tokens)
|
||||
if failures:
|
||||
write_json(source_state_path, state)
|
||||
write_json(source_state_path, state)
|
||||
total_written += 1
|
||||
print(f" wrote {target_path} ({calls} provider calls)", flush=True)
|
||||
|
||||
@@ -59,7 +59,7 @@ def fetch_directory_json(api_url: str) -> list[dict]:
|
||||
r.raise_for_status()
|
||||
data = r.json()
|
||||
if not isinstance(data, list):
|
||||
raise RuntimeError("GitHub API no devolvió una lista.")
|
||||
raise RuntimeError("The GitHub API did not return a list.")
|
||||
return data
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ def main() -> int:
|
||||
try:
|
||||
directory = fetch_directory_json(API_URL)
|
||||
except Exception as e:
|
||||
print(f"ERROR: No se pudo leer el índice de JSONs: {e}", file=sys.stderr)
|
||||
print(f"ERROR: Could not read the JSON index: {e}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
cache: list[dict] = []
|
||||
|
||||
@@ -97,10 +97,23 @@ class I18nMessagesTests(unittest.TestCase):
|
||||
if text == "Two":
|
||||
raise RuntimeError("offline fixture failure")
|
||||
return "IT " + text
|
||||
# --refresh alone never replaces an existing translation.
|
||||
result, actual, calls, output, _ = self.run_generator(
|
||||
{"items": ["One", "Two", "Three"]}, {"items": ["Uno", "Due"]},
|
||||
"--refresh", "--save-every", "1", provider=provider)
|
||||
self.assertEqual(result, 0)
|
||||
self.assertEqual(actual, {"items": ["Uno", "Due", "IT Three"]})
|
||||
self.assertEqual(len(calls), 1)
|
||||
# Named keys are retranslated; a provider failure keeps the value.
|
||||
with tempfile.NamedTemporaryFile("w", suffix=".txt", delete=False) as keys:
|
||||
keys.write("items.0\nitems.1\n")
|
||||
try:
|
||||
result, actual, calls, output, _ = self.run_generator(
|
||||
{"items": ["One", "Two", "Three"]}, {"items": ["Uno", "Due"]},
|
||||
"--refresh", "--refresh-keys", keys.name, "--save-every", "1", provider=provider)
|
||||
finally:
|
||||
Path(keys.name).unlink()
|
||||
self.assertEqual(result, 0)
|
||||
self.assertEqual(actual, {"items": ["IT One", "Due", "IT Three"]})
|
||||
self.assertEqual(len(calls), 3)
|
||||
self.assertIn("1 translation failures", output)
|
||||
@@ -178,9 +191,10 @@ class I18nMessagesTests(unittest.TestCase):
|
||||
mock.patch.object(MODULE, "write_json", wraps=MODULE.write_json) as writer, \
|
||||
redirect_stderr(output), redirect_stdout(output):
|
||||
self.assertEqual(MODULE.main(), 1)
|
||||
# --refresh without --refresh-keys keeps the existing value.
|
||||
self.assertEqual(json.loads((root / "sk/common.json").read_text()),
|
||||
{"items": ["SK One" if options else "Human", "SK Two"]})
|
||||
self.assertEqual(provider.call_count, 2 if options else 1)
|
||||
{"items": ["Human", "SK Two"]})
|
||||
self.assertEqual(provider.call_count, 1)
|
||||
self.assertTrue(all(call.args[0].parent.name == "sk" for call in writer.call_args_list))
|
||||
for lang in ["en", "it", "de"]:
|
||||
self.assertEqual((root / lang / "common.json").read_bytes(), before[lang])
|
||||
|
||||
@@ -58,7 +58,7 @@ class WebDocsI18nTests(unittest.TestCase):
|
||||
def test_human_translation_is_not_pending(self):
|
||||
source = {"title": "Updates", "url": "https://example.com"}
|
||||
target = {"title": "Actualizaciones", "url": "https://example.com"}
|
||||
self.assertEqual(MODULE.pending_leaves(source, target, refresh=False), [])
|
||||
self.assertEqual(MODULE.pending_leaves(source, target), [])
|
||||
|
||||
def test_changed_source_text_is_pending_even_with_existing_translation(self):
|
||||
source = {"title": "Updated installation guidance"}
|
||||
@@ -67,7 +67,6 @@ class WebDocsI18nTests(unittest.TestCase):
|
||||
leaves = MODULE.pending_leaves(
|
||||
source,
|
||||
target,
|
||||
refresh=False,
|
||||
forced_tokens={token},
|
||||
)
|
||||
self.assertEqual([leaf.path for leaf in leaves], [("title",)])
|
||||
|
||||
@@ -35,8 +35,7 @@ def consumers():
|
||||
def fixture(directory, backend='pbs', consumer='attached', rows='', second=None,
|
||||
locale='en', catalog=None, real_dialog=None):
|
||||
directory = Path(directory)
|
||||
if catalog is not None:
|
||||
(directory / f'{locale}.json').write_text(json.dumps(catalog), encoding='utf-8')
|
||||
(directory / 'xx.json').write_text(json.dumps(catalog or {}))
|
||||
(directory / 'rows').write_text(rows)
|
||||
(directory / 'second').write_text(rows if second is None else second)
|
||||
bindir = directory / 'bin'
|
||||
@@ -52,7 +51,7 @@ FIXTURE={shlex.quote(str(directory))}
|
||||
BACKEND={backend}
|
||||
HB_UI_MENU_H=20 HB_UI_MENU_W=84 HB_UI_MENU_LIST=10
|
||||
command_not_found_handle() {{ printf 'FORBIDDEN:%s\\n' "$*" >> "$FIXTURE/errors"; return 99; }}
|
||||
jq() {{ [[ "$#" == 6 && "$1" == -r && "$2" == --arg && "$3" == text && "$5" == '.[$text] // empty' && "$6" == "$FIXTURE/$LANGUAGE.json" ]] || {{ printf 'bad jq' >> "$FIXTURE/errors"; return 99; }}; command jq "$@"; }}
|
||||
jq() {{ [[ "$#" == 6 && "$1" == -r && "$2" == --arg && "$3" == text && "$5" == '.[$text] // empty' && "$6" == "$FIXTURE/xx.json" ]] || {{ printf 'bad jq' >> "$FIXTURE/errors"; return 99; }}; command jq "$@"; }}
|
||||
head() {{ [[ "$*" == '-1' ]] || return 99; local first; IFS= read -r first; printf '%s\\n' "$first"; while IFS= read -r first; do :; done; }}
|
||||
hb_pve_list_vzdump_jobs() {{
|
||||
local file="$FIXTURE/rows" line
|
||||
@@ -108,40 +107,20 @@ class SchedulerMessages(unittest.TestCase):
|
||||
self.assertEqual(result['status'], '1')
|
||||
|
||||
def test_lookup_cache_modes_at_both_consumers(self):
|
||||
# Unconditional synthetic coverage, independent of cache completeness.
|
||||
shipped = json.loads((ROOT / 'lang/it.json').read_text())
|
||||
for backend, message in MESSAGES.items():
|
||||
for consumer in ('attached', 'new'):
|
||||
for mode, locale, catalog, expected, hint in (
|
||||
('english', 'en', {message: 'ignored', HINT: 'ignored'}, message, HINT),
|
||||
('missing-file', 'missing', None, message, HINT),
|
||||
('missing-key', 'xx', {'unrelated': 'unrelated'}, message, HINT),
|
||||
('translated', 'xx', {message: 'SYNTHETIC reordered backend: ' + backend,
|
||||
HINT: 'SYNTHETIC hint'},
|
||||
'SYNTHETIC reordered backend: ' + backend, 'SYNTHETIC hint'),
|
||||
for locale, catalog, expected in (
|
||||
('en', {message: 'ignored'}, message),
|
||||
('missing', {}, message),
|
||||
('xx', {'unrelated': 'unrelated'}, message),
|
||||
('xx', shipped, shipped.get(message, message)),
|
||||
('xx', {message: 'SYNTHETIC reordered backend: ' + backend},
|
||||
'SYNTHETIC reordered backend: ' + backend),
|
||||
):
|
||||
with self.subTest(backend=backend, consumer=consumer, mode=mode):
|
||||
with self.subTest(backend=backend, consumer=consumer, locale=locale, expected=expected):
|
||||
result = run_case(backend=backend, consumer=consumer, locale=locale, catalog=catalog)
|
||||
suffix = '\n\n' + hint if consumer == 'new' else ''
|
||||
self.assertEqual(result['message'], expected + suffix)
|
||||
self.assertEqual(result['status'], '1')
|
||||
|
||||
def test_all_shipped_caches_at_both_consumers(self):
|
||||
catalogs = sorted((ROOT / 'lang').glob('*.json'))
|
||||
self.assertTrue(catalogs, 'No shipped locale catalogs discovered')
|
||||
for path in catalogs:
|
||||
catalog = json.loads(path.read_text(encoding='utf-8'))
|
||||
self.assertIsInstance(catalog, dict, path.name)
|
||||
for backend, message in MESSAGES.items():
|
||||
for consumer in ('attached', 'new'):
|
||||
with self.subTest(locale=path.stem, backend=backend, consumer=consumer):
|
||||
# Exercise the real translate function with the actual locale
|
||||
# filename, not just a comparison of JSON values. Missing or
|
||||
# empty translations are valid: runtime falls back to English.
|
||||
result = run_case(backend=backend, consumer=consumer,
|
||||
locale=path.stem, catalog=catalog)
|
||||
expected = message if path.stem == 'en' else catalog.get(message) or message
|
||||
hint = HINT if path.stem == 'en' else catalog.get(HINT) or HINT
|
||||
suffix = '\n\n' + hint if consumer == 'new' else ''
|
||||
suffix = '\n\n' + catalog.get(HINT, HINT) if consumer == 'new' else ''
|
||||
self.assertEqual(result['message'], expected + suffix)
|
||||
self.assertEqual(result['status'], '1')
|
||||
|
||||
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
9216421e41d7927e188fd157adf2704d5f5f465819e19041cb619602637746be ProxMenux-1.2.6.1-beta.AppImage
|
||||
b546a85dfe0fd2c5920042893a5a96ae007f962921f997183ebac8fb6697b53b ProxMenux-1.2.6.2-beta.AppImage
|
||||
|
||||
@@ -595,9 +595,9 @@ function CardsGrid({
|
||||
// `changeTab` switches the outer tab (dashboard-level) and
|
||||
// `openLxcAppModal` tells VirtualMachines which guest to open and on
|
||||
// which inner tab to land. Both fire in the same tick.
|
||||
function openLxcModalOnAppTab(vmid: number) {
|
||||
function openLxcModalOnAppTab(vmid: number, tab: "app" | "updates" = "app") {
|
||||
window.dispatchEvent(new CustomEvent("changeTab", { detail: { tab: "vms" } }))
|
||||
window.dispatchEvent(new CustomEvent("openLxcAppModal", { detail: { vmid } }))
|
||||
window.dispatchEvent(new CustomEvent("openLxcAppModal", { detail: { vmid, tab } }))
|
||||
}
|
||||
|
||||
// Same pattern for a QEMU guest: land on the modal's Status tab
|
||||
@@ -637,6 +637,15 @@ function AppCard({
|
||||
}
|
||||
}
|
||||
|
||||
// The update icon leads to where the update is applied: the Updates
|
||||
// tab of the container.
|
||||
const goToUpdates = (e: React.MouseEvent | React.KeyboardEvent) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
if (link.vmid == null) return
|
||||
openLxcModalOnAppTab(link.vmid, "updates")
|
||||
}
|
||||
|
||||
const goToEditor = (e: React.MouseEvent | React.KeyboardEvent) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
@@ -682,7 +691,20 @@ function AppCard({
|
||||
<Pencil className="h-4 w-4" />
|
||||
</button>
|
||||
) : link.updateAvailable && (
|
||||
<ArrowUpCircle className="h-5 w-5 text-purple-400 flex-shrink-0 self-start mt-0.5" aria-hidden="true" />
|
||||
link.vmid != null && link.guestType !== "qemu" ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={goToUpdates}
|
||||
onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") goToUpdates(e) }}
|
||||
className="rounded-full flex-shrink-0 self-start mt-0.5 text-purple-400 hover:text-purple-300 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
||||
aria-label={t("apps.openUpdatesAria", { name: link.appName })}
|
||||
title={t("apps.openUpdatesTitle")}
|
||||
>
|
||||
<ArrowUpCircle className="h-5 w-5" />
|
||||
</button>
|
||||
) : (
|
||||
<ArrowUpCircle className="h-5 w-5 text-purple-400 flex-shrink-0 self-start mt-0.5" aria-hidden="true" />
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -629,7 +629,7 @@ export default function Hardware() {
|
||||
const hasRealtimeData = (): boolean => {
|
||||
if (!realtimeGPUData) return false
|
||||
|
||||
// Esto permite mostrar datos incluso cuando la GPU está inactiva (valores en 0 o null)
|
||||
// Show the data even while the GPU is idle, when values are 0 or null
|
||||
return realtimeGPUData.has_monitoring_tool === true
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ import { useT } from "@/lib/i18n/provider"
|
||||
// apps and casual "just want a link" registrations use this default.
|
||||
type InstalledVia = "" | "dpkg" | "apk" | "file" | "binary" |
|
||||
"python_dist" | "docker_label" | "docker_exec" |
|
||||
"command" | "manual"
|
||||
"command" | "manual" | "oci_image"
|
||||
type GithubSource = "releases" | "tags"
|
||||
|
||||
interface PortEntry {
|
||||
@@ -120,6 +120,10 @@ interface DetectedApp {
|
||||
// auto-fill the Web Link editor when the user clicks "Register".
|
||||
category?: string | null
|
||||
tracking_suggestion?: TrackingSuggestion | null
|
||||
// The scheme the application is served on, when it is known rather than
|
||||
// guessed. A ProxMenux OCI install records it; Chromium answers on 3001
|
||||
// over https, which no port heuristic can tell from 3000 over http.
|
||||
scheme?: "http" | "https" | null
|
||||
}
|
||||
|
||||
interface AppState {
|
||||
@@ -129,8 +133,31 @@ interface AppState {
|
||||
update_available: boolean | null
|
||||
error: string | null
|
||||
checked_at: string | null
|
||||
// An application installed from an OCI image: the image it runs and the
|
||||
// one its registry publishes today. The image decides whether there is an
|
||||
// update; the version above only says which application it carries.
|
||||
installed_digest?: string | null
|
||||
latest_digest?: string | null
|
||||
image_created?: string | null
|
||||
latest_image_created?: string | null
|
||||
image_reference?: string | null
|
||||
image_repository?: string | null
|
||||
}
|
||||
|
||||
// The repository of an OCI image, shown the way the repository of a tracked
|
||||
// application is: owner/name for GitHub, the image name for Docker Hub.
|
||||
export const ociRepoLabel = (url: string) =>
|
||||
url.replace(/^https?:\/\/(www\.)?/, "")
|
||||
.replace(/^github\.com\//, "")
|
||||
.replace(/^hub\.docker\.com\/(r|_)\//, "")
|
||||
.replace(/\/$/, "")
|
||||
|
||||
// "2026-09-24 · a3f21c08": an image as a reader can compare two of them.
|
||||
export const ociImageLabel = (created?: string | null, digest?: string | null) =>
|
||||
[created ? created.slice(0, 10) : null, digest ? digest.split(":").pop()!.slice(0, 8) : null]
|
||||
.filter(Boolean)
|
||||
.join(" · ")
|
||||
|
||||
interface AppEntry extends AppConfig {
|
||||
id: string
|
||||
state?: AppState
|
||||
@@ -219,10 +246,25 @@ interface DockerWebLinkSuggestion {
|
||||
logo_url?: string | null
|
||||
}
|
||||
|
||||
// Identity of a container ProxMenux installed from an OCI image. It comes
|
||||
// from the installation record rather than a probe, so it names the
|
||||
// application even when the guest also ships something else — CT 152 runs
|
||||
// Chromium and carries a docker client the probe reported instead.
|
||||
interface OciInstance {
|
||||
template_id: string | null
|
||||
image_reference: string | null
|
||||
repository: string | null
|
||||
scheme: string | null
|
||||
port: number | null
|
||||
path: string | null
|
||||
website: string | null
|
||||
}
|
||||
|
||||
interface Suggestions {
|
||||
ready?: boolean
|
||||
name_suggestion: string | null
|
||||
helper_slug: string | null
|
||||
oci_instance?: OciInstance | null
|
||||
port_suggestions: number[]
|
||||
web_path_hint: string | null
|
||||
tracking_suggestion?: TrackingSuggestion | null
|
||||
@@ -400,6 +442,7 @@ export function LxcAppPanel({ vmid, ctIp, onChange, managed, initialData }: Prop
|
||||
const [loading, setLoading] = useState(!seed)
|
||||
const [sidecar, setSidecar] = useState<SidecarResponse | null>(seed?.sidecar ?? null)
|
||||
const [suggestions, setSuggestions] = useState<Suggestions | null>(seed?.suggestions ?? null)
|
||||
const [adguardSetupAvailable, setAdguardSetupAvailable] = useState(false)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
const [searchingApplications, setSearchingApplications] = useState(false)
|
||||
const [detectionNotice, setDetectionNotice] = useState<{ found: boolean; text: string } | null>(null)
|
||||
@@ -589,14 +632,19 @@ export function LxcAppPanel({ vmid, ctIp, onChange, managed, initialData }: Prop
|
||||
const detectedList: DetectedApp[] = useMemo(() => {
|
||||
if (!suggestions) return []
|
||||
const out: DetectedApp[] = []
|
||||
if (suggestions.helper_slug && suggestions.name_suggestion) {
|
||||
// A ProxMenux OCI install has no helper slug — nothing was installed by a
|
||||
// community script — so its template id identifies it instead.
|
||||
const primarySlug = suggestions.helper_slug || suggestions.oci_instance?.template_id
|
||||
if (primarySlug && suggestions.name_suggestion) {
|
||||
out.push({
|
||||
slug: suggestions.helper_slug,
|
||||
slug: primarySlug,
|
||||
name: suggestions.name_suggestion,
|
||||
logo_url: suggestions.logo_url,
|
||||
default_ports: suggestions.default_ports,
|
||||
category: suggestions.category,
|
||||
tracking_suggestion: suggestions.tracking_suggestion,
|
||||
scheme: suggestions.oci_instance?.scheme === "https" ? "https"
|
||||
: suggestions.oci_instance?.scheme === "http" ? "http" : null,
|
||||
})
|
||||
}
|
||||
const seen = new Set(out.map((d) => d.slug))
|
||||
@@ -639,6 +687,43 @@ export function LxcAppPanel({ vmid, ctIp, onChange, managed, initialData }: Prop
|
||||
const hiddenDetections = [...detectedList, ...(suggestions?.docker_workloads || [])]
|
||||
.filter((d, index, items) => dismissedSlugs.has(d.slug) && items.findIndex(item => item.slug === d.slug) === index)
|
||||
|
||||
// A container installed from an OCI image holds exactly the application its
|
||||
// record names, so there is nothing to search for and nothing else to add.
|
||||
// What can go stale is what the record and the registry say, and this
|
||||
// reads both again.
|
||||
const isOciInstall = !!suggestions?.oci_instance
|
||||
const isOciAdguard = suggestions?.oci_instance?.template_id === "image-adguard-home"
|
||||
useEffect(() => {
|
||||
if (!isOciAdguard) return
|
||||
let cancelled = false
|
||||
fetchApi<{ available: boolean }>(`/api/vms/${vmid}/apps/adguard-setup`)
|
||||
.then((result) => { if (!cancelled) setAdguardSetupAvailable(result.available === true) })
|
||||
.catch(() => { if (!cancelled) setAdguardSetupAvailable(false) })
|
||||
return () => { cancelled = true }
|
||||
}, [vmid, isOciAdguard])
|
||||
const refreshOciData = async () => {
|
||||
setSearchingApplications(true)
|
||||
setDetectionNotice(null)
|
||||
setError(null)
|
||||
try {
|
||||
const result: Suggestions = await fetchApi(`/api/vms/${vmid}/apps/suggestions`, {
|
||||
method: "POST",
|
||||
})
|
||||
setSuggestions(result)
|
||||
let next = sidecar
|
||||
if (apps.length > 0) {
|
||||
next = await fetchApi(`/api/vms/${vmid}/apps/check`, { method: "POST" })
|
||||
setSidecar(next)
|
||||
}
|
||||
if (next) setLxcAppsCached(vmid, next, result)
|
||||
onChange?.()
|
||||
} catch (e: any) {
|
||||
setError(e?.message || t("vmLxc.appEditor.checkFailed"))
|
||||
} finally {
|
||||
setSearchingApplications(false)
|
||||
}
|
||||
}
|
||||
|
||||
const searchInstalledApplications = async () => {
|
||||
const before = new Set([...visibleDetected, ...visibleWorkloads].map((item) => item.slug))
|
||||
setSearchingApplications(true)
|
||||
@@ -756,10 +841,16 @@ export function LxcAppPanel({ vmid, ctIp, onChange, managed, initialData }: Prop
|
||||
// Docker endpoints come from the real published host-port mappings
|
||||
// listed under Web links. Do not pre-save a catalog default such as
|
||||
// 9000; the user explicitly chooses which workload links to add.
|
||||
if (p.slug !== "docker" && p.default_ports?.length) {
|
||||
seed.ports = p.default_ports.map((port) => ({
|
||||
const suggestedPorts = isOciAdguard && p.slug === "image-adguard-home"
|
||||
? [80, ...(adguardSetupAvailable ? [3000] : [])]
|
||||
: p.default_ports || []
|
||||
if (p.slug !== "docker" && suggestedPorts.length) {
|
||||
seed.ports = suggestedPorts.map((port) => ({
|
||||
port,
|
||||
scheme: defaultSchemeFor(port),
|
||||
...(isOciAdguard && port === 3000 ? { description: "Config" } : {}),
|
||||
// A recorded scheme beats the port heuristic: getting this wrong
|
||||
// hands the user a link that cannot connect.
|
||||
scheme: p.scheme || defaultSchemeFor(port),
|
||||
web_path: s?.web_path_hint || "",
|
||||
// Auto-fill Categoría from helpers_cache.category_names[0]
|
||||
// when the catalog entry carries one. User can still change
|
||||
@@ -822,7 +913,7 @@ export function LxcAppPanel({ vmid, ctIp, onChange, managed, initialData }: Prop
|
||||
setEditing({ appId: existing?.id || null, draft: seed })
|
||||
setDetectorTest(null)
|
||||
setError(null)
|
||||
}, [suggestions, vmid, sidecar])
|
||||
}, [suggestions, vmid, sidecar, isOciAdguard, adguardSetupAvailable])
|
||||
|
||||
const closeEditor = () => {
|
||||
setEditing(null)
|
||||
@@ -1686,10 +1777,26 @@ export function LxcAppPanel({ vmid, ctIp, onChange, managed, initialData }: Prop
|
||||
<SelectItem value="docker_exec">{t("vmLxc.appEditor.methodDockerExec")}</SelectItem>
|
||||
<SelectItem value="command">{t("vmLxc.appEditor.methodCommand")}</SelectItem>
|
||||
<SelectItem value="manual">{t("vmLxc.appEditor.methodManual")}</SelectItem>
|
||||
{/* Only meaningful on a container ProxMenux installed
|
||||
from an image: the record it reads exists nowhere else. */}
|
||||
{(method === "oci_image" || suggestions?.oci_instance) && (
|
||||
<SelectItem value="oci_image">{t("vmLxc.appEditor.methodOciImage")}</SelectItem>
|
||||
)}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
{method === "oci_image" && (
|
||||
<div className="sm:col-span-2 text-xs text-muted-foreground leading-relaxed">
|
||||
{t("vmLxc.appEditor.ociImageHelp")}
|
||||
{suggestions?.oci_instance?.image_reference && (
|
||||
<div className="mt-1">
|
||||
<code className="text-foreground/80">{suggestions.oci_instance.image_reference}</code>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{isPackaged && (
|
||||
<div>
|
||||
<Label htmlFor="app-package">{t("vmLxc.appEditor.packageIdentifierLabel")}</Label>
|
||||
@@ -1892,7 +1999,9 @@ export function LxcAppPanel({ vmid, ctIp, onChange, managed, initialData }: Prop
|
||||
</div>
|
||||
)}
|
||||
|
||||
{method && (() => {
|
||||
{/* The registry of the image is the upstream of an OCI
|
||||
install, and the record already names it. */}
|
||||
{method && method !== "oci_image" && (() => {
|
||||
// Upstream source selector — 3 methods (github,
|
||||
// http_json, docker_hub). Legacy sidecars with a
|
||||
// `repo` set but no `upstream_type` default to
|
||||
@@ -2466,17 +2575,20 @@ export function LxcAppPanel({ vmid, ctIp, onChange, managed, initialData }: Prop
|
||||
)}
|
||||
<div className="pt-1 flex flex-wrap justify-center gap-2">
|
||||
<Button
|
||||
onClick={searchInstalledApplications}
|
||||
onClick={isOciInstall ? refreshOciData : searchInstalledApplications}
|
||||
disabled={searchingApplications}
|
||||
className="bg-blue-500 hover:bg-blue-600 text-white"
|
||||
>
|
||||
{searchingApplications
|
||||
? <Loader2 className="h-4 w-4 mr-1.5 animate-spin" />
|
||||
: <Search className="h-4 w-4 mr-1.5" />}
|
||||
{searchingApplications
|
||||
? t("vmLxc.appEditor.searchingApplications")
|
||||
: t("vmLxc.appEditor.searchApplications")}
|
||||
: isOciInstall ? <RefreshCw className="h-4 w-4 mr-1.5" /> : <Search className="h-4 w-4 mr-1.5" />}
|
||||
{isOciInstall
|
||||
? t(searchingApplications ? "vmLxc.appEditor.refreshingData" : "vmLxc.appEditor.refreshData")
|
||||
: searchingApplications
|
||||
? t("vmLxc.appEditor.searchingApplications")
|
||||
: t("vmLxc.appEditor.searchApplications")}
|
||||
</Button>
|
||||
{!isOciInstall && (
|
||||
<Button
|
||||
onClick={openBrowseOrEditor}
|
||||
className="bg-blue-500 hover:bg-blue-600 text-white"
|
||||
@@ -2489,6 +2601,7 @@ export function LxcAppPanel({ vmid, ctIp, onChange, managed, initialData }: Prop
|
||||
</span>
|
||||
)}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
{detectionNotice && (
|
||||
<p className={`text-xs text-center ${detectionNotice.found ? "text-emerald-400" : "text-muted-foreground"}`}>
|
||||
@@ -2524,6 +2637,7 @@ export function LxcAppPanel({ vmid, ctIp, onChange, managed, initialData }: Prop
|
||||
{app.installed_via === "apk" && app.package && <>apk · <code className="text-foreground/80">{app.package}</code></>}
|
||||
{app.installed_via === "file" && app.file_path && <>file · <code className="text-foreground/80">{app.file_path}</code></>}
|
||||
{app.installed_via === "binary" && app.binary_path && <>binary · <code className="text-foreground/80">{app.binary_path}</code></>}
|
||||
{app.installed_via === "oci_image" && st?.image_reference && <>OCI · <code className="text-foreground/80 break-all">{st.image_reference}</code></>}
|
||||
</div>
|
||||
)}
|
||||
{tracking && st?.checked_at && (
|
||||
@@ -2535,6 +2649,17 @@ export function LxcAppPanel({ vmid, ctIp, onChange, managed, initialData }: Prop
|
||||
stack below Checked, full-width so long repo
|
||||
names wrap cleanly instead of competing with
|
||||
the top-right on narrow screens. */}
|
||||
{app.installed_via === "oci_image" && tracking && st?.image_repository && (
|
||||
<a
|
||||
href={st.image_repository}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="md:hidden mt-1 text-xs text-muted-foreground hover:text-foreground inline-flex items-center gap-1 min-w-0"
|
||||
>
|
||||
<span className="truncate">{ociRepoLabel(st.image_repository)}</span>
|
||||
<ExternalLink className="h-3 w-3 flex-shrink-0" />
|
||||
</a>
|
||||
)}
|
||||
{app.repo && tracking && (
|
||||
<a
|
||||
href={`https://github.com/${app.repo}`}
|
||||
@@ -2551,6 +2676,17 @@ export function LxcAppPanel({ vmid, ctIp, onChange, managed, initialData }: Prop
|
||||
{/* Desktop-only repo link: same row as the title on md+,
|
||||
hidden on mobile where the stacked variant above
|
||||
handles it. */}
|
||||
{app.installed_via === "oci_image" && tracking && st?.image_repository && (
|
||||
<a
|
||||
href={st.image_repository}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="hidden md:inline-flex text-xs text-muted-foreground hover:text-foreground items-center gap-1 flex-shrink-0 mt-1"
|
||||
>
|
||||
{ociRepoLabel(st.image_repository)}
|
||||
<ExternalLink className="h-3 w-3" />
|
||||
</a>
|
||||
)}
|
||||
{app.repo && tracking && (
|
||||
<a
|
||||
href={`https://github.com/${app.repo}`}
|
||||
@@ -2565,6 +2701,41 @@ export function LxcAppPanel({ vmid, ctIp, onChange, managed, initialData }: Prop
|
||||
</div>
|
||||
|
||||
{(() => {
|
||||
// An application installed from an OCI image changes when its
|
||||
// image does. Both are shown — the application version it
|
||||
// carries and the image it runs — and the image decides.
|
||||
if (app.installed_via === "oci_image") {
|
||||
if (!tracking) return null
|
||||
const newImage = st?.update_available === true
|
||||
const appMoved = !!(st?.latest_version && st.latest_version !== st.installed_version)
|
||||
return (
|
||||
<div className="mb-3 grid gap-3 grid-cols-1 sm:grid-cols-2">
|
||||
<div className="p-3 rounded-md bg-muted/40">
|
||||
<div className="text-[10px] text-muted-foreground uppercase tracking-wider mb-1">{t("vmLxc.appEditor.ociAppVersion")}</div>
|
||||
<div className="text-lg font-semibold font-mono text-foreground break-all">
|
||||
{st?.installed_version || "—"}
|
||||
</div>
|
||||
{appMoved && (
|
||||
<div className="text-xs font-mono text-purple-400 mt-1 break-all">→ {st!.latest_version}</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="p-3 rounded-md bg-muted/40">
|
||||
<div className="text-[10px] text-muted-foreground uppercase tracking-wider mb-1">{t("vmLxc.appEditor.ociImage")}</div>
|
||||
<div className="text-sm font-semibold font-mono text-foreground">
|
||||
{ociImageLabel(st?.image_created, st?.installed_digest) || "—"}
|
||||
</div>
|
||||
{newImage ? (
|
||||
<div className="text-sm font-semibold font-mono text-purple-400 mt-1 flex items-center gap-2">
|
||||
{t("vmLxc.appEditor.ociNewImage")}: {ociImageLabel(st?.latest_image_created, st?.latest_digest)}
|
||||
<ArrowUpCircle className="h-5 w-5 text-purple-400 flex-shrink-0" aria-label={t("vmLxc.appEditor.updateAvailableBadge")} />
|
||||
</div>
|
||||
) : st?.latest_digest ? (
|
||||
<div className="text-xs text-muted-foreground mt-1">{t("vmLxc.appEditor.ociImageCurrent")}</div>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
// A delegated app has no upstream of its own; the version to
|
||||
// compare against comes from the image it updates with.
|
||||
const delegated = app.update_via === "docker"
|
||||
@@ -2614,9 +2785,14 @@ export function LxcAppPanel({ vmid, ctIp, onChange, managed, initialData }: Prop
|
||||
Logo is optional (per-port `logo_url`); when absent
|
||||
the row indents naturally to align with the text.
|
||||
If we can't resolve an IP for the CT we hide the row. */}
|
||||
{app.ports && app.ports.length > 0 && (
|
||||
{(isOciAdguard ? true : !!app.ports?.length) && (
|
||||
<div className="mb-3 space-y-4">
|
||||
{app.ports.map((p) => {
|
||||
{(isOciAdguard
|
||||
? [
|
||||
{ port: 80, description: app.name, scheme: "http" as const },
|
||||
...(adguardSetupAvailable ? [{ port: 3000, description: "Config", scheme: "http" as const }] : []),
|
||||
]
|
||||
: app.ports).map((p) => {
|
||||
const url = buildWebUrl(ctIp, p.port, p.scheme, p.custom_url)
|
||||
if (!url) return null
|
||||
const label = p.description || app.name
|
||||
@@ -2766,22 +2942,27 @@ export function LxcAppPanel({ vmid, ctIp, onChange, managed, initialData }: Prop
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={searchInstalledApplications}
|
||||
onClick={isOciInstall ? refreshOciData : searchInstalledApplications}
|
||||
disabled={searchingApplications || editMode}
|
||||
className="min-w-[7rem] sm:min-w-0 px-2.5 sm:px-3"
|
||||
aria-label={searchingApplications
|
||||
? t("vmLxc.appEditor.searchingApplications")
|
||||
: t("vmLxc.appEditor.searchApplications")}
|
||||
aria-label={isOciInstall
|
||||
? t(searchingApplications ? "vmLxc.appEditor.refreshingData" : "vmLxc.appEditor.refreshData")
|
||||
: searchingApplications
|
||||
? t("vmLxc.appEditor.searchingApplications")
|
||||
: t("vmLxc.appEditor.searchApplications")}
|
||||
>
|
||||
{searchingApplications
|
||||
? <Loader2 className="h-4 w-4 sm:mr-1.5 animate-spin" />
|
||||
: <Search className="h-4 w-4 sm:mr-1.5" />}
|
||||
: isOciInstall ? <RefreshCw className="h-4 w-4 sm:mr-1.5" /> : <Search className="h-4 w-4 sm:mr-1.5" />}
|
||||
<span className="hidden sm:inline">
|
||||
{searchingApplications
|
||||
? t("vmLxc.appEditor.searchingApplications")
|
||||
: t("vmLxc.appEditor.searchApplications")}
|
||||
{isOciInstall
|
||||
? t(searchingApplications ? "vmLxc.appEditor.refreshingData" : "vmLxc.appEditor.refreshData")
|
||||
: searchingApplications
|
||||
? t("vmLxc.appEditor.searchingApplications")
|
||||
: t("vmLxc.appEditor.searchApplications")}
|
||||
</span>
|
||||
</Button>
|
||||
{!isOciInstall && (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
@@ -2800,6 +2981,7 @@ export function LxcAppPanel({ vmid, ctIp, onChange, managed, initialData }: Prop
|
||||
)}
|
||||
</span>
|
||||
</Button>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setEditMode((v) => !v)}
|
||||
|
||||
@@ -178,8 +178,7 @@ export function LxcTerminalModal({
|
||||
// `cancelled` short-circuits the async init if the modal closes
|
||||
// before the dynamic xterm import resolves. Without this, we'd
|
||||
// construct a Terminal instance, attach it to a now-stale ref, and
|
||||
// open a WebSocket that nobody listens to. Audit Tier 6 — useEffect
|
||||
// con `import("xterm")` sin cancelación.
|
||||
// open a WebSocket that nobody listens to.
|
||||
let cancelled = false
|
||||
|
||||
// Small delay to ensure Dialog content is rendered
|
||||
|
||||
@@ -665,9 +665,8 @@ function renderVertical(data: NetworkFlowData, labels: FlowLabels, unit: Network
|
||||
const NIC_PATH_START_OFFSET = 46 // clears SUB_OFFSET_Y + text height
|
||||
const NIC_VERTICAL_LEG = 56
|
||||
const HOST_GAP_FROM_CONVERGE = 56
|
||||
const GUEST_ROW_H = 100 // más separación vertical entre
|
||||
// guests para que sub no toque
|
||||
// el círculo del siguiente
|
||||
const GUEST_ROW_H = 100 // enough vertical room that one guest's
|
||||
// sub clears the next guest's circle
|
||||
const BRIDGE_PITCH_PAD = 36
|
||||
// Vertical positions of the label and the sub (rate) BELOW each
|
||||
// node's circle. Both grew when the font went up to 12.5 px; this
|
||||
|
||||
@@ -15,7 +15,7 @@ import { useT } from "../lib/i18n/provider"
|
||||
import {
|
||||
Bell, BellOff, Send, CheckCircle2, XCircle, Loader2,
|
||||
AlertTriangle, Info, Settings2, Zap, Eye, EyeOff,
|
||||
Trash2, ChevronDown, ChevronUp, ChevronRight, TestTube2, Mail, Webhook,
|
||||
Trash2, ChevronRight, TestTube2, Mail, Webhook,
|
||||
Copy, Server, Shield, ExternalLink, RefreshCw, Download, Upload,
|
||||
Cloud, Brain, Globe, MessageSquareText, Sparkles, Pencil, Save, RotateCcw, Lightbulb,
|
||||
Moon, Newspaper
|
||||
@@ -343,7 +343,6 @@ export function NotificationSettings() {
|
||||
const [testing, setTesting] = useState<string | null>(null)
|
||||
const [testResult, setTestResult] = useState<{ channel: string; success: boolean; message: string } | null>(null)
|
||||
const [showHistory, setShowHistory] = useState(false)
|
||||
const [showAdvanced, setShowAdvanced] = useState(false)
|
||||
const [showSecrets, setShowSecrets] = useState<Record<string, boolean>>({})
|
||||
// Cleartext secrets cached only while the eye toggle is "on" for
|
||||
// that field. Settings GET returns "************" for everything in
|
||||
@@ -509,13 +508,6 @@ export function NotificationSettings() {
|
||||
if (showHistory) loadHistory()
|
||||
}, [showHistory, loadHistory])
|
||||
|
||||
// Auto-expand AI section when AI is enabled
|
||||
useEffect(() => {
|
||||
if (config.ai_enabled) {
|
||||
setShowAdvanced(true)
|
||||
}
|
||||
}, [config.ai_enabled])
|
||||
|
||||
const updateConfig = (updater: (prev: NotificationConfig) => NotificationConfig) => {
|
||||
setConfig(prev => {
|
||||
const next = updater(prev)
|
||||
@@ -919,13 +911,13 @@ export function NotificationSettings() {
|
||||
return flat
|
||||
}
|
||||
|
||||
const handleSave = async () => {
|
||||
const saveConfig = async (nextConfig: NotificationConfig): Promise<boolean> => {
|
||||
setSaving(true)
|
||||
setSaveError(null)
|
||||
try {
|
||||
// If notifications are being disabled, clean up PVE webhook first
|
||||
const wasEnabled = originalConfig.enabled
|
||||
const isNowDisabled = !config.enabled
|
||||
const isNowDisabled = !nextConfig.enabled
|
||||
|
||||
if (wasEnabled && isNowDisabled) {
|
||||
try {
|
||||
@@ -935,26 +927,33 @@ export function NotificationSettings() {
|
||||
}
|
||||
}
|
||||
|
||||
const payload = flattenConfig(config)
|
||||
const payload = flattenConfig(nextConfig)
|
||||
await fetchApi("/api/notifications/settings", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
setOriginalConfig(config)
|
||||
setConfig(nextConfig)
|
||||
setOriginalConfig(nextConfig)
|
||||
setHasChanges(false)
|
||||
setEditMode(false)
|
||||
setSaved(true)
|
||||
setTimeout(() => setSaved(false), 3000)
|
||||
loadStatus()
|
||||
return true
|
||||
} catch (err) {
|
||||
console.error("Failed to save notification settings:", err)
|
||||
const msg = err instanceof Error ? err.message : t("settings.notifications.errors.saveFailed")
|
||||
setSaveError(msg)
|
||||
return false
|
||||
} finally {
|
||||
setSaving(false)
|
||||
}
|
||||
}
|
||||
|
||||
const handleSave = async () => {
|
||||
await saveConfig(config)
|
||||
}
|
||||
|
||||
const handleCancel = () => {
|
||||
setConfig(originalConfig)
|
||||
setHasChanges(false)
|
||||
@@ -2226,74 +2225,45 @@ export function NotificationSettings() {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* ── Advanced: AI Enhancement ── */}
|
||||
<div>
|
||||
<div className="flex items-center justify-between py-1">
|
||||
<button
|
||||
className="flex items-center gap-2 text-sm text-foreground hover:bg-muted/60 rounded-md px-2 py-1.5 -mx-2 transition-colors"
|
||||
onClick={() => setShowAdvanced(!showAdvanced)}
|
||||
>
|
||||
{showAdvanced ? (
|
||||
<ChevronUp className="h-4 w-4 text-muted-foreground" />
|
||||
) : (
|
||||
<ChevronDown className="h-4 w-4 text-muted-foreground" />
|
||||
)}
|
||||
<Sparkles className="h-4 w-4 text-purple-400" />
|
||||
<span className="font-medium">{t("settings.notifications.ai.title")}</span>
|
||||
{config.ai_enabled ? (
|
||||
<Badge variant="outline" className="text-[10px] border-purple-500/40 text-purple-400 ml-1">
|
||||
{t("status.active")}
|
||||
</Badge>
|
||||
) : (
|
||||
<Badge variant="outline" className="text-[10px] border-border text-muted-foreground ml-1">
|
||||
{t("settings.notifications.ui.optional")}
|
||||
</Badge>
|
||||
)}
|
||||
</button>
|
||||
{showAdvanced && (
|
||||
<div className="flex items-center gap-2">
|
||||
{editMode ? (
|
||||
<>
|
||||
<button
|
||||
className="h-6 px-2 text-xs rounded-md border border-border bg-background hover:bg-muted transition-colors text-muted-foreground"
|
||||
onClick={handleCancel}
|
||||
disabled={saving}
|
||||
>
|
||||
{t("actions.cancel")}
|
||||
</button>
|
||||
<button
|
||||
className="h-6 px-2 text-xs rounded-md bg-blue-600 hover:bg-blue-700 text-white transition-colors disabled:opacity-50 flex items-center gap-1"
|
||||
onClick={handleSave}
|
||||
disabled={saving || !hasChanges}
|
||||
>
|
||||
{saving ? <Loader2 className="h-3 w-3 animate-spin" /> : <CheckCircle2 className="h-3 w-3" />}
|
||||
{t("actions.save")}
|
||||
</button>
|
||||
</>
|
||||
) : (
|
||||
<button
|
||||
className="h-6 px-2 text-xs rounded-md border border-border bg-background hover:bg-muted transition-colors flex items-center gap-1"
|
||||
onClick={() => setEditMode(true)}
|
||||
>
|
||||
<Settings2 className="h-3 w-3" />
|
||||
{t("actions.edit")}
|
||||
</button>
|
||||
)}
|
||||
{/* ── AI Enhancement ── */}
|
||||
<div className="space-y-3">
|
||||
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between py-1">
|
||||
<div className="flex items-start gap-3">
|
||||
<Sparkles className="h-5 w-5 text-purple-400 mt-0.5 shrink-0" />
|
||||
<div>
|
||||
<span className="text-sm font-medium">{t("settings.notifications.ai.title")}</span>
|
||||
<p className="text-xs sm:text-sm text-muted-foreground">{t("settings.notifications.ai.enhancedMessagesDescription")}</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{showAdvanced && (
|
||||
<div className="space-y-4 mt-3 p-4 rounded-lg bg-muted/30 border border-border/50">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-start gap-3">
|
||||
<Sparkles className="h-5 w-5 text-purple-400 mt-0.5 shrink-0" />
|
||||
<div>
|
||||
<span className="text-sm font-medium">{t("settings.notifications.ai.enhancedMessages")}</span>
|
||||
<p className="text-xs sm:text-sm text-muted-foreground">{t("settings.notifications.ai.enhancedMessagesDescription")}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center justify-end gap-2">
|
||||
{editMode ? (
|
||||
<>
|
||||
<button
|
||||
className="h-7 px-2 text-xs rounded-md border border-border bg-background hover:bg-muted transition-colors text-muted-foreground"
|
||||
onClick={handleCancel}
|
||||
disabled={saving}
|
||||
>
|
||||
{t("actions.cancel")}
|
||||
</button>
|
||||
<button
|
||||
className="h-7 px-2 text-xs rounded-md bg-blue-600 hover:bg-blue-700 text-white transition-colors disabled:opacity-50 flex items-center gap-1"
|
||||
onClick={handleSave}
|
||||
disabled={saving || !hasChanges}
|
||||
>
|
||||
{saving ? <Loader2 className="h-3 w-3 animate-spin" /> : <CheckCircle2 className="h-3 w-3" />}
|
||||
{t("actions.save")}
|
||||
</button>
|
||||
</>
|
||||
) : (
|
||||
<button
|
||||
className="h-7 px-2 text-xs rounded-md border border-border bg-background hover:bg-muted transition-colors flex items-center gap-1"
|
||||
onClick={() => setEditMode(true)}
|
||||
>
|
||||
<Settings2 className="h-3 w-3" />
|
||||
{t("actions.edit")}
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
className={`relative w-9 h-[18px] rounded-full transition-colors ${
|
||||
config.ai_enabled ? "bg-purple-600" : "bg-muted-foreground/20 border border-muted-foreground/40"
|
||||
} ${!editMode ? "opacity-60 cursor-not-allowed" : "cursor-pointer"}`}
|
||||
@@ -2305,10 +2275,12 @@ export function NotificationSettings() {
|
||||
<span className={`absolute top-[1px] left-[1px] h-4 w-4 rounded-full bg-white shadow transition-transform ${
|
||||
config.ai_enabled ? "translate-x-[18px]" : "translate-x-0"
|
||||
}`} />
|
||||
</button>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{config.ai_enabled && (
|
||||
{config.ai_enabled && (
|
||||
<div className="space-y-4 p-4 rounded-lg bg-muted/30 border border-border/50">
|
||||
<>
|
||||
{/* Provider + Info button */}
|
||||
<div className="space-y-2">
|
||||
@@ -2661,10 +2633,12 @@ export function NotificationSettings() {
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
updateConfig(p => ({ ...p, ai_custom_prompt: customPromptDraft }))
|
||||
setEditingCustomPrompt(false)
|
||||
handleSave()
|
||||
onClick={async () => {
|
||||
const nextConfig = { ...config, ai_custom_prompt: customPromptDraft }
|
||||
if (await saveConfig(nextConfig)) {
|
||||
setEditingCustomPrompt(false)
|
||||
setCustomPromptDraft("")
|
||||
}
|
||||
}}
|
||||
className="h-7 px-2 text-xs flex items-center gap-1 bg-blue-600 hover:bg-blue-700 text-white border-blue-600"
|
||||
>
|
||||
@@ -2714,8 +2688,8 @@ export function NotificationSettings() {
|
||||
const file = (e.target as HTMLInputElement).files?.[0]
|
||||
if (file) {
|
||||
const text = await file.text()
|
||||
updateConfig(p => ({ ...p, ai_custom_prompt: text }))
|
||||
handleSave()
|
||||
const nextConfig = { ...config, ai_custom_prompt: text }
|
||||
await saveConfig(nextConfig)
|
||||
}
|
||||
}
|
||||
input.click()
|
||||
@@ -2783,7 +2757,6 @@ export function NotificationSettings() {
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,255 @@
|
||||
"use client"
|
||||
|
||||
// Console output of a native OCI container: what the image's main process
|
||||
// writes to stdout/stderr, kept on the host by liblxc. The first request
|
||||
// brings the last N lines; while following, each poll sends back the byte
|
||||
// offset and inode it holds and receives only what was appended. Nothing is
|
||||
// cached — the backend reads the file on every request.
|
||||
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react"
|
||||
import { Card, CardContent } from "./ui/card"
|
||||
import { Badge } from "./ui/badge"
|
||||
import { Button } from "./ui/button"
|
||||
import { Input } from "./ui/input"
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./ui/select"
|
||||
import { AlertCircle, Download, FileText, Loader2, Pause, Play, RefreshCw } from "lucide-react"
|
||||
import { fetchApi } from "../lib/api-config"
|
||||
import { useT } from "@/lib/i18n/provider"
|
||||
|
||||
interface ConsoleLogResponse {
|
||||
ok: boolean
|
||||
enabled: boolean
|
||||
lines: string[]
|
||||
offset: number
|
||||
inode: number | null
|
||||
reset?: boolean
|
||||
head_truncated?: boolean
|
||||
error?: string
|
||||
}
|
||||
|
||||
const LINE_OPTIONS = [100, 500, 1000] as const
|
||||
const POLL_MS = 2000
|
||||
|
||||
const lineTone = (line: string) => {
|
||||
if (/\b(error|fatal|panic|critical|exception)\b/i.test(line)) return "text-red-400"
|
||||
if (/\bwarn(ing)?\b/i.test(line)) return "text-amber-400"
|
||||
return "text-foreground/90"
|
||||
}
|
||||
|
||||
export function OciConsoleLogPanel({ vmid, running }: { vmid: number; running: boolean }) {
|
||||
const t = useT()
|
||||
const [lineCount, setLineCount] = useState<number>(500)
|
||||
const [lines, setLines] = useState<string[]>([])
|
||||
const [enabled, setEnabled] = useState(true)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
const [follow, setFollow] = useState(true)
|
||||
const [filter, setFilter] = useState("")
|
||||
const position = useRef<{ offset: number; inode: number | null } | null>(null)
|
||||
const scroller = useRef<HTMLDivElement>(null)
|
||||
const inFlight = useRef(false)
|
||||
|
||||
const load = useCallback(async () => {
|
||||
setLoading(true)
|
||||
setError(null)
|
||||
try {
|
||||
const r = await fetchApi<ConsoleLogResponse>(`/api/lxc/${vmid}/console-log?lines=${lineCount}`)
|
||||
setEnabled(r.enabled)
|
||||
setLines(r.lines || [])
|
||||
position.current = { offset: r.offset, inode: r.inode }
|
||||
if (r.error) setError(r.error)
|
||||
} catch (e) {
|
||||
setError(e instanceof Error ? e.message : String(e))
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}, [vmid, lineCount])
|
||||
|
||||
const poll = useCallback(async () => {
|
||||
const pos = position.current
|
||||
if (!pos || inFlight.current) return
|
||||
inFlight.current = true
|
||||
try {
|
||||
const inode = pos.inode === null ? "" : `&inode=${pos.inode}`
|
||||
const r = await fetchApi<ConsoleLogResponse>(
|
||||
`/api/lxc/${vmid}/console-log?lines=${lineCount}&offset=${pos.offset}${inode}`,
|
||||
)
|
||||
position.current = { offset: r.offset, inode: r.inode }
|
||||
if (r.reset) {
|
||||
setLines(r.lines || [])
|
||||
} else if (r.lines?.length) {
|
||||
setLines((prev) => {
|
||||
const next = prev.concat(r.lines)
|
||||
return next.length > lineCount ? next.slice(next.length - lineCount) : next
|
||||
})
|
||||
}
|
||||
} catch {
|
||||
// A failed poll leaves the view as it is; the next one retries.
|
||||
} finally {
|
||||
inFlight.current = false
|
||||
}
|
||||
}, [vmid, lineCount])
|
||||
|
||||
useEffect(() => {
|
||||
load()
|
||||
}, [load])
|
||||
|
||||
useEffect(() => {
|
||||
if (!follow || !running || !enabled || loading) return
|
||||
const timer = setInterval(() => {
|
||||
if (document.visibilityState === "visible") poll()
|
||||
}, POLL_MS)
|
||||
poll()
|
||||
return () => clearInterval(timer)
|
||||
}, [follow, running, enabled, loading, poll])
|
||||
|
||||
const shown = useMemo(() => {
|
||||
const needle = filter.trim().toLowerCase()
|
||||
return needle ? lines.filter((l) => l.toLowerCase().includes(needle)) : lines
|
||||
}, [lines, filter])
|
||||
|
||||
useEffect(() => {
|
||||
if (follow && scroller.current) scroller.current.scrollTop = scroller.current.scrollHeight
|
||||
}, [shown, follow])
|
||||
|
||||
// Scrolling up to read stops following; the Follow button resumes it.
|
||||
const onScroll = () => {
|
||||
const el = scroller.current
|
||||
if (!el || !follow) return
|
||||
if (el.scrollHeight - el.scrollTop - el.clientHeight > 40) setFollow(false)
|
||||
}
|
||||
|
||||
const download = () => {
|
||||
const blob = new Blob([lines.join("\n") + "\n"], { type: "text/plain;charset=utf-8" })
|
||||
const url = URL.createObjectURL(blob)
|
||||
const a = document.createElement("a")
|
||||
a.href = url
|
||||
a.download = `ct-${vmid}-console.log`
|
||||
a.click()
|
||||
URL.revokeObjectURL(url)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="h-full flex flex-col min-h-0">
|
||||
<Card className="border border-border bg-card/50 flex flex-col flex-1 min-h-0">
|
||||
<CardContent className="p-4 flex flex-col flex-1 min-h-0">
|
||||
<div className="flex items-center justify-between mb-2 gap-2 flex-wrap shrink-0">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="p-1.5 rounded-md bg-sky-500/10">
|
||||
<FileText className="h-4 w-4 text-sky-500" />
|
||||
</div>
|
||||
<h3 className="text-sm font-semibold text-foreground">{t("vmLxc.consoleLog.title")}</h3>
|
||||
{enabled && shown.length > 0 && (
|
||||
<Badge variant="secondary" className="text-xs h-5 ml-1">{shown.length}</Badge>
|
||||
)}
|
||||
</div>
|
||||
{enabled && (
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<Select value={String(lineCount)} onValueChange={(v) => setLineCount(Number(v))}>
|
||||
<SelectTrigger className="h-7 w-auto text-xs gap-1">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{LINE_OPTIONS.map((n) => (
|
||||
<SelectItem key={n} value={String(n)} className="text-xs">
|
||||
{t("vmLxc.consoleLog.lastLines", { count: n })}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{running && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
className="h-7 text-xs gap-1"
|
||||
onClick={() => setFollow((f) => !f)}
|
||||
aria-pressed={follow}
|
||||
>
|
||||
{follow ? <Pause className="h-3 w-3" /> : <Play className="h-3 w-3" />}
|
||||
<span>{follow ? t("vmLxc.consoleLog.pause") : t("vmLxc.consoleLog.follow")}</span>
|
||||
</Button>
|
||||
)}
|
||||
<Button size="sm" variant="outline" className="h-7 text-xs gap-1" onClick={load} disabled={loading}>
|
||||
{loading ? <Loader2 className="h-3 w-3 animate-spin" /> : <RefreshCw className="h-3 w-3" />}
|
||||
<span>{t("vmLxc.consoleLog.refresh")}</span>
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
className="h-7 text-xs gap-1"
|
||||
onClick={download}
|
||||
disabled={lines.length === 0}
|
||||
>
|
||||
<Download className="h-3 w-3" />
|
||||
<span>{t("vmLxc.consoleLog.download")}</span>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<p className="text-xs text-muted-foreground mb-3 shrink-0">
|
||||
{t("vmLxc.consoleLog.description")}
|
||||
{enabled && !running && <> {t("vmLxc.consoleLog.stopped")}</>}
|
||||
</p>
|
||||
|
||||
{enabled && (
|
||||
<Input
|
||||
value={filter}
|
||||
onChange={(e) => setFilter(e.target.value)}
|
||||
placeholder={t("vmLxc.consoleLog.filter")}
|
||||
className="h-8 text-xs mb-3 shrink-0"
|
||||
/>
|
||||
)}
|
||||
|
||||
{loading && lines.length === 0 ? (
|
||||
<div className="flex-1 flex items-center justify-center text-muted-foreground min-h-0">
|
||||
<Loader2 className="h-4 w-4 animate-spin mr-2" />
|
||||
<span className="text-sm">{t("vmLxc.consoleLog.loading")}</span>
|
||||
</div>
|
||||
) : error ? (
|
||||
<div className="rounded-md border border-red-500/30 bg-red-500/5 p-4 text-sm shrink-0">
|
||||
<div className="flex items-start gap-2">
|
||||
<AlertCircle className="h-4 w-4 text-red-500 shrink-0 mt-0.5" />
|
||||
<div>
|
||||
<p className="font-medium text-red-500 mb-1">{t("vmLxc.consoleLog.readFailed")}</p>
|
||||
<p className="text-xs text-muted-foreground break-all">{error}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : !enabled ? (
|
||||
<div className="rounded-md border border-amber-500/30 bg-amber-500/5 p-4 text-sm shrink-0">
|
||||
<div className="flex items-start gap-2">
|
||||
<FileText className="h-4 w-4 text-amber-500 shrink-0 mt-0.5" />
|
||||
<div className="space-y-2">
|
||||
<p className="font-medium text-amber-500">{t("vmLxc.consoleLog.notAvailableTitle")}</p>
|
||||
<p className="text-xs text-muted-foreground leading-relaxed">{t("vmLxc.consoleLog.notAvailableHint")}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : lines.length === 0 ? (
|
||||
<div className="flex-1 flex flex-col items-center justify-center text-sm text-muted-foreground min-h-0">
|
||||
{t("vmLxc.consoleLog.empty")}
|
||||
<div className="text-xs mt-1">{t("vmLxc.consoleLog.emptyHint")}</div>
|
||||
</div>
|
||||
) : shown.length === 0 ? (
|
||||
<div className="flex-1 flex items-center justify-center text-sm text-muted-foreground min-h-0">
|
||||
{t("vmLxc.consoleLog.noMatches")}
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
ref={scroller}
|
||||
onScroll={onScroll}
|
||||
className="rounded-md border border-border bg-background/50 flex-1 overflow-y-auto min-h-0"
|
||||
>
|
||||
<pre className="text-[11px] font-mono leading-snug whitespace-pre-wrap break-all p-3">
|
||||
{shown.map((line, idx) => (
|
||||
<div key={idx} className={lineTone(line)}>{line || " "}</div>
|
||||
))}
|
||||
</pre>
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -239,8 +239,7 @@ export function ProxmoxDashboard() {
|
||||
fetchHealthInfoCount()
|
||||
fetchUpdateStatus()
|
||||
|
||||
// En overview: cada 30 segundos para actualización frecuente del estado de salud
|
||||
// En otras tabs: cada 60 segundos para reducir carga
|
||||
// Overview polls health every 30 s; the other tabs every 60 s.
|
||||
let interval: ReturnType<typeof setInterval> | null = null
|
||||
let healthInterval: ReturnType<typeof setInterval> | null = null
|
||||
if (activeTab === "overview") {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { useState, useEffect } from "react"
|
||||
import { Button } from "./ui/button"
|
||||
import { Dialog, DialogContent, DialogTitle } from "./ui/dialog"
|
||||
import { X, Sparkles, Thermometer, Activity, HardDrive, Shield, Globe, Cpu, Zap, Sliders, Wrench, RefreshCw, Server, BellOff, Bell, Calendar, DatabaseBackup, Smartphone, Languages } from "lucide-react"
|
||||
import { X, Sparkles, Thermometer, Activity, HardDrive, Shield, Globe, Cpu, Zap, Sliders, Wrench, RefreshCw, Server, BellOff, Bell, Calendar, DatabaseBackup, Smartphone, Languages, Package, ScrollText, ArrowUpCircle } from "lucide-react"
|
||||
import { Checkbox } from "./ui/checkbox"
|
||||
import { useT } from "../lib/i18n/provider"
|
||||
import { APP_VERSION } from "../lib/version"
|
||||
@@ -305,34 +305,39 @@ export const CHANGELOG: Record<string, ReleaseNote> = {
|
||||
// that haven't been curated by hand.
|
||||
const CURRENT_VERSION_FEATURES = [
|
||||
{
|
||||
icon: <Activity className="h-5 w-5" />,
|
||||
key: "releaseNotes.currentFeatures.auditAssessment",
|
||||
text: "Audit & Report — a new page that documents and assesses the node. The Assessment runs a catalogue of checks across security, backups, capacity, storage, network, hardware, guests and system, classifying each finding as critical, warning, observation or conformant and stating what it read rather than judging it.",
|
||||
icon: <Package className="h-5 w-5" />,
|
||||
key: "releaseNotes.currentFeatures.ociAppTab",
|
||||
text: "OCI containers in the App tab — a container installed by OCI manager Apps is recognised from its installation record: the application and its image, a new image detected by digest, and a link to the image repository.",
|
||||
},
|
||||
{
|
||||
icon: <Sliders className="h-5 w-5" />,
|
||||
key: "releaseNotes.currentFeatures.changeJournal",
|
||||
text: "Change journal — a Changes view that lists exactly what ProxMenux modified on this host: every configuration file, package and service it touched, with the prior state of each, deduplicated to a current-state view that shows the host as it stands now rather than a log of every run.",
|
||||
icon: <RefreshCw className="h-5 w-5" />,
|
||||
key: "releaseNotes.currentFeatures.ociUpdatesTab",
|
||||
text: "Updates for OCI containers — Update and Recreate open the same flow as the OCI menu, the backup taken before updating can be kept in a backup storage, and the image can be updated on a schedule.",
|
||||
},
|
||||
{
|
||||
icon: <Sparkles className="h-5 w-5" />,
|
||||
key: "releaseNotes.currentFeatures.auditReports",
|
||||
text: "Reports — a full audit plus focused Security review, Backup assurance and Capacity & wear reports, each opening on its own posture header, and a printable Inventory; all export to PDF. A security assessment asks before running Lynis so a run stays fast.",
|
||||
icon: <ScrollText className="h-5 w-5" />,
|
||||
key: "releaseNotes.currentFeatures.ociLogsTab",
|
||||
text: "Logs tab for OCI containers — the console output of the application, kept on the host and followed live, with a filter and a download. The Proxmox console of these containers opens a shell.",
|
||||
},
|
||||
{
|
||||
icon: <Calendar className="h-5 w-5" />,
|
||||
key: "releaseNotes.currentFeatures.auditPolicyBaseline",
|
||||
text: "Policy and baseline — declare what the host is expected to be (backup requirements, firewall, root SSH login) so findings grade against it, mark a run as the reference, and see what changed since, with new, resolved and accepted findings kept apart.",
|
||||
icon: <ArrowUpCircle className="h-5 w-5" />,
|
||||
key: "releaseNotes.currentFeatures.appsUpdateShortcut",
|
||||
text: "The update icon on the Apps page opens the container straight on its Updates tab.",
|
||||
},
|
||||
{
|
||||
icon: <Bell className="h-5 w-5" />,
|
||||
key: "releaseNotes.currentFeatures.groupedAppUpdates",
|
||||
text: "Grouped application update notifications — one complete message per scan instead of one per application, grouped by LXC with the installed and available versions.",
|
||||
key: "releaseNotes.currentFeatures.webhookHttps",
|
||||
text: "Proxmox notifications reach the Monitor with HTTPS enabled — they are delivered on a local-only address and no longer fail with a certificate error.",
|
||||
},
|
||||
{
|
||||
icon: <Shield className="h-5 w-5" />,
|
||||
key: "releaseNotes.currentFeatures.adminTokenScope",
|
||||
text: "Administrative scope — opening a Monitor terminal and disabling authentication now require a full-admin token, so a read-only API token issued to a monitoring integration stays read-only (reported by @f3rs3n).",
|
||||
icon: <Activity className="h-5 w-5" />,
|
||||
key: "releaseNotes.currentFeatures.persistentLogs",
|
||||
text: "A burst of log errors that ended is no longer reported as persistent: a pattern has to keep appearing for 15 minutes, and its warning clears on its own (reported by @Joshua1264).",
|
||||
},
|
||||
{
|
||||
icon: <HardDrive className="h-5 w-5" />,
|
||||
key: "releaseNotes.currentFeatures.mountsLanAddress",
|
||||
text: "Mount points on LVM-thin and other block storage show their usage, and multi-container applications open at their LAN address.",
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
@@ -287,8 +287,7 @@ const initMessage = {
|
||||
// Snapshot the open-state at call time. After the dynamic xterm
|
||||
// imports resolve, bail out if the modal has since been closed —
|
||||
// otherwise we attach a Terminal to a stale ref and open a WS that
|
||||
// nobody reads. Audit Tier 6 — useEffect con `import("xterm")` sin
|
||||
// cancelación.
|
||||
// nobody reads.
|
||||
const wasOpenAtCall = isOpenRef.current
|
||||
const [TerminalClass, FitAddonClass] = await Promise.all([
|
||||
import("xterm").then((mod) => mod.Terminal),
|
||||
|
||||
@@ -639,7 +639,7 @@ export const TerminalPanel: React.FC<TerminalPanelProps> = ({ websocketUrl, onCl
|
||||
}
|
||||
|
||||
const handleKeyButton = (key: string, e?: React.MouseEvent | React.TouchEvent) => {
|
||||
// Prevenir comportamientos por defecto del navegador
|
||||
// Stop the browser default for this key
|
||||
if (e) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
|
||||
@@ -21,7 +21,8 @@ import useSWR from "swr"
|
||||
import { MetricsView } from "./metrics-dialog"
|
||||
import { LxcTerminalModal } from "./lxc-terminal-modal"
|
||||
import { ScriptTerminalModal } from "./script-terminal-modal"
|
||||
import { LxcAppPanel, ThemeAwareLogo } from "./lxc-app-panel"
|
||||
import { LxcAppPanel, ThemeAwareLogo, ociImageLabel } from "./lxc-app-panel"
|
||||
import { OciConsoleLogPanel } from "./oci-console-log-panel"
|
||||
import { AppUpdaterEditor, type AppUpdateMethod } from "./app-updater-editor"
|
||||
import { formatStorage } from "../lib/utils"
|
||||
import { formatNetworkTraffic, getNetworkUnit } from "../lib/format-network"
|
||||
@@ -41,6 +42,17 @@ interface LxcPackageUpdate {
|
||||
latest: string
|
||||
security: boolean
|
||||
}
|
||||
// A container installed by OCI manager Apps, read from its record.
|
||||
interface OciInstanceInfo {
|
||||
oci_instance: boolean
|
||||
console_log: boolean
|
||||
stack: boolean
|
||||
primary_vmid: number
|
||||
members: number[]
|
||||
host_directories: boolean
|
||||
pending: boolean
|
||||
}
|
||||
|
||||
interface LxcUpdateCheck {
|
||||
available: boolean
|
||||
count: number
|
||||
@@ -115,6 +127,12 @@ interface LxcAppWatch {
|
||||
error: string | null
|
||||
checked_at: string | null
|
||||
has_repo?: boolean
|
||||
// OCI image of an application installed by OCI manager Apps.
|
||||
image_reference?: string | null
|
||||
image_created?: string | null
|
||||
installed_digest?: string | null
|
||||
latest_image_created?: string | null
|
||||
latest_digest?: string | null
|
||||
// Set for the synthetic entry that represents a ProxMenux-managed
|
||||
// OCI app (Secure Gateway). The frontend renders it read-only +
|
||||
// wires the Update action to /api/oci/installed/<id>/update.
|
||||
@@ -925,7 +943,15 @@ export function VirtualMachines() {
|
||||
const [backupPbsChangeMode, setBackupPbsChangeMode] = useState<string>("default")
|
||||
|
||||
// Tab state for modal
|
||||
const [activeModalTab, setActiveModalTab] = useState<"status" | "mounts" | "backups" | "app" | "updates" | "firewall">("status")
|
||||
const [activeModalTab, setActiveModalTab] = useState<"status" | "mounts" | "backups" | "app" | "updates" | "firewall" | "logs">("status")
|
||||
// OCI containers keep their console output on the host; the Logs tab is
|
||||
// offered only when the backend finds that log for the open container.
|
||||
const [consoleLogAvailable, setConsoleLogAvailable] = useState(false)
|
||||
// Set when the open container was installed by OCI manager Apps: its
|
||||
// Updates tab replaces the image instead of updating packages.
|
||||
const [ociInstance, setOciInstance] = useState<OciInstanceInfo | null>(null)
|
||||
const [ociAction, setOciAction] = useState<{ vmid: number; action: "update" | "recreate" } | null>(null)
|
||||
const [scheduleAckExternal, setScheduleAckExternal] = useState(false)
|
||||
|
||||
// Firewall log state — fetched only when the operator opens that tab
|
||||
// so a CT/VM without firewall use doesn't pay the pvesh cost on every
|
||||
@@ -1068,9 +1094,10 @@ export function VirtualMachines() {
|
||||
if (!vm) return
|
||||
handleVMClick(vm)
|
||||
// handleVMClick resets the inner tab to "status"; override to
|
||||
// "app" in the same render tick — React batches these and the
|
||||
// the requested tab ("app" by default, "updates" from the update
|
||||
// icon) in the same render tick — React batches these and the
|
||||
// last setActiveModalTab wins.
|
||||
setActiveModalTab("app")
|
||||
setActiveModalTab(detail.tab === "updates" ? "updates" : "app")
|
||||
}
|
||||
window.addEventListener("openLxcAppModal", handler as EventListener)
|
||||
return () => window.removeEventListener("openLxcAppModal", handler as EventListener)
|
||||
@@ -1126,6 +1153,7 @@ export function VirtualMachines() {
|
||||
cache.details.delete(vm.vmid)
|
||||
cache.backups.delete(vm.vmid)
|
||||
cache.mountPoints.delete(vm.vmid)
|
||||
if (vm.type === "lxc") reseedMountPoints(vm.vmid)
|
||||
cache.schedule.delete(vm.vmid)
|
||||
cache.firewall.delete(vm.vmid)
|
||||
dockerInventoryRequestedRef.current.delete(vm.vmid)
|
||||
@@ -1223,6 +1251,8 @@ export function VirtualMachines() {
|
||||
setFirewallLogs([])
|
||||
setFirewallLogError(null)
|
||||
setFirewallEnabled(true)
|
||||
setConsoleLogAvailable(false)
|
||||
setOciInstance(null)
|
||||
|
||||
// Prime UI from last-known payloads so a reopened guest never
|
||||
// flashes "Loading…" — the backend and this cache both revalidate
|
||||
@@ -1264,6 +1294,7 @@ export function VirtualMachines() {
|
||||
// extends the same idea to the two tabs still on lazy-fetch.
|
||||
if (vm.type === "lxc") {
|
||||
fetchMountPoints(vm.vmid)
|
||||
fetchOciInstance(vm.vmid)
|
||||
// Shared cache dedup: if a hover already fired this, we share
|
||||
// the same promise (no duplicate backend work). The App panel
|
||||
// reads from the same cache, so switching to that tab either
|
||||
@@ -1325,7 +1356,8 @@ export function VirtualMachines() {
|
||||
useEffect(() => {
|
||||
if (!vmData || vmData.length === 0) return
|
||||
let cancelled = false
|
||||
fetchApi<{
|
||||
let retryTimer: ReturnType<typeof setTimeout> | undefined
|
||||
const hydrate = (attempt: number) => fetchApi<{
|
||||
guests: Array<{
|
||||
vmid: number
|
||||
type: "qemu" | "lxc"
|
||||
@@ -1340,6 +1372,10 @@ export function VirtualMachines() {
|
||||
.then((payload) => {
|
||||
if (cancelled || !payload?.guests) return
|
||||
const cache = vmModalCacheRef.current
|
||||
// Guests the server has not warmed yet come back null; ask again
|
||||
// shortly so their mount tab is seeded before the modal opens.
|
||||
const pending = payload.guests.some((g) => g.type === "lxc" && !g.mount_points)
|
||||
if (pending && attempt < 3) retryTimer = setTimeout(() => hydrate(attempt + 1), 20000)
|
||||
for (const g of payload.guests) {
|
||||
if (g.details) cache.details.set(g.vmid, g.details)
|
||||
if (g.backups?.backups) {
|
||||
@@ -1373,10 +1409,25 @@ export function VirtualMachines() {
|
||||
// Silent — modal open handlers fall back to individual
|
||||
// fetches if the ref cache is empty.
|
||||
})
|
||||
return () => { cancelled = true }
|
||||
hydrate(0)
|
||||
return () => {
|
||||
cancelled = true
|
||||
if (retryTimer) clearTimeout(retryTimer)
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [vmidsKey])
|
||||
|
||||
const fetchOciInstance = (vmid: number) =>
|
||||
fetchApi<OciInstanceInfo>(`/api/lxc/${vmid}/oci-instance`)
|
||||
.then((r) => {
|
||||
setConsoleLogAvailable(!!r?.console_log)
|
||||
setOciInstance(r?.oci_instance ? r : null)
|
||||
})
|
||||
.catch(() => {
|
||||
setConsoleLogAvailable(false)
|
||||
setOciInstance(null)
|
||||
})
|
||||
|
||||
const fetchMountPoints = async (vmid: number) => {
|
||||
// Two fetches in parallel:
|
||||
// 1) STATIC — configured mp entries + PVE classification. Backed
|
||||
@@ -1390,49 +1441,66 @@ export function VirtualMachines() {
|
||||
// user perceives no lag.
|
||||
const hasSeed = mountPoints.length > 0
|
||||
if (!hasSeed) setLoadingMounts(true)
|
||||
try {
|
||||
const [staticResp, runtimeResp] = await Promise.all([
|
||||
fetchApi<{
|
||||
ok: boolean
|
||||
mount_points: LxcMountPoint[]
|
||||
ad_hoc_hint_count?: number
|
||||
}>(`/api/lxc/${vmid}/mount-points`).catch((e) => {
|
||||
console.error("Error fetching static mount points:", e)
|
||||
return null
|
||||
}),
|
||||
fetchApi<{
|
||||
ok: boolean
|
||||
running: boolean
|
||||
runtime: Record<string, Partial<LxcMountPoint>>
|
||||
ad_hoc: LxcMountPoint[]
|
||||
}>(`/api/lxc/${vmid}/mount-points/runtime`).catch((e) => {
|
||||
console.error("Error fetching runtime mount points:", e)
|
||||
return null
|
||||
}),
|
||||
])
|
||||
if (staticResp?.ok) {
|
||||
const mp = staticResp.mount_points || []
|
||||
const hint = staticResp.ad_hoc_hint_count ?? 0
|
||||
setMountPoints(mp)
|
||||
setMountsAdHocHint(hint)
|
||||
vmModalCacheRef.current.mountPoints.set(vmid, { mount_points: mp, ad_hoc_hint_count: hint })
|
||||
} else if (!hasSeed) {
|
||||
setMountPoints([])
|
||||
}
|
||||
if (runtimeResp?.ok) {
|
||||
setMountPointsRuntime(runtimeResp.runtime || {})
|
||||
setAdHocMounts(runtimeResp.ad_hoc || [])
|
||||
} else {
|
||||
// Each half is applied as soon as it lands: the static list decides
|
||||
// whether the tab exists and must not wait for df/stat.
|
||||
const staticReq = fetchApi<{
|
||||
ok: boolean
|
||||
mount_points: LxcMountPoint[]
|
||||
ad_hoc_hint_count?: number
|
||||
}>(`/api/lxc/${vmid}/mount-points`)
|
||||
.then((staticResp) => {
|
||||
if (staticResp?.ok) {
|
||||
const mp = staticResp.mount_points || []
|
||||
const hint = staticResp.ad_hoc_hint_count ?? 0
|
||||
setMountPoints(mp)
|
||||
setMountsAdHocHint(hint)
|
||||
vmModalCacheRef.current.mountPoints.set(vmid, { mount_points: mp, ad_hoc_hint_count: hint })
|
||||
} else if (!hasSeed) {
|
||||
setMountPoints([])
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error("Error fetching static mount points:", e)
|
||||
if (!hasSeed) setMountPoints([])
|
||||
})
|
||||
.finally(() => setLoadingMounts(false))
|
||||
const runtimeReq = fetchApi<{
|
||||
ok: boolean
|
||||
running: boolean
|
||||
runtime: Record<string, Partial<LxcMountPoint>>
|
||||
ad_hoc: LxcMountPoint[]
|
||||
}>(`/api/lxc/${vmid}/mount-points/runtime`)
|
||||
.then((runtimeResp) => {
|
||||
if (runtimeResp?.ok) {
|
||||
setMountPointsRuntime(runtimeResp.runtime || {})
|
||||
setAdHocMounts(runtimeResp.ad_hoc || [])
|
||||
} else {
|
||||
setMountPointsRuntime({})
|
||||
setAdHocMounts([])
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error("Error fetching runtime mount points:", e)
|
||||
setMountPointsRuntime({})
|
||||
setAdHocMounts([])
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching LXC mount points:", error)
|
||||
if (!hasSeed) setMountPoints([])
|
||||
setAdHocMounts([])
|
||||
} finally {
|
||||
setLoadingMounts(false)
|
||||
}
|
||||
})
|
||||
await Promise.all([staticReq, runtimeReq])
|
||||
}
|
||||
|
||||
// Background refill of the static mount list after a lifecycle event,
|
||||
// so the next open of that guest renders its tab bar complete.
|
||||
const reseedMountPoints = (vmid: number) => {
|
||||
fetchApi<{ ok: boolean; mount_points: LxcMountPoint[]; ad_hoc_hint_count?: number }>(
|
||||
`/api/lxc/${vmid}/mount-points`,
|
||||
)
|
||||
.then((r) => {
|
||||
if (!r?.ok) return
|
||||
vmModalCacheRef.current.mountPoints.set(vmid, {
|
||||
mount_points: r.mount_points || [],
|
||||
ad_hoc_hint_count: r.ad_hoc_hint_count ?? 0,
|
||||
})
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const handleMetricsClick = () => {
|
||||
@@ -1967,6 +2035,7 @@ const handleDownloadLogs = async (vmid: number, vmName: string) => {
|
||||
? s.targets.map((value: any) => String(value))
|
||||
: ([...(legacyTarget !== "app" ? ["os"] : []), ...(legacyTarget !== "os" ? ["apps"] : [])]))
|
||||
setScheduleReleaseDelayDays(Number.isInteger(Number(s.release_delay_days)) ? Number(s.release_delay_days) : 0)
|
||||
setScheduleAckExternal(s.acknowledge_external_data === true)
|
||||
if (s.backup !== undefined) setApplyBackup(!!s.backup)
|
||||
if (s.backup_storage) setApplyBackupStorage(s.backup_storage)
|
||||
if (s.restart !== undefined) setApplyRestart(!!s.restart)
|
||||
@@ -2118,8 +2187,11 @@ const handleDownloadLogs = async (vmid: number, vmName: string) => {
|
||||
// leave scheduleConfigured=false and Save PUTs cron="" so the
|
||||
// backend doesn't resurrect the schedule.
|
||||
const cronToSave = scheduleEnabled || scheduleConfigured ? scheduleCron : ""
|
||||
const hasOsTarget = scheduleTargets.includes("os")
|
||||
const hasAppTarget = scheduleTargets.some((value) => value !== "os")
|
||||
// A container installed by OCI manager Apps has one thing to update on
|
||||
// a schedule: its image.
|
||||
const targetsToSave = ociInstance ? ["oci_image"] : scheduleTargets
|
||||
const hasOsTarget = targetsToSave.includes("os")
|
||||
const hasAppTarget = targetsToSave.some((value) => value !== "os")
|
||||
const derivedTarget: "os" | "app" | "both" = hasOsTarget && hasAppTarget ? "both" : hasOsTarget ? "os" : "app"
|
||||
try {
|
||||
await fetchApi(`/api/vms/${vmid}/schedule`, {
|
||||
@@ -2129,11 +2201,12 @@ const handleDownloadLogs = async (vmid: number, vmName: string) => {
|
||||
enabled: scheduleEnabled,
|
||||
cron: cronToSave,
|
||||
target: derivedTarget,
|
||||
targets: scheduleTargets,
|
||||
targets: targetsToSave,
|
||||
release_delay_days: scheduleReleaseDelayDays,
|
||||
backup: applyBackup,
|
||||
backup_storage: applyBackupStorage || selectedBackupStorage || "",
|
||||
restart: applyRestart,
|
||||
restart: ociInstance ? false : applyRestart,
|
||||
acknowledge_external_data: ociInstance ? scheduleAckExternal : false,
|
||||
}),
|
||||
})
|
||||
if (cronToSave.trim()) setScheduleConfigured(true)
|
||||
@@ -2155,6 +2228,7 @@ const handleDownloadLogs = async (vmid: number, vmName: string) => {
|
||||
scheduleTarget: scheduleTarget,
|
||||
scheduleTargets: [...scheduleTargets],
|
||||
scheduleReleaseDelayDays: scheduleReleaseDelayDays,
|
||||
scheduleAckExternal: scheduleAckExternal,
|
||||
})
|
||||
setOptionsEditMode(true)
|
||||
}
|
||||
@@ -2169,6 +2243,7 @@ const handleDownloadLogs = async (vmid: number, vmName: string) => {
|
||||
setScheduleTarget(optionsSnapshot.scheduleTarget)
|
||||
setScheduleTargets(optionsSnapshot.scheduleTargets || ["os", "apps"])
|
||||
setScheduleReleaseDelayDays(optionsSnapshot.scheduleReleaseDelayDays)
|
||||
setScheduleAckExternal(!!optionsSnapshot.scheduleAckExternal)
|
||||
}
|
||||
setOptionsSnapshot(null)
|
||||
setOptionsEditMode(false)
|
||||
@@ -3746,6 +3821,24 @@ const handleDownloadLogs = async (vmid: number, vmName: string) => {
|
||||
</Badge>
|
||||
</button>
|
||||
)}
|
||||
{/* Logs tab — native OCI containers only: the console
|
||||
output of the image's main process, read live from
|
||||
the host on every open. */}
|
||||
{selectedVM?.type === "lxc" && (consoleLogAvailable || selectedVM?.update_check?.is_oci_lxc) && (
|
||||
<button
|
||||
onClick={() => setActiveModalTab("logs")}
|
||||
className={`flex items-center gap-1.5 sm:gap-2 px-2.5 sm:px-4 py-2.5 text-sm font-medium transition-colors border-b-2 -mb-px whitespace-nowrap shrink-0 ${
|
||||
activeModalTab === "logs"
|
||||
? "border-sky-500 text-sky-500"
|
||||
: "border-transparent text-muted-foreground hover:text-foreground"
|
||||
}`}
|
||||
>
|
||||
<FileText className="h-4 w-4" />
|
||||
<span className={activeModalTab === "logs" ? "" : "hidden sm:inline"}>
|
||||
{t("vmLxc.tabs.logs")}
|
||||
</span>
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
onClick={() => setActiveModalTab("backups")}
|
||||
className={`flex items-center gap-1.5 sm:gap-2 px-2.5 sm:px-4 py-2.5 text-sm font-medium transition-colors border-b-2 -mb-px whitespace-nowrap shrink-0 ${
|
||||
@@ -5115,8 +5208,299 @@ const handleDownloadLogs = async (vmid: number, vmName: string) => {
|
||||
)
|
||||
})()}
|
||||
|
||||
{/* Branch 1 — OCI-image container */}
|
||||
{!selectedVM.update_check?.managed_oci_app &&
|
||||
{/* Branch 0b — container installed by OCI manager Apps. It is
|
||||
updated by replacing its image, through the same flow as
|
||||
the OCI menu; nothing of the package or app updaters of an
|
||||
ordinary LXC applies. */}
|
||||
{!selectedVM.update_check?.managed_oci_app && ociInstance && (() => {
|
||||
const ociApp = (selectedVM.app_watches || []).find((a) => a.installed_via === "oci_image")
|
||||
const hasUpdate = ociApp?.update_available === true
|
||||
const upToDate = ociApp?.update_available === false
|
||||
const installedLabel = ociApp ? ociImageLabel(ociApp.image_created, ociApp.installed_digest) : ""
|
||||
const latestLabel = ociApp ? ociImageLabel(ociApp.latest_image_created, ociApp.latest_digest) : ""
|
||||
const updateBtnCls = hasUpdate
|
||||
? "bg-purple-600/15 hover:bg-purple-600/25 border border-purple-500/40 text-purple-300 hover:text-purple-200"
|
||||
: "bg-green-500/10 hover:bg-green-500/20 border border-green-500/30 text-green-400 hover:text-green-300"
|
||||
const neutralBtnCls = "border border-input bg-background text-foreground/80 hover:bg-accent hover:text-accent-foreground"
|
||||
const storageForBackup = applyBackupStorage || selectedBackupStorage
|
||||
return (
|
||||
<>
|
||||
<Card className="border border-border bg-card/50">
|
||||
<CardContent className="p-4">
|
||||
<div className="flex items-center gap-2 mb-3 min-w-0">
|
||||
<Package className="h-4 w-4 text-muted-foreground flex-shrink-0" />
|
||||
<h3 className="text-sm font-semibold text-foreground truncate">
|
||||
{ociApp?.name || selectedVM.name}
|
||||
</h3>
|
||||
</div>
|
||||
{ociApp?.checked_at && (
|
||||
<div className="text-xs text-muted-foreground mb-3 leading-relaxed">
|
||||
{t("vmLxc.updates.lastCheckedPrefix")} {new Date(ociApp.checked_at).toLocaleString()}
|
||||
</div>
|
||||
)}
|
||||
{!ociApp ? (
|
||||
<div className="text-sm text-muted-foreground">{t("vmLxc.ociUpdates.notTracked")}</div>
|
||||
) : hasUpdate ? (
|
||||
<div className="space-y-2 text-sm">
|
||||
<div className="flex items-center gap-2">
|
||||
<Package className="h-4 w-4 text-muted-foreground flex-shrink-0" />
|
||||
<span>{t("vmLxc.ociUpdates.installedImage")} <code className="text-foreground/80">{installedLabel}</code></span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<ArrowUpCircle className="h-4 w-4 text-purple-400 flex-shrink-0" />
|
||||
<span>{t("vmLxc.ociUpdates.newImage", { image: latestLabel })}</span>
|
||||
</div>
|
||||
</div>
|
||||
) : upToDate ? (
|
||||
<div className="text-sm text-muted-foreground flex items-center gap-2">
|
||||
<CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" />
|
||||
<span>{t("vmLxc.updates.upToDateAtLabel")} <code className="text-foreground/80">{installedLabel}</code></span>
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-sm text-muted-foreground flex items-center gap-2">
|
||||
<Package className="h-4 w-4 flex-shrink-0" />
|
||||
<span>{t("vmLxc.ociUpdates.installedImage")} <code className="text-foreground/80">{installedLabel || "—"}</code></span>
|
||||
</div>
|
||||
)}
|
||||
{ociInstance.stack && (
|
||||
<div className="text-xs text-muted-foreground mt-3 leading-relaxed">
|
||||
{t("vmLxc.ociUpdates.stackNote", { primary: ociInstance.primary_vmid, count: ociInstance.members.length })}
|
||||
</div>
|
||||
)}
|
||||
{ociInstance.pending && (
|
||||
<div className="text-xs text-amber-400 mt-3 leading-relaxed">{t("vmLxc.ociUpdates.pendingNote")}</div>
|
||||
)}
|
||||
<div className="mt-4 pt-4 border-t border-border/50 flex flex-wrap justify-end gap-2">
|
||||
{!ociInstance.stack && !ociInstance.pending && (
|
||||
<Button
|
||||
size="sm"
|
||||
className={neutralBtnCls}
|
||||
onClick={() => setOciAction({ vmid: selectedVM.vmid, action: "recreate" })}
|
||||
>
|
||||
<RotateCcw className="h-4 w-4 mr-1.5" />
|
||||
{t("vmLxc.ociUpdates.recreate")}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
size="sm"
|
||||
className={updateBtnCls}
|
||||
onClick={() => setOciAction({ vmid: selectedVM.vmid, action: "update" })}
|
||||
>
|
||||
{hasUpdate
|
||||
? <ArrowUpCircle className="h-4 w-4 mr-1.5" />
|
||||
: <RefreshCw className="h-4 w-4 mr-1.5" />}
|
||||
{ociInstance.pending ? t("vmLxc.ociUpdates.recover") : t("vmLxc.ociUpdates.update")}
|
||||
</Button>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Options — the backup the update keeps and the
|
||||
scheduled image update. */}
|
||||
<Card className={optionsEditMode ? "border border-border bg-card" : "border border-border bg-card/50"}>
|
||||
<CardContent className="p-4 space-y-4">
|
||||
<h3 className="text-sm font-semibold text-foreground">{t("vmLxc.options.title")}</h3>
|
||||
{!optionsEditMode ? (
|
||||
<div className="text-sm flex items-center gap-2">
|
||||
{applyBackup ? (
|
||||
<CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" />
|
||||
) : (
|
||||
<div className="h-4 w-4 rounded-full border border-muted-foreground/40 flex-shrink-0" />
|
||||
)}
|
||||
<span>
|
||||
{applyBackup
|
||||
? <>{t("vmLxc.ociUpdates.keepBackup")} <span className="text-muted-foreground">{t("vmLxc.options.snapshotOn", { storage: storageForBackup || t("vmLxc.options.storageAuto") })}</span></>
|
||||
: <span className="text-muted-foreground">{t("vmLxc.ociUpdates.noKeepBackup")}</span>}
|
||||
</span>
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-start gap-2 text-sm">
|
||||
<Checkbox
|
||||
id="oci-keep-backup"
|
||||
checked={applyBackup}
|
||||
onCheckedChange={(v) => setApplyBackup(Boolean(v))}
|
||||
className="mt-0.5"
|
||||
/>
|
||||
<Label htmlFor="oci-keep-backup" className="leading-tight cursor-pointer">
|
||||
<span>{t("vmLxc.ociUpdates.keepBackup")}</span>
|
||||
<div className="text-xs text-muted-foreground mt-0.5">{t("vmLxc.ociUpdates.keepBackupHelp")}</div>
|
||||
</Label>
|
||||
</div>
|
||||
{applyBackup && backupStorages.length > 0 && (
|
||||
<div className="pl-6">
|
||||
<Label className="text-xs text-muted-foreground">{t("vmLxc.options.backupStorage")}</Label>
|
||||
<Select value={storageForBackup} onValueChange={setApplyBackupStorage}>
|
||||
<SelectTrigger className="h-8 text-sm mt-1 max-w-xs">
|
||||
<SelectValue placeholder={t("vmLxc.options.pickStorage")} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{backupStorages.map((st) => (
|
||||
<SelectItem key={st.storage} value={st.storage}>{st.storage}</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="pt-4 border-t border-border/50 space-y-3">
|
||||
<div className="flex items-start justify-between gap-3">
|
||||
<div className="min-w-0">
|
||||
<div className="text-sm font-medium text-foreground">{t("vmLxc.scheduled.title")}</div>
|
||||
{optionsEditMode && (
|
||||
<div className="text-xs text-muted-foreground mt-0.5">{t("vmLxc.ociUpdates.scheduleHelp")}</div>
|
||||
)}
|
||||
</div>
|
||||
<Switch
|
||||
checked={scheduleEnabled}
|
||||
onCheckedChange={(v) => { if (optionsEditMode) setScheduleEnabled(v) }}
|
||||
disabled={!optionsEditMode}
|
||||
className="data-[state=checked]:bg-blue-600 data-[state=unchecked]:bg-input border border-border"
|
||||
/>
|
||||
</div>
|
||||
{!optionsEditMode && scheduleConfigured && (
|
||||
<div className="text-sm space-y-1.5">
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<span className={"h-2 w-2 rounded-full flex-shrink-0 " + (scheduleEnabled ? "bg-green-500" : "bg-muted-foreground/40")} />
|
||||
<span className={scheduleEnabled ? "" : "text-muted-foreground"}>
|
||||
<span className="text-foreground/80">{t("vmLxc.scheduled.chipLabel")}</span> — {humanCron(scheduleCron)}
|
||||
{!scheduleEnabled && <span className="text-muted-foreground"> {t("vmLxc.scheduled.disabledSuffix")}</span>}
|
||||
</span>
|
||||
</div>
|
||||
{scheduleReleaseDelayDays > 0 && (
|
||||
<div className="text-xs text-muted-foreground pl-4">
|
||||
{t("vmLxc.scheduled.releaseDelaySummary", { days: scheduleReleaseDelayDays })}
|
||||
</div>
|
||||
)}
|
||||
{renderScheduleRunDetails(true)}
|
||||
</div>
|
||||
)}
|
||||
{!optionsEditMode && !scheduleConfigured && (
|
||||
<div className="text-sm flex items-center gap-2 text-muted-foreground">
|
||||
<div className="h-4 w-4 rounded-full border border-muted-foreground/40 flex-shrink-0" />
|
||||
<span>{t("vmLxc.scheduled.notScheduled")}</span>
|
||||
</div>
|
||||
)}
|
||||
{optionsEditMode && scheduleEnabled && (
|
||||
<div className="space-y-3">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
|
||||
<div>
|
||||
<Label className="text-xs text-muted-foreground">{t("vmLxc.scheduled.frequency")}</Label>
|
||||
<Select
|
||||
value={schedulePreset}
|
||||
onValueChange={(v) => {
|
||||
setSchedulePreset(v)
|
||||
const preset = CRON_PRESETS.find((p) => p.value === v)
|
||||
if (preset && preset.cron) setScheduleCron(preset.cron)
|
||||
}}
|
||||
>
|
||||
<SelectTrigger className="h-8 text-sm mt-1"><SelectValue /></SelectTrigger>
|
||||
<SelectContent>
|
||||
{CRON_PRESETS.map((p) => (
|
||||
<SelectItem key={p.value} value={p.value}>{p.label}</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div>
|
||||
<Label className="text-xs text-muted-foreground">{t("vmLxc.scheduled.cronExpression")}</Label>
|
||||
<Input
|
||||
value={scheduleCron}
|
||||
onChange={(e) => { setScheduleCron(e.target.value); setSchedulePreset("custom") }}
|
||||
placeholder={t("vmLxc.scheduled.cronPlaceholder")}
|
||||
className="h-8 text-sm mt-1 font-mono"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<Label className="text-xs text-muted-foreground">{t("vmLxc.scheduled.releaseDelayLabel")}</Label>
|
||||
<Select value={String(scheduleReleaseDelayDays)} onValueChange={(v) => setScheduleReleaseDelayDays(Number(v))}>
|
||||
<SelectTrigger className="h-8 text-sm mt-1 max-w-xs"><SelectValue /></SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="0">{t("vmLxc.scheduled.releaseDelayNone")}</SelectItem>
|
||||
{[1, 3, 7, 14].map((days) => (
|
||||
<SelectItem key={days} value={String(days)}>{t("vmLxc.scheduled.releaseDelayDays", { days })}</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<div className="text-[10px] text-muted-foreground mt-1 max-w-xl">{t("vmLxc.ociUpdates.releaseDelayHelp")}</div>
|
||||
</div>
|
||||
{ociInstance.host_directories && (
|
||||
<div className="flex items-start gap-2 text-sm">
|
||||
<Checkbox
|
||||
id="oci-ack-external"
|
||||
checked={scheduleAckExternal}
|
||||
onCheckedChange={(v) => setScheduleAckExternal(Boolean(v))}
|
||||
className="mt-0.5"
|
||||
/>
|
||||
<Label htmlFor="oci-ack-external" className="leading-tight cursor-pointer">
|
||||
<span>{t("vmLxc.ociUpdates.ackExternal")}</span>
|
||||
<div className="text-xs text-muted-foreground mt-0.5">{t("vmLxc.ociUpdates.ackExternalHelp")}</div>
|
||||
</Label>
|
||||
</div>
|
||||
)}
|
||||
{renderScheduleRunDetails()}
|
||||
</div>
|
||||
)}
|
||||
{optionsEditMode && scheduleConfigured && (
|
||||
<div className="flex justify-end">
|
||||
<button
|
||||
type="button"
|
||||
onClick={deleteScheduleFromOptions}
|
||||
disabled={scheduleSaving}
|
||||
className="h-8 px-3 text-xs rounded-md border border-red-500/30 bg-red-500/10 hover:bg-red-500/20 text-red-400 transition-colors inline-flex items-center gap-1.5 disabled:opacity-60"
|
||||
>
|
||||
<Trash2 className="h-3.5 w-3.5" />
|
||||
{t("vmLxc.scheduled.deleteButton")}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
{scheduleError && <div className="text-xs text-red-400">{scheduleError}</div>}
|
||||
</div>
|
||||
|
||||
<div className="pt-4 border-t border-border/50 flex items-center justify-end gap-2">
|
||||
{!optionsEditMode ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={enterOptionsEdit}
|
||||
className="h-8 px-3 text-xs rounded-md border border-border bg-background hover:bg-muted transition-colors inline-flex items-center gap-1.5"
|
||||
>
|
||||
<Settings2 className="h-3.5 w-3.5" />
|
||||
{t("vmLxc.options.editButton")}
|
||||
</button>
|
||||
) : (
|
||||
<>
|
||||
<button
|
||||
type="button"
|
||||
onClick={cancelOptionsEdit}
|
||||
disabled={scheduleSaving}
|
||||
className="h-8 px-3 text-xs rounded-md border border-border bg-background hover:bg-muted transition-colors inline-flex items-center gap-1.5 disabled:opacity-60"
|
||||
>
|
||||
{t("vmLxc.options.cancelButton")}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={saveOptionsEdit}
|
||||
disabled={scheduleSaving || (scheduleEnabled && ociInstance.host_directories && !scheduleAckExternal)}
|
||||
className="h-8 px-3 text-xs rounded-md bg-blue-600 hover:bg-blue-700 text-white transition-colors disabled:opacity-40 inline-flex items-center gap-1.5"
|
||||
>
|
||||
{scheduleSaving ? <Loader2 className="h-3.5 w-3.5 animate-spin" /> : <Check className="h-3.5 w-3.5" />}
|
||||
{t("vmLxc.options.saveButton")}
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</>
|
||||
)
|
||||
})()}
|
||||
|
||||
{/* Branch 1 — OCI-image container not installed by
|
||||
OCI manager Apps */}
|
||||
{!selectedVM.update_check?.managed_oci_app && !ociInstance &&
|
||||
selectedVM.update_check?.is_oci_lxc && (
|
||||
<Card className="border border-border bg-card/50">
|
||||
<CardContent className="p-4 space-y-2">
|
||||
@@ -5149,7 +5533,7 @@ const handleDownloadLogs = async (vmid: number, vmName: string) => {
|
||||
Individual actions stay with their section. The
|
||||
optional reusable bulk action is configured in its
|
||||
own card immediately before Options. */}
|
||||
{!selectedVM.update_check?.managed_oci_app &&
|
||||
{!selectedVM.update_check?.managed_oci_app && !ociInstance &&
|
||||
!selectedVM.update_check?.is_oci_lxc && (() => {
|
||||
const uc = selectedVM.update_check
|
||||
const osUpdateStatusKnown = !!uc && !uc.error
|
||||
@@ -6942,6 +7326,14 @@ const handleDownloadLogs = async (vmid: number, vmName: string) => {
|
||||
</Card>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{activeModalTab === "logs" && selectedVM?.type === "lxc" && (
|
||||
<OciConsoleLogPanel
|
||||
key={selectedVM.vmid}
|
||||
vmid={selectedVM.vmid}
|
||||
running={selectedVM.status === "running"}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="border-t border-border bg-background px-6 py-4 mt-auto shrink-0">
|
||||
@@ -7375,6 +7767,37 @@ const handleDownloadLogs = async (vmid: number, vmName: string) => {
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Update or recreate an OCI instance: the same flow as OCI manager
|
||||
Apps -> Manage installed OCI applications, for this container. */}
|
||||
{ociAction && (
|
||||
<ScriptTerminalModal
|
||||
open={!!ociAction}
|
||||
onClose={() => {
|
||||
const vmid = ociAction.vmid
|
||||
setOciAction(null)
|
||||
// The image, the digest and the record changed: read them again.
|
||||
fetchApi(`/api/vms/${vmid}/apps/check`, { method: "POST" })
|
||||
.catch(() => undefined)
|
||||
.finally(() => {
|
||||
invalidateLxcApps(vmid)
|
||||
vmModalCacheRef.current.mountPoints.delete(vmid)
|
||||
fetchOciInstance(vmid)
|
||||
fetchMountPoints(vmid)
|
||||
mutate()
|
||||
})
|
||||
}}
|
||||
scriptPath="/usr/local/share/proxmenux/scripts/oci/manage_instance.sh"
|
||||
scriptName="oci_manage_instance"
|
||||
title={ociAction.action === "update" ? t("vmLxc.ociUpdates.terminalTitleUpdate") : t("vmLxc.ociUpdates.terminalTitleRecreate")}
|
||||
description={t("vmLxc.ociUpdates.terminalDescription")}
|
||||
params={{
|
||||
VMID: String(ociAction.vmid),
|
||||
ACTION: ociAction.action,
|
||||
KEEP_BACKUP: ociAction.action === "update" && applyBackup ? (applyBackupStorage || selectedBackupStorage || "") : "",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,4 +8,4 @@
|
||||
// 3. beta_version.txt ← bash pipeline (build_appimage.sh)
|
||||
//
|
||||
// Keep the three in sync on every bump.
|
||||
export const APP_VERSION = "1.2.6.1-beta"
|
||||
export const APP_VERSION = "1.2.6.2-beta"
|
||||
|
||||
+193
-137
@@ -1069,7 +1069,8 @@
|
||||
"backups": "Backups",
|
||||
"updates": "Aktualisierungen",
|
||||
"firewall": "Firewall",
|
||||
"app": "App"
|
||||
"app": "App",
|
||||
"logs": "Logs"
|
||||
},
|
||||
"actions": {
|
||||
"start": "Start",
|
||||
@@ -1169,6 +1170,44 @@
|
||||
"empty": "Es wurden noch keine Firewall-Ereignisse aufgezeichnet.",
|
||||
"emptyHint": "Regeln mit log:info oder höher füllen diese Ansicht, wenn Pakete eintreffen."
|
||||
},
|
||||
"consoleLog": {
|
||||
"title": "Konsolenausgabe",
|
||||
"description": "Standardausgabe und Fehlerausgabe des Hauptprozesses des Images.",
|
||||
"stopped": "Der Container ist gestoppt; das Log enthält die Ausgabe seiner vorherigen Läufe.",
|
||||
"lastLines": "Letzte {count} Zeilen",
|
||||
"follow": "Folgen",
|
||||
"pause": "Pausieren",
|
||||
"refresh": "Aktualisieren",
|
||||
"download": "Herunterladen",
|
||||
"filter": "Zeilen filtern",
|
||||
"loading": "Konsolenausgabe wird geladen...",
|
||||
"empty": "Noch keine Ausgabe aufgezeichnet.",
|
||||
"emptyHint": "Zeilen erscheinen hier, sobald der Container auf seine Konsole schreibt.",
|
||||
"noMatches": "Keine Zeile entspricht dem Filter.",
|
||||
"readFailed": "Das Konsolen-Log konnte nicht gelesen werden",
|
||||
"notAvailableTitle": "Dieser Container hat kein Konsolen-Log",
|
||||
"notAvailableHint": "Das Konsolen-Log wird eingerichtet, wenn ProxMenux den Container aus seinem OCI-Image installiert."
|
||||
},
|
||||
"ociUpdates": {
|
||||
"notTracked": "Wird die Anwendung in der App-Registerkarte registriert, wird ihr Image hier verfolgt.",
|
||||
"installedImage": "Installiertes Image",
|
||||
"newImage": "Neues Image {image} verfügbar",
|
||||
"stackNote": "Teil einer Multi-Container-Anwendung (Haupt-CT {primary}, {count} Container): Das Update umfasst alle.",
|
||||
"pendingNote": "Ein Vorgang an diesem Container wurde unterbrochen; Wiederherstellen öffnet seine Wiederherstellung.",
|
||||
"update": "Aktualisieren",
|
||||
"recreate": "Neu erstellen",
|
||||
"recover": "Wiederherstellen",
|
||||
"terminalTitleUpdate": "OCI-Anwendung aktualisieren",
|
||||
"terminalTitleRecreate": "OCI-Anwendung neu erstellen",
|
||||
"terminalDescription": "Derselbe Ablauf wie OCI manager Apps → Installierte OCI-Anwendungen verwalten.",
|
||||
"keepBackup": "Das vor dem Update erstellte Backup behalten",
|
||||
"noKeepBackup": "Das vor dem Update erstellte Backup wird nicht behalten",
|
||||
"keepBackupHelp": "Jedes Update sichert den Container, bevor sein Image ersetzt wird, um ihn wiederherzustellen, falls das Update fehlschlägt. Mit dieser Option wird dieses Backup im gewählten Speicher behalten; auf Proxmox Backup Server wird vor dem Update ein Backup geschrieben.",
|
||||
"scheduleHelp": "Nur das Image wird aktualisiert, und nur wenn seine Registry ein neues veröffentlicht.",
|
||||
"releaseDelayHelp": "Ein neues Image wird erst installiert, wenn es mindestens so alt ist.",
|
||||
"ackExternal": "Host-Verzeichnisse werden durch das Backup nicht zurückgesetzt",
|
||||
"ackExternalHelp": "Dieser Container nutzt Host-Verzeichnisse. Ein geplantes Update läuft nur, wenn dies bestätigt ist."
|
||||
},
|
||||
"options": {
|
||||
"title": "Optionen",
|
||||
"snapshotBefore": "Schnappschuss vor der Bewerbung",
|
||||
@@ -1429,6 +1468,14 @@
|
||||
"loadFailed": "Die Massenaktualisierungskonfiguration konnte nicht geladen werden."
|
||||
},
|
||||
"appEditor": {
|
||||
"methodOciImage": "OCI-Image (von ProxMenux installiert)",
|
||||
"ociImageHelp": "Version und Updates werden aus dem Image gelesen, aus dem dieser Container erstellt wurde. ProxMenux hat ihn installiert, daher gibt es nichts zu konfigurieren: Das installierte Image wird mit dem verglichen, das seine Registry heute veröffentlicht.",
|
||||
"ociAppVersion": "Anwendung",
|
||||
"ociImage": "Image",
|
||||
"ociNewImage": "Neues Image",
|
||||
"ociImageCurrent": "Version",
|
||||
"refreshData": "Daten aktualisieren",
|
||||
"refreshingData": "Wird aktualisiert…",
|
||||
"dockerDetectedWithWorkloads": "Docker mit {count} Anwendungen in Containern erkannt",
|
||||
"dockerWorkloadsHeading": "Anwendungen in Docker",
|
||||
"runsInsideDocker": "Wird mit dem Docker-Image aktualisiert",
|
||||
@@ -1487,7 +1534,6 @@
|
||||
"containerNameLabel": "Containername",
|
||||
"containerNamePlaceholder": "z. B. <Ihr-Container-Name>",
|
||||
"ociLabelKeyLabel": "OCI-Labelschlüssel",
|
||||
"ociLabelPlaceholder": "org.opencontainers.image.version",
|
||||
"pythonInterpreterLabel": "Pfad des Python-Interpreters",
|
||||
"pythonInterpreterPlaceholder": "z. B. /opt/<your-app>/venv/bin/python",
|
||||
"pipDistLabel": "Distributionsname (Pip-Paket)",
|
||||
@@ -1534,11 +1580,8 @@
|
||||
"portHttps": "https",
|
||||
"portLogoLabel": "Logo-URL für diesen Link (optional)",
|
||||
"portLogoPlaceholder": "z. B. https://example.com/logo.webp",
|
||||
"portCategoryPlaceholder": "Category for the Apps dashboard (optional)",
|
||||
"portCategoryNone": "No category",
|
||||
"portCategoryAddNew": "+ Add new category…",
|
||||
"portCategoryCustomPlaceholder": "Type a category and press Enter (Esc to cancel)",
|
||||
"portCustomUrlPlaceholder": "Custom URL (e.g. https://vault.example.com) — overrides IP:port",
|
||||
"removePortTooltip": "Port entfernen",
|
||||
"detectMethodDpkg": "dpkg ·",
|
||||
"detectMethodApk": "apk ·",
|
||||
@@ -1631,7 +1674,11 @@
|
||||
"notifyUpstreamLabel": "Benachrichtigen Sie mich, wenn eine neue Upstream-Version verfügbar ist",
|
||||
"notifyUpstreamHelp": "Sendet „app_update_available“ an die Kanäle, die in Einstellungen → Benachrichtigungen aktiviert sind. Deaktivieren Sie diese Option, wenn diese App auf Ihrer Box nicht aktualisiert werden kann.",
|
||||
"excludeFromBadgeLabel": "Vom LXC-Aktualisierungszähler ausschließen",
|
||||
"excludeFromBadgeHelp": "Zählen Sie diese App nicht im Abzeichen „Aggregate Updates“ auf der LXC-Listenkarte. Nützlich, wenn Sie absichtlich an eine bestimmte Version gebunden sind (Tracker-Anforderung, Kompatibilitätsstopp).Hat keinen Einfluss auf den eigenen Status der App-Registerkarte oder die ausgehende Benachrichtigung."
|
||||
"excludeFromBadgeHelp": "Zählen Sie diese App nicht im Abzeichen „Aggregate Updates“ auf der LXC-Listenkarte. Nützlich, wenn Sie absichtlich an eine bestimmte Version gebunden sind (Tracker-Anforderung, Kompatibilitätsstopp).Hat keinen Einfluss auf den eigenen Status der App-Registerkarte oder die ausgehende Benachrichtigung.",
|
||||
"ociLabelPlaceholder": "org.opencontainers.image.version",
|
||||
"portCategoryPlaceholder": "Kategorie für das Apps-Dashboard (optional)",
|
||||
"portCategoryCustomPlaceholder": "Geben Sie eine Kategorie ein und drücken Sie Enter (Esc to cancel)",
|
||||
"portCustomUrlPlaceholder": "Benutzerdefinierte URL (z. B. https://vault.example.com) überschreibt IP:port"
|
||||
},
|
||||
"statusFilter": {
|
||||
"ariaLabel": "Virtuelle Maschinen und Container filtern",
|
||||
@@ -2515,10 +2562,10 @@
|
||||
"scope": {
|
||||
"label": "Token permissions",
|
||||
"readOnly": "Read-only",
|
||||
"readOnlyHint": "Reads metrics and status. Recommended for dashboards and integrations.",
|
||||
"fullAdmin": "Full admin",
|
||||
"fullAdminHint": "Full control, like your own session.",
|
||||
"fullAdminWarning": "A full-admin token can do everything you can: power off or reboot the host, run updates and open a terminal. Share it only with fully trusted integrations."
|
||||
"readOnlyHint": "Lesen Sie Metriken und Status. Empfohlen für Dashboards und Integrationen.",
|
||||
"fullAdminHint": "Volle Kontrolle, wie Ihre eigene Sitzung.",
|
||||
"fullAdminWarning": "Ein Full-Admin-Token kann alles tun, was Sie können: den Host ausschalten oder neu starten, Updates ausführen und ein Terminal öffnen. Teilen Sie es nur mit vollständig vertrauenswürdigen Integrationen."
|
||||
}
|
||||
},
|
||||
"firewall": {
|
||||
@@ -3302,26 +3349,33 @@
|
||||
"gotIt": "Habe es!",
|
||||
"dontShowAgain": "Für diese Version nicht mehr anzeigen",
|
||||
"currentFeatures": {
|
||||
"appDetection": "Smarter app detection in the App tab: Docker is correctly promoted as the parent workload during cold start (Portainer/SearXNG no longer briefly show up as native apps), unregistered suggestions live in the startup cache, and 'Find applications' runs a fresh catalog-backed scan on demand.",
|
||||
"dockerUpdates": "The Updates tab now covers Docker end-to-end: Docker Engine and per-image update tracking follow the same 24-hour rolling cycle as OS packages, with a 'Check now' action for on-demand digest comparison — no more waiting for the daily collector.",
|
||||
"appCatalog": "New application detection catalog with over 380 tracked workloads, generated live from community-scripts across seven detector methods (file, binary, dpkg, apk, Python, Docker exec, Docker label). Primary and fallback detectors cover both new and historical LXC layouts.",
|
||||
"pushover": "Pushover joins Telegram, Gotify, Discord, Email and Apprise as a native notification channel — user/API key, device and sound selectors, priority 0 for regular messages, optional priority 1 for CRITICAL events. Suggested by @benginx (#308).",
|
||||
"appsDashboard": "New top-level Apps dashboard — a single launcher for every Web Link across the node. LXC-registered apps and user-defined Custom Web Links share the same grid with category badges, search, and one-click deep-links back to the guest modal.",
|
||||
"lxcAppsUpdates": "App tab inside every LXC modal registers installed apps, captures weblinks and tracks upstream versions. Reworked Updates tab applies OS packages and app updates from a single button; Docker Engine and per-image tracking follow the same 24-hour cycle, with a 'Check now' action on demand.",
|
||||
"multilingual": "The Monitor now speaks 8 languages: English, Spanish, German, French, Italian, Portuguese, Swedish and Slovak. Huge thanks to @vaso73 for building the i18n scaffolding that made this possible.",
|
||||
"nvidiaMultiGpu": "NVIDIA driver lifecycle moves to per-BDF ownership so a multi-GPU host can pass one card to a VM and keep the other operational on the host or in LXCs, plus a kernel + branch + GPU-aware version picker (#298).",
|
||||
"aiCustomEndpoint": "AI Assistant custom OpenAI endpoint — LiteLLM, LM Studio, LocalAI, vLLM, OmniRoute and any self-hosted proxy on private IPs, loopback or Docker networks are recognised when loading the model catalogue. The dropdown surfaces the server's error (or the underlying network reason) directly under the Load button (#325, reported by @jorgeffonte).",
|
||||
"secureGatewayArch": "Secure Gateway wizard — the Alpine template download, local template selection and pct create all match the host's real architecture, so x86_64 hosts receive amd64 containers and arm64 hosts receive arm64 containers (#324, reported by @N0X4DD0).",
|
||||
"atomicNotifications": "Notification events reserve their deduplication fingerprint atomically before AI processing and channel delivery, so concurrent collectors, completion callbacks or parallel Monitor processes cannot send the same event twice. The reservation is released when no channel succeeds, preserving retries.",
|
||||
"borgSshPort": "Borg remote target — the Add Borg destination dialog and the shell TUI accept a custom SSH port. BORG_RSH, the auto key install flow and the capacity probe all honour it. Fully backwards compatible with existing entries created without an explicit port (suggested by @songochain in discussion #236).",
|
||||
"githubToken": "Settings → GitHub API accepts an optional personal access token for release and tag checks when the anonymous quota is exhausted. The token is encrypted at rest and never returned to the browser; the rate-limit error is translated in every Monitor language (suggested by @SystemIdleProcess in discussion #306).",
|
||||
"replicationContext": "Native Proxmox replication failure notifications resolve the replication job ID, affected VM/LXC ID and guest name; the exact error block from Proxmox is preserved as the reason, and each replication job deduplicates independently (reported by Ale R.).",
|
||||
"auditAssessment": "Audit & Report — a new page that documents and assesses the node. The Assessment runs a catalogue of checks across security, backups, capacity, storage, network, hardware, guests and system, classifying each finding as critical, warning, observation or conformant and stating what it read rather than judging it.",
|
||||
"changeJournal": "Change journal — a Changes view that lists exactly what ProxMenux modified on this host: every configuration file, package and service it touched, with the prior state of each, deduplicated to a current-state view that shows the host as it stands now rather than a log of every run.",
|
||||
"auditReports": "Reports — a full audit plus focused Security review, Backup assurance and Capacity & wear reports, each opening on its own posture header, and a printable Inventory; all export to PDF. A security assessment asks before running Lynis so a run stays fast.",
|
||||
"auditPolicyBaseline": "Policy and baseline — declare what the host is expected to be (backup requirements, firewall, root SSH login) so findings grade against it, mark a run as the reference, and see what changed since, with new, resolved and accepted findings kept apart.",
|
||||
"groupedAppUpdates": "Grouped application update notifications — one complete message per scan instead of one per application, grouped by LXC with the installed and available versions.",
|
||||
"adminTokenScope": "Administrative scope — opening a Monitor terminal and disabling authentication now require a full-admin token, so a read-only API token issued to a monitoring integration stays read-only (reported by @f3rs3n)."
|
||||
"appDetection": "Intelligentere App-Erkennung im App-Tab: Docker wird korrekt gefördert, da der übergeordnete Workload während des Kaltstarts (Portainer/SearXNG wird nicht mehr kurzzeitig als native Apps angezeigt), nicht registrierte Vorschläge live im Start-Cache und \"Anwendungen finden\" führt bei Bedarf einen neuen kataloggestützten Scan aus.",
|
||||
"dockerUpdates": "Die Registerkarte Updates umfasst jetzt Docker Ende-zu-Ende: Docker Engine und Per-Image-Update-Tracking folgen dem gleichen 24-Stunden-Rollenzyklus wie OS-Pakete, mit einer \"Check now\" -Aktion für den On-Demand-Digest-Vergleich - nicht mehr auf den täglichen Sammler warten.",
|
||||
"appCatalog": "Neuer Anwendungserkennungskatalog mit über 380 verfolgten Workloads, der live aus Community-Scripts über sieben Detektormethoden generiert wurde (Datei, Binär, dpkg, apk, Python, Docker exec, Docker Label). Primär- und Fallbackdetektoren decken sowohl neue als auch historische LXC-Layouts ab.",
|
||||
"pushover": "Pushover verbindet Telegram, Gotify, Discord, E-Mail und Apprise als nativen Benachrichtigungskanal - Benutzer / API-Schlüssel, Geräte- und Sound-Selektoren, Priorität 0 für reguläre Nachrichten, optionale Priorität 1 für kritische Ereignisse. Vorgeschlagen von @benginx (#308).",
|
||||
"appsDashboard": "Neues Top-Level-Apps-Dashboard - ein einziger Launcher für jeden Weblink über den Knoten. LXC-registrierte Apps und benutzerdefiniertes Custom Web Links teilen sich das gleiche Raster mit Kategorieabzeichen, Suche und Ein-Klick-Deep-Links zurück zum Gastmodal.",
|
||||
"lxcAppsUpdates": "Die App-Registerkarte in jedem LXC-Modal registriert installierte Apps, erfasst Weblinks und verfolgt Upstream-Versionen. Überarbeitete Updates Tab wendet OS-Pakete und App-Updates von einer einzigen Schaltfläche; Docker Engine und Per-Image-Tracking folgen dem gleichen 24-Stunden-Zyklus, mit einer \"Check now\" -Aktion auf Anfrage.",
|
||||
"multilingual": "Der Monitor spricht jetzt 8 Sprachen: Englisch, Spanisch, Deutsch, Französisch, Italienisch, Portugiesisch, Schwedisch und Slowakisch. Großer Dank an @vaso73 für den Bau des i18n-Gerüsts, das dies ermöglicht hat.",
|
||||
"nvidiaMultiGpu": "Der NVIDIA-Treiber-Lebenszyklus bewegt sich in den Besitz pro BDF, so dass ein Multi-GPU-Host eine Karte an einen VM übergeben und den anderen auf dem Host oder in LXCs betriebsbereit halten kann, sowie einen Kernel + Branch + GPU-fähige Versionsauswahl (# 298).",
|
||||
"aiCustomEndpoint": "AI Assistant benutzerdefinierte OpenAI-Endpunkte – LiteLLM, LM Studio, LocalAI, vLLM, OmniRoute und jeder selbst gehostete Proxy auf privaten IPs, Loopback- oder Docker-Netzwerken werden beim Laden des Modellkatalogs erkannt. Der Dropdown zeigt den Fehler des Servers (oder den zugrunde liegenden Netzwerkgrund) direkt unter der Schaltfläche Laden (#325, berichtet von @jorgeffonte).",
|
||||
"secureGatewayArch": "Secure Gateway-Assistent - der Alpine Template-Download, die lokale Template-Auswahl und pct create passen alle zur realen Architektur des Hosts, so dass x86 64-Hosts amd64-Container und arm64-Hosts arm64-Container erhalten (#324, berichtet von @N0X4DD0).",
|
||||
"atomicNotifications": "Benachrichtigungsereignisse reservieren ihren Deduplizierungs-Fingerabdruck atomar vor der KI-Verarbeitung und Kanalzustellung, so dass gleichzeitige Sammler, Abschlussrückrufe oder parallele Monitorprozesse dasselbe Ereignis nicht zweimal senden können. Die Reservierung wird freigegeben, wenn kein Kanal erfolgreich ist, wobei Wiederholungen beibehalten werden.",
|
||||
"borgSshPort": "Borg-Remoteziel – der Add Borg-Zieldialog und die Shell TUI akzeptieren einen benutzerdefinierten SSH-Port. BORG RSH, der Autoschlüssel-Installationsfluss und die Kapazitätssonde ehren dies. Vollständig rückwärtskompatibel mit vorhandenen Einträgen, die ohne expliziten Port erstellt wurden (vorgeschlagen von @songochain in Diskussion #236).",
|
||||
"githubToken": "Einstellungen → GitHub API akzeptiert ein optionales persönliches Zugriffstoken für die Freigabe und Tag-Prüfung, wenn das anonyme Kontingent erschöpft ist. Das Token wird im Ruhezustand verschlüsselt und niemals an den Browser zurückgegeben; der Rate-Limit-Fehler wird in jede Monitorsprache übersetzt (vorgeschlagen von @SystemIdleProcess in Diskussion #306).",
|
||||
"replicationContext": "Native Proxmox Replikationsfehlermeldungen lösen die Replikationsauftrags-ID, die betroffene VM/LXC ID und den Gastnamen; der genaue Fehlerblock aus Proxmox bleibt als Grund erhalten, und jeder Replikationsauftrag wird unabhängig dedupliziert (von Ale R. berichtet).",
|
||||
"auditAssessment": "Audit & Report - eine neue Seite, die den Knoten dokumentiert und bewertet. Die Bewertung führt einen Katalog von Prüfungen über Sicherheit, Backups, Kapazität, Speicher, Netzwerk, Hardware, Gäste und System durch, wobei jeder Befund als kritisch, Warnung, Beobachtung oder konform eingestuft wird und angegeben wird, was er gelesen hat, anstatt ihn zu beurteilen.",
|
||||
"changeJournal": "Änderungsjournal - eine Änderungsansicht, in der genau aufgeführt ist, was ProxMenux auf diesem Host geändert hat: jede Konfigurationsdatei, jedes Paket und jeder Dienst, die es berührt hat, mit dem vorherigen Status von jedem, dedupliziert zu einer aktuellen Zustandsansicht, die den Host so zeigt, wie er jetzt steht, anstatt ein Protokoll von jedem Lauf.",
|
||||
"auditReports": "Berichte - ein vollständiges Audit sowie eine fokussierte Sicherheitsüberprüfung, Backup Assurance und Capacity & Wear-Berichte, jede Öffnung auf einem eigenen Haltungskopf und ein druckbares Inventar; alle exportieren in PDF. Eine Sicherheitsbewertung fragt vor dem Ausführen von Lynis, damit ein Lauf schnell bleibt.",
|
||||
"auditPolicyBaseline": "Policy und Baseline - Deklarieren Sie, was der Host sein soll (Backup-Anforderungen, Firewall, Root SSH-Login), damit die Ergebnisse dagegen bewertet werden, markieren Sie einen Lauf als Referenz und sehen Sie, was sich seitdem geändert hat, wobei neue, gelöste und akzeptierte Ergebnisse auseinandergehalten werden.",
|
||||
"groupedAppUpdates": "Gruppierte Anwendungsaktualisierungsbenachrichtigungen — eine vollständige Nachricht pro Scan statt einer pro Anwendung, gruppiert nach LXC mit den installierten und verfügbaren Versionen.",
|
||||
"adminTokenScope": "Administrativer Umfang: Das Öffnen eines Monitor-Terminals und das Deaktivieren der Authentifizierung erfordern jetzt ein Full-Admin-Token, so dass ein schreibgeschütztes API-Token, das an eine Überwachungsintegration ausgegeben wird, schreibgeschützt bleibt (berichtet von @f3rs3n).",
|
||||
"ociAppTab": "OCI-Container in der App-Registerkarte — ein von OCI manager Apps installierter Container wird anhand seines Installationsdatensatzes erkannt: Anwendung und Image, ein neues Image per Digest erkannt und ein Link zum Image-Repository.",
|
||||
"ociUpdatesTab": "Updates für OCI-Container — Aktualisieren und Neu erstellen öffnen denselben Ablauf wie das OCI-Menü, das vor dem Update erstellte Backup kann in einem Backup-Speicher behalten werden und das Image lässt sich zeitgesteuert aktualisieren.",
|
||||
"ociLogsTab": "Logs-Registerkarte für OCI-Container — die Konsolenausgabe der Anwendung, auf dem Host gespeichert und live verfolgt, mit Filter und Download. Die Proxmox-Konsole dieser Container öffnet eine Shell.",
|
||||
"appsUpdateShortcut": "Das Update-Symbol auf der Apps-Seite öffnet den Container direkt auf seiner Registerkarte Updates.",
|
||||
"webhookHttps": "Proxmox-Benachrichtigungen erreichen den Monitor auch mit aktiviertem HTTPS — sie werden über eine nur lokale Adresse zugestellt und scheitern nicht mehr an einem Zertifikatsfehler.",
|
||||
"persistentLogs": "Eine beendete Häufung von Log-Fehlern wird nicht mehr als dauerhaft gemeldet: Ein Muster muss 15 Minuten lang weiter auftreten, und seine Warnung schließt sich von selbst (gemeldet von @Joshua1264).",
|
||||
"mountsLanAddress": "Mountpunkte auf LVM-thin und anderem Blockspeicher zeigen ihre Belegung, und Multi-Container-Anwendungen öffnen sich unter ihrer LAN-Adresse."
|
||||
}
|
||||
},
|
||||
"network": {
|
||||
@@ -5027,23 +5081,20 @@
|
||||
"uncategorized": "Uncategorized",
|
||||
"openAriaLabel": "Open {name} in a new tab",
|
||||
"openGuestAriaLabel": "{name} öffnen ({type} {id})",
|
||||
"emptyTitle": "No apps with a web link yet.",
|
||||
"emptyHint": "Register a Web Link for any app (App tab of a CT) to see it here.",
|
||||
"customLinkAdd": "Add link",
|
||||
"editModeToggle": "Edit",
|
||||
"editModeDone": "Done",
|
||||
"customLinkNewTitle": "New web link",
|
||||
"customLinkEditTitle": "Edit web link",
|
||||
"customLinkEditAria": "Benutzerdefinierten Link {name} bearbeiten",
|
||||
"openUpdatesAria": "Registerkarte Updates von {name} öffnen",
|
||||
"openUpdatesTitle": "Update verfügbar — Registerkarte Updates öffnen",
|
||||
"customLinkName": "Name",
|
||||
"customLinkNamePlaceholder": "e.g. My app",
|
||||
"customLinkUrl": "URL",
|
||||
"customLinkLogo": "Logo URL (optional)",
|
||||
"customLinkLogoPlaceholder": "e.g., https://example.com/logo.webp",
|
||||
"customLinkCategory": "Category (optional)",
|
||||
"customLinkBinding": "Bound to",
|
||||
"customLinkBindingNone": "Not bound to any guest",
|
||||
"customLinkBindingHelp": "Bind this link to a VM or CT to add its ID + name to the card and jump to the guest with one click.",
|
||||
"customLinkSave": "Save",
|
||||
"customLinkCreate": "Create",
|
||||
"customLinkCancel": "Cancel",
|
||||
@@ -5079,7 +5130,12 @@
|
||||
"remoteAccessVpn": "Remote Access & VPN",
|
||||
"webserversProxies": "Webservers & Proxies",
|
||||
"zigbeeZwaveMatter": "ZigBee, Z-Wave & Matter"
|
||||
}
|
||||
},
|
||||
"emptyTitle": "Noch keine Apps mit einem Weblink.",
|
||||
"emptyHint": "Registrieren Sie einen Weblink für eine beliebige App (App-Tab eines CT), um ihn hier zu sehen.",
|
||||
"customLinkLogoPlaceholder": "z. B. https://example.com/logo.webp",
|
||||
"customLinkBindingNone": "Nicht an einen Gast gebunden",
|
||||
"customLinkBindingHelp": "Binden Sie diesen Link an eine VM oder CT, um die ID + den Namen der Karte hinzuzufügen und mit einem Klick zum Gast zu springen."
|
||||
},
|
||||
"audit": {
|
||||
"presentation": {
|
||||
@@ -5234,13 +5290,10 @@
|
||||
"loading": "Loading assessment…",
|
||||
"run": "Run assessment",
|
||||
"running": "Assessing…",
|
||||
"neverRun": "This host has not been assessed yet.",
|
||||
"lastRun": "Last assessed on {when}",
|
||||
"stale": "{days} days ago",
|
||||
"unverifiedChecks": "Nicht erhoben: {checks}. Jede nennt in ihrer Evidenz, was sie nicht lesen konnte.",
|
||||
"noFindings": "No findings match the current filter.",
|
||||
"affectedCount": "{count} affected",
|
||||
"acceptedNotice": "{count} accepted risk(s) recorded on this host.",
|
||||
"reviewOn": "Überprüfen am: {when}",
|
||||
"reviewDue": "Zur Überprüfung fällig — die Entscheidung gilt weiter",
|
||||
"reviewDueNotice": "{count} akzeptierte Entscheidung(en) stehen zur Überprüfung an.",
|
||||
@@ -5272,7 +5325,7 @@
|
||||
"sources": "Quellen und Erfassungszeitpunkte"
|
||||
},
|
||||
"errors": {
|
||||
"runFailed": "The assessment could not be started."
|
||||
"runFailed": "Mit der Bewertung konnte nicht begonnen werden."
|
||||
},
|
||||
"checks": {
|
||||
"backup": {
|
||||
@@ -5285,7 +5338,7 @@
|
||||
"uncovered": "{count} von {total} Gästen werden von keinem aktivierten Sicherungsauftrag ausgewählt",
|
||||
"excludedData": "{count} Datenträger- oder Mountpoint-Ausschlüsse prüfen",
|
||||
"uncoveredExpected": "{required} Gäste, für die eine Sicherung erklärt wurde, wählt kein aktivierter Auftrag aus",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
},
|
||||
"nextStep": {
|
||||
"noJobs": "Erstellen Sie einen Backup-Job auf diesem Knoten und wählen Sie die Gäste mit Daten aus, die Sie nicht von Hand neu erstellen möchten. Ein Job, der existiert, aber deaktiviert ist, wählt nichts aus.",
|
||||
@@ -5300,10 +5353,10 @@
|
||||
"rationale": "Alter: vergangene Zeit seit der letzten gespeicherten Sicherung. Verwendeter Grenzwert: das Referenzalter, mit dem diese Sicherung verglichen wird.",
|
||||
"summary": {
|
||||
"recent": "Alle {total} Gast-/Zielprüfungen erfüllen die angegebene Altersrichtlinie",
|
||||
"stale": "{count} of {total} guests have no backup from the last 30 days",
|
||||
"noBackups": "No stored backup matches a guest on this node",
|
||||
"attention": "{count} von {total} Gast-/Zielprüfungen erfordern eine Überprüfung",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"stale": "{count} von {total}-Gästen haben kein Backup der letzten 30 Tage",
|
||||
"noBackups": "Kein gespeichertes Backup passt zu einem Gast auf diesem Knoten",
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
},
|
||||
"nextStep": {
|
||||
"stale": "Finden Sie heraus, warum der Job aufhörte, Kopien für diese Gäste zu produzieren: Möglicherweise wurde er deaktiviert, sein Zeitplan wird möglicherweise nie ausgelöst oder seine Läufe können fehlschlagen. Der Run Results Check berichtet, wie jeder Job zuletzt beendet wurde.",
|
||||
@@ -5317,10 +5370,10 @@
|
||||
"rationale": "Die Aufbewahrung, wie Proxmox sie auflöst: Einstellung des Auftrags, dann des Speichers, dann der Knotenstandard. Aufbewahrung, die ein Sicherungsserver anwendet, ist von diesem Knoten aus nicht lesbar.",
|
||||
"summary": {
|
||||
"allDefined": "Alle {total} Aufträge lösen eine Aufbewahrungseinstellung auf",
|
||||
"missing": "{count} of {total} enabled job(s) declare no retention",
|
||||
"notDeclared": "{count} von {total} Aufträgen behalten jede Kopie: für sie ist keine Aufbewahrung erklärt",
|
||||
"onServer": "{count} von {total} Aufträgen schreiben auf einen Sicherungsserver, der sie mit eigenen Aufträgen bereinigt",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"missing": "{count} von {total}-fähigen Job(s) erklären keine Aufbewahrung",
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
},
|
||||
"nextStep": {
|
||||
"missing": "Legen Sie eine Aufbewahrung für diese Jobs oder für den Speicher fest, an den sie schreiben. Proxmox nimmt zuerst die Einstellung des Jobs, dann den Speicher und dann den Node Default an.",
|
||||
@@ -5383,36 +5436,36 @@
|
||||
"summary": {
|
||||
"none": "Nichts hat einen Neustart angefordert",
|
||||
"pending": "{count} Elemente sind installiert und warten auf einen Neustart",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
},
|
||||
"enterprise_repo_without_subscription": {
|
||||
"title": "Enterprise repository",
|
||||
"rationale": "Verweise auf `enterprise.proxmox.com` in `/etc/apt/sources.list` und `sources.list.d`, gegenüber dem Status aus `pvesubscription get`.",
|
||||
"summary": {
|
||||
"notEnabled": "The enterprise repository is not enabled",
|
||||
"subscribed": "The enterprise repository is backed by a subscription",
|
||||
"unsubscribed": "The enterprise repository is enabled without an active subscription",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"notEnabled": "Das Enterprise Repository ist nicht aktiviert",
|
||||
"subscribed": "Das Enterprise-Repository wird durch ein Abonnement gesichert",
|
||||
"unsubscribed": "Das Enterprise-Repository ist ohne aktives Abonnement aktiviert",
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
},
|
||||
"memory_overcommit": {
|
||||
"title": "Memory allocation",
|
||||
"rationale": "Die `memory`-Obergrenze jeder Gastkonfiguration gegenüber MemTotal, laufende Gäste getrennt gezählt. Container verbrauchen bis zu dieser Grenze; virtuelle Maschinen ohne Ballooning reservieren sie.",
|
||||
"summary": {
|
||||
"withinRatio": "Guests are allocated {percent}% of host memory",
|
||||
"aboveRatio": "Guests are allocated {percent}% of host memory",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"withinRatio": "Gäste erhalten {percent}% des Host-Speichers",
|
||||
"aboveRatio": "Gäste erhalten {percent}% des Host-Speichers",
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
},
|
||||
"time_synchronisation": {
|
||||
"title": "Time synchronisation",
|
||||
"rationale": "NTP und NTPSynchronized, wie `timedatectl` sie meldet. Clusterzugehörigkeit, Zertifikatsprüfung und Protokollreihenfolge hängen von übereinstimmenden Uhren ab. Ein anderer Mechanismus kann die Uhr führen.",
|
||||
"summary": {
|
||||
"synchronised": "The clock is synchronised with a time source",
|
||||
"disabled": "Time synchronisation is disabled",
|
||||
"notSynchronised": "Time synchronisation is enabled but the clock is not synchronised",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"synchronised": "Die Uhr wird mit einer Zeitquelle synchronisiert",
|
||||
"notSynchronised": "Zeitsynchronisation ist aktiviert, aber die Uhr ist nicht synchronisiert",
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
},
|
||||
"kernel_current": {
|
||||
@@ -5420,21 +5473,21 @@
|
||||
"rationale": "Der laufende Kernel gegenüber dem, den der Host als Nächstes starten würde, wie `proxmox-boot-tool` ihn meldet. Ein lediglich installierter neuerer Kernel kann bewusst zurückgehalten sein; ein Unterschied nach einem Neustart bedeutet einen Start, der nicht griff.",
|
||||
"summary": {
|
||||
"current": "Der laufende Kernel {version} ist der, den der Host als Nächstes starten würde",
|
||||
"newerAvailable": "The host runs {running} while {newest} is installed",
|
||||
"newerSelected": "Der Host führt {running} aus und würde beim nächsten Neustart {selected} starten",
|
||||
"wouldDowngrade": "Der Host führt {running} aus, würde beim nächsten Neustart aber das ältere {selected} starten",
|
||||
"bootTargetUnknown": "Der Host führt {version} aus; der für den nächsten Start gewählte Kernel war nicht lesbar",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"newerAvailable": "Der Host führt {running} aus, während {newest} installiert ist",
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
},
|
||||
"security_updates": {
|
||||
"title": "Security updates",
|
||||
"rationale": "Ausstehende Pakete, deren Quelle ein Sicherheits-Repository ist, aus einem simulierten `apt-get upgrade`. Die Zahl gibt wieder, was apt meldet, nicht die Schwere dessen, was jedes Paket behebt.",
|
||||
"summary": {
|
||||
"none": "No package updates are pending",
|
||||
"noSecurity": "{total} update(s) pending, none from a security repository",
|
||||
"pending": "{count} of {total} pending update(s) come from a security repository",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"none": "Keine Paket-Updates stehen aus",
|
||||
"noSecurity": "{total}-Update(s) ausstehend, keine aus einem Sicherheitsrepository",
|
||||
"pending": "{count} von {total} ausstehende Updates stammen aus einem Sicherheitsrepository",
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
},
|
||||
"journal_size": {
|
||||
@@ -5442,10 +5495,10 @@
|
||||
"rationale": "Das Journal auf der Platte gegenüber der für es geltenden Obergrenze: SystemMaxUse, sofern gesetzt, sonst der journald-Standard von einem Zehntel des Dateisystems, auf dem es liegt.",
|
||||
"summary": {
|
||||
"bounded": "Das Journal belegt {size} und bleibt unter seiner wirksamen Obergrenze",
|
||||
"large": "The journal holds {size} on disk",
|
||||
"nearCap": "Das Journal belegt {size} und liegt bei {percent}% seiner wirksamen Obergrenze",
|
||||
"capUnknown": "Das Journal belegt {size}; die wirksame Obergrenze war nicht zu ermitteln",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"large": "Das Journal hält {size} auf der Festplatte",
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
},
|
||||
"swap_configured": {
|
||||
@@ -5454,7 +5507,7 @@
|
||||
"summary": {
|
||||
"active": "{size} of swap is active",
|
||||
"none": "No swap area is active",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
},
|
||||
"filesystem_capacity": {
|
||||
@@ -5500,7 +5553,7 @@
|
||||
"summary": {
|
||||
"synchronised": "Die {total} Bootpartitionen tragen dieselben Kernel",
|
||||
"attention": "{count} von {total} Bootpartitionen bedürfen der Prüfung",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
},
|
||||
"rationale": "Die EFI-Systempartitionen proxmox-boot-tool-Berichte und die Kernel, die jeder trägt. proxmox-boot-tool-Status kann EFI-Systempartitionen vorübergehend bereitstellen; Es wird kein Bootversuch unternommen."
|
||||
},
|
||||
@@ -5510,7 +5563,7 @@
|
||||
"summary": {
|
||||
"allRunning": "Die {total} wesentlichen Dienste sind aktiv und keine Unit ist fehlgeschlagen",
|
||||
"attention": "{count} Feststellung(en) unter den Units",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
},
|
||||
"ha_state": {
|
||||
@@ -5519,7 +5572,7 @@
|
||||
"summary": {
|
||||
"managed": "Die {total} verwalteten Dienste sind auf {nodes} Knoten in einem gesetzten Zustand",
|
||||
"attention": "{count} Feststellung(en) zu {total} verwalteten Diensten",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5528,27 +5581,27 @@
|
||||
"title": "Container privileges",
|
||||
"rationale": "Die Einstellung `unprivileged` jeder Containerkonfiguration. Ihr Fehlen bedeutet, dass der Container den Benutzernamensraum des Hosts teilt, was manche Arbeitslasten benötigen.",
|
||||
"summary": {
|
||||
"allUnprivileged": "All {total} containers are unprivileged",
|
||||
"privileged": "{count} of {total} containers run privileged",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"allUnprivileged": "Alle {total} Container sind unprivilegiert",
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
},
|
||||
"qemu_without_agent": {
|
||||
"title": "Guest agent on virtual machines",
|
||||
"rationale": "Die Einstellung `agent` in jeder Konfiguration einer virtuellen Maschine. Die Einstellung besagt, dass der Agent deklariert ist, nicht dass er antwortet.",
|
||||
"summary": {
|
||||
"allHaveAgent": "All {total} virtual machines declare the guest agent",
|
||||
"missingAgent": "{count} of {total} virtual machines do not declare the guest agent",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
}
|
||||
"allHaveAgent": "Alle virtuellen {total}-Maschinen erklären den Gastagenten",
|
||||
"missingAgent": "{count} von virtuellen {total} Maschinen deklarieren nicht den Gastagenten",
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
},
|
||||
"title": "Gastagent auf virtuellen Maschinen"
|
||||
},
|
||||
"autostart": {
|
||||
"title": "Automatic start",
|
||||
"rationale": "Die Einstellung `onboot` jedes Gastes, ohne Vorlagen und von HA verwaltete Gäste. Ob ein Gast von selbst zurückkehren soll, ergibt sich aus der erklärten Richtlinie.",
|
||||
"summary": {
|
||||
"allAutostart": "All {total} guests start with the host",
|
||||
"notAutostart": "{count} of {total} guests do not start with the host",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"allAutostart": "Alle {total} Gäste beginnen mit dem Gastgeber",
|
||||
"notAutostart": "{count} der {total} Gäste starten nicht mit dem Gastgeber",
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
},
|
||||
"stuck_snapshots": {
|
||||
@@ -5556,28 +5609,28 @@
|
||||
"rationale": "Zustand und Alter der Snapshots sowie aktive Aufgaben. Ein kürzlicher oder undatierter Vorgang gilt nicht als unterbrochen.",
|
||||
"summary": {
|
||||
"noSnapshots": "No guest holds snapshots",
|
||||
"allComplete": "The {total} snapshot(s) are complete",
|
||||
"stuck": "{count} of {total} snapshot(s) were left mid-operation",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"allComplete": "Die {total} Snapshots sind vollständig",
|
||||
"stuck": "{count} von {total} Snapshot(s) wurden mitten in Betrieb gelassen",
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
},
|
||||
"cpu_host_type": {
|
||||
"title": "Virtual CPU model",
|
||||
"rationale": "Der Wert `cpu` jeder virtuellen Maschine. `host` gibt den Funktionsumfang des physischen Prozessors weiter, was die Knoten einschränkt, auf die der Gast migrieren kann. Unverträglichkeit mit einem bestimmten Ziel wird hier nicht ermittelt.",
|
||||
"summary": {
|
||||
"none": "None of the {total} virtual machines is pinned to the host processor",
|
||||
"pinned": "{count} of {total} virtual machines are pinned to the host processor",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"none": "Keine der virtuellen {total}-Maschinen ist an den Host-Prozessor gebunden",
|
||||
"pinned": "{count} von virtuellen {total}-Maschinen werden an den Host-Prozessor angeheftet",
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
},
|
||||
"replication_state": {
|
||||
"title": "Replication",
|
||||
"rationale": "Replikationsaufträge aus der API: Fehlerzahl, letzter Fehler, letzte Synchronisierung und der Kalender, den jeder Auftrag angibt. Pausierte Aufträge werden als solche ausgewiesen.",
|
||||
"summary": {
|
||||
"healthy": "The {total} replication job(s) report no error",
|
||||
"failing": "{count} of {total} replication job(s) report an error",
|
||||
"statusUnavailable": "Replication jobs are defined but their status could not be read",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"healthy": "Die {total} Replikationsjob(s) melden keinen Fehler",
|
||||
"failing": "{count} von {total} Replikationsjob(s) melden einen Fehler",
|
||||
"statusUnavailable": "Replikationsjobs sind definiert, aber ihr Status konnte nicht gelesen werden",
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5589,39 +5642,39 @@
|
||||
"bothEnabled": "Die Firewall-Aktivierung ist auf Datacenter- und Knotenebene konfiguriert",
|
||||
"datacenterOff": "Die Firewall ist auf Datacenter-Ebene deaktiviert; Knotenregeln werden daher nicht angewendet",
|
||||
"nodeOff": "Die Firewall ist auf Datacenter-Ebene aktiviert, aber nicht auf diesem Knoten",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
},
|
||||
"lynis_warnings": {
|
||||
"title": "Lynis warnings",
|
||||
"rationale": "Warnungen der letzten Lynis-Prüfung, jeweils mit Test-Kennung, und das Alter dieser Prüfung. Eine Prüfung läuft nur, wenn Lynis installiert ist und kein vollständiger Bericht vorliegt. Vorschläge sind nicht enthalten.",
|
||||
"summary": {
|
||||
"none": "The last Lynis audit recorded no warnings",
|
||||
"found": "The last Lynis audit recorded {count} warning(s)",
|
||||
"incomplete": "The Lynis report is incomplete",
|
||||
"evaluationFailed": "The check could not be evaluated",
|
||||
"noneStale": "Die letzte Lynis-Prüfung verzeichnete keine Warnungen, und ihr Bericht ist {days} Tag(e) alt",
|
||||
"foundStale": "Die letzte Lynis-Prüfung verzeichnete {count} Warnung(en), und ihr Bericht ist {days} Tag(e) alt"
|
||||
"foundStale": "Die letzte Lynis-Prüfung verzeichnete {count} Warnung(en), und ihr Bericht ist {days} Tag(e) alt",
|
||||
"none": "Das letzte Lynis-Audit verzeichnete keine Warnungen",
|
||||
"found": "Das letzte Lynis-Audit hat {count}-Warnungen aufgezeichnet",
|
||||
"incomplete": "Der Bericht Lynis ist unvollständig",
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
},
|
||||
"certificate_expiry": {
|
||||
"title": "Certificate validity",
|
||||
"rationale": "Das Ablaufdatum des Zertifikats, das pveproxy aus /etc/pve/local ausliefert. Ein eigenes Zertifikat hat Vorrang vor dem von Proxmox erzeugten.",
|
||||
"summary": {
|
||||
"valid": "The certificate is valid for {days} more day(s)",
|
||||
"expiring": "The certificate expires in {days} day(s)",
|
||||
"expired": "The certificate expired {days} day(s) ago",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"valid": "Das Zertifikat gilt für {days} weitere Tage",
|
||||
"expiring": "Das Zertifikat läuft in {days} Tagen ab",
|
||||
"expired": "Das Zertifikat ist vor {days} Tagen abgelaufen",
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
},
|
||||
"ssh_root_login": {
|
||||
"title": "SSH root access",
|
||||
"rationale": "PermitRootLogin in der effektiven `sshd -T`-Konfiguration samt den kombinierten Authentifizierungsmethoden. Proxmox liefert `yes` aus, was ein Passwort zulässt.",
|
||||
"summary": {
|
||||
"password": "Root may sign in over SSH with a password",
|
||||
"keyOnly": "Root may sign in over SSH with a key only",
|
||||
"denied": "Root may not sign in over SSH",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"password": "Root kann sich über SSH mit einem Passwort anmelden",
|
||||
"keyOnly": "Root kann sich über SSH nur mit einem Schlüssel anmelden",
|
||||
"denied": "Root kann sich nicht über SSH anmelden",
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5630,9 +5683,9 @@
|
||||
"title": "Volume assignment",
|
||||
"rationale": "Gastvolumes auf lokalem Speicher gegenüber den Verweisen in aktuellen, ausstehenden und Snapshot-Konfigurationen. Sicherungen, ISOs und Vorlagen bleiben außerhalb des Vergleichs. Ein Volume ohne Verweis ist ein Kandidat zur Prüfung.",
|
||||
"summary": {
|
||||
"none": "No orphaned volumes were found",
|
||||
"found": "{count} Volumes ohne Verweis in den geprüften Konfigurationen",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"none": "Es wurden keine verwaisten Volumen gefunden",
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
},
|
||||
"zfs_arc_max": {
|
||||
@@ -5640,21 +5693,21 @@
|
||||
"rationale": "Effektive Werte von c_min, c_max und ARC-Größe, der geladene Modulparameter und die persistenten Einstellungen in /etc/modprobe.d. Ein konfigurierter Wert von null wählt den Modulstandard; der ARC ist eine Obergrenze, und der belegte Speicher ist rückgewinnbar.",
|
||||
"summary": {
|
||||
"bounded": "Die ARC-Grenze liegt bei {percent}% des Hostspeichers, und der belegte Speicher ist rückgewinnbar",
|
||||
"high": "The ARC may use {percent}% of host memory",
|
||||
"unset": "The ARC has no explicit limit set",
|
||||
"conflicting": "{count} ARC-Einstellungen widersprechen einander",
|
||||
"pending": "Eine persistente ARC-Einstellung weicht vom Wert des laufenden Moduls ab",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"high": "Der ARC kann {percent}% des Hostspeichers verwenden",
|
||||
"unset": "Der ARC hat kein explizites Limit",
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
},
|
||||
"zfs_scrub_age": {
|
||||
"title": "ZFS scrub",
|
||||
"rationale": "Der letzte abgeschlossene Scrub, den `zpool status` je Pool meldet. Ein Resilver ist kein Scrub. Ein kürzlich erstellter Pool hatte noch keine Gelegenheit dazu.",
|
||||
"summary": {
|
||||
"recent": "The {total} pool(s) were scrubbed within the last 35 days",
|
||||
"overdue": "{count} of {total} pool(s) have not been scrubbed in 35 days",
|
||||
"neverScrubbed": "{count} pool(s) record no scrub",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"recent": "Die {total}-Pools wurden innerhalb der letzten 35 Tage gewaschen",
|
||||
"overdue": "{count} von {total} Pool(s) wurden in 35 Tagen nicht geschrubbt",
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
},
|
||||
"thin_pool_overprovisioning": {
|
||||
@@ -5664,7 +5717,7 @@
|
||||
"withinRatio": "Die {total} Thin-Pools liegen unter den angewendeten Prüfgrenzen",
|
||||
"aboveRatio": "{count} von {total} Thin-Pools vergeben mehr Kapazität, als sie besitzen",
|
||||
"pressure": "{pressure} von {total} Thin-Pools füllen ihre Daten oder Metadaten fast aus",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
},
|
||||
"connected_storage": {
|
||||
@@ -5673,7 +5726,7 @@
|
||||
"summary": {
|
||||
"available": "PVE meldet alle {total} Speicher als verfügbar; interne Remote-Komponenten und Schreibzugriff wurden nicht geprüft",
|
||||
"attention": "{count} von {total} Speichern müssen geprüft werden",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
},
|
||||
"pool_integrity": {
|
||||
@@ -5691,7 +5744,7 @@
|
||||
"summary": {
|
||||
"healthy": "Ceph meldet HEALTH_OK",
|
||||
"degraded": "Ceph meldet {state}, mit {count} benannten Prüfung(en)",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
},
|
||||
"array_integrity": {
|
||||
@@ -5700,7 +5753,7 @@
|
||||
"summary": {
|
||||
"intact": "Die {total} Arrays und Maps halten ihre Redundanz",
|
||||
"degraded": "{count} von {total} Arrays oder Maps fehlt sie",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5712,7 +5765,7 @@
|
||||
"withinLife": "Die {total} Datenträgermessungen liegen unter der Fünfjahresschwelle",
|
||||
"pastLife": "{count} von {total} Datenträgermessungen liegen über fünf Betriebsjahren",
|
||||
"noReadings": "Keine Festplatte meldet verwertbare SMART-Werte ({skipped} ohne Messwerte)",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
},
|
||||
"disk_errors": {
|
||||
@@ -5729,23 +5782,22 @@
|
||||
"title": "Bond members",
|
||||
"rationale": "Der MII-Status jedes Bond-Mitglieds aus /proc/net/bonding und wie viele Verbindungen bleiben. In active-backup meldet sich ein Reservemitglied als aktiv und überträgt nichts.",
|
||||
"summary": {
|
||||
"allUp": "All members of the {total} bond(s) are up",
|
||||
"membersDown": "{count} bond member(s) are not up",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"allUp": "Alle Mitglieder der {total} Bond (s) sind up",
|
||||
"membersDown": "{count} Bond Mitglied (s) sind nicht oben",
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
},
|
||||
"bridge_without_ports": {
|
||||
"title": "Bridge ports",
|
||||
"rationale": "Die Portkonfiguration jeder Bridge. Eine Bridge ohne physischen Port bedient ein internes oder geroutetes Netz.",
|
||||
"summary": {
|
||||
"allConnected": "The {total} bridge(s) carry a port",
|
||||
"isolated": "{count} of {total} bridge(s) carry no port",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"allConnected": "Die {total} Bridge(s) tragen einen Port",
|
||||
"evaluationFailed": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"summaryFallback": "The check could not be evaluated",
|
||||
"acceptRisk": {
|
||||
"action": "Risiko akzeptieren",
|
||||
"revoke": "Wieder aktivieren",
|
||||
@@ -5779,17 +5831,15 @@
|
||||
"OK": "OK"
|
||||
},
|
||||
"viewSwitch": {
|
||||
"ariaLabel": "Switch between assessment and inventory",
|
||||
"assessment": "Assessment",
|
||||
"inventory": "Inventory",
|
||||
"policy": "Richtlinie",
|
||||
"changes": "Änderungen"
|
||||
"changes": "Änderungen",
|
||||
"ariaLabel": "Wechsel zwischen Assessment und Inventar"
|
||||
},
|
||||
"inventory": {
|
||||
"loading": "Loading inventory…",
|
||||
"failed": "The inventory could not be composed.",
|
||||
"collectedAt": "Composed on {when}",
|
||||
"unavailable": "Not read in this inventory",
|
||||
"unresolved": "path not resolved",
|
||||
"noUplink": "no uplink",
|
||||
"identity": "Node identity",
|
||||
@@ -5832,12 +5882,10 @@
|
||||
"protection": "Backup",
|
||||
"passthrough": "Passthrough",
|
||||
"noBackup": "No backup",
|
||||
"noBackupDetail": "No enabled backup job selects this guest.",
|
||||
"applications": "Applications",
|
||||
"versionUnknown": "version not detected",
|
||||
"passthroughTitle": "PCI passthrough",
|
||||
"iommuGroup": "IOMMU group {group}",
|
||||
"sharedGroup": "{count} more device(s) in the same group",
|
||||
"proxmenux": "ProxMenux optimizations",
|
||||
"latency": "Netzwerklatenz",
|
||||
"subscriptionStatus": {
|
||||
@@ -5848,7 +5896,11 @@
|
||||
"suspended": "Ausgesetzt",
|
||||
"new": "Aktivierung ausstehend",
|
||||
"unknown": "Unbekannt"
|
||||
}
|
||||
},
|
||||
"failed": "Das Inventar konnte nicht zusammengestellt werden.",
|
||||
"unavailable": "Nicht in diesem Inventar lesen",
|
||||
"noBackupDetail": "Kein aktivierter Backup-Job wählt diesen Gast aus.",
|
||||
"sharedGroup": "{count} weitere Geräte in derselben Gruppe"
|
||||
},
|
||||
"profile": {
|
||||
"label": "Report",
|
||||
@@ -5871,7 +5923,6 @@
|
||||
"area": "Area",
|
||||
"inventoryAnnex": "Inventory annex",
|
||||
"scopeTitle": "Scope of this report",
|
||||
"scopeBody": "This report describes the Proxmox VE node named above, as observed from the node itself at the time stated. It does not cover the interior of the guests beyond what they declare, network equipment outside the host, physical infrastructure, or any dependency not visible from this node. Findings marked as not determined were not measured and are not evidence of absence.",
|
||||
"building": "Bericht wird zusammengestellt…",
|
||||
"node": "Knoten",
|
||||
"profile": "Profil",
|
||||
@@ -6020,11 +6071,12 @@
|
||||
"structureSubtitle": "Wie {node} aufgebaut und konfiguriert ist",
|
||||
"postureTitle": "Posture",
|
||||
"posture": {
|
||||
"security": "Host exposure and access.",
|
||||
"backup": "Guest protection and whether it is real.",
|
||||
"capacity": "Room to grow and the wear on the disks."
|
||||
"security": "Host Exposition und Zugang.",
|
||||
"backup": "Gästeschutz und ob es real ist.",
|
||||
"capacity": "Raum zum Wachsen und der Verschleiß an den Scheiben."
|
||||
},
|
||||
"scopeReadOnly": "Die Bewertung überprüft die Hosteinstellungen und den Zustand. Es kann Berichte und Protokolle schreiben; Boot-Statusprüfungen können EFI-Systempartitionen vorübergehend bereitstellen."
|
||||
"scopeReadOnly": "Die Bewertung überprüft die Hosteinstellungen und den Zustand. Es kann Berichte und Protokolle schreiben; Boot-Statusprüfungen können EFI-Systempartitionen vorübergehend bereitstellen.",
|
||||
"scopeBody": "Dieser Bericht beschreibt den oben genannten Proxmox VE-Knoten, wie er vom Knoten selbst zum angegebenen Zeitpunkt beobachtet wurde. Es umfasst nicht das Innere der Gäste über das hinaus, was sie deklarieren, Netzwerkausrüstung außerhalb des Hosts, physische Infrastruktur oder jede Abhängigkeit, die von diesem Knoten nicht sichtbar ist. Befunde, die als nicht bestimmt markiert wurden, wurden nicht gemessen und sind kein Hinweis auf Abwesenheit."
|
||||
},
|
||||
"results": "Ergebnisse",
|
||||
"classifications": {
|
||||
@@ -6178,15 +6230,19 @@
|
||||
"notApplicableScope": "Im geprüften Umfang gibt es nichts, worauf diese Prüfung zutrifft.",
|
||||
"lynis": {
|
||||
"title": "Run Lynis",
|
||||
"bodyNotRun": "Lynis is installed but has not been run yet. Running it now completes the security review, but the process can take a few minutes.",
|
||||
"bodyStale": "The Lynis report is {days} days old. You can run it now to refresh the data (it takes a little longer) or continue with the existing report.",
|
||||
"withLynis": "Run with Lynis",
|
||||
"withoutLynis": "Run without Lynis",
|
||||
"cancel": "Cancel"
|
||||
"cancel": "Cancel",
|
||||
"bodyNotRun": "Lynis ist installiert, wurde aber noch nicht ausgeführt. Die Ausführung vervollständigt nun die Sicherheitsüberprüfung, aber der Prozess kann einige Minuten dauern.",
|
||||
"bodyStale": "Der Lynis-Bericht ist {days} Tage alt. Sie können es jetzt ausführen, um die Daten zu aktualisieren (es dauert etwas länger) oder mit dem vorhandenen Bericht fortzufahren."
|
||||
},
|
||||
"readOnlyNotice": "Die Bewertung überprüft die Hosteinstellungen und den Zustand. Es kann Berichte und Protokolle schreiben; Boot-Statusprüfungen können EFI-Systempartitionen vorübergehend bereitstellen.",
|
||||
"noActionNeeded": "Nichts zu tun. Dieser Check hat herausgefunden, was er erwartet.",
|
||||
"couldNotEvaluate": "Diese Überprüfung konnte nicht ausgewertet werden, so dass sie nichts meldet. Die Beweise dokumentieren, was sie nicht lesen konnten."
|
||||
"couldNotEvaluate": "Diese Überprüfung konnte nicht ausgewertet werden, so dass sie nichts meldet. Die Beweise dokumentieren, was sie nicht lesen konnten.",
|
||||
"neverRun": "Dieser Gastgeber wurde noch nicht bewertet.",
|
||||
"noFindings": "Keine Ergebnisse stimmen mit dem aktuellen Filter überein.",
|
||||
"acceptedNotice": "{count} akzeptierte Risiken, die auf diesem Host aufgezeichnet wurden.",
|
||||
"summaryFallback": "Die Überprüfung konnte nicht ausgewertet werden"
|
||||
},
|
||||
"runtime": {
|
||||
"notifications": {
|
||||
|
||||
@@ -1090,7 +1090,8 @@
|
||||
"backups": "Backups",
|
||||
"updates": "Updates",
|
||||
"firewall": "Firewall",
|
||||
"app": "App"
|
||||
"app": "App",
|
||||
"logs": "Logs"
|
||||
},
|
||||
"actions": {
|
||||
"start": "Start",
|
||||
@@ -1190,6 +1191,44 @@
|
||||
"empty": "No firewall events recorded yet.",
|
||||
"emptyHint": "Rules with log: info or higher will populate this view as packets arrive."
|
||||
},
|
||||
"consoleLog": {
|
||||
"title": "Console output",
|
||||
"description": "Standard output and error of the image's main process.",
|
||||
"stopped": "The container is stopped; the log keeps the output of its previous runs.",
|
||||
"lastLines": "Last {count} lines",
|
||||
"follow": "Follow",
|
||||
"pause": "Pause",
|
||||
"refresh": "Refresh",
|
||||
"download": "Download",
|
||||
"filter": "Filter lines",
|
||||
"loading": "Loading console output...",
|
||||
"empty": "No output recorded yet.",
|
||||
"emptyHint": "Lines appear here as the container writes to its console.",
|
||||
"noMatches": "No lines match the filter.",
|
||||
"readFailed": "Failed to read the console log",
|
||||
"notAvailableTitle": "This container has no console log",
|
||||
"notAvailableHint": "The console log is set up when ProxMenux installs the container from its OCI image."
|
||||
},
|
||||
"ociUpdates": {
|
||||
"notTracked": "Registering the application in the App tab follows its image here.",
|
||||
"installedImage": "Installed image",
|
||||
"newImage": "New image {image} available",
|
||||
"stackNote": "Part of a multi-container application (main CT {primary}, {count} containers): the update covers all of them.",
|
||||
"pendingNote": "An operation on this container was interrupted; Recover opens its recovery.",
|
||||
"update": "Update",
|
||||
"recreate": "Recreate",
|
||||
"recover": "Recover",
|
||||
"terminalTitleUpdate": "Update OCI application",
|
||||
"terminalTitleRecreate": "Recreate OCI application",
|
||||
"terminalDescription": "The same flow as OCI manager Apps → Manage installed OCI applications.",
|
||||
"keepBackup": "Keep the backup taken before updating",
|
||||
"noKeepBackup": "The backup taken before updating is not kept",
|
||||
"keepBackupHelp": "Every update backs up the container before replacing its image, to restore it if the update fails. With this option that backup is kept in the chosen storage; on Proxmox Backup Server a backup is written before the update.",
|
||||
"scheduleHelp": "Only the image is updated, and only when its registry publishes a new one.",
|
||||
"releaseDelayHelp": "A new image is installed only once it is at least this old.",
|
||||
"ackExternal": "Host directories are not reverted by the backup",
|
||||
"ackExternalHelp": "This container uses host directories. A scheduled update runs only with this confirmed."
|
||||
},
|
||||
"options": {
|
||||
"title": "Options",
|
||||
"snapshotBefore": "Snapshot before applying",
|
||||
@@ -1393,7 +1432,7 @@
|
||||
"otherPackagesPending": "+{count} other packages pending in the container",
|
||||
"noManagedUpdateInfo": "No update information yet — check from Security → Secure Gateway.",
|
||||
"ociTitle": "OCI image container",
|
||||
"ociBody": "This container was created from an OCI (Docker) image. Update management for OCI containers is coming with the upcoming OCI install feature — updates will rebuild the container from a newer image tag rather than patching packages inside.",
|
||||
"ociBody": "This container was created from an OCI image outside OCI manager Apps. It is updated by replacing its image, which ProxMenux does not manage for it.",
|
||||
"dockerImagesTitle": "Docker images",
|
||||
"dockerAppTitle": "Docker",
|
||||
"dockerImagesSubheading": "Images",
|
||||
@@ -1652,7 +1691,15 @@
|
||||
"notifyUpstreamLabel": "Notify me when a new upstream version is available",
|
||||
"notifyUpstreamHelp": "Sends `app_update_available` to the channels enabled in Settings → Notifications. Turn off if this app can't be updated on your box.",
|
||||
"excludeFromBadgeLabel": "Exclude from the LXC updates counter",
|
||||
"excludeFromBadgeHelp": "Don't count this app in the aggregate updates badge on the LXC list card. Useful when you're pinned to a specific version on purpose (tracker requirement, compatibility freeze). Doesn't affect the App tab's own state or the outbound notification."
|
||||
"excludeFromBadgeHelp": "Don't count this app in the aggregate updates badge on the LXC list card. Useful when you're pinned to a specific version on purpose (tracker requirement, compatibility freeze). Doesn't affect the App tab's own state or the outbound notification.",
|
||||
"methodOciImage": "OCI image (installed by ProxMenux)",
|
||||
"ociImageHelp": "The version and its updates are read from the image this container was created from. ProxMenux installed it, so there is nothing to configure: the installed image is compared with the one its registry publishes today.",
|
||||
"ociAppVersion": "Application",
|
||||
"ociImage": "Image",
|
||||
"ociNewImage": "New image",
|
||||
"ociImageCurrent": "Version",
|
||||
"refreshData": "Refresh data",
|
||||
"refreshingData": "Refreshing…"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
@@ -3320,7 +3367,14 @@
|
||||
"auditReports": "Reports — a full audit plus focused Security review, Backup assurance and Capacity & wear reports, each opening on its own posture header, and a printable Inventory; all export to PDF. A security assessment asks before running Lynis so a run stays fast.",
|
||||
"auditPolicyBaseline": "Policy and baseline — declare what the host is expected to be (backup requirements, firewall, root SSH login) so findings grade against it, mark a run as the reference, and see what changed since, with new, resolved and accepted findings kept apart.",
|
||||
"groupedAppUpdates": "Grouped application update notifications — one complete message per scan instead of one per application, grouped by LXC with the installed and available versions.",
|
||||
"adminTokenScope": "Administrative scope — opening a Monitor terminal and disabling authentication now require a full-admin token, so a read-only API token issued to a monitoring integration stays read-only (reported by @f3rs3n)."
|
||||
"adminTokenScope": "Administrative scope — opening a Monitor terminal and disabling authentication now require a full-admin token, so a read-only API token issued to a monitoring integration stays read-only (reported by @f3rs3n).",
|
||||
"ociAppTab": "OCI containers in the App tab — a container installed by OCI manager Apps is recognised from its installation record: the application and its image, a new image detected by digest, and a link to the image repository.",
|
||||
"ociUpdatesTab": "Updates for OCI containers — Update and Recreate open the same flow as the OCI menu, the backup taken before updating can be kept in a backup storage, and the image can be updated on a schedule.",
|
||||
"ociLogsTab": "Logs tab for OCI containers — the console output of the application, kept on the host and followed live, with a filter and a download. The Proxmox console of these containers opens a shell.",
|
||||
"appsUpdateShortcut": "The update icon on the Apps page opens the container straight on its Updates tab.",
|
||||
"webhookHttps": "Proxmox notifications reach the Monitor with HTTPS enabled — they are delivered on a local-only address and no longer fail with a certificate error.",
|
||||
"persistentLogs": "A burst of log errors that ended is no longer reported as persistent: a pattern has to keep appearing for 15 minutes, and its warning clears on its own (reported by @Joshua1264).",
|
||||
"mountsLanAddress": "Mount points on LVM-thin and other block storage show their usage, and multi-container applications open at their LAN address."
|
||||
}
|
||||
},
|
||||
"network": {
|
||||
@@ -5034,6 +5088,8 @@
|
||||
"customLinkNewTitle": "New web link",
|
||||
"customLinkEditTitle": "Edit web link",
|
||||
"customLinkEditAria": "Edit custom link {name}",
|
||||
"openUpdatesAria": "Open the Updates tab of {name}",
|
||||
"openUpdatesTitle": "Update available — open the Updates tab",
|
||||
"customLinkName": "Name",
|
||||
"customLinkNamePlaceholder": "e.g. My app",
|
||||
"customLinkUrl": "URL",
|
||||
|
||||
@@ -377,7 +377,7 @@
|
||||
"criticalStatus": "Crítico: requiere atención inmediata",
|
||||
"warningStatus": "Advertencia: debe ser monitoreado",
|
||||
"moreIssues": "...y {count} problemas más (ver detalles a continuación)",
|
||||
"dismissed": "Despedido",
|
||||
"dismissed": "Descartado",
|
||||
"occurrences": "Ocurrencias",
|
||||
"errorSignature": "Firma de error",
|
||||
"rawMessage": "Mensaje sin procesar",
|
||||
@@ -1066,10 +1066,11 @@
|
||||
"tabs": {
|
||||
"status": "Estado",
|
||||
"mounts": "Montajes",
|
||||
"backups": "Copias",
|
||||
"backups": "Backups",
|
||||
"updates": "Actualiz.",
|
||||
"firewall": "Cortafuegos",
|
||||
"app": "App"
|
||||
"app": "App",
|
||||
"logs": "Logs"
|
||||
},
|
||||
"actions": {
|
||||
"start": "Iniciar",
|
||||
@@ -1087,9 +1088,9 @@
|
||||
"guest": "Invitado:"
|
||||
},
|
||||
"guestTypes": {
|
||||
"container": "recipiente",
|
||||
"container": "contenedor",
|
||||
"vm": "VM",
|
||||
"containerUi": "Recipiente"
|
||||
"containerUi": "Contenedor"
|
||||
},
|
||||
"backups": {
|
||||
"title": "Copias de seguridad",
|
||||
@@ -1146,7 +1147,7 @@
|
||||
"variables": "Variables: {{cluster}}, {{guestname}}, {{node}}, {{vmid}}",
|
||||
"creating": "Creando...",
|
||||
"submit": "Backup",
|
||||
"typeContainer": "recipiente",
|
||||
"typeContainer": "contenedor",
|
||||
"typeVirtualMachine": "máquina virtual",
|
||||
"modes": {
|
||||
"snapshot": "Instantánea",
|
||||
@@ -1169,16 +1170,54 @@
|
||||
"empty": "Aún no se han registrado eventos del cortafuegos.",
|
||||
"emptyHint": "Las reglas con log: info o superior completarán esta vista a medida que lleguen los paquetes."
|
||||
},
|
||||
"consoleLog": {
|
||||
"title": "Salida de consola",
|
||||
"description": "Salida estándar y de errores del proceso principal de la imagen.",
|
||||
"stopped": "El contenedor está detenido; el log conserva la salida de sus ejecuciones anteriores.",
|
||||
"lastLines": "Últimas {count} líneas",
|
||||
"follow": "Seguir",
|
||||
"pause": "Pausar",
|
||||
"refresh": "Actualizar",
|
||||
"download": "Descargar",
|
||||
"filter": "Filtrar líneas",
|
||||
"loading": "Cargando la salida de consola...",
|
||||
"empty": "Todavía no hay salida registrada.",
|
||||
"emptyHint": "Las líneas aparecen aquí a medida que el contenedor escribe en su consola.",
|
||||
"noMatches": "Ninguna línea coincide con el filtro.",
|
||||
"readFailed": "No se pudo leer el log de consola",
|
||||
"notAvailableTitle": "Este contenedor no tiene log de consola",
|
||||
"notAvailableHint": "El log de consola se configura cuando ProxMenux instala el contenedor desde su imagen OCI."
|
||||
},
|
||||
"ociUpdates": {
|
||||
"notTracked": "Al registrar la aplicación en la pestaña App, aquí se sigue su imagen.",
|
||||
"installedImage": "Imagen instalada",
|
||||
"newImage": "Nueva imagen {image} disponible",
|
||||
"stackNote": "Forma parte de una aplicación multicontenedor (CT principal {primary}, {count} contenedores): la actualización los abarca a todos.",
|
||||
"pendingNote": "Una operación sobre este contenedor quedó interrumpida; Recuperar abre su recuperación.",
|
||||
"update": "Actualizar",
|
||||
"recreate": "Recrear",
|
||||
"recover": "Recuperar",
|
||||
"terminalTitleUpdate": "Actualizar aplicación OCI",
|
||||
"terminalTitleRecreate": "Recrear aplicación OCI",
|
||||
"terminalDescription": "El mismo recorrido que OCI manager Apps → Gestionar aplicaciones OCI instaladas.",
|
||||
"keepBackup": "Conservar el backup previo a la actualización",
|
||||
"noKeepBackup": "El backup previo a la actualización no se conserva",
|
||||
"keepBackupHelp": "Cada actualización hace un backup del contenedor antes de sustituir su imagen, para restaurarlo si la actualización falla. Con esta opción ese backup se conserva en el almacenamiento elegido; en Proxmox Backup Server se escribe un backup antes de actualizar.",
|
||||
"scheduleHelp": "Solo se actualiza la imagen, y solo cuando su registro publica una nueva.",
|
||||
"releaseDelayHelp": "Una imagen nueva solo se instala cuando tiene al menos esta antigüedad.",
|
||||
"ackExternal": "Los directorios del host no se revierten con el backup",
|
||||
"ackExternalHelp": "Este contenedor usa directorios del host. Una actualización programada solo se ejecuta con esto confirmado."
|
||||
},
|
||||
"options": {
|
||||
"title": "Opciones",
|
||||
"snapshotBefore": "Instantánea antes de aplicar",
|
||||
"snapshotOn": "— el {storage}",
|
||||
"noSnapshot": "Sin instantánea previa a la solicitud",
|
||||
"restartAfter": "Reiniciar el contenedor después de aplicar.",
|
||||
"noRestart": "Sin reinicio posterior a la aplicación",
|
||||
"snapshotBefore": "Backup antes de aplicar",
|
||||
"snapshotOn": "— en {storage}",
|
||||
"noSnapshot": "Sin backup antes de aplicar",
|
||||
"restartAfter": "Reiniciar el contenedor después de aplicar",
|
||||
"noRestart": "Sin reinicio después de aplicar",
|
||||
"snapshotLabel": "Backup del contenedor antes de aplicar (vzdump)",
|
||||
"appliesToBoth": "Aplica para ejecuciones manuales + programadas.",
|
||||
"backupStorage": "Almacenamiento de respaldo",
|
||||
"backupStorage": "Almacenamiento de backups",
|
||||
"pickStorage": "Elige un almacenamiento",
|
||||
"editButton": "Editar",
|
||||
"cancelButton": "Cancelar",
|
||||
@@ -1372,7 +1411,7 @@
|
||||
"otherPackagesPending": "+{count} otros paquetes pendientes en el contenedor",
|
||||
"noManagedUpdateInfo": "Aún no hay información de actualización: verifique desde Seguridad → Secure Gateway.",
|
||||
"ociTitle": "Contenedor de imágenes OCI",
|
||||
"ociBody": "Este contenedor se creó a partir de una imagen OCI (Docker). La gestión de actualizaciones para contenedores OCI viene con la próxima función de instalación de OCI: las actualizaciones reconstruirán el contenedor a partir de una etiqueta de imagen más nueva en lugar de aplicar parches a los paquetes internos.",
|
||||
"ociBody": "Este contenedor se creó desde una imagen OCI fuera de OCI manager Apps. Se actualiza sustituyendo su imagen, algo que ProxMenux no gestiona en este caso.",
|
||||
"dockerImagesTitle": "Imágenes Docker",
|
||||
"dockerAppTitle": "Docker",
|
||||
"dockerImagesSubheading": "Imágenes",
|
||||
@@ -1487,7 +1526,6 @@
|
||||
"containerNameLabel": "Nombre del contenedor",
|
||||
"containerNamePlaceholder": "por ejemplo, <nombre-de-su-contenedor>",
|
||||
"ociLabelKeyLabel": "Clave de etiqueta OCI",
|
||||
"ociLabelPlaceholder": "org.opencontainers.image.version",
|
||||
"pythonInterpreterLabel": "Ruta del intérprete de Python",
|
||||
"pythonInterpreterPlaceholder": "por ejemplo, /opt/<tu-aplicación>/venv/bin/python",
|
||||
"pipDistLabel": "Nombre de distribución (paquete pip)",
|
||||
@@ -1631,7 +1669,16 @@
|
||||
"notifyUpstreamLabel": "Notificarme cuando haya una nueva versión disponible",
|
||||
"notifyUpstreamHelp": "Envía `app_update_available` a los canales activos en Ajustes → Notificaciones. Desactívalo si esta app no se puede actualizar en tu instalación.",
|
||||
"excludeFromBadgeLabel": "Excluir del contador de actualizaciones del LXC",
|
||||
"excludeFromBadgeHelp": "No sumar esta app al contador agregado de actualizaciones del card del LXC. Útil cuando mantienes una versión concreta a propósito (requisito de tracker, compatibilidad). No afecta al estado que se muestra en la pestaña App ni al envío de la notificación."
|
||||
"excludeFromBadgeHelp": "No sumar esta app al contador agregado de actualizaciones del card del LXC. Útil cuando mantienes una versión concreta a propósito (requisito de tracker, compatibilidad). No afecta al estado que se muestra en la pestaña App ni al envío de la notificación.",
|
||||
"ociLabelPlaceholder": "org.opencontainers.image.version",
|
||||
"methodOciImage": "Imagen OCI (instalada por ProxMenux)",
|
||||
"ociImageHelp": "La versión y sus actualizaciones se leen de la imagen con la que se creó este contenedor. La instaló ProxMenux, así que no hay nada que configurar: la imagen instalada se compara con la que publica hoy su registro.",
|
||||
"ociAppVersion": "Aplicación",
|
||||
"ociImage": "Imagen",
|
||||
"ociNewImage": "Nueva imagen",
|
||||
"ociImageCurrent": "Versión",
|
||||
"refreshData": "Actualizar datos",
|
||||
"refreshingData": "Actualizando…"
|
||||
},
|
||||
"statusFilter": {
|
||||
"ariaLabel": "Filtrar máquinas virtuales y contenedores",
|
||||
@@ -1702,7 +1749,7 @@
|
||||
"labels": {
|
||||
"category": "categoría",
|
||||
"severity": "gravedad",
|
||||
"dismissed": "despedido"
|
||||
"dismissed": "descartado"
|
||||
},
|
||||
"errorNames": {
|
||||
"security_login_attempts": "Intentos de inicio de sesión de seguridad"
|
||||
@@ -3321,7 +3368,14 @@
|
||||
"auditReports": "Informes — una auditoría completa más informes enfocados de Revisión de seguridad, Garantía de backups y Capacidad y desgaste, cada uno con su propia cabecera de postura, y un Inventario imprimible; todos se exportan a PDF. La evaluación de seguridad pregunta antes de ejecutar Lynis para que sea rápida.",
|
||||
"auditPolicyBaseline": "Política y referencia — declara qué se espera del host (backups requeridos, firewall, acceso SSH de root) para que los hallazgos se evalúen contra ello, marca una ejecución como referencia y ve qué cambió desde entonces, con los hallazgos nuevos, resueltos y aceptados por separado.",
|
||||
"groupedAppUpdates": "Notificaciones de actualización de aplicaciones agrupadas — un mensaje completo por escaneo en lugar de uno por aplicación, agrupado por LXC con las versiones instalada y disponible.",
|
||||
"adminTokenScope": "Ámbito administrativo — abrir un terminal del Monitor y desactivar la autenticación ahora requieren un token de administrador completo, así que un token de API de solo lectura se mantiene de solo lectura (reportado por @f3rs3n)."
|
||||
"adminTokenScope": "Ámbito administrativo — abrir un terminal del Monitor y desactivar la autenticación ahora requieren un token de administrador completo, así que un token de API de solo lectura se mantiene de solo lectura (reportado por @f3rs3n).",
|
||||
"ociAppTab": "Contenedores OCI en la pestaña App — un contenedor instalado por OCI manager Apps se reconoce desde su registro de instalación: la aplicación y su imagen, una imagen nueva detectada por digest y el enlace al repositorio de la imagen.",
|
||||
"ociUpdatesTab": "Actualizaciones de contenedores OCI — Actualizar y Recrear abren el mismo recorrido que el menú OCI, el backup previo a la actualización puede conservarse en un almacenamiento de backups y la imagen puede actualizarse de forma programada.",
|
||||
"ociLogsTab": "Pestaña Logs para contenedores OCI — la salida de consola de la aplicación, guardada en el host y seguida en directo, con filtro y descarga. La consola de Proxmox de estos contenedores abre un shell.",
|
||||
"appsUpdateShortcut": "El icono de actualización de la página Apps abre el contenedor directamente en su pestaña Actualizaciones.",
|
||||
"webhookHttps": "Las notificaciones de Proxmox llegan al Monitor con HTTPS activado — se entregan en una dirección solo local y ya no fallan por un error de certificado.",
|
||||
"persistentLogs": "Una ráfaga de errores en los logs que ya terminó no se presenta como persistente: el patrón tiene que seguir apareciendo durante 15 minutos, y su aviso se cierra solo (reportado por @Joshua1264).",
|
||||
"mountsLanAddress": "Los puntos de montaje en LVM-thin y otros almacenamientos de bloques muestran su uso, y las aplicaciones multicontenedor se abren en su dirección de la LAN."
|
||||
}
|
||||
},
|
||||
"network": {
|
||||
@@ -4668,7 +4722,7 @@
|
||||
"updateNow": "Actualizar ahora",
|
||||
"dismissedItems": "Artículos descartados ({count})",
|
||||
"permanent": "Permanente",
|
||||
"dismissed": "Despedido",
|
||||
"dismissed": "Descartado",
|
||||
"wasStatus": "era {status}",
|
||||
"permanentlySuppressed": "Permanentemente suprimido",
|
||||
"suppressedForMore": "Suprimido por {duration} más",
|
||||
@@ -4677,7 +4731,7 @@
|
||||
"lastUpdated": "Última actualización: {date}",
|
||||
"updateTerminalTitle": "Actualización del sistema Proxmox",
|
||||
"updateTerminalDescription": "Ejecuta apt-get update + dist-upgrade y limpieza posterior a la actualización en el host.",
|
||||
"dismiss": "Despedir",
|
||||
"dismiss": "Descartar",
|
||||
"silenceFor": "Silencia esta alerta por",
|
||||
"permanently": "Permanentemente",
|
||||
"duration": {
|
||||
@@ -5035,6 +5089,8 @@
|
||||
"customLinkNewTitle": "Nuevo enlace web",
|
||||
"customLinkEditTitle": "Editar enlace web",
|
||||
"customLinkEditAria": "Editar el enlace personalizado {name}",
|
||||
"openUpdatesAria": "Abrir la pestaña Actualizaciones de {name}",
|
||||
"openUpdatesTitle": "Actualización disponible — abrir la pestaña Actualizaciones",
|
||||
"customLinkName": "Nombre",
|
||||
"customLinkNamePlaceholder": "p. ej. Mi app",
|
||||
"customLinkUrl": "URL",
|
||||
|
||||
+193
-137
@@ -1069,7 +1069,8 @@
|
||||
"backups": "Sauvegardes",
|
||||
"updates": "Mises à jour",
|
||||
"firewall": "Pare-feu",
|
||||
"app": "Application"
|
||||
"app": "Application",
|
||||
"logs": "Logs"
|
||||
},
|
||||
"actions": {
|
||||
"start": "Commencer",
|
||||
@@ -1169,6 +1170,44 @@
|
||||
"empty": "Aucun événement de pare-feu enregistré pour le moment.",
|
||||
"emptyHint": "Règles avec journal : informations ou supérieures rempliront cette vue à mesure que les paquets arrivent."
|
||||
},
|
||||
"consoleLog": {
|
||||
"title": "Sortie console",
|
||||
"description": "Sortie standard et sortie d'erreur du processus principal de l'image.",
|
||||
"stopped": "Le conteneur est arrêté ; le log conserve la sortie de ses exécutions précédentes.",
|
||||
"lastLines": "{count} dernières lignes",
|
||||
"follow": "Suivre",
|
||||
"pause": "Pause",
|
||||
"refresh": "Actualiser",
|
||||
"download": "Télécharger",
|
||||
"filter": "Filtrer les lignes",
|
||||
"loading": "Chargement de la sortie console...",
|
||||
"empty": "Aucune sortie enregistrée pour l'instant.",
|
||||
"emptyHint": "Les lignes apparaissent ici à mesure que le conteneur écrit sur sa console.",
|
||||
"noMatches": "Aucune ligne ne correspond au filtre.",
|
||||
"readFailed": "Impossible de lire le log de la console",
|
||||
"notAvailableTitle": "Ce conteneur n'a pas de log de console",
|
||||
"notAvailableHint": "Le log de la console est configuré lorsque ProxMenux installe le conteneur depuis son image OCI."
|
||||
},
|
||||
"ociUpdates": {
|
||||
"notTracked": "En enregistrant l'application dans l'onglet App, son image est suivie ici.",
|
||||
"installedImage": "Image installée",
|
||||
"newImage": "Nouvelle image {image} disponible",
|
||||
"stackNote": "Fait partie d'une application multi-conteneurs (CT principal {primary}, {count} conteneurs) : la mise à jour les couvre tous.",
|
||||
"pendingNote": "Une opération sur ce conteneur a été interrompue ; Récupérer ouvre sa récupération.",
|
||||
"update": "Mettre à jour",
|
||||
"recreate": "Recréer",
|
||||
"recover": "Récupérer",
|
||||
"terminalTitleUpdate": "Mettre à jour l'application OCI",
|
||||
"terminalTitleRecreate": "Recréer l'application OCI",
|
||||
"terminalDescription": "Le même parcours que OCI manager Apps → Gérer les applications OCI installées.",
|
||||
"keepBackup": "Conserver la sauvegarde prise avant la mise à jour",
|
||||
"noKeepBackup": "La sauvegarde prise avant la mise à jour n'est pas conservée",
|
||||
"keepBackupHelp": "Chaque mise à jour sauvegarde le conteneur avant de remplacer son image, pour le restaurer si la mise à jour échoue. Avec cette option, cette sauvegarde est conservée dans le stockage choisi ; sur Proxmox Backup Server, une sauvegarde est écrite avant la mise à jour.",
|
||||
"scheduleHelp": "Seule l'image est mise à jour, et seulement lorsque son registre en publie une nouvelle.",
|
||||
"releaseDelayHelp": "Une nouvelle image n'est installée qu'une fois qu'elle a au moins cette ancienneté.",
|
||||
"ackExternal": "Les répertoires de l'hôte ne sont pas rétablis par la sauvegarde",
|
||||
"ackExternalHelp": "Ce conteneur utilise des répertoires de l'hôte. Une mise à jour planifiée ne s'exécute qu'avec cette confirmation."
|
||||
},
|
||||
"options": {
|
||||
"title": "Possibilités",
|
||||
"snapshotBefore": "Instantané avant de postuler",
|
||||
@@ -1429,6 +1468,14 @@
|
||||
"loadFailed": "Impossible de charger la configuration de la mise à jour groupée."
|
||||
},
|
||||
"appEditor": {
|
||||
"methodOciImage": "Image OCI (installée par ProxMenux)",
|
||||
"ociImageHelp": "La version et ses mises à jour sont lues depuis l'image à partir de laquelle ce conteneur a été créé. ProxMenux l'a installé, il n'y a donc rien à configurer : l'image installée est comparée à celle que son registre publie aujourd'hui.",
|
||||
"ociAppVersion": "Application",
|
||||
"ociImage": "Image",
|
||||
"ociNewImage": "Nouvelle image",
|
||||
"ociImageCurrent": "Version",
|
||||
"refreshData": "Actualiser les données",
|
||||
"refreshingData": "Actualisation…",
|
||||
"dockerDetectedWithWorkloads": "Docker détecté avec {count} applications conteneurisées",
|
||||
"dockerWorkloadsHeading": "Applications dans Docker",
|
||||
"runsInsideDocker": "Mise à jour avec son image Docker",
|
||||
@@ -1487,7 +1534,6 @@
|
||||
"containerNameLabel": "Nom du conteneur",
|
||||
"containerNamePlaceholder": "par exemple, <votre-nom-de-conteneur>",
|
||||
"ociLabelKeyLabel": "Clé d'étiquette OCI",
|
||||
"ociLabelPlaceholder": "org.opencontainers.image.version",
|
||||
"pythonInterpreterLabel": "Chemin de l'interpréteur Python",
|
||||
"pythonInterpreterPlaceholder": "par exemple, /opt/<votre-application>/venv/bin/python",
|
||||
"pipDistLabel": "Nom de la distribution (paquet pip)",
|
||||
@@ -1534,11 +1580,8 @@
|
||||
"portHttps": "https",
|
||||
"portLogoLabel": "URL du logo pour ce lien (facultatif)",
|
||||
"portLogoPlaceholder": "par exemple, https://example.com/logo.webp",
|
||||
"portCategoryPlaceholder": "Category for the Apps dashboard (optional)",
|
||||
"portCategoryNone": "No category",
|
||||
"portCategoryAddNew": "+ Add new category…",
|
||||
"portCategoryCustomPlaceholder": "Type a category and press Enter (Esc to cancel)",
|
||||
"portCustomUrlPlaceholder": "Custom URL (e.g. https://vault.example.com) — overrides IP:port",
|
||||
"removePortTooltip": "Supprimer le port",
|
||||
"detectMethodDpkg": "dpkg ·",
|
||||
"detectMethodApk": "apk ·",
|
||||
@@ -1631,7 +1674,11 @@
|
||||
"notifyUpstreamLabel": "Me prévenir lorsqu'une nouvelle version en amont est disponible",
|
||||
"notifyUpstreamHelp": "envoie `app_update_available` aux canaux activés dans Paramètres → Notifications. Désactivez-la si cette application ne peut pas être mise à jour sur votre box.",
|
||||
"excludeFromBadgeLabel": "exclure du compteur de mises à jour LXC",
|
||||
"excludeFromBadgeHelp": "Ne comptez pas cette application dans le badge de mises à jour globales sur la carte de liste LXC.Utile lorsque vous êtes volontairement épinglé à une version spécifique (exigence de suivi, gel de la compatibilité).N'affecte pas l'état de l'onglet Application ni la notification sortante."
|
||||
"excludeFromBadgeHelp": "Ne comptez pas cette application dans le badge de mises à jour globales sur la carte de liste LXC.Utile lorsque vous êtes volontairement épinglé à une version spécifique (exigence de suivi, gel de la compatibilité).N'affecte pas l'état de l'onglet Application ni la notification sortante.",
|
||||
"ociLabelPlaceholder": "org.opencontainers.image.version",
|
||||
"portCategoryPlaceholder": "Catégorie pour le tableau de bord Apps (facultatif)",
|
||||
"portCategoryCustomPlaceholder": "Tapez une catégorie et appuyez sur Entrée (Esc pour annuler)",
|
||||
"portCustomUrlPlaceholder": "URL personnalisée (par exemple https://vault.example.com) — remplace IP:port"
|
||||
},
|
||||
"statusFilter": {
|
||||
"ariaLabel": "Filtrer les machines virtuelles et les conteneurs",
|
||||
@@ -2515,10 +2562,10 @@
|
||||
"scope": {
|
||||
"label": "Token permissions",
|
||||
"readOnly": "Read-only",
|
||||
"readOnlyHint": "Reads metrics and status. Recommended for dashboards and integrations.",
|
||||
"fullAdmin": "Full admin",
|
||||
"fullAdminHint": "Full control, like your own session.",
|
||||
"fullAdminWarning": "A full-admin token can do everything you can: power off or reboot the host, run updates and open a terminal. Share it only with fully trusted integrations."
|
||||
"readOnlyHint": "Lire les paramètres et l'état. Recommandé pour les tableaux de bord et les intégrations.",
|
||||
"fullAdminHint": "Contrôle complet, comme votre propre session.",
|
||||
"fullAdminWarning": "Un jeton entièrement administratif peut faire tout ce que vous pouvez : désactiver ou redémarrer l'hôte, lancer des mises à jour et ouvrir un terminal. Partagez-le seulement avec des intégrations entièrement fiables."
|
||||
}
|
||||
},
|
||||
"firewall": {
|
||||
@@ -3302,26 +3349,33 @@
|
||||
"gotIt": "J'ai compris!",
|
||||
"dontShowAgain": "Ne plus afficher pour cette version",
|
||||
"currentFeatures": {
|
||||
"appDetection": "Smarter app detection in the App tab: Docker is correctly promoted as the parent workload during cold start (Portainer/SearXNG no longer briefly show up as native apps), unregistered suggestions live in the startup cache, and 'Find applications' runs a fresh catalog-backed scan on demand.",
|
||||
"dockerUpdates": "The Updates tab now covers Docker end-to-end: Docker Engine and per-image update tracking follow the same 24-hour rolling cycle as OS packages, with a 'Check now' action for on-demand digest comparison — no more waiting for the daily collector.",
|
||||
"appCatalog": "New application detection catalog with over 380 tracked workloads, generated live from community-scripts across seven detector methods (file, binary, dpkg, apk, Python, Docker exec, Docker label). Primary and fallback detectors cover both new and historical LXC layouts.",
|
||||
"pushover": "Pushover joins Telegram, Gotify, Discord, Email and Apprise as a native notification channel — user/API key, device and sound selectors, priority 0 for regular messages, optional priority 1 for CRITICAL events. Suggested by @benginx (#308).",
|
||||
"appsDashboard": "New top-level Apps dashboard — a single launcher for every Web Link across the node. LXC-registered apps and user-defined Custom Web Links share the same grid with category badges, search, and one-click deep-links back to the guest modal.",
|
||||
"lxcAppsUpdates": "App tab inside every LXC modal registers installed apps, captures weblinks and tracks upstream versions. Reworked Updates tab applies OS packages and app updates from a single button; Docker Engine and per-image tracking follow the same 24-hour cycle, with a 'Check now' action on demand.",
|
||||
"multilingual": "The Monitor now speaks 8 languages: English, Spanish, German, French, Italian, Portuguese, Swedish and Slovak. Huge thanks to @vaso73 for building the i18n scaffolding that made this possible.",
|
||||
"nvidiaMultiGpu": "NVIDIA driver lifecycle moves to per-BDF ownership so a multi-GPU host can pass one card to a VM and keep the other operational on the host or in LXCs, plus a kernel + branch + GPU-aware version picker (#298).",
|
||||
"aiCustomEndpoint": "AI Assistant custom OpenAI endpoint — LiteLLM, LM Studio, LocalAI, vLLM, OmniRoute and any self-hosted proxy on private IPs, loopback or Docker networks are recognised when loading the model catalogue. The dropdown surfaces the server's error (or the underlying network reason) directly under the Load button (#325, reported by @jorgeffonte).",
|
||||
"secureGatewayArch": "Secure Gateway wizard — the Alpine template download, local template selection and pct create all match the host's real architecture, so x86_64 hosts receive amd64 containers and arm64 hosts receive arm64 containers (#324, reported by @N0X4DD0).",
|
||||
"atomicNotifications": "Notification events reserve their deduplication fingerprint atomically before AI processing and channel delivery, so concurrent collectors, completion callbacks or parallel Monitor processes cannot send the same event twice. The reservation is released when no channel succeeds, preserving retries.",
|
||||
"borgSshPort": "Borg remote target — the Add Borg destination dialog and the shell TUI accept a custom SSH port. BORG_RSH, the auto key install flow and the capacity probe all honour it. Fully backwards compatible with existing entries created without an explicit port (suggested by @songochain in discussion #236).",
|
||||
"githubToken": "Settings → GitHub API accepts an optional personal access token for release and tag checks when the anonymous quota is exhausted. The token is encrypted at rest and never returned to the browser; the rate-limit error is translated in every Monitor language (suggested by @SystemIdleProcess in discussion #306).",
|
||||
"replicationContext": "Native Proxmox replication failure notifications resolve the replication job ID, affected VM/LXC ID and guest name; the exact error block from Proxmox is preserved as the reason, and each replication job deduplicates independently (reported by Ale R.).",
|
||||
"auditAssessment": "Audit & Report — a new page that documents and assesses the node. The Assessment runs a catalogue of checks across security, backups, capacity, storage, network, hardware, guests and system, classifying each finding as critical, warning, observation or conformant and stating what it read rather than judging it.",
|
||||
"changeJournal": "Change journal — a Changes view that lists exactly what ProxMenux modified on this host: every configuration file, package and service it touched, with the prior state of each, deduplicated to a current-state view that shows the host as it stands now rather than a log of every run.",
|
||||
"auditReports": "Reports — a full audit plus focused Security review, Backup assurance and Capacity & wear reports, each opening on its own posture header, and a printable Inventory; all export to PDF. A security assessment asks before running Lynis so a run stays fast.",
|
||||
"auditPolicyBaseline": "Policy and baseline — declare what the host is expected to be (backup requirements, firewall, root SSH login) so findings grade against it, mark a run as the reference, and see what changed since, with new, resolved and accepted findings kept apart.",
|
||||
"groupedAppUpdates": "Grouped application update notifications — one complete message per scan instead of one per application, grouped by LXC with the installed and available versions.",
|
||||
"adminTokenScope": "Administrative scope — opening a Monitor terminal and disabling authentication now require a full-admin token, so a read-only API token issued to a monitoring integration stays read-only (reported by @f3rs3n)."
|
||||
"appDetection": "La détection d'applications plus intelligentes dans l'onglet App : Docker est correctement promue en tant que charge de travail parent lors du démarrage à froid (Portainer/SearXNG ne s'affiche plus brièvement en tant qu'applications natives), suggestions non enregistrées en direct dans le cache de démarrage, et 'Trouver des applications' lance un nouveau scanner soutenu par catalogue à la demande.",
|
||||
"dockerUpdates": "L'onglet Mises à jour couvre maintenant le Docker de bout en bout : Docker Le suivi de la mise à jour du moteur et de l'image suit le même cycle de roulement de 24 heures que les paquets OS, avec une action 'Vérifiez maintenant' pour la comparaison de digest à la demande — pas plus attendre le collecteur quotidien.",
|
||||
"appCatalog": "Nouveau catalogue de détection d'applications avec plus de 380 charges de travail suivies, généré en direct à partir de scripts communautaires sur sept méthodes de détecteurs (fichier, binaire, dpkg, apk, Python, Docker exec, étiquette Docker). Les détecteurs primaires et les détecteurs de recul couvrent les mises en page nouvelles et historiques du LXC.",
|
||||
"pushover": "Pushover rejoint Telegram, Gotify, Discord, Email et Apprise en tant que canal de notification natif — touche utilisateur/API, sélecteurs de périphérique et de son, priorité 0 pour les messages réguliers, priorité 1 optionnelle pour les événements CRITIQUES. Proposé par @benginx (#308).",
|
||||
"appsDashboard": "Nouveau tableau de bord des applications de haut niveau — un lanceur unique pour chaque lien Web à travers le nœud. Applications enregistrées par LXC et Web personnalisé Les liens partagent la même grille avec les badges de catégorie, les liens de recherche et les liens profonds à un clic vers le modal invité.",
|
||||
"lxcAppsUpdates": "Onglet App à l'intérieur de chaque LXC modal enregistre les applications installées, capture les liens web et suit les versions en amont. L'onglet Mises à jour retravaillées applique les paquets OS et les mises à jour d'applications à partir d'un seul bouton; Docker Moteur et suivi par image suivent le même cycle de 24 heures, avec une action 'Vérifier maintenant' sur demande.",
|
||||
"multilingual": "Le moniteur parle maintenant 8 langues: anglais, espagnol, allemand, français, italien, portugais, suédois et slovaque. Un énorme merci à @vaso73 pour la construction de l'échafaudage i18n qui a rendu cela possible.",
|
||||
"nvidiaMultiGpu": "Le cycle de vie du pilote NVIDIA passe à la propriété par BDF de sorte qu'un hôte multi-GPU peut transmettre une carte à un VM et garder l'autre opérationnel sur l'hôte ou en LXCs, plus un noyau + branche + GPU-aware sélecteur de version (#298).",
|
||||
"aiCustomEndpoint": "AI Assistant personnalisé OpenAI endpoint — LiteLLM, LM Studio, LocalAI, vLLM, OmniRoute et tout proxy auto-organisé sur les IP privées, les réseaux loopback ou Docker sont reconnus lors du chargement du catalogue modèle. Le menu déroulant couvre l'erreur du serveur (ou la raison réseau sous-jacente) directement sous le bouton Charger (#325, signalé par @jorgeffonte).",
|
||||
"secureGatewayArch": "Secure Gateway assistant — le téléchargement de modèle Alpine, la sélection de modèle local et pct create correspondent tous à l'architecture réelle de l'hôte, donc x86 64 hôtes reçoivent amd64 conteneurs et arm64 hôtes reçoivent arm64 conteneurs (#324, rapporté par @N0X4DD0).",
|
||||
"atomicNotifications": "Les événements de notification réservent leur empreinte digitale de duplication atomiquement avant le traitement de l'IA et la livraison du canal, de sorte que les collecteurs concurrents, les callbacks d'achèvement ou les processus Moniteur parallèles ne peuvent pas envoyer le même événement deux fois. La réservation est libérée lorsqu'aucun canal ne réussit, en préservant les relevés.",
|
||||
"borgSshPort": "Cible distante Borg — la boîte de dialogue Add Borg destination et le shell TUI acceptent un port SSH personnalisé. BORG RSH, la clé automatique installe le flux et la sonde de capacité tout l'honore. Entièrement en arrière compatible avec les entrées existantes créées sans port explicite (suggéré par @songochain dans la discussion #236).",
|
||||
"githubToken": "Paramètres → L'API GitHub accepte un jeton d'accès personnel optionnel pour la libération et vérifie les étiquettes lorsque le quota anonyme est épuisé. Le jeton est chiffré au repos et n'est jamais retourné dans le navigateur; l'erreur de limite de taux est traduite dans chaque langue Monitor (suggéré par @SystemIdleProcess dans la discussion #306).",
|
||||
"replicationContext": "Les notifications de défaillance de réplication natives Proxmox résolvent l'ID de la tâche de réplication, l'ID touché VM/LXC et le nom de l'invité; le bloc d'erreur exact de Proxmox est conservé comme raison, et chaque tâche de réplication se dédouble indépendamment (rapporté par Ale R.).",
|
||||
"auditAssessment": "Audit & Report — une nouvelle page qui documente et évalue le nœud. L'évaluation comporte un catalogue de vérifications de sécurité, de sauvegardes, de capacité, de stockage, de réseau, de matériel, d'invités et de système, classant chaque constatation comme critique, d'avertissement, d'observation ou conforme et indiquant ce qu'elle lit plutôt que de le juger.",
|
||||
"changeJournal": "Change journal — a Changes view that listes exact what ProxMenux modified on this host: every configuration file, package and service it touched, with the previous state of chaque, dupliquée to a current-state view that shows the host as it stands now plutôt qu'un journal de chaque exécution.",
|
||||
"auditReports": "Rapports — un audit complet plus un examen de sécurité ciblé, l'assurance de sauvegarde et rapports de capacité et d'usure, chaque ouverture sur son propre en-tête de posture, et un inventaire imprimable; tous exportent vers PDF. Une évaluation de sécurité demande avant de courir Lynis donc une course reste rapide.",
|
||||
"auditPolicyBaseline": "Politique et base de référence — déclarer ce que l'hôte est censé être (exigences de sauvegarde, pare-feu, connexion à la racine SSH) de sorte que les constatations notent contre elle, marquent une course comme référence, et voir ce qui a changé puisque, avec les nouvelles, les conclusions résolues et acceptées restent séparées.",
|
||||
"groupedAppUpdates": "Notifications groupées de mise à jour des applications — un message complet par balayage au lieu d'un message par application, groupé par LXC avec les versions installées et disponibles.",
|
||||
"adminTokenScope": "Champ d'application administratif — l'ouverture d'un terminal de monitoring et la désactivation de l'authentification nécessitent maintenant un jeton d'administration complet, de sorte qu'un jeton d'API en lecture seule émis à un monitoring intégré reste en lecture seule (rapporté par @f3rs3n).",
|
||||
"ociAppTab": "Conteneurs OCI dans l'onglet App — un conteneur installé par OCI manager Apps est reconnu à partir de son enregistrement d'installation : l'application et son image, une nouvelle image détectée par digest et un lien vers le dépôt de l'image.",
|
||||
"ociUpdatesTab": "Mises à jour des conteneurs OCI — Mettre à jour et Recréer ouvrent le même parcours que le menu OCI, la sauvegarde prise avant la mise à jour peut être conservée dans un stockage de sauvegardes et l'image peut être mise à jour de façon planifiée.",
|
||||
"ociLogsTab": "Onglet Logs pour les conteneurs OCI — la sortie console de l'application, conservée sur l'hôte et suivie en direct, avec un filtre et un téléchargement. La console Proxmox de ces conteneurs ouvre un shell.",
|
||||
"appsUpdateShortcut": "L'icône de mise à jour de la page Apps ouvre directement le conteneur sur son onglet Mises à jour.",
|
||||
"webhookHttps": "Les notifications de Proxmox atteignent le Monitor avec HTTPS activé — elles sont livrées sur une adresse uniquement locale et n'échouent plus sur une erreur de certificat.",
|
||||
"persistentLogs": "Une rafale d'erreurs de logs terminée n'est plus signalée comme persistante : un motif doit continuer d'apparaître pendant 15 minutes, et son avertissement se ferme de lui-même (signalé par @Joshua1264).",
|
||||
"mountsLanAddress": "Les points de montage sur LVM-thin et autres stockages en mode bloc affichent leur utilisation, et les applications multi-conteneurs s'ouvrent sur leur adresse LAN."
|
||||
}
|
||||
},
|
||||
"network": {
|
||||
@@ -5027,23 +5081,20 @@
|
||||
"uncategorized": "Uncategorized",
|
||||
"openAriaLabel": "Open {name} in a new tab",
|
||||
"openGuestAriaLabel": "Ouvrir {name} ({type} {id})",
|
||||
"emptyTitle": "No apps with a web link yet.",
|
||||
"emptyHint": "Register a Web Link for any app (App tab of a CT) to see it here.",
|
||||
"customLinkAdd": "Add link",
|
||||
"editModeToggle": "Edit",
|
||||
"editModeDone": "Done",
|
||||
"customLinkNewTitle": "New web link",
|
||||
"customLinkEditTitle": "Edit web link",
|
||||
"customLinkEditAria": "Modifier le lien personnalisé {name}",
|
||||
"openUpdatesAria": "Ouvrir l'onglet Mises à jour de {name}",
|
||||
"openUpdatesTitle": "Mise à jour disponible — ouvrir l'onglet Mises à jour",
|
||||
"customLinkName": "Name",
|
||||
"customLinkNamePlaceholder": "e.g. My app",
|
||||
"customLinkUrl": "URL",
|
||||
"customLinkLogo": "Logo URL (optional)",
|
||||
"customLinkLogoPlaceholder": "e.g., https://example.com/logo.webp",
|
||||
"customLinkCategory": "Category (optional)",
|
||||
"customLinkBinding": "Bound to",
|
||||
"customLinkBindingNone": "Not bound to any guest",
|
||||
"customLinkBindingHelp": "Bind this link to a VM or CT to add its ID + name to the card and jump to the guest with one click.",
|
||||
"customLinkSave": "Save",
|
||||
"customLinkCreate": "Create",
|
||||
"customLinkCancel": "Cancel",
|
||||
@@ -5079,7 +5130,12 @@
|
||||
"remoteAccessVpn": "Remote Access & VPN",
|
||||
"webserversProxies": "Webservers & Proxies",
|
||||
"zigbeeZwaveMatter": "ZigBee, Z-Wave & Matter"
|
||||
}
|
||||
},
|
||||
"emptyTitle": "Pas encore d'applications avec un lien web.",
|
||||
"emptyHint": "Enregistrez un lien Web pour toute application (onglet App d'un CT) pour le voir ici.",
|
||||
"customLinkLogoPlaceholder": "Par exemple, https://exemple.com/logo.webp",
|
||||
"customLinkBindingNone": "Non lié à un invité",
|
||||
"customLinkBindingHelp": "Relier ce lien à un VM ou CT pour ajouter son ID + nom à la carte et sauter à l'invité en un clic."
|
||||
},
|
||||
"audit": {
|
||||
"presentation": {
|
||||
@@ -5234,13 +5290,10 @@
|
||||
"loading": "Loading assessment…",
|
||||
"run": "Run assessment",
|
||||
"running": "Assessing…",
|
||||
"neverRun": "This host has not been assessed yet.",
|
||||
"lastRun": "Last assessed on {when}",
|
||||
"stale": "{days} days ago",
|
||||
"unverifiedChecks": "Non relevés : {checks}. Chacun indique dans ses évidences ce qu'il n'a pas pu lire.",
|
||||
"noFindings": "No findings match the current filter.",
|
||||
"affectedCount": "{count} affected",
|
||||
"acceptedNotice": "{count} accepted risk(s) recorded on this host.",
|
||||
"reviewOn": "À revoir le : {when}",
|
||||
"reviewDue": "À revoir — la décision reste en vigueur",
|
||||
"reviewDueNotice": "{count} décision(s) acceptée(s) sont à revoir.",
|
||||
@@ -5272,7 +5325,7 @@
|
||||
"sources": "Sources et dates de collecte"
|
||||
},
|
||||
"errors": {
|
||||
"runFailed": "The assessment could not be started."
|
||||
"runFailed": "L'évaluation n'a pas pu être entreprise."
|
||||
},
|
||||
"checks": {
|
||||
"backup": {
|
||||
@@ -5285,7 +5338,7 @@
|
||||
"uncovered": "{count} invités sur {total} ne sont sélectionnés par aucune tâche de sauvegarde activée",
|
||||
"excludedData": "{count} exclusions de disques ou montages à vérifier",
|
||||
"uncoveredExpected": "{required} invités déclarés comme devant être sauvegardés ne sont sélectionnés par aucune tâche activée",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
},
|
||||
"nextStep": {
|
||||
"noJobs": "Créez un travail de sauvegarde sur ce noeud et sélectionnez les invités qui détiennent des données que vous ne voudriez pas reconstruire à la main. Un emploi qui existe mais qui est handicapé ne sélectionne rien.",
|
||||
@@ -5300,10 +5353,10 @@
|
||||
"rationale": "Ancienneté : temps écoulé depuis la dernière copie stockée. Limite utilisée : ancienneté de référence à laquelle cette copie est comparée.",
|
||||
"summary": {
|
||||
"recent": "Les {total} vérifications invité/destination respectent le critère d’ancienneté indiqué",
|
||||
"stale": "{count} of {total} guests have no backup from the last 30 days",
|
||||
"noBackups": "No stored backup matches a guest on this node",
|
||||
"attention": "{count} vérifications invité/destination sur {total} nécessitent un examen",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"stale": "{count} de {total} invités n'ont aucune sauvegarde depuis les 30 derniers jours",
|
||||
"noBackups": "Aucune sauvegarde enregistrée ne correspond à un invité sur ce nœud",
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
},
|
||||
"nextStep": {
|
||||
"stale": "Découvrez pourquoi le travail a cessé de produire des copies pour ces invités : il a peut-être été désactivé, son emploi du temps peut ne jamais tirer, ou ses pistes peuvent échouer. La vérification des résultats de l'exécution indique comment chaque travail s'est terminé.",
|
||||
@@ -5317,10 +5370,10 @@
|
||||
"rationale": "La rétention telle que Proxmox la résout : réglage de la tâche, puis du stockage, puis la valeur par défaut du nœud. La rétention appliquée par un serveur de sauvegarde n'est pas lisible depuis ce nœud.",
|
||||
"summary": {
|
||||
"allDefined": "Les {total} tâches résolvent un réglage de rétention",
|
||||
"missing": "{count} of {total} enabled job(s) declare no retention",
|
||||
"notDeclared": "{count} tâches sur {total} conservent toutes les copies : aucune rétention n'est déclarée",
|
||||
"onServer": "{count} tâches sur {total} écrivent sur un serveur de sauvegarde, qui les élague avec ses propres tâches",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"missing": "{count} de {total} emploi(s) autorisé(s) déclarer aucune rétention",
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
},
|
||||
"nextStep": {
|
||||
"missing": "Réglez une rétention sur ces tâches, ou sur le stockage auquel ils écrivent. Proxmox prend le réglage du travail d'abord, puis le stockage, puis le noeud par défaut.",
|
||||
@@ -5383,36 +5436,36 @@
|
||||
"summary": {
|
||||
"none": "Rien n'a demandé de redémarrage",
|
||||
"pending": "{count} éléments sont installés et attendent un redémarrage",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
},
|
||||
"enterprise_repo_without_subscription": {
|
||||
"title": "Enterprise repository",
|
||||
"rationale": "Références à `enterprise.proxmox.com` dans `/etc/apt/sources.list` et `sources.list.d`, face au statut renvoyé par `pvesubscription get`.",
|
||||
"summary": {
|
||||
"notEnabled": "The enterprise repository is not enabled",
|
||||
"subscribed": "The enterprise repository is backed by a subscription",
|
||||
"unsubscribed": "The enterprise repository is enabled without an active subscription",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"notEnabled": "Le dépôt d'entreprise n'est pas activé",
|
||||
"subscribed": "Le dépôt d'entreprise est soutenu par un abonnement",
|
||||
"unsubscribed": "Le dépôt d'entreprise est activé sans abonnement actif",
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
},
|
||||
"memory_overcommit": {
|
||||
"title": "Memory allocation",
|
||||
"rationale": "Le plafond `memory` de chaque configuration d'invité face à MemTotal, les invités en cours comptés séparément. Les conteneurs consomment jusqu'à cette limite ; les machines virtuelles sans ballooning la réservent.",
|
||||
"summary": {
|
||||
"withinRatio": "Guests are allocated {percent}% of host memory",
|
||||
"aboveRatio": "Guests are allocated {percent}% of host memory",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"withinRatio": "Les invités reçoivent {percent}% de la mémoire hôte",
|
||||
"aboveRatio": "Les invités reçoivent {percent}% de la mémoire hôte",
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
},
|
||||
"time_synchronisation": {
|
||||
"title": "Time synchronisation",
|
||||
"rationale": "NTP et NTPSynchronized tels que `timedatectl` les rapporte. L'appartenance au cluster, la validation des certificats et l'ordre des journaux dépendent d'horloges concordantes. Un autre mécanisme peut discipliner l'horloge.",
|
||||
"summary": {
|
||||
"synchronised": "The clock is synchronised with a time source",
|
||||
"disabled": "Time synchronisation is disabled",
|
||||
"notSynchronised": "Time synchronisation is enabled but the clock is not synchronised",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"synchronised": "L'horloge est synchronisée avec une source de temps",
|
||||
"notSynchronised": "La synchronisation du temps est activée mais l'horloge n'est pas synchronisée",
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
},
|
||||
"kernel_current": {
|
||||
@@ -5420,21 +5473,21 @@
|
||||
"rationale": "Le noyau en cours face à celui que l'hôte démarrerait ensuite, tel que `proxmox-boot-tool` le rapporte. Un noyau plus récent seulement installé peut être retenu délibérément ; un écart après un redémarrage indique un démarrage qui n'a pas pris.",
|
||||
"summary": {
|
||||
"current": "Le noyau en cours {version} est celui que l'hôte démarrerait ensuite",
|
||||
"newerAvailable": "The host runs {running} while {newest} is installed",
|
||||
"newerSelected": "L'hôte exécute {running} et démarrerait {selected} au prochain redémarrage",
|
||||
"wouldDowngrade": "L'hôte exécute {running} mais démarrerait le plus ancien {selected} au prochain redémarrage",
|
||||
"bootTargetUnknown": "L'hôte exécute {version} ; le noyau choisi pour le prochain démarrage n'a pas pu être lu",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"newerAvailable": "L'hôte exécute {running} alors que {newest} est installé",
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
},
|
||||
"security_updates": {
|
||||
"title": "Security updates",
|
||||
"rationale": "Paquets en attente dont l'origine est un dépôt de sécurité, à partir d'un `apt-get upgrade` simulé. Le nombre reflète ce que rapporte apt, non la gravité de ce que chaque paquet corrige.",
|
||||
"summary": {
|
||||
"none": "No package updates are pending",
|
||||
"noSecurity": "{total} update(s) pending, none from a security repository",
|
||||
"pending": "{count} of {total} pending update(s) come from a security repository",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"none": "Aucune mise à jour du paquet n'est en cours",
|
||||
"noSecurity": "{total} mise(s) à jour en attente, aucune depuis un dépôt de sécurité",
|
||||
"pending": "{count} de {total} en attente de mise(s) à jour proviennent d'un dépôt de sécurité",
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
},
|
||||
"journal_size": {
|
||||
@@ -5442,10 +5495,10 @@
|
||||
"rationale": "Le journal sur disque face au plafond qui s'y applique : SystemMaxUse lorsqu'il est défini, sinon la valeur par défaut de journald, un dixième du système de fichiers qui l'héberge.",
|
||||
"summary": {
|
||||
"bounded": "Le journal occupe {size}, en deçà de son plafond effectif",
|
||||
"large": "The journal holds {size} on disk",
|
||||
"nearCap": "Le journal occupe {size} et atteint {percent}% de son plafond effectif",
|
||||
"capUnknown": "Le journal occupe {size} ; son plafond effectif n'a pas pu être déterminé",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"large": "La revue détient {size} sur disque",
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
},
|
||||
"swap_configured": {
|
||||
@@ -5454,7 +5507,7 @@
|
||||
"summary": {
|
||||
"active": "{size} of swap is active",
|
||||
"none": "No swap area is active",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
},
|
||||
"filesystem_capacity": {
|
||||
@@ -5500,7 +5553,7 @@
|
||||
"summary": {
|
||||
"synchronised": "Les {total} partitions d'amorçage portent les mêmes noyaux",
|
||||
"attention": "{count} partitions d'amorçage sur {total} demandent un examen",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
},
|
||||
"rationale": "Le système EFI partitionne les rapports proxmox-boot-tool et les noyaux que chacun transporte. L'état proxmox-boot-tool peut monter temporairement les partitions système EFI ;aucun démarrage n'est tenté."
|
||||
},
|
||||
@@ -5510,7 +5563,7 @@
|
||||
"summary": {
|
||||
"allRunning": "Les {total} services essentiels sont actifs et aucune unité n'est en échec",
|
||||
"attention": "{count} constat(s) parmi les unités",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
},
|
||||
"ha_state": {
|
||||
@@ -5519,7 +5572,7 @@
|
||||
"summary": {
|
||||
"managed": "Les {total} services gérés sont dans un état stabilisé sur {nodes} nœud(s)",
|
||||
"attention": "{count} constat(s) sur {total} service(s) géré(s)",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5528,27 +5581,27 @@
|
||||
"title": "Container privileges",
|
||||
"rationale": "Le réglage `unprivileged` de chaque configuration de conteneur. Son absence signifie que le conteneur partage l'espace de noms utilisateur de l'hôte, ce dont certaines charges ont besoin.",
|
||||
"summary": {
|
||||
"allUnprivileged": "All {total} containers are unprivileged",
|
||||
"privileged": "{count} of {total} containers run privileged",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"allUnprivileged": "Tous les conteneurs {total} ne sont pas privilégiés",
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
},
|
||||
"qemu_without_agent": {
|
||||
"title": "Guest agent on virtual machines",
|
||||
"rationale": "Le réglage `agent` dans la configuration de chaque machine virtuelle. Le réglage indique que l'agent est déclaré, non qu'il répond.",
|
||||
"summary": {
|
||||
"allHaveAgent": "All {total} virtual machines declare the guest agent",
|
||||
"missingAgent": "{count} of {total} virtual machines do not declare the guest agent",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
}
|
||||
"allHaveAgent": "Toutes les machines virtuelles {total} déclarent l'agent invité",
|
||||
"missingAgent": "{count} des machines virtuelles {total} ne déclarent pas l'agent invité",
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
},
|
||||
"title": "Agent invité sur machines virtuelles"
|
||||
},
|
||||
"autostart": {
|
||||
"title": "Automatic start",
|
||||
"rationale": "Le réglage `onboot` de chaque invité, hors modèles et invités gérés par HA. Qu'un invité doive revenir de lui-même relève de la politique déclarée.",
|
||||
"summary": {
|
||||
"allAutostart": "All {total} guests start with the host",
|
||||
"notAutostart": "{count} of {total} guests do not start with the host",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"allAutostart": "Tous les invités {total} commencent par l'hôte",
|
||||
"notAutostart": "{count} des invités {total} ne commencent pas avec l'hôte",
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
},
|
||||
"stuck_snapshots": {
|
||||
@@ -5556,28 +5609,28 @@
|
||||
"rationale": "État et ancienneté des snapshots ainsi que les tâches actives. Une opération récente ou sans date vérifiable n'est pas considérée comme interrompue.",
|
||||
"summary": {
|
||||
"noSnapshots": "No guest holds snapshots",
|
||||
"allComplete": "The {total} snapshot(s) are complete",
|
||||
"stuck": "{count} of {total} snapshot(s) were left mid-operation",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"allComplete": "Les instantanés {total} sont complets",
|
||||
"stuck": "{count} du ou des instantanés {total} ont été laissés en milieu de fonctionnement",
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
},
|
||||
"cpu_host_type": {
|
||||
"title": "Virtual CPU model",
|
||||
"rationale": "La valeur `cpu` de chaque machine virtuelle. `host` expose le jeu d'instructions du processeur physique, ce qui restreint les nœuds vers lesquels l'invité peut migrer. L'incompatibilité avec une destination précise n'est pas déterminée ici.",
|
||||
"summary": {
|
||||
"none": "None of the {total} virtual machines is pinned to the host processor",
|
||||
"pinned": "{count} of {total} virtual machines are pinned to the host processor",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"none": "Aucune des machines virtuelles {total} n'est épinglée au processeur hôte",
|
||||
"pinned": "{count} des machines virtuelles {total} sont épinglées au processeur hôte",
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
},
|
||||
"replication_state": {
|
||||
"title": "Replication",
|
||||
"rationale": "Tâches de réplication issues de l'API : nombre d'échecs, dernière erreur, dernière synchronisation et le calendrier que chaque tâche déclare. Les tâches en pause sont signalées comme telles.",
|
||||
"summary": {
|
||||
"healthy": "The {total} replication job(s) report no error",
|
||||
"failing": "{count} of {total} replication job(s) report an error",
|
||||
"statusUnavailable": "Replication jobs are defined but their status could not be read",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"healthy": "La ou les tâches de réplication {total} ne signalent aucune erreur",
|
||||
"failing": "{count} des tâches de réplication {total} signalent une erreur",
|
||||
"statusUnavailable": "Les emplois de replication sont définis mais leur statut n'a pas pu être lu.",
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5589,39 +5642,39 @@
|
||||
"bothEnabled": "L'activation du pare-feu est configurée au niveau du datacenter et du nœud",
|
||||
"datacenterOff": "Le pare-feu est désactivé au niveau du datacenter ; les règles du nœud ne sont donc pas appliquées",
|
||||
"nodeOff": "Le pare-feu est activé au niveau du datacenter, mais pas sur ce nœud",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
},
|
||||
"lynis_warnings": {
|
||||
"title": "Lynis warnings",
|
||||
"rationale": "Avertissements du dernier audit Lynis, chacun avec son identifiant de test, et l'ancienneté de cet audit. Un audit n'est lancé que si Lynis est installé et qu'aucun rapport complet n'existe. Les suggestions ne sont pas incluses.",
|
||||
"summary": {
|
||||
"none": "The last Lynis audit recorded no warnings",
|
||||
"found": "The last Lynis audit recorded {count} warning(s)",
|
||||
"incomplete": "The Lynis report is incomplete",
|
||||
"evaluationFailed": "The check could not be evaluated",
|
||||
"noneStale": "Le dernier audit Lynis n'a relevé aucun avertissement, et son rapport a {days} jour(s)",
|
||||
"foundStale": "Le dernier audit Lynis a relevé {count} avertissement(s), et son rapport a {days} jour(s)"
|
||||
"foundStale": "Le dernier audit Lynis a relevé {count} avertissement(s), et son rapport a {days} jour(s)",
|
||||
"none": "La dernière vérification de Lynis n'a enregistré aucun avertissement",
|
||||
"found": "La dernière vérification de Lynis a enregistré des avertissements {count}",
|
||||
"incomplete": "Le rapport Lynis est incomplet",
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
},
|
||||
"certificate_expiry": {
|
||||
"title": "Certificate validity",
|
||||
"rationale": "La date d'expiration du certificat que pveproxy sert depuis /etc/pve/local. Un certificat personnalisé prime sur celui que Proxmox génère.",
|
||||
"summary": {
|
||||
"valid": "The certificate is valid for {days} more day(s)",
|
||||
"expiring": "The certificate expires in {days} day(s)",
|
||||
"expired": "The certificate expired {days} day(s) ago",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"valid": "Le certificat est valide pour {days} plus jour(s)",
|
||||
"expiring": "Le certificat expire en {days} jour(s)",
|
||||
"expired": "Le certificat a expiré {days} jour(s)",
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
},
|
||||
"ssh_root_login": {
|
||||
"title": "SSH root access",
|
||||
"rationale": "PermitRootLogin dans la configuration effective de `sshd -T`, avec les méthodes d'authentification associées. Proxmox est livré avec `yes`, qui accepte un mot de passe.",
|
||||
"summary": {
|
||||
"password": "Root may sign in over SSH with a password",
|
||||
"keyOnly": "Root may sign in over SSH with a key only",
|
||||
"denied": "Root may not sign in over SSH",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"password": "Root peut se connecter sur SSH avec un mot de passe",
|
||||
"keyOnly": "La racine peut se connecter sur SSH avec une clé seulement",
|
||||
"denied": "La racine ne peut pas se connecter au-dessus de SSH",
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5630,9 +5683,9 @@
|
||||
"title": "Volume assignment",
|
||||
"rationale": "Volumes d'invité sur le stockage local face aux références des configurations actuelles, en attente et de snapshots. Les sauvegardes, ISO et modèles restent hors de la comparaison. Un volume sans référence est un candidat à examiner.",
|
||||
"summary": {
|
||||
"none": "No orphaned volumes were found",
|
||||
"found": "{count} volumes sans référence dans les configurations examinées",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"none": "Aucun volume d'orphelins n'a été trouvé",
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
},
|
||||
"zfs_arc_max": {
|
||||
@@ -5640,21 +5693,21 @@
|
||||
"rationale": "Valeurs effectives de c_min, c_max et taille de l'ARC, le paramètre de module chargé et les réglages persistants de /etc/modprobe.d. Une valeur configurée à zéro sélectionne la valeur par défaut du module ; l'ARC est un plafond et la mémoire qu'il occupe est récupérable.",
|
||||
"summary": {
|
||||
"bounded": "La limite de l'ARC représente {percent}% de la mémoire de l'hôte, et la mémoire qu'elle occupe est récupérable",
|
||||
"high": "The ARC may use {percent}% of host memory",
|
||||
"unset": "The ARC has no explicit limit set",
|
||||
"conflicting": "{count} réglages ARC ne concordent pas entre eux",
|
||||
"pending": "Un réglage ARC persistant diffère de la valeur portée par le module en cours",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"high": "L'ARC peut utiliser {percent}% de la mémoire hôte",
|
||||
"unset": "L'ARC n'a pas de limite explicite",
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
},
|
||||
"zfs_scrub_age": {
|
||||
"title": "ZFS scrub",
|
||||
"rationale": "Le dernier scrub terminé que `zpool status` rapporte pour chaque pool. Un resilver n'est pas un scrub. Un pool créé récemment n'a pas encore eu l'occasion d'en effectuer un.",
|
||||
"summary": {
|
||||
"recent": "The {total} pool(s) were scrubbed within the last 35 days",
|
||||
"overdue": "{count} of {total} pool(s) have not been scrubbed in 35 days",
|
||||
"neverScrubbed": "{count} pool(s) record no scrub",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"recent": "Les piscines {total} ont été nettoyées au cours des 35 derniers jours.",
|
||||
"overdue": "{count} de la ou des piscines {total} n'ont pas été nettoyées en 35 jours",
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
},
|
||||
"thin_pool_overprovisioning": {
|
||||
@@ -5664,7 +5717,7 @@
|
||||
"withinRatio": "Les {total} thin pools restent sous les seuils d'examen appliqués",
|
||||
"aboveRatio": "{count} pools légers sur {total} distribuent plus de capacité qu'ils n'en possèdent",
|
||||
"pressure": "{pressure} pools légers sur {total} approchent le remplissage de leurs données ou métadonnées",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
},
|
||||
"connected_storage": {
|
||||
@@ -5673,7 +5726,7 @@
|
||||
"summary": {
|
||||
"available": "PVE indique que les {total} stockages sont disponibles ; les composants internes distants et l'accès en écriture n'ont pas été testés",
|
||||
"attention": "{count} stockages sur {total} nécessitent un examen",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
},
|
||||
"pool_integrity": {
|
||||
@@ -5691,7 +5744,7 @@
|
||||
"summary": {
|
||||
"healthy": "Ceph rapporte HEALTH_OK",
|
||||
"degraded": "Ceph rapporte {state}, avec {count} vérification(s) nommée(s)",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
},
|
||||
"array_integrity": {
|
||||
@@ -5700,7 +5753,7 @@
|
||||
"summary": {
|
||||
"intact": "Les {total} grappes et cartes conservent leur redondance",
|
||||
"degraded": "{count} grappes ou cartes sur {total} en manquent",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5712,7 +5765,7 @@
|
||||
"withinLife": "Les {total} relevés de disques ne dépassent pas le seuil indicatif de cinq ans",
|
||||
"pastLife": "{count} relevés de disques sur {total} dépassent cinq ans de service",
|
||||
"noReadings": "Aucun disque ne rapporte de compteurs SMART exploitables ({skipped} sans relevés)",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
},
|
||||
"disk_errors": {
|
||||
@@ -5729,23 +5782,22 @@
|
||||
"title": "Bond members",
|
||||
"rationale": "L'état MII de chaque membre du bond selon /proc/net/bonding et le nombre de liens restants. En active-backup, un membre de secours se déclare actif et ne transporte rien.",
|
||||
"summary": {
|
||||
"allUp": "All members of the {total} bond(s) are up",
|
||||
"membersDown": "{count} bond member(s) are not up",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"allUp": "Tous les membres des obligations {total} sont en hausse",
|
||||
"membersDown": "Les membres d'obligations {count} ne sont pas en hausse",
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
},
|
||||
"bridge_without_ports": {
|
||||
"title": "Bridge ports",
|
||||
"rationale": "La configuration des ports de chaque bridge. Un bridge sans port physique dessert un réseau interne ou routé.",
|
||||
"summary": {
|
||||
"allConnected": "The {total} bridge(s) carry a port",
|
||||
"isolated": "{count} of {total} bridge(s) carry no port",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"allConnected": "Le ou les ponts {total} portent un port",
|
||||
"evaluationFailed": "La vérification n'a pas pu être évaluée"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"summaryFallback": "The check could not be evaluated",
|
||||
"acceptRisk": {
|
||||
"action": "Accepter le risque",
|
||||
"revoke": "Remettre en actif",
|
||||
@@ -5779,17 +5831,15 @@
|
||||
"OK": "OK"
|
||||
},
|
||||
"viewSwitch": {
|
||||
"ariaLabel": "Switch between assessment and inventory",
|
||||
"assessment": "Assessment",
|
||||
"inventory": "Inventory",
|
||||
"policy": "Politique",
|
||||
"changes": "Modifications"
|
||||
"changes": "Modifications",
|
||||
"ariaLabel": "Changement entre l'évaluation et l'inventaire"
|
||||
},
|
||||
"inventory": {
|
||||
"loading": "Loading inventory…",
|
||||
"failed": "The inventory could not be composed.",
|
||||
"collectedAt": "Composed on {when}",
|
||||
"unavailable": "Not read in this inventory",
|
||||
"unresolved": "path not resolved",
|
||||
"noUplink": "no uplink",
|
||||
"identity": "Node identity",
|
||||
@@ -5832,12 +5882,10 @@
|
||||
"protection": "Backup",
|
||||
"passthrough": "Passthrough",
|
||||
"noBackup": "No backup",
|
||||
"noBackupDetail": "No enabled backup job selects this guest.",
|
||||
"applications": "Applications",
|
||||
"versionUnknown": "version not detected",
|
||||
"passthroughTitle": "PCI passthrough",
|
||||
"iommuGroup": "IOMMU group {group}",
|
||||
"sharedGroup": "{count} more device(s) in the same group",
|
||||
"proxmenux": "ProxMenux optimizations",
|
||||
"latency": "Latence réseau",
|
||||
"subscriptionStatus": {
|
||||
@@ -5848,7 +5896,11 @@
|
||||
"suspended": "Suspendu",
|
||||
"new": "En attente d'activation",
|
||||
"unknown": "Inconnu"
|
||||
}
|
||||
},
|
||||
"failed": "L'inventaire n'a pas pu être composé.",
|
||||
"unavailable": "Non lu dans cet inventaire",
|
||||
"noBackupDetail": "Aucune tâche de sauvegarde activée ne sélectionne cet invité.",
|
||||
"sharedGroup": "{count} plus de dispositif(s) dans le même groupe"
|
||||
},
|
||||
"profile": {
|
||||
"label": "Report",
|
||||
@@ -5871,7 +5923,6 @@
|
||||
"area": "Area",
|
||||
"inventoryAnnex": "Inventory annex",
|
||||
"scopeTitle": "Scope of this report",
|
||||
"scopeBody": "This report describes the Proxmox VE node named above, as observed from the node itself at the time stated. It does not cover the interior of the guests beyond what they declare, network equipment outside the host, physical infrastructure, or any dependency not visible from this node. Findings marked as not determined were not measured and are not evidence of absence.",
|
||||
"building": "Composition du rapport…",
|
||||
"node": "Nœud",
|
||||
"profile": "Profil",
|
||||
@@ -6020,11 +6071,12 @@
|
||||
"structureSubtitle": "Comment {node} est construit et configuré",
|
||||
"postureTitle": "Posture",
|
||||
"posture": {
|
||||
"security": "Host exposure and access.",
|
||||
"backup": "Guest protection and whether it is real.",
|
||||
"capacity": "Room to grow and the wear on the disks."
|
||||
"security": "Exposition de l'hôte et accès.",
|
||||
"backup": "Protection des invités et si elle est réelle.",
|
||||
"capacity": "La place pour grandir et l'usure sur les disques."
|
||||
},
|
||||
"scopeReadOnly": "L’évaluation inspecte les paramètres et l’état de l’hôte. Il peut rédiger des rapports et des journaux ;les vérifications de l'état de démarrage peuvent monter temporairement les partitions système EFI."
|
||||
"scopeReadOnly": "L’évaluation inspecte les paramètres et l’état de l’hôte. Il peut rédiger des rapports et des journaux ;les vérifications de l'état de démarrage peuvent monter temporairement les partitions système EFI.",
|
||||
"scopeBody": "Le présent rapport décrit le noeud Proxmox VE nommé ci-dessus, comme on l'a vu dans le nœud lui-même à l'époque indiquée. Il ne couvre pas l'intérieur des invités au-delà de ce qu'ils déclarent, l'équipement réseau en dehors de l'hôte, l'infrastructure physique, ou toute dépendance non visible de ce noeud. Les résultats marqués comme non déterminés n'ont pas été mesurés et ne sont pas une preuve d'absence."
|
||||
},
|
||||
"results": "Résultats",
|
||||
"classifications": {
|
||||
@@ -6178,15 +6230,19 @@
|
||||
"notApplicableScope": "Rien dans le périmètre examiné auquel cette vérification s'applique.",
|
||||
"lynis": {
|
||||
"title": "Run Lynis",
|
||||
"bodyNotRun": "Lynis is installed but has not been run yet. Running it now completes the security review, but the process can take a few minutes.",
|
||||
"bodyStale": "The Lynis report is {days} days old. You can run it now to refresh the data (it takes a little longer) or continue with the existing report.",
|
||||
"withLynis": "Run with Lynis",
|
||||
"withoutLynis": "Run without Lynis",
|
||||
"cancel": "Cancel"
|
||||
"cancel": "Cancel",
|
||||
"bodyNotRun": "Lynis est installé mais n'a pas encore été exécuté. Il termine maintenant l'examen de sécurité, mais le processus peut prendre quelques minutes.",
|
||||
"bodyStale": "Le rapport Lynis date de {days} jours. Vous pouvez l'exécuter maintenant pour actualiser les données (il faut un peu plus longtemps) ou continuer avec le rapport existant."
|
||||
},
|
||||
"readOnlyNotice": "L’évaluation inspecte les paramètres et l’état de l’hôte. Il peut rédiger des rapports et des journaux ;les vérifications de l'état de démarrage peuvent monter temporairement les partitions système EFI.",
|
||||
"noActionNeeded": "Rien à faire. Ce chèque a trouvé ce qu'il s'attend à trouver.",
|
||||
"couldNotEvaluate": "Cette vérification n'a pu être évaluée, de sorte qu'elle ne fait aucun rapport. La preuve enregistre ce qu'elle n'a pas pu lire."
|
||||
"couldNotEvaluate": "Cette vérification n'a pu être évaluée, de sorte qu'elle ne fait aucun rapport. La preuve enregistre ce qu'elle n'a pas pu lire.",
|
||||
"neverRun": "Cet hôte n'a pas encore été évalué.",
|
||||
"noFindings": "Aucune découverte ne correspond au filtre actuel.",
|
||||
"acceptedNotice": "{count} a accepté les risques enregistrés sur cet hôte.",
|
||||
"summaryFallback": "La vérification n'a pas pu être évaluée"
|
||||
},
|
||||
"runtime": {
|
||||
"notifications": {
|
||||
|
||||
+193
-137
@@ -1069,7 +1069,8 @@
|
||||
"backups": "Backup",
|
||||
"updates": "Aggiornamenti",
|
||||
"firewall": "Firewall",
|
||||
"app": "App"
|
||||
"app": "App",
|
||||
"logs": "Logs"
|
||||
},
|
||||
"actions": {
|
||||
"start": "Inizio",
|
||||
@@ -1169,6 +1170,44 @@
|
||||
"empty": "Nessun evento firewall ancora registrato.",
|
||||
"emptyHint": "Le regole con log: info o superiore popoleranno questa visualizzazione all'arrivo dei pacchetti."
|
||||
},
|
||||
"consoleLog": {
|
||||
"title": "Output della console",
|
||||
"description": "Output standard e di errore del processo principale dell'immagine.",
|
||||
"stopped": "Il container è fermo; il log conserva l'output delle esecuzioni precedenti.",
|
||||
"lastLines": "Ultime {count} righe",
|
||||
"follow": "Segui",
|
||||
"pause": "Pausa",
|
||||
"refresh": "Aggiorna",
|
||||
"download": "Scarica",
|
||||
"filter": "Filtra righe",
|
||||
"loading": "Caricamento dell'output della console...",
|
||||
"empty": "Nessun output registrato finora.",
|
||||
"emptyHint": "Le righe compaiono qui man mano che il container scrive sulla sua console.",
|
||||
"noMatches": "Nessuna riga corrisponde al filtro.",
|
||||
"readFailed": "Impossibile leggere il log della console",
|
||||
"notAvailableTitle": "Questo container non ha un log della console",
|
||||
"notAvailableHint": "Il log della console viene configurato quando ProxMenux installa il container dalla sua immagine OCI."
|
||||
},
|
||||
"ociUpdates": {
|
||||
"notTracked": "Registrando l'applicazione nella scheda App, qui se ne segue l'immagine.",
|
||||
"installedImage": "Immagine installata",
|
||||
"newImage": "Nuova immagine {image} disponibile",
|
||||
"stackNote": "Parte di un'applicazione multi-container (CT principale {primary}, {count} container): l'aggiornamento li comprende tutti.",
|
||||
"pendingNote": "Un'operazione su questo container è stata interrotta; Recupera ne apre il ripristino.",
|
||||
"update": "Aggiorna",
|
||||
"recreate": "Ricrea",
|
||||
"recover": "Recupera",
|
||||
"terminalTitleUpdate": "Aggiorna applicazione OCI",
|
||||
"terminalTitleRecreate": "Ricrea applicazione OCI",
|
||||
"terminalDescription": "Lo stesso percorso di OCI manager Apps → Gestisci le applicazioni OCI installate.",
|
||||
"keepBackup": "Conserva il backup eseguito prima dell'aggiornamento",
|
||||
"noKeepBackup": "Il backup eseguito prima dell'aggiornamento non viene conservato",
|
||||
"keepBackupHelp": "Ogni aggiornamento esegue il backup del container prima di sostituirne l'immagine, per ripristinarlo se l'aggiornamento fallisce. Con questa opzione quel backup viene conservato nello storage scelto; su Proxmox Backup Server viene scritto un backup prima dell'aggiornamento.",
|
||||
"scheduleHelp": "Viene aggiornata solo l'immagine, e solo quando il suo registro ne pubblica una nuova.",
|
||||
"releaseDelayHelp": "Una nuova immagine viene installata solo quando ha almeno questa età.",
|
||||
"ackExternal": "Le directory dell'host non vengono ripristinate dal backup",
|
||||
"ackExternalHelp": "Questo container usa directory dell'host. Un aggiornamento pianificato viene eseguito solo con questa conferma."
|
||||
},
|
||||
"options": {
|
||||
"title": "Opzioni",
|
||||
"snapshotBefore": "Istantanea prima dell'applicazione",
|
||||
@@ -1429,6 +1468,14 @@
|
||||
"loadFailed": "impossibile caricare la configurazione dell'aggiornamento collettivo."
|
||||
},
|
||||
"appEditor": {
|
||||
"methodOciImage": "Immagine OCI (installata da ProxMenux)",
|
||||
"ociImageHelp": "La versione e i suoi aggiornamenti vengono letti dall'immagine da cui è stato creato questo container. ProxMenux lo ha installato, quindi non c'è nulla da configurare: l'immagine installata viene confrontata con quella che il suo registro pubblica oggi.",
|
||||
"ociAppVersion": "Applicazione",
|
||||
"ociImage": "Immagine",
|
||||
"ociNewImage": "Nuova immagine",
|
||||
"ociImageCurrent": "Versione",
|
||||
"refreshData": "Aggiorna dati",
|
||||
"refreshingData": "Aggiornamento…",
|
||||
"dockerDetectedWithWorkloads": "Docker rilevato con {count} applicazioni in container",
|
||||
"dockerWorkloadsHeading": "Applicazioni in Docker",
|
||||
"runsInsideDocker": "Si aggiorna con la sua immagine Docker",
|
||||
@@ -1487,7 +1534,6 @@
|
||||
"containerNameLabel": "Nome del contenitore",
|
||||
"containerNamePlaceholder": "ad esempio, <nome-contenitore>",
|
||||
"ociLabelKeyLabel": "Chiave etichetta OCI",
|
||||
"ociLabelPlaceholder": "org.opencontainers.image.version",
|
||||
"pythonInterpreterLabel": "Percorso dell'interprete Python",
|
||||
"pythonInterpreterPlaceholder": "ad esempio, /opt/<tua-app>/venv/bin/python",
|
||||
"pipDistLabel": "Nome della distribuzione (pacchetto pip)",
|
||||
@@ -1534,11 +1580,8 @@
|
||||
"portHttps": "https",
|
||||
"portLogoLabel": "URL del logo per questo collegamento (facoltativo)",
|
||||
"portLogoPlaceholder": "ad esempio, https://example.com/logo.webp",
|
||||
"portCategoryPlaceholder": "Category for the Apps dashboard (optional)",
|
||||
"portCategoryNone": "No category",
|
||||
"portCategoryAddNew": "+ Add new category…",
|
||||
"portCategoryCustomPlaceholder": "Type a category and press Enter (Esc to cancel)",
|
||||
"portCustomUrlPlaceholder": "Custom URL (e.g. https://vault.example.com) — overrides IP:port",
|
||||
"removePortTooltip": "Rimuovere la porta",
|
||||
"detectMethodDpkg": "dpkg ·",
|
||||
"detectMethodApk": "apk ·",
|
||||
@@ -1631,7 +1674,11 @@
|
||||
"notifyUpstreamLabel": "avvisami quando è disponibile una nuova versione upstream",
|
||||
"notifyUpstreamHelp": "invia `app_update_available` ai canali abilitati in Impostazioni → Notifiche. Disattiva se questa app non può essere aggiornata sul tuo box.",
|
||||
"excludeFromBadgeLabel": "esclusione dal contatore degli aggiornamenti LXC",
|
||||
"excludeFromBadgeHelp": "non contare questa app nel badge degli aggiornamenti aggregati sulla scheda dell'elenco LXC.Utile quando sei bloccato di proposito su una versione specifica (requisito del tracker, blocco della compatibilità).Non influisce sullo stato della scheda App o sulla notifica in uscita."
|
||||
"excludeFromBadgeHelp": "non contare questa app nel badge degli aggiornamenti aggregati sulla scheda dell'elenco LXC.Utile quando sei bloccato di proposito su una versione specifica (requisito del tracker, blocco della compatibilità).Non influisce sullo stato della scheda App o sulla notifica in uscita.",
|
||||
"ociLabelPlaceholder": "org.opencontainers.image.version",
|
||||
"portCategoryPlaceholder": "Categoria per il cruscotto App (opzionale)",
|
||||
"portCategoryCustomPlaceholder": "Digitare una categoria e premere Invio (Esc per annullare)",
|
||||
"portCustomUrlPlaceholder": "URL personalizzato (ad esempio https://vault.example.com) — overrides IP:port"
|
||||
},
|
||||
"statusFilter": {
|
||||
"ariaLabel": "Filtra macchine virtuali e container",
|
||||
@@ -2515,10 +2562,10 @@
|
||||
"scope": {
|
||||
"label": "Token permissions",
|
||||
"readOnly": "Read-only",
|
||||
"readOnlyHint": "Reads metrics and status. Recommended for dashboards and integrations.",
|
||||
"fullAdmin": "Full admin",
|
||||
"fullAdminHint": "Full control, like your own session.",
|
||||
"fullAdminWarning": "A full-admin token can do everything you can: power off or reboot the host, run updates and open a terminal. Share it only with fully trusted integrations."
|
||||
"readOnlyHint": "Legge metriche e stato. Consigliato per cruscotti e integrazioni.",
|
||||
"fullAdminHint": "Controllo completo, come la tua sessione.",
|
||||
"fullAdminWarning": "Un token full-admin può fare tutto il possibile: spegnere o riavviare l'host, eseguire aggiornamenti e aprire un terminale. Condividi solo con integrazioni completamente affidabili."
|
||||
}
|
||||
},
|
||||
"firewall": {
|
||||
@@ -3302,26 +3349,33 @@
|
||||
"gotIt": "Fatto!",
|
||||
"dontShowAgain": "Non mostrare più per questa versione",
|
||||
"currentFeatures": {
|
||||
"appDetection": "Smarter app detection in the App tab: Docker is correctly promoted as the parent workload during cold start (Portainer/SearXNG no longer briefly show up as native apps), unregistered suggestions live in the startup cache, and 'Find applications' runs a fresh catalog-backed scan on demand.",
|
||||
"dockerUpdates": "The Updates tab now covers Docker end-to-end: Docker Engine and per-image update tracking follow the same 24-hour rolling cycle as OS packages, with a 'Check now' action for on-demand digest comparison — no more waiting for the daily collector.",
|
||||
"appCatalog": "New application detection catalog with over 380 tracked workloads, generated live from community-scripts across seven detector methods (file, binary, dpkg, apk, Python, Docker exec, Docker label). Primary and fallback detectors cover both new and historical LXC layouts.",
|
||||
"pushover": "Pushover joins Telegram, Gotify, Discord, Email and Apprise as a native notification channel — user/API key, device and sound selectors, priority 0 for regular messages, optional priority 1 for CRITICAL events. Suggested by @benginx (#308).",
|
||||
"appsDashboard": "New top-level Apps dashboard — a single launcher for every Web Link across the node. LXC-registered apps and user-defined Custom Web Links share the same grid with category badges, search, and one-click deep-links back to the guest modal.",
|
||||
"lxcAppsUpdates": "App tab inside every LXC modal registers installed apps, captures weblinks and tracks upstream versions. Reworked Updates tab applies OS packages and app updates from a single button; Docker Engine and per-image tracking follow the same 24-hour cycle, with a 'Check now' action on demand.",
|
||||
"multilingual": "The Monitor now speaks 8 languages: English, Spanish, German, French, Italian, Portuguese, Swedish and Slovak. Huge thanks to @vaso73 for building the i18n scaffolding that made this possible.",
|
||||
"nvidiaMultiGpu": "NVIDIA driver lifecycle moves to per-BDF ownership so a multi-GPU host can pass one card to a VM and keep the other operational on the host or in LXCs, plus a kernel + branch + GPU-aware version picker (#298).",
|
||||
"aiCustomEndpoint": "AI Assistant custom OpenAI endpoint — LiteLLM, LM Studio, LocalAI, vLLM, OmniRoute and any self-hosted proxy on private IPs, loopback or Docker networks are recognised when loading the model catalogue. The dropdown surfaces the server's error (or the underlying network reason) directly under the Load button (#325, reported by @jorgeffonte).",
|
||||
"secureGatewayArch": "Secure Gateway wizard — the Alpine template download, local template selection and pct create all match the host's real architecture, so x86_64 hosts receive amd64 containers and arm64 hosts receive arm64 containers (#324, reported by @N0X4DD0).",
|
||||
"atomicNotifications": "Notification events reserve their deduplication fingerprint atomically before AI processing and channel delivery, so concurrent collectors, completion callbacks or parallel Monitor processes cannot send the same event twice. The reservation is released when no channel succeeds, preserving retries.",
|
||||
"borgSshPort": "Borg remote target — the Add Borg destination dialog and the shell TUI accept a custom SSH port. BORG_RSH, the auto key install flow and the capacity probe all honour it. Fully backwards compatible with existing entries created without an explicit port (suggested by @songochain in discussion #236).",
|
||||
"githubToken": "Settings → GitHub API accepts an optional personal access token for release and tag checks when the anonymous quota is exhausted. The token is encrypted at rest and never returned to the browser; the rate-limit error is translated in every Monitor language (suggested by @SystemIdleProcess in discussion #306).",
|
||||
"replicationContext": "Native Proxmox replication failure notifications resolve the replication job ID, affected VM/LXC ID and guest name; the exact error block from Proxmox is preserved as the reason, and each replication job deduplicates independently (reported by Ale R.).",
|
||||
"auditAssessment": "Audit & Report — a new page that documents and assesses the node. The Assessment runs a catalogue of checks across security, backups, capacity, storage, network, hardware, guests and system, classifying each finding as critical, warning, observation or conformant and stating what it read rather than judging it.",
|
||||
"changeJournal": "Change journal — a Changes view that lists exactly what ProxMenux modified on this host: every configuration file, package and service it touched, with the prior state of each, deduplicated to a current-state view that shows the host as it stands now rather than a log of every run.",
|
||||
"auditReports": "Reports — a full audit plus focused Security review, Backup assurance and Capacity & wear reports, each opening on its own posture header, and a printable Inventory; all export to PDF. A security assessment asks before running Lynis so a run stays fast.",
|
||||
"auditPolicyBaseline": "Policy and baseline — declare what the host is expected to be (backup requirements, firewall, root SSH login) so findings grade against it, mark a run as the reference, and see what changed since, with new, resolved and accepted findings kept apart.",
|
||||
"groupedAppUpdates": "Grouped application update notifications — one complete message per scan instead of one per application, grouped by LXC with the installed and available versions.",
|
||||
"adminTokenScope": "Administrative scope — opening a Monitor terminal and disabling authentication now require a full-admin token, so a read-only API token issued to a monitoring integration stays read-only (reported by @f3rs3n)."
|
||||
"appDetection": "Rilevamento delle app più intelligenti nella scheda App: Docker è correttamente promosso come il carico di lavoro dei genitori durante l'avvio a freddo (Portainer/SearXNG non si presenta più brevemente come applicazioni native), suggerimenti non registrati dal vivo nella cache di avvio, e 'Find application' esegue una nuova scansione a catalogo a richiesta.",
|
||||
"dockerUpdates": "La scheda Aggiornamenti ora copre Docker end-to-end: Docker Aggiornamento motore e per immagine seguire lo stesso ciclo di rotolamento 24 ore di pacchetti OS, con un'azione 'Check now' per il confronto on-demand digest — non più in attesa per il collettore quotidiano.",
|
||||
"appCatalog": "Nuovo catalogo di rilevamento delle applicazioni con oltre 380 carichi di lavoro tracciati, generati dal vivo da codici comunitari attraverso sette metodi di rivelatore (file, binario, dpkg, apk, Python, Docker exec, Docker label). I rilevatori primari e fallback coprono sia i nuovi che storici layout LXC.",
|
||||
"pushover": "Pushover unisce Telegram, Gotify, Discord, Email e Apprise come canale di notifica nativo — chiave utente/API, selettori di dispositivo e suono, priorità 0 per messaggi regolari, priorità opzionale 1 per eventi CRITICAL. Suggerito da @benginx (#308).",
|
||||
"appsDashboard": "Nuovo cruscotto App di alto livello — un singolo lanciatore per ogni collegamento Web attraverso il nodo. Applicazioni registrate da LXC e Web personalizzato definito dall'utente I collegamenti condividono la stessa griglia con i distintivi di categoria, la ricerca e un clic deep-link torna al modal guest.",
|
||||
"lxcAppsUpdates": "Scheda App all'interno di ogni LXC modal registra app installate, cattura weblink e traccia versioni a monte. La scheda Aggiornamenti rielaborati applica i pacchetti OS e gli aggiornamenti delle app da un singolo pulsante; Docker Engine e per-image tracking seguono lo stesso ciclo di 24 ore, con un'azione 'Check now' a richiesta.",
|
||||
"multilingual": "Il Monitor ora parla 8 lingue: inglese, spagnolo, tedesco, francese, italiano, portoghese, svedese e slovacco. Enorme grazie a @vaso73 per la costruzione del ponteggio i18n che ha reso possibile questo.",
|
||||
"nvidiaMultiGpu": "Il ciclo di vita del driver NVIDIA si sposta alla proprietà per-BDF in modo che un host multi-GPU possa passare una scheda a un VM e mantenere l'altra operativa sull'host o in LXCs, oltre a un kernel + branch + GPU-aware versione picker (#298).",
|
||||
"aiCustomEndpoint": "AI Assistant Custom OpenAI endpoint — LiteLLM, LM Studio, LocalAI, vLLM, OmniRoute e qualsiasi proxy self-hosted su IP privati, loopback o reti Docker sono riconosciuti al momento del caricamento del catalogo del modello. Il dropdown supera l'errore del server (o la ragione di rete sottostante) direttamente sotto il pulsante Carica (#325, riportato da @jorgeffonte).",
|
||||
"secureGatewayArch": "Secure Gateway wizard — il download del modello alpino, la selezione dei modelli locali e pct create tutti corrispondono all'architettura reale dell'host, così gli host x86 64 ricevono i container amd64 e gli host arm64 ricevono i container arm64 (#324, segnalati da @N0X4DD0).",
|
||||
"atomicNotifications": "Gli eventi di notifica riservano le loro impronte di deduplicazione atomicamente prima dell'elaborazione di AI e della consegna dei canali, così i collettori concomitanti, i callback di completamento o i processi di Monitor parallelo non possono inviare lo stesso evento due volte. La prenotazione viene rilasciata quando nessun canale riesce, conservando i retries.",
|
||||
"borgSshPort": "Borg obiettivo remoto — la finestra di dialogo Aggiungi destinazione Borg e la shell TUI accettano una porta SSH personalizzata. BORG RSH, il flusso di installazione chiave automatica e la sonda di capacità lo onorano tutti. Pienamente compatibile con le voci esistenti create senza un porto esplicito (suggested da @songochain in discussione #236).",
|
||||
"githubToken": "Impostazioni → GitHub API accetta un gettone di accesso personale facoltativo per il rilascio e i controlli dei tag quando la quota anonima è esaurita. Il token è crittografato a riposo e non è mai tornato al browser; l'errore di tasso-limit è tradotto in ogni lingua Monitor (suggested da @SystemIdleProcess in discussione #306).",
|
||||
"replicationContext": "Le notifiche di errori di replica Proxmox native risolvono l'ID del lavoro di replica, l'ID VM/LXC interessato e il nome dell'ospite; il blocco di errore esatto da Proxmox è conservato come il motivo, e ogni lavoro di replica deduplica indipendentemente (riportato da Ale R.).",
|
||||
"auditAssessment": "Audit & Report — una nuova pagina che documenta e valuta il nodo. La valutazione gestisce un catalogo di controlli su sicurezza, backup, capacità, storage, rete, hardware, ospiti e sistema, classificando ogni ricerca come critico, avviso, osservazione o conformante e affermando ciò che legge anziché giudicarlo.",
|
||||
"changeJournal": "Cambia la rivista — una vista Modifiche che elenca esattamente ciò che ProxMenux modificato su questo host: ogni file di configurazione, pacchetto e servizio che ha toccato, con lo stato precedente di ciascuno, deduplicato a una vista corrente-stato che mostra l'host come si trova ora piuttosto che un registro di ogni corsa.",
|
||||
"auditReports": "Rapporti — una revisione completa di audit più focalizzata di sicurezza, garanzia di backup e report di capacità & usura, ogni apertura sul proprio intestazione postura, e un Inventory stampabile; tutte le esportazioni in PDF. Una valutazione di sicurezza chiede prima di eseguire Lynis così una corsa rimane veloce.",
|
||||
"auditPolicyBaseline": "Politica e linea di base — dichiarare ciò che l'host è previsto per essere (requisiti di backup, firewall, root SSH login) in modo da trovare grado contro di esso, contrassegnare una corsa come il riferimento, e vedere che cosa cambiato da, con nuovi, risolti e accettati risultati tenuti separati.",
|
||||
"groupedAppUpdates": "Notifiche di aggiornamento dell'applicazione raggruppate — un messaggio completo per scansione invece di uno per applicazione, raggruppate da LXC con le versioni installate e disponibili.",
|
||||
"adminTokenScope": "Amministrativo — l'apertura di un terminale Monitor e la disattivazione dell'autenticazione richiedono ora un token full-admin, quindi un token API di sola lettura rilasciato ad un'integrazione di monitoraggio resta in sola lettura (reported by @f3rs3n).",
|
||||
"ociAppTab": "Container OCI nella scheda App — un container installato da OCI manager Apps viene riconosciuto dal suo registro di installazione: l'applicazione e la sua immagine, una nuova immagine rilevata tramite digest e un link al repository dell'immagine.",
|
||||
"ociUpdatesTab": "Aggiornamenti dei container OCI — Aggiorna e Ricrea aprono lo stesso percorso del menu OCI, il backup eseguito prima dell'aggiornamento può essere conservato in uno storage di backup e l'immagine può essere aggiornata in modo pianificato.",
|
||||
"ociLogsTab": "Scheda Logs per i container OCI — l'output della console dell'applicazione, conservato sull'host e seguito in tempo reale, con filtro e download. La console di Proxmox di questi container apre una shell.",
|
||||
"appsUpdateShortcut": "L'icona di aggiornamento nella pagina App apre il container direttamente sulla sua scheda Aggiornamenti.",
|
||||
"webhookHttps": "Le notifiche di Proxmox raggiungono il Monitor con HTTPS attivo — vengono consegnate su un indirizzo solo locale e non falliscono più per un errore di certificato.",
|
||||
"persistentLogs": "Una raffica di errori nei log che si è conclusa non viene più segnalata come persistente: un pattern deve continuare a comparire per 15 minuti, e il suo avviso si chiude da solo (segnalato da @Joshua1264).",
|
||||
"mountsLanAddress": "I punti di mount su LVM-thin e altri storage a blocchi mostrano il loro utilizzo, e le applicazioni multi-container si aprono sul loro indirizzo LAN."
|
||||
}
|
||||
},
|
||||
"network": {
|
||||
@@ -5027,23 +5081,20 @@
|
||||
"uncategorized": "Uncategorized",
|
||||
"openAriaLabel": "Open {name} in a new tab",
|
||||
"openGuestAriaLabel": "Apri {name} ({type} {id})",
|
||||
"emptyTitle": "No apps with a web link yet.",
|
||||
"emptyHint": "Register a Web Link for any app (App tab of a CT) to see it here.",
|
||||
"customLinkAdd": "Add link",
|
||||
"editModeToggle": "Edit",
|
||||
"editModeDone": "Done",
|
||||
"customLinkNewTitle": "New web link",
|
||||
"customLinkEditTitle": "Edit web link",
|
||||
"customLinkEditAria": "Modifica il collegamento personalizzato {name}",
|
||||
"openUpdatesAria": "Apri la scheda Aggiornamenti di {name}",
|
||||
"openUpdatesTitle": "Aggiornamento disponibile — apri la scheda Aggiornamenti",
|
||||
"customLinkName": "Name",
|
||||
"customLinkNamePlaceholder": "e.g. My app",
|
||||
"customLinkUrl": "URL",
|
||||
"customLinkLogo": "Logo URL (optional)",
|
||||
"customLinkLogoPlaceholder": "e.g., https://example.com/logo.webp",
|
||||
"customLinkCategory": "Category (optional)",
|
||||
"customLinkBinding": "Bound to",
|
||||
"customLinkBindingNone": "Not bound to any guest",
|
||||
"customLinkBindingHelp": "Bind this link to a VM or CT to add its ID + name to the card and jump to the guest with one click.",
|
||||
"customLinkSave": "Save",
|
||||
"customLinkCreate": "Create",
|
||||
"customLinkCancel": "Cancel",
|
||||
@@ -5079,7 +5130,12 @@
|
||||
"remoteAccessVpn": "Remote Access & VPN",
|
||||
"webserversProxies": "Webservers & Proxies",
|
||||
"zigbeeZwaveMatter": "ZigBee, Z-Wave & Matter"
|
||||
}
|
||||
},
|
||||
"emptyTitle": "Nessuna applicazione con un link web ancora.",
|
||||
"emptyHint": "Registrare un Web Link per qualsiasi applicazione (App scheda di un CT) per vederlo qui.",
|
||||
"customLinkLogoPlaceholder": "ad esempio, https://example.com/logo.webp",
|
||||
"customLinkBindingNone": "Non vincolato a nessun ospite",
|
||||
"customLinkBindingHelp": "Collegare questo link a un VM o CT per aggiungere il suo ID + nome alla scheda e saltare all'ospite con un clic."
|
||||
},
|
||||
"audit": {
|
||||
"presentation": {
|
||||
@@ -5234,13 +5290,10 @@
|
||||
"loading": "Loading assessment…",
|
||||
"run": "Run assessment",
|
||||
"running": "Assessing…",
|
||||
"neverRun": "This host has not been assessed yet.",
|
||||
"lastRun": "Last assessed on {when}",
|
||||
"stale": "{days} days ago",
|
||||
"unverifiedChecks": "Non effettuate: {checks}. Ciascuna dice nella propria evidenza cosa non ha potuto leggere.",
|
||||
"noFindings": "No findings match the current filter.",
|
||||
"affectedCount": "{count} affected",
|
||||
"acceptedNotice": "{count} accepted risk(s) recorded on this host.",
|
||||
"reviewOn": "Da rivedere il: {when}",
|
||||
"reviewDue": "Da rivedere — la decisione resta valida",
|
||||
"reviewDueNotice": "{count} decisione/i accettata/e da rivedere.",
|
||||
@@ -5272,7 +5325,7 @@
|
||||
"sources": "Fonti e date di raccolta"
|
||||
},
|
||||
"errors": {
|
||||
"runFailed": "The assessment could not be started."
|
||||
"runFailed": "La valutazione non potrebbe essere iniziata."
|
||||
},
|
||||
"checks": {
|
||||
"backup": {
|
||||
@@ -5285,7 +5338,7 @@
|
||||
"uncovered": "{count} guest su {total} non sono selezionati da alcun processo di backup attivo",
|
||||
"excludedData": "{count} esclusioni di dischi o mount point da verificare",
|
||||
"uncoveredExpected": "{required} guest dichiarati come da proteggere non sono selezionati da alcun processo attivo",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
},
|
||||
"nextStep": {
|
||||
"noJobs": "Creare un lavoro di backup su questo nodo e selezionare gli ospiti in possesso di dati che non si desidera ricostruire a mano. Un lavoro che esiste ma è disabilitato non seleziona nulla.",
|
||||
@@ -5300,10 +5353,10 @@
|
||||
"rationale": "Età: tempo trascorso dall’ultima copia archiviata. Limite utilizzato: età di riferimento con cui viene confrontata la copia.",
|
||||
"summary": {
|
||||
"recent": "Tutte le {total} verifiche guest/destinazione rispettano il criterio di anzianità indicato",
|
||||
"stale": "{count} of {total} guests have no backup from the last 30 days",
|
||||
"noBackups": "No stored backup matches a guest on this node",
|
||||
"attention": "{count} verifiche guest/destinazione su {total} richiedono attenzione",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"stale": "{count} degli ospiti di {total} non hanno alcun backup dagli ultimi 30 giorni",
|
||||
"noBackups": "Nessun backup memorizzato corrisponde a un ospite su questo nodo",
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
},
|
||||
"nextStep": {
|
||||
"stale": "Scopri perché il lavoro ha smesso di produrre copie per questi ospiti: potrebbe essere stato disabilitato, il suo programma potrebbe non sparare, o le sue piste potrebbero essere in fallimento. I risultati dell'esecuzione controllano i rapporti come ogni lavoro è finito.",
|
||||
@@ -5317,10 +5370,10 @@
|
||||
"rationale": "La ritenzione come la risolve Proxmox: impostazione del processo, poi dello storage, poi il valore predefinito del nodo. La ritenzione applicata da un server di backup non è leggibile da questo nodo.",
|
||||
"summary": {
|
||||
"allDefined": "Tutti i {total} processi risolvono un'impostazione di ritenzione",
|
||||
"missing": "{count} of {total} enabled job(s) declare no retention",
|
||||
"notDeclared": "{count} processi su {total} conservano ogni copia: non hanno una ritenzione dichiarata",
|
||||
"onServer": "{count} processi su {total} scrivono su un server di backup, che le pota con i propri processi",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"missing": "{count} di {total} abilitato lavori(i) non dichiarano nessuna ritenzione",
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
},
|
||||
"nextStep": {
|
||||
"missing": "Impostare una ritenzione su questi lavori, o sullo storage a cui scrivono. Proxmox prende l'impostazione del lavoro prima, poi lo storage è, poi il nodo predefinito.",
|
||||
@@ -5383,36 +5436,36 @@
|
||||
"summary": {
|
||||
"none": "Nulla ha richiesto un riavvio",
|
||||
"pending": "{count} elementi sono installati e attendono un riavvio",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
},
|
||||
"enterprise_repo_without_subscription": {
|
||||
"title": "Enterprise repository",
|
||||
"rationale": "Riferimenti a `enterprise.proxmox.com` in `/etc/apt/sources.list` e `sources.list.d`, rispetto allo stato restituito da `pvesubscription get`.",
|
||||
"summary": {
|
||||
"notEnabled": "The enterprise repository is not enabled",
|
||||
"subscribed": "The enterprise repository is backed by a subscription",
|
||||
"unsubscribed": "The enterprise repository is enabled without an active subscription",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"notEnabled": "Il repository enterprise non è abilitato",
|
||||
"subscribed": "Il repository enterprise è supportato da un abbonamento",
|
||||
"unsubscribed": "Il repository enterprise è abilitato senza un abbonamento attivo",
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
},
|
||||
"memory_overcommit": {
|
||||
"title": "Memory allocation",
|
||||
"rationale": "Il tetto `memory` di ogni configurazione guest rispetto a MemTotal, con i guest in esecuzione conteggiati a parte. I container consumano fino a quel limite; le macchine virtuali senza ballooning lo riservano.",
|
||||
"summary": {
|
||||
"withinRatio": "Guests are allocated {percent}% of host memory",
|
||||
"aboveRatio": "Guests are allocated {percent}% of host memory",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"withinRatio": "Gli ospiti sono assegnati {percent}% della memoria host",
|
||||
"aboveRatio": "Gli ospiti sono assegnati {percent}% della memoria host",
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
},
|
||||
"time_synchronisation": {
|
||||
"title": "Time synchronisation",
|
||||
"rationale": "NTP e NTPSynchronized come li riporta `timedatectl`. L'appartenenza al cluster, la validazione dei certificati e l'ordine dei log dipendono da orologi concordi. Un altro meccanismo può regolare l'orologio.",
|
||||
"summary": {
|
||||
"synchronised": "The clock is synchronised with a time source",
|
||||
"disabled": "Time synchronisation is disabled",
|
||||
"notSynchronised": "Time synchronisation is enabled but the clock is not synchronised",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"synchronised": "L'orologio è sincronizzato con una fonte di tempo",
|
||||
"notSynchronised": "La sincronizzazione del tempo è abilitata ma l'orologio non è sincronizzato",
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
},
|
||||
"kernel_current": {
|
||||
@@ -5420,21 +5473,21 @@
|
||||
"rationale": "Il kernel in esecuzione rispetto a quello che l'host avvierebbe successivamente, come lo riporta `proxmox-boot-tool`. Un kernel più recente solo installato può essere trattenuto di proposito; una differenza dopo un riavvio indica un avvio che non ha avuto effetto.",
|
||||
"summary": {
|
||||
"current": "Il kernel in esecuzione {version} è quello che l'host avvierebbe successivamente",
|
||||
"newerAvailable": "The host runs {running} while {newest} is installed",
|
||||
"newerSelected": "L'host esegue {running} e avvierebbe {selected} al prossimo riavvio",
|
||||
"wouldDowngrade": "L'host esegue {running} ma avvierebbe il più vecchio {selected} al prossimo riavvio",
|
||||
"bootTargetUnknown": "L'host esegue {version}; non è stato possibile leggere il kernel scelto per il prossimo avvio",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"newerAvailable": "L'host esegue {running} mentre {newest} è installato",
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
},
|
||||
"security_updates": {
|
||||
"title": "Security updates",
|
||||
"rationale": "Pacchetti in sospeso la cui origine è un repository di sicurezza, da un `apt-get upgrade` simulato. Il numero riflette quanto riporta apt, non la gravità di ciò che ogni pacchetto corregge.",
|
||||
"summary": {
|
||||
"none": "No package updates are pending",
|
||||
"noSecurity": "{total} update(s) pending, none from a security repository",
|
||||
"pending": "{count} of {total} pending update(s) come from a security repository",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"none": "Nessun aggiornamento dei pacchetti sono in sospeso",
|
||||
"noSecurity": "{total} update(s) in attesa, nessuno da un repository di sicurezza",
|
||||
"pending": "{count} di {total} in attesa di aggiornamenti(i) provengono da un repository di sicurezza",
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
},
|
||||
"journal_size": {
|
||||
@@ -5442,10 +5495,10 @@
|
||||
"rationale": "Il journal su disco rispetto al tetto che gli si applica: SystemMaxUse quando è impostato, altrimenti il predefinito di journald, un decimo del filesystem su cui risiede.",
|
||||
"summary": {
|
||||
"bounded": "Il journal occupa {size}, entro il suo tetto effettivo",
|
||||
"large": "The journal holds {size} on disk",
|
||||
"nearCap": "Il journal occupa {size} ed è al {percent}% del suo tetto effettivo",
|
||||
"capUnknown": "Il journal occupa {size}; non è stato possibile determinarne il tetto effettivo",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"large": "La rivista contiene {size} su disco",
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
},
|
||||
"swap_configured": {
|
||||
@@ -5454,7 +5507,7 @@
|
||||
"summary": {
|
||||
"active": "{size} of swap is active",
|
||||
"none": "No swap area is active",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
},
|
||||
"filesystem_capacity": {
|
||||
@@ -5500,7 +5553,7 @@
|
||||
"summary": {
|
||||
"synchronised": "Le {total} partizioni di avvio portano gli stessi kernel",
|
||||
"attention": "{count} di {total} partizioni di avvio richiedono una revisione",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
},
|
||||
"rationale": "I report sulle partizioni di sistema EFI proxmox-boot-tool e i kernel che ciascuna trasporta. Lo stato proxmox-boot-tool può montare temporaneamente partizioni di sistema EFI; non viene tentato alcun avvio."
|
||||
},
|
||||
@@ -5510,7 +5563,7 @@
|
||||
"summary": {
|
||||
"allRunning": "I {total} servizi essenziali sono attivi e nessuna unità è fallita",
|
||||
"attention": "{count} rilievo/i tra le unità",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
},
|
||||
"ha_state": {
|
||||
@@ -5519,7 +5572,7 @@
|
||||
"summary": {
|
||||
"managed": "I {total} servizi gestiti sono in uno stato assestato su {nodes} nodo/i",
|
||||
"attention": "{count} rilievo/i su {total} servizio/i gestito/i",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5528,27 +5581,27 @@
|
||||
"title": "Container privileges",
|
||||
"rationale": "L'impostazione `unprivileged` di ogni configurazione container. La sua assenza significa che il container condivide lo spazio dei nomi utente dell'host, cosa che alcuni carichi richiedono.",
|
||||
"summary": {
|
||||
"allUnprivileged": "All {total} containers are unprivileged",
|
||||
"privileged": "{count} of {total} containers run privileged",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"allUnprivileged": "Tutti i contenitori {total} non sono privati",
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
},
|
||||
"qemu_without_agent": {
|
||||
"title": "Guest agent on virtual machines",
|
||||
"rationale": "L'impostazione `agent` nella configurazione di ogni macchina virtuale. L'impostazione indica che l'agente è dichiarato, non che risponda.",
|
||||
"summary": {
|
||||
"allHaveAgent": "All {total} virtual machines declare the guest agent",
|
||||
"missingAgent": "{count} of {total} virtual machines do not declare the guest agent",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
}
|
||||
"allHaveAgent": "Tutte le macchine virtuali {total} dichiarano l'agente ospite",
|
||||
"missingAgent": "{count} delle macchine virtuali {total} non dichiarano l'agente ospite",
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
},
|
||||
"title": "Agente ospite su macchine virtuali"
|
||||
},
|
||||
"autostart": {
|
||||
"title": "Automatic start",
|
||||
"rationale": "L'impostazione `onboot` di ogni guest, esclusi i template e i guest gestiti da HA. Se un guest debba tornare da solo lo indica la politica dichiarata.",
|
||||
"summary": {
|
||||
"allAutostart": "All {total} guests start with the host",
|
||||
"notAutostart": "{count} of {total} guests do not start with the host",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"allAutostart": "Tutti gli ospiti {total} iniziano con l'host",
|
||||
"notAutostart": "{count} degli ospiti di {total} non iniziano con l'host",
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
},
|
||||
"stuck_snapshots": {
|
||||
@@ -5556,28 +5609,28 @@
|
||||
"rationale": "Stato e anzianità degli snapshot e attività in corso. Un'operazione recente o senza data verificabile non è considerata interrotta.",
|
||||
"summary": {
|
||||
"noSnapshots": "No guest holds snapshots",
|
||||
"allComplete": "The {total} snapshot(s) are complete",
|
||||
"stuck": "{count} of {total} snapshot(s) were left mid-operation",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"allComplete": "Le snapshot {total} sono complete",
|
||||
"stuck": "{count} di {total} snapshot(s) sono stati lasciati a metà operazione",
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
},
|
||||
"cpu_host_type": {
|
||||
"title": "Virtual CPU model",
|
||||
"rationale": "Il valore `cpu` di ogni macchina virtuale. `host` espone il set di istruzioni del processore fisico, il che limita i nodi verso cui il guest può migrare. L'incompatibilità con una destinazione precisa non viene determinata qui.",
|
||||
"summary": {
|
||||
"none": "None of the {total} virtual machines is pinned to the host processor",
|
||||
"pinned": "{count} of {total} virtual machines are pinned to the host processor",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"none": "Nessuna delle macchine virtuali {total} è fissata al processore host",
|
||||
"pinned": "Le macchine virtuali {count} di {total} sono fissate al processore host",
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
},
|
||||
"replication_state": {
|
||||
"title": "Replication",
|
||||
"rationale": "Processi di replica dalle API: numero di errori, ultimo errore, ultima sincronizzazione e il calendario dichiarato da ciascun processo. I processi in pausa sono indicati come tali.",
|
||||
"summary": {
|
||||
"healthy": "The {total} replication job(s) report no error",
|
||||
"failing": "{count} of {total} replication job(s) report an error",
|
||||
"statusUnavailable": "Replication jobs are defined but their status could not be read",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"healthy": "Il lavoro di replica {total} non segnala errore",
|
||||
"failing": "{count} del lavoro di replica {total} segnala un errore",
|
||||
"statusUnavailable": "I lavori di replica sono definiti ma il loro stato non può essere letto",
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5589,39 +5642,39 @@
|
||||
"bothEnabled": "L'attivazione del firewall è configurata a livello di datacenter e nodo",
|
||||
"datacenterOff": "Il firewall è disattivato a livello di datacenter, quindi le regole del nodo non vengono applicate",
|
||||
"nodeOff": "Il firewall è attivato a livello di datacenter ma non su questo nodo",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
},
|
||||
"lynis_warnings": {
|
||||
"title": "Lynis warnings",
|
||||
"rationale": "Avvisi dell'ultimo audit di Lynis, ciascuno con il proprio identificatore di test, e l'età di quell'audit. Un audit viene eseguito solo se Lynis è installato e non esiste alcun report completo. I suggerimenti non sono inclusi.",
|
||||
"summary": {
|
||||
"none": "The last Lynis audit recorded no warnings",
|
||||
"found": "The last Lynis audit recorded {count} warning(s)",
|
||||
"incomplete": "The Lynis report is incomplete",
|
||||
"evaluationFailed": "The check could not be evaluated",
|
||||
"noneStale": "L'ultimo audit di Lynis non ha registrato avvisi, e il suo report ha {days} giorno/i",
|
||||
"foundStale": "L'ultimo audit di Lynis ha registrato {count} avviso/i, e il suo report ha {days} giorno/i"
|
||||
"foundStale": "L'ultimo audit di Lynis ha registrato {count} avviso/i, e il suo report ha {days} giorno/i",
|
||||
"none": "L'ultima verifica di Lynis non ha registrato avvisi",
|
||||
"found": "L'ultimo controllo di Lynis ha registrato {count} avvisi(i)",
|
||||
"incomplete": "La relazione Lynis è incompleta",
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
},
|
||||
"certificate_expiry": {
|
||||
"title": "Certificate validity",
|
||||
"rationale": "La data di scadenza del certificato che pveproxy serve da /etc/pve/local. Un certificato personalizzato ha la precedenza su quello generato da Proxmox.",
|
||||
"summary": {
|
||||
"valid": "The certificate is valid for {days} more day(s)",
|
||||
"expiring": "The certificate expires in {days} day(s)",
|
||||
"expired": "The certificate expired {days} day(s) ago",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"valid": "Il certificato è valido per {days} più giorno(i)",
|
||||
"expiring": "Il certificato scade in {days} day(s)",
|
||||
"expired": "Il certificato è scaduto {days} giorno(i) fa",
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
},
|
||||
"ssh_root_login": {
|
||||
"title": "SSH root access",
|
||||
"rationale": "PermitRootLogin nella configurazione effettiva di `sshd -T`, con i metodi di autenticazione a cui si combina. Proxmox viene consegnato con `yes`, che accetta una password.",
|
||||
"summary": {
|
||||
"password": "Root may sign in over SSH with a password",
|
||||
"keyOnly": "Root may sign in over SSH with a key only",
|
||||
"denied": "Root may not sign in over SSH",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"password": "Root può accedere a SSH con una password",
|
||||
"keyOnly": "Root può firmare in oltre SSH con una chiave solo",
|
||||
"denied": "La radice non può firmare su SSH",
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5630,9 +5683,9 @@
|
||||
"title": "Volume assignment",
|
||||
"rationale": "Volumi dei guest sullo storage locale rispetto ai riferimenti nelle configurazioni correnti, in sospeso e di snapshot. Backup, ISO e template restano fuori dal confronto. Un volume senza riferimento è un candidato alla verifica.",
|
||||
"summary": {
|
||||
"none": "No orphaned volumes were found",
|
||||
"found": "{count} volumi senza riferimenti nelle configurazioni esaminate",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"none": "Non sono stati trovati volumi orfani",
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
},
|
||||
"zfs_arc_max": {
|
||||
@@ -5640,21 +5693,21 @@
|
||||
"rationale": "Valori effettivi di c_min, c_max e dimensione dell'ARC, il parametro del modulo caricato e le impostazioni persistenti in /etc/modprobe.d. Un valore configurato a zero seleziona il predefinito del modulo; l'ARC è un tetto e la memoria che occupa è recuperabile.",
|
||||
"summary": {
|
||||
"bounded": "Il limite dell'ARC è il {percent}% della memoria dell'host, e la memoria che occupa è recuperabile",
|
||||
"high": "The ARC may use {percent}% of host memory",
|
||||
"unset": "The ARC has no explicit limit set",
|
||||
"conflicting": "{count} impostazioni dell'ARC non concordano tra loro",
|
||||
"pending": "Un'impostazione persistente dell'ARC differisce dal valore del modulo in esecuzione",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"high": "L'ARC può utilizzare {percent}% della memoria host",
|
||||
"unset": "L'ARC non ha un limite esplicito",
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
},
|
||||
"zfs_scrub_age": {
|
||||
"title": "ZFS scrub",
|
||||
"rationale": "L'ultimo scrub completato registrato da `zpool status` per ogni pool. Un resilver non è uno scrub. Un pool creato di recente non ha ancora avuto occasione di eseguirne uno.",
|
||||
"summary": {
|
||||
"recent": "The {total} pool(s) were scrubbed within the last 35 days",
|
||||
"overdue": "{count} of {total} pool(s) have not been scrubbed in 35 days",
|
||||
"neverScrubbed": "{count} pool(s) record no scrub",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"recent": "La piscina {total} è stata lavata negli ultimi 35 giorni",
|
||||
"overdue": "{count} della piscina {total} non sono stati ripuliti in 35 giorni",
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
},
|
||||
"thin_pool_overprovisioning": {
|
||||
@@ -5664,7 +5717,7 @@
|
||||
"withinRatio": "I {total} thin pool sono al di sotto delle soglie di verifica applicate",
|
||||
"aboveRatio": "{count} thin pool su {total} distribuiscono più capacità di quella che possiedono",
|
||||
"pressure": "{pressure} thin pool su {total} sono vicini a riempire dati o metadati",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
},
|
||||
"connected_storage": {
|
||||
@@ -5673,7 +5726,7 @@
|
||||
"summary": {
|
||||
"available": "PVE indica tutti i {total} archivi come disponibili; i componenti interni remoti e l'accesso in scrittura non sono stati verificati",
|
||||
"attention": "{count} archivi su {total} richiedono una verifica",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
},
|
||||
"pool_integrity": {
|
||||
@@ -5691,7 +5744,7 @@
|
||||
"summary": {
|
||||
"healthy": "Ceph riporta HEALTH_OK",
|
||||
"degraded": "Ceph riporta {state}, con {count} controllo/i nominato/i",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
},
|
||||
"array_integrity": {
|
||||
@@ -5700,7 +5753,7 @@
|
||||
"summary": {
|
||||
"intact": "I {total} array e mappe conservano la loro ridondanza",
|
||||
"degraded": "{count} di {total} array o mappe ne sono a corto",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5712,7 +5765,7 @@
|
||||
"withinLife": "Le {total} letture dei dischi non superano la soglia indicativa di cinque anni",
|
||||
"pastLife": "{count} di {total} letture dei dischi superano cinque anni di servizio",
|
||||
"noReadings": "Nessun disco espone contatori SMART utilizzabili ({skipped} senza letture)",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
},
|
||||
"disk_errors": {
|
||||
@@ -5729,23 +5782,22 @@
|
||||
"title": "Bond members",
|
||||
"rationale": "Lo stato MII di ogni membro del bond da /proc/net/bonding e quanti collegamenti restano. In active-backup un membro di riserva risulta attivo e non trasporta traffico.",
|
||||
"summary": {
|
||||
"allUp": "All members of the {total} bond(s) are up",
|
||||
"membersDown": "{count} bond member(s) are not up",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"allUp": "Tutti i membri delle obbligazioni {total} sono in aumento",
|
||||
"membersDown": "I membri delle obbligazioni {count} non sono aggiornati",
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
},
|
||||
"bridge_without_ports": {
|
||||
"title": "Bridge ports",
|
||||
"rationale": "La configurazione delle porte di ogni bridge. Un bridge senza porta fisica serve una rete interna o instradata.",
|
||||
"summary": {
|
||||
"allConnected": "The {total} bridge(s) carry a port",
|
||||
"isolated": "{count} of {total} bridge(s) carry no port",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"allConnected": "Il ponte {total} porta una porta",
|
||||
"evaluationFailed": "Il controllo non potrebbe essere valutato"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"summaryFallback": "The check could not be evaluated",
|
||||
"acceptRisk": {
|
||||
"action": "Accetta il rischio",
|
||||
"revoke": "Riporta tra gli attivi",
|
||||
@@ -5779,17 +5831,15 @@
|
||||
"OK": "OK"
|
||||
},
|
||||
"viewSwitch": {
|
||||
"ariaLabel": "Switch between assessment and inventory",
|
||||
"assessment": "Assessment",
|
||||
"inventory": "Inventory",
|
||||
"policy": "Politica",
|
||||
"changes": "Modifiche"
|
||||
"changes": "Modifiche",
|
||||
"ariaLabel": "Interruttore tra valutazione e inventario"
|
||||
},
|
||||
"inventory": {
|
||||
"loading": "Loading inventory…",
|
||||
"failed": "The inventory could not be composed.",
|
||||
"collectedAt": "Composed on {when}",
|
||||
"unavailable": "Not read in this inventory",
|
||||
"unresolved": "path not resolved",
|
||||
"noUplink": "no uplink",
|
||||
"identity": "Node identity",
|
||||
@@ -5832,12 +5882,10 @@
|
||||
"protection": "Backup",
|
||||
"passthrough": "Passthrough",
|
||||
"noBackup": "No backup",
|
||||
"noBackupDetail": "No enabled backup job selects this guest.",
|
||||
"applications": "Applications",
|
||||
"versionUnknown": "version not detected",
|
||||
"passthroughTitle": "PCI passthrough",
|
||||
"iommuGroup": "IOMMU group {group}",
|
||||
"sharedGroup": "{count} more device(s) in the same group",
|
||||
"proxmenux": "ProxMenux optimizations",
|
||||
"latency": "Latenza di rete",
|
||||
"subscriptionStatus": {
|
||||
@@ -5848,7 +5896,11 @@
|
||||
"suspended": "Sospeso",
|
||||
"new": "In attesa di attivazione",
|
||||
"unknown": "Sconosciuto"
|
||||
}
|
||||
},
|
||||
"failed": "L'inventario non poteva essere composto.",
|
||||
"unavailable": "Non leggere in questo inventario",
|
||||
"noBackupDetail": "Nessun lavoro di backup abilitato seleziona questo guest.",
|
||||
"sharedGroup": "{count} più dispositivo(i) nello stesso gruppo"
|
||||
},
|
||||
"profile": {
|
||||
"label": "Report",
|
||||
@@ -5871,7 +5923,6 @@
|
||||
"area": "Area",
|
||||
"inventoryAnnex": "Inventory annex",
|
||||
"scopeTitle": "Scope of this report",
|
||||
"scopeBody": "This report describes the Proxmox VE node named above, as observed from the node itself at the time stated. It does not cover the interior of the guests beyond what they declare, network equipment outside the host, physical infrastructure, or any dependency not visible from this node. Findings marked as not determined were not measured and are not evidence of absence.",
|
||||
"building": "Composizione del rapporto…",
|
||||
"node": "Nodo",
|
||||
"profile": "Profilo",
|
||||
@@ -6020,11 +6071,12 @@
|
||||
"structureSubtitle": "Com'è costruito e configurato {node}",
|
||||
"postureTitle": "Posture",
|
||||
"posture": {
|
||||
"security": "Host exposure and access.",
|
||||
"backup": "Guest protection and whether it is real.",
|
||||
"capacity": "Room to grow and the wear on the disks."
|
||||
"security": "Esposizione e accesso host.",
|
||||
"backup": "Protezione degli ospiti e se è reale.",
|
||||
"capacity": "Stanza per crescere e l'usura sui dischi."
|
||||
},
|
||||
"scopeReadOnly": "La valutazione esamina le impostazioni e l'integrità dell'host. Può scrivere report e log; i controlli dello stato di avvio possono montare temporaneamente partizioni di sistema EFI."
|
||||
"scopeReadOnly": "La valutazione esamina le impostazioni e l'integrità dell'host. Può scrivere report e log; i controlli dello stato di avvio possono montare temporaneamente partizioni di sistema EFI.",
|
||||
"scopeBody": "Questo rapporto descrive il nodo VE Proxmox sopra indicato, come osservato dal nodo stesso al momento indicato. Non copre l'interno degli ospiti al di là di quanto dichiarano, apparecchiature di rete al di fuori dell'host, infrastrutture fisiche, o qualsiasi dipendenza non visibile da questo nodo. I risultati contrassegnati come non determinati non sono stati misurati e non sono prove di assenza."
|
||||
},
|
||||
"results": "Risultati",
|
||||
"classifications": {
|
||||
@@ -6178,15 +6230,19 @@
|
||||
"notApplicableScope": "Nulla nell'ambito esaminato a cui questo controllo si applichi.",
|
||||
"lynis": {
|
||||
"title": "Run Lynis",
|
||||
"bodyNotRun": "Lynis is installed but has not been run yet. Running it now completes the security review, but the process can take a few minutes.",
|
||||
"bodyStale": "The Lynis report is {days} days old. You can run it now to refresh the data (it takes a little longer) or continue with the existing report.",
|
||||
"withLynis": "Run with Lynis",
|
||||
"withoutLynis": "Run without Lynis",
|
||||
"cancel": "Cancel"
|
||||
"cancel": "Cancel",
|
||||
"bodyNotRun": "Lynis è installato ma non è stato ancora eseguito. L'esecuzione ora completa la revisione di sicurezza, ma il processo può richiedere alcuni minuti.",
|
||||
"bodyStale": "Il rapporto Lynis è {days} giorni. È possibile eseguire ora per aggiornare i dati (ci vuole un po 'di più) o continuare con il rapporto esistente."
|
||||
},
|
||||
"readOnlyNotice": "La valutazione esamina le impostazioni e l'integrità dell'host. Può scrivere report e log; i controlli dello stato di avvio possono montare temporaneamente partizioni di sistema EFI.",
|
||||
"noActionNeeded": "Niente da fare. Questo assegno ha trovato quello che si aspetta di trovare.",
|
||||
"couldNotEvaluate": "Questo controllo non può essere valutato, quindi non segnala nulla in entrambi i casi. Le prove riportano ciò che non era in grado di leggere."
|
||||
"couldNotEvaluate": "Questo controllo non può essere valutato, quindi non segnala nulla in entrambi i casi. Le prove riportano ciò che non era in grado di leggere.",
|
||||
"neverRun": "Questo host non è stato ancora valutato.",
|
||||
"noFindings": "Nessun risultato corrisponde al filtro corrente.",
|
||||
"acceptedNotice": "{count} ha accettato i rischi registrati su questo host.",
|
||||
"summaryFallback": "Il controllo non potrebbe essere valutato"
|
||||
},
|
||||
"runtime": {
|
||||
"notifications": {
|
||||
|
||||
+193
-137
@@ -1069,7 +1069,8 @@
|
||||
"backups": "Cópias de segurança",
|
||||
"updates": "Atualizações",
|
||||
"firewall": "Firewall",
|
||||
"app": "Aplicativo"
|
||||
"app": "Aplicativo",
|
||||
"logs": "Logs"
|
||||
},
|
||||
"actions": {
|
||||
"start": "Começar",
|
||||
@@ -1169,6 +1170,44 @@
|
||||
"empty": "Nenhum evento de firewall registrado ainda.",
|
||||
"emptyHint": "Regras com log: info ou superior preencherão esta visualização conforme os pacotes chegam."
|
||||
},
|
||||
"consoleLog": {
|
||||
"title": "Saída da consola",
|
||||
"description": "Saída padrão e de erro do processo principal da imagem.",
|
||||
"stopped": "O contentor está parado; o log conserva a saída das execuções anteriores.",
|
||||
"lastLines": "Últimas {count} linhas",
|
||||
"follow": "Seguir",
|
||||
"pause": "Pausar",
|
||||
"refresh": "Atualizar",
|
||||
"download": "Transferir",
|
||||
"filter": "Filtrar linhas",
|
||||
"loading": "A carregar a saída da consola...",
|
||||
"empty": "Ainda não há saída registada.",
|
||||
"emptyHint": "As linhas aparecem aqui à medida que o contentor escreve na sua consola.",
|
||||
"noMatches": "Nenhuma linha corresponde ao filtro.",
|
||||
"readFailed": "Não foi possível ler o log da consola",
|
||||
"notAvailableTitle": "Este contentor não tem log da consola",
|
||||
"notAvailableHint": "O log da consola é configurado quando o ProxMenux instala o contentor a partir da sua imagem OCI."
|
||||
},
|
||||
"ociUpdates": {
|
||||
"notTracked": "Ao registar a aplicação no separador App, a sua imagem é acompanhada aqui.",
|
||||
"installedImage": "Imagem instalada",
|
||||
"newImage": "Nova imagem {image} disponível",
|
||||
"stackNote": "Faz parte de uma aplicação com vários contentores (CT principal {primary}, {count} contentores): a atualização abrange todos.",
|
||||
"pendingNote": "Uma operação neste contentor foi interrompida; Recuperar abre a sua recuperação.",
|
||||
"update": "Atualizar",
|
||||
"recreate": "Recriar",
|
||||
"recover": "Recuperar",
|
||||
"terminalTitleUpdate": "Atualizar aplicação OCI",
|
||||
"terminalTitleRecreate": "Recriar aplicação OCI",
|
||||
"terminalDescription": "O mesmo percurso de OCI manager Apps → Gerir aplicações OCI instaladas.",
|
||||
"keepBackup": "Manter o backup feito antes da atualização",
|
||||
"noKeepBackup": "O backup feito antes da atualização não é mantido",
|
||||
"keepBackupHelp": "Cada atualização faz um backup do contentor antes de substituir a sua imagem, para o restaurar se a atualização falhar. Com esta opção esse backup é mantido no armazenamento escolhido; no Proxmox Backup Server é escrito um backup antes da atualização.",
|
||||
"scheduleHelp": "Só a imagem é atualizada, e apenas quando o seu registo publica uma nova.",
|
||||
"releaseDelayHelp": "Uma imagem nova só é instalada quando tem pelo menos esta idade.",
|
||||
"ackExternal": "Os diretórios do host não são revertidos pelo backup",
|
||||
"ackExternalHelp": "Este contentor usa diretórios do host. Uma atualização agendada só é executada com esta confirmação."
|
||||
},
|
||||
"options": {
|
||||
"title": "Opções",
|
||||
"snapshotBefore": "Instantâneo antes de aplicar",
|
||||
@@ -1429,6 +1468,14 @@
|
||||
"loadFailed": "não foi possível carregar a configuração de atualização em massa."
|
||||
},
|
||||
"appEditor": {
|
||||
"methodOciImage": "Imagem OCI (instalada pelo ProxMenux)",
|
||||
"ociImageHelp": "A versão e as suas atualizações são lidas da imagem a partir da qual este contentor foi criado. O ProxMenux instalou-o, pelo que não há nada a configurar: a imagem instalada é comparada com a que o seu registo publica hoje.",
|
||||
"ociAppVersion": "Aplicação",
|
||||
"ociImage": "Imagem",
|
||||
"ociNewImage": "Nova imagem",
|
||||
"ociImageCurrent": "Versão",
|
||||
"refreshData": "Atualizar dados",
|
||||
"refreshingData": "A atualizar…",
|
||||
"dockerDetectedWithWorkloads": "Docker detetado com {count} aplicações em contentores",
|
||||
"dockerWorkloadsHeading": "Aplicações no Docker",
|
||||
"runsInsideDocker": "Atualizada através da sua imagem Docker",
|
||||
@@ -1487,7 +1534,6 @@
|
||||
"containerNameLabel": "Nome do contêiner",
|
||||
"containerNamePlaceholder": "por exemplo, <seu-nome-do-contêiner>",
|
||||
"ociLabelKeyLabel": "Chave de rótulo OCI",
|
||||
"ociLabelPlaceholder": "org.opencontainers.image.version",
|
||||
"pythonInterpreterLabel": "Caminho do interpretador Python",
|
||||
"pythonInterpreterPlaceholder": "por exemplo, /opt/<seu-app>/venv/bin/python",
|
||||
"pipDistLabel": "Nome da distribuição (pacote pip)",
|
||||
@@ -1534,11 +1580,8 @@
|
||||
"portHttps": "https",
|
||||
"portLogoLabel": "URL do logotipo deste link (opcional)",
|
||||
"portLogoPlaceholder": "por exemplo, https://example.com/logo.webp",
|
||||
"portCategoryPlaceholder": "Category for the Apps dashboard (optional)",
|
||||
"portCategoryNone": "No category",
|
||||
"portCategoryAddNew": "+ Add new category…",
|
||||
"portCategoryCustomPlaceholder": "Type a category and press Enter (Esc to cancel)",
|
||||
"portCustomUrlPlaceholder": "Custom URL (e.g. https://vault.example.com) — overrides IP:port",
|
||||
"removePortTooltip": "Remover porta",
|
||||
"detectMethodDpkg": "dpkg ·",
|
||||
"detectMethodApk": "APK ·",
|
||||
@@ -1631,7 +1674,11 @@
|
||||
"notifyUpstreamLabel": "Notifique-me quando uma nova versão upstream estiver disponível",
|
||||
"notifyUpstreamHelp": "Envia `app_update_available` para os canais habilitados em Configurações → Notificações. Desligue se este aplicativo não puder ser atualizado em sua caixa.",
|
||||
"excludeFromBadgeLabel": "Excluir do contador de atualizações LXC",
|
||||
"excludeFromBadgeHelp": "não conte este aplicativo no selo de atualizações agregadas no cartão de lista LXC.Útil quando você está fixado em uma versão específica propositalmente (requisito do rastreador, congelamento de compatibilidade).Não afeta o próprio estado da guia Aplicativo ou a notificação de saída."
|
||||
"excludeFromBadgeHelp": "não conte este aplicativo no selo de atualizações agregadas no cartão de lista LXC.Útil quando você está fixado em uma versão específica propositalmente (requisito do rastreador, congelamento de compatibilidade).Não afeta o próprio estado da guia Aplicativo ou a notificação de saída.",
|
||||
"ociLabelPlaceholder": "org.opencontainers.image.version",
|
||||
"portCategoryPlaceholder": "Categoria para o painel de aplicativos (opcional)",
|
||||
"portCategoryCustomPlaceholder": "Digite uma categoria e pressione Enter (Esc para cancelar)",
|
||||
"portCustomUrlPlaceholder": "URL personalizada (por exemplo, https://vault.example.com) — substitui IP:port"
|
||||
},
|
||||
"statusFilter": {
|
||||
"ariaLabel": "Filtrar máquinas virtuais e contêineres",
|
||||
@@ -2515,10 +2562,10 @@
|
||||
"scope": {
|
||||
"label": "Token permissions",
|
||||
"readOnly": "Read-only",
|
||||
"readOnlyHint": "Reads metrics and status. Recommended for dashboards and integrations.",
|
||||
"fullAdmin": "Full admin",
|
||||
"fullAdminHint": "Full control, like your own session.",
|
||||
"fullAdminWarning": "A full-admin token can do everything you can: power off or reboot the host, run updates and open a terminal. Share it only with fully trusted integrations."
|
||||
"readOnlyHint": "Lê métricas e status. Recomendado para painéis e integrações.",
|
||||
"fullAdminHint": "Controle total, como a sua própria sessão.",
|
||||
"fullAdminWarning": "Um token de administração completa pode fazer tudo que puder: desligar ou reiniciar o host, executar atualizações e abrir um terminal. Compartilhe-o apenas com integrações totalmente confiáveis."
|
||||
}
|
||||
},
|
||||
"firewall": {
|
||||
@@ -3302,26 +3349,33 @@
|
||||
"gotIt": "Entendi!",
|
||||
"dontShowAgain": "Não mostrar novamente para esta versão",
|
||||
"currentFeatures": {
|
||||
"appDetection": "Smarter app detection in the App tab: Docker is correctly promoted as the parent workload during cold start (Portainer/SearXNG no longer briefly show up as native apps), unregistered suggestions live in the startup cache, and 'Find applications' runs a fresh catalog-backed scan on demand.",
|
||||
"dockerUpdates": "The Updates tab now covers Docker end-to-end: Docker Engine and per-image update tracking follow the same 24-hour rolling cycle as OS packages, with a 'Check now' action for on-demand digest comparison — no more waiting for the daily collector.",
|
||||
"appCatalog": "New application detection catalog with over 380 tracked workloads, generated live from community-scripts across seven detector methods (file, binary, dpkg, apk, Python, Docker exec, Docker label). Primary and fallback detectors cover both new and historical LXC layouts.",
|
||||
"pushover": "Pushover joins Telegram, Gotify, Discord, Email and Apprise as a native notification channel — user/API key, device and sound selectors, priority 0 for regular messages, optional priority 1 for CRITICAL events. Suggested by @benginx (#308).",
|
||||
"appsDashboard": "New top-level Apps dashboard — a single launcher for every Web Link across the node. LXC-registered apps and user-defined Custom Web Links share the same grid with category badges, search, and one-click deep-links back to the guest modal.",
|
||||
"lxcAppsUpdates": "App tab inside every LXC modal registers installed apps, captures weblinks and tracks upstream versions. Reworked Updates tab applies OS packages and app updates from a single button; Docker Engine and per-image tracking follow the same 24-hour cycle, with a 'Check now' action on demand.",
|
||||
"multilingual": "The Monitor now speaks 8 languages: English, Spanish, German, French, Italian, Portuguese, Swedish and Slovak. Huge thanks to @vaso73 for building the i18n scaffolding that made this possible.",
|
||||
"nvidiaMultiGpu": "NVIDIA driver lifecycle moves to per-BDF ownership so a multi-GPU host can pass one card to a VM and keep the other operational on the host or in LXCs, plus a kernel + branch + GPU-aware version picker (#298).",
|
||||
"aiCustomEndpoint": "AI Assistant custom OpenAI endpoint — LiteLLM, LM Studio, LocalAI, vLLM, OmniRoute and any self-hosted proxy on private IPs, loopback or Docker networks are recognised when loading the model catalogue. The dropdown surfaces the server's error (or the underlying network reason) directly under the Load button (#325, reported by @jorgeffonte).",
|
||||
"secureGatewayArch": "Secure Gateway wizard — the Alpine template download, local template selection and pct create all match the host's real architecture, so x86_64 hosts receive amd64 containers and arm64 hosts receive arm64 containers (#324, reported by @N0X4DD0).",
|
||||
"atomicNotifications": "Notification events reserve their deduplication fingerprint atomically before AI processing and channel delivery, so concurrent collectors, completion callbacks or parallel Monitor processes cannot send the same event twice. The reservation is released when no channel succeeds, preserving retries.",
|
||||
"borgSshPort": "Borg remote target — the Add Borg destination dialog and the shell TUI accept a custom SSH port. BORG_RSH, the auto key install flow and the capacity probe all honour it. Fully backwards compatible with existing entries created without an explicit port (suggested by @songochain in discussion #236).",
|
||||
"githubToken": "Settings → GitHub API accepts an optional personal access token for release and tag checks when the anonymous quota is exhausted. The token is encrypted at rest and never returned to the browser; the rate-limit error is translated in every Monitor language (suggested by @SystemIdleProcess in discussion #306).",
|
||||
"replicationContext": "Native Proxmox replication failure notifications resolve the replication job ID, affected VM/LXC ID and guest name; the exact error block from Proxmox is preserved as the reason, and each replication job deduplicates independently (reported by Ale R.).",
|
||||
"auditAssessment": "Audit & Report — a new page that documents and assesses the node. The Assessment runs a catalogue of checks across security, backups, capacity, storage, network, hardware, guests and system, classifying each finding as critical, warning, observation or conformant and stating what it read rather than judging it.",
|
||||
"changeJournal": "Change journal — a Changes view that lists exactly what ProxMenux modified on this host: every configuration file, package and service it touched, with the prior state of each, deduplicated to a current-state view that shows the host as it stands now rather than a log of every run.",
|
||||
"auditReports": "Reports — a full audit plus focused Security review, Backup assurance and Capacity & wear reports, each opening on its own posture header, and a printable Inventory; all export to PDF. A security assessment asks before running Lynis so a run stays fast.",
|
||||
"auditPolicyBaseline": "Policy and baseline — declare what the host is expected to be (backup requirements, firewall, root SSH login) so findings grade against it, mark a run as the reference, and see what changed since, with new, resolved and accepted findings kept apart.",
|
||||
"groupedAppUpdates": "Grouped application update notifications — one complete message per scan instead of one per application, grouped by LXC with the installed and available versions.",
|
||||
"adminTokenScope": "Administrative scope — opening a Monitor terminal and disabling authentication now require a full-admin token, so a read-only API token issued to a monitoring integration stays read-only (reported by @f3rs3n)."
|
||||
"appDetection": "Detecção de aplicativos mais inteligente na aba App: Docker é corretamente promovido como a carga de trabalho pai durante o início frio (Portainer/SearXNG já não aparece brevemente como aplicativos nativos), sugestões não registradas ao vivo no cache de inicialização, e 'Find applications' executa uma nova varredura baseada em catálogo sob demanda.",
|
||||
"dockerUpdates": "A página Atualizações agora cobre o Docker de ponta a ponta: Docker O rastreamento de atualização do motor e por imagem segue o mesmo ciclo de rolamento de 24 horas que os pacotes OS, com uma ação 'Check now' para comparação de digest sob demanda – sem mais esperar pelo coletor diário.",
|
||||
"appCatalog": "Novo catálogo de detecção de aplicativos com mais de 380 cargas de trabalho rastreadas, geradas ao vivo a partir de scripts comunitários em sete métodos de detector (ficheiro, binário, dpkg, apk, Python, Docker exec, etiqueta Docker). Os detectores primários e de retorno cobrem layouts LXC novos e históricos.",
|
||||
"pushover": "Pushover junta-se ao Telegram, Gotify, Discord, Email e Apprise como um canal de notificação nativo — chave de usuário/API, seletores de som e dispositivo, prioridade 0 para mensagens regulares, prioridade opcional 1 para eventos CRITICAIS. Sugerido por @benginx (# 308).",
|
||||
"appsDashboard": "Novo painel de topo de Apps — um único lançador para cada Web Link em todo o nó. Aplicativos registrados em LXC e Web personalizada definida pelo usuário Links compartilham a mesma grade com crachás de categoria, pesquisa e links profundos de um clique de volta para o modal convidado.",
|
||||
"lxcAppsUpdates": "A guia App dentro de cada LXC registra aplicativos instalados, captura weblinks e rastreia versões upstream. A guia Atualizações retrabalhadas aplica pacotes OS e atualizações de aplicativos a partir de um único botão; o motor Docker e o rastreamento por imagem seguem o mesmo ciclo de 24 horas, com uma ação 'Cheque agora' sob demanda.",
|
||||
"multilingual": "O Monitor agora fala 8 línguas: inglês, espanhol, alemão, francês, italiano, português, sueco e eslovaco. Enormes graças a @vaso73 por construir o andaime i18n que tornou isso possível.",
|
||||
"nvidiaMultiGpu": "O ciclo de vida do driver NVIDIA se move para a propriedade por BDF para que um host multi-GPU possa passar um cartão para um VM e manter o outro operacional no host ou em LXCs, além de um kernel + branch + GPU-aware version picker (#298).",
|
||||
"aiCustomEndpoint": "AI Assistant custom OpenAI endpoint — LiteLLM, LM Studio, LocalAI, vLLM, OmniRoute e qualquer proxy self-hosted em IPs privados, loopback ou Docker redes são reconhecidas ao carregar o catálogo do modelo. A superfície dropdown do erro do servidor (ou a razão de rede subjacente) diretamente sob o botão Carregar (#325, relatado por @jorgeffonte).",
|
||||
"secureGatewayArch": "Assistente de Gateway seguro — o download do modelo alpino, seleção de modelos local e pct create todos correspondem à arquitetura real do host, então os hosts x86 64 recebem containers amd64 e os hosts arm64 recebem containers arm64 (#324, reportados por @N0X4DD0).",
|
||||
"atomicNotifications": "Eventos de notificação reservam sua impressão digital de deduplicação atomicamente antes do processamento de IA e entrega de canais, então coletores simultâneos, callbacks de conclusão ou processos de monitoramento paralelos não podem enviar o mesmo evento duas vezes. A reserva é liberada quando nenhum canal tem sucesso, preservando repetições.",
|
||||
"borgSshPort": "Alvo remoto Borg — a janela Adicionar destino Borg e o shell TUI aceitam uma porta SSH personalizada. BORG RSH, o fluxo de instalação da chave automática e a sonda de capacidade todos honram. Totalmente compatível com entradas existentes criadas sem uma porta explícita (sugerida por @songochain na discussão #236).",
|
||||
"githubToken": "Configurações → GitHub API aceita um token de acesso pessoal opcional para liberação e verificação de tags quando a quota anônima está esgotada. O token é criptografado em repouso e nunca retorna ao navegador; o erro de limite de taxa é traduzido em cada idioma Monitor (sugerido por @SystemIdleProcess em discussão #306).",
|
||||
"replicationContext": "As notificações de falha de replicação nativa do Proxmox resolvem o ID do trabalho de replicação, afeta o ID do VM/LXC e o nome do convidado; o bloco de erro exato do Proxmox é preservado como razão, e cada tarefa de replicação deduplica-se independentemente (referido por Ale R.).",
|
||||
"auditAssessment": "Auditoria & Relatório — uma nova página que documenta e avalia o nó. A Avaliação realiza um catálogo de verificações em segurança, backups, capacidade, armazenamento, rede, hardware, convidados e sistema, classificando cada achado como crítico, alerta, observação ou conforme e declarando o que leu em vez de julgá-lo.",
|
||||
"changeJournal": "Change journal — uma visão de mudanças que lista exatamente o que ProxMenux modificou nesta máquina: cada arquivo de configuração, pacote e serviço que tocou, com o estado anterior de cada um, deduplicado para uma visão de estado atual que mostra o host como ele está agora em vez de um log de cada execução.",
|
||||
"auditReports": "Relatórios – uma auditoria completa mais revisão de segurança focada, garantia de backup e relatórios de capacidade e desgaste, cada abertura em seu próprio cabeçalho postura, e um Inventário imprimível; todas as exportações para PDF. Uma avaliação de segurança pede antes de executar Lynis para que uma corrida seja rápida.",
|
||||
"auditPolicyBaseline": "Política e linha de base — declarar o que o host deve ser (requisitos de backup, firewall, login do root SSH) para que as descobertas classem contra ele, marque uma corrida como referência e veja o que mudou desde, com novas descobertas resolvidas e aceitas mantidas separadas.",
|
||||
"groupedAppUpdates": "Notificações de atualização de aplicativos agrupadas — uma mensagem completa por digitalização em vez de uma por aplicação, agrupadas por LXC com as versões instaladas e disponíveis.",
|
||||
"adminTokenScope": "Âmbito administrativo — abrir um terminal Monitor e desativar a autenticação agora requer um token de administração completa, então um token API somente para leitura emitido para uma integração de monitoramento permanece somente para leitura (referido por @f3rs3n).",
|
||||
"ociAppTab": "Contentores OCI no separador App — um contentor instalado pelo OCI manager Apps é reconhecido a partir do seu registo de instalação: a aplicação e a sua imagem, uma nova imagem detetada por digest e uma ligação ao repositório da imagem.",
|
||||
"ociUpdatesTab": "Atualizações de contentores OCI — Atualizar e Recriar abrem o mesmo percurso do menu OCI, o backup feito antes da atualização pode ser mantido num armazenamento de backups e a imagem pode ser atualizada de forma agendada.",
|
||||
"ociLogsTab": "Separador Logs para contentores OCI — a saída da consola da aplicação, guardada no host e acompanhada em direto, com filtro e transferência. A consola do Proxmox destes contentores abre uma shell.",
|
||||
"appsUpdateShortcut": "O ícone de atualização da página Apps abre o contentor diretamente no seu separador Atualizações.",
|
||||
"webhookHttps": "As notificações do Proxmox chegam ao Monitor com HTTPS ativo — são entregues num endereço apenas local e já não falham por um erro de certificado.",
|
||||
"persistentLogs": "Uma rajada de erros nos logs que terminou já não é apresentada como persistente: um padrão tem de continuar a aparecer durante 15 minutos, e o seu aviso fecha-se sozinho (reportado por @Joshua1264).",
|
||||
"mountsLanAddress": "Os pontos de montagem em LVM-thin e outros armazenamentos em bloco mostram a sua utilização, e as aplicações com vários contentores abrem no seu endereço LAN."
|
||||
}
|
||||
},
|
||||
"network": {
|
||||
@@ -5027,23 +5081,20 @@
|
||||
"uncategorized": "Uncategorized",
|
||||
"openAriaLabel": "Open {name} in a new tab",
|
||||
"openGuestAriaLabel": "Abrir {name} ({type} {id})",
|
||||
"emptyTitle": "No apps with a web link yet.",
|
||||
"emptyHint": "Register a Web Link for any app (App tab of a CT) to see it here.",
|
||||
"customLinkAdd": "Add link",
|
||||
"editModeToggle": "Edit",
|
||||
"editModeDone": "Done",
|
||||
"customLinkNewTitle": "New web link",
|
||||
"customLinkEditTitle": "Edit web link",
|
||||
"customLinkEditAria": "Editar o link personalizado {name}",
|
||||
"openUpdatesAria": "Abrir o separador Atualizações de {name}",
|
||||
"openUpdatesTitle": "Atualização disponível — abrir o separador Atualizações",
|
||||
"customLinkName": "Name",
|
||||
"customLinkNamePlaceholder": "e.g. My app",
|
||||
"customLinkUrl": "URL",
|
||||
"customLinkLogo": "Logo URL (optional)",
|
||||
"customLinkLogoPlaceholder": "e.g., https://example.com/logo.webp",
|
||||
"customLinkCategory": "Category (optional)",
|
||||
"customLinkBinding": "Bound to",
|
||||
"customLinkBindingNone": "Not bound to any guest",
|
||||
"customLinkBindingHelp": "Bind this link to a VM or CT to add its ID + name to the card and jump to the guest with one click.",
|
||||
"customLinkSave": "Save",
|
||||
"customLinkCreate": "Create",
|
||||
"customLinkCancel": "Cancel",
|
||||
@@ -5079,7 +5130,12 @@
|
||||
"remoteAccessVpn": "Remote Access & VPN",
|
||||
"webserversProxies": "Webservers & Proxies",
|
||||
"zigbeeZwaveMatter": "ZigBee, Z-Wave & Matter"
|
||||
}
|
||||
},
|
||||
"emptyTitle": "Nenhum aplicativo com um link web ainda.",
|
||||
"emptyHint": "Registre um Web Link para qualquer aplicativo (App tab de um CT) para vê-lo aqui.",
|
||||
"customLinkLogoPlaceholder": "Por exemplo, https://exemplo.com/logo.webp",
|
||||
"customLinkBindingNone": "Não está ligado a nenhum hóspede.",
|
||||
"customLinkBindingHelp": "Ligar este link a um VM ou CT para adicionar o seu ID + nome ao cartão e saltar para o hóspede com um clique."
|
||||
},
|
||||
"audit": {
|
||||
"presentation": {
|
||||
@@ -5234,13 +5290,10 @@
|
||||
"loading": "Loading assessment…",
|
||||
"run": "Run assessment",
|
||||
"running": "Assessing…",
|
||||
"neverRun": "This host has not been assessed yet.",
|
||||
"lastRun": "Last assessed on {when}",
|
||||
"stale": "{days} days ago",
|
||||
"unverifiedChecks": "Não obtidas: {checks}. Cada uma diz na sua evidência o que não conseguiu ler.",
|
||||
"noFindings": "No findings match the current filter.",
|
||||
"affectedCount": "{count} affected",
|
||||
"acceptedNotice": "{count} accepted risk(s) recorded on this host.",
|
||||
"reviewOn": "Rever em: {when}",
|
||||
"reviewDue": "A rever — a decisão continua em vigor",
|
||||
"reviewDueNotice": "{count} decisão(ões) aceite(s) aguardam revisão.",
|
||||
@@ -5272,7 +5325,7 @@
|
||||
"sources": "Fontes e datas de coleta"
|
||||
},
|
||||
"errors": {
|
||||
"runFailed": "The assessment could not be started."
|
||||
"runFailed": "A avaliação não pôde ser iniciada."
|
||||
},
|
||||
"checks": {
|
||||
"backup": {
|
||||
@@ -5285,7 +5338,7 @@
|
||||
"uncovered": "{count} de {total} convidados não são selecionados por nenhuma tarefa de backup ativa",
|
||||
"excludedData": "Há {count} exclusões de discos ou montagens para revisar",
|
||||
"uncoveredExpected": "{required} convidados declarados como necessitando backup não são selecionados por nenhuma tarefa ativa",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
},
|
||||
"nextStep": {
|
||||
"noJobs": "Crie uma tarefa de backup neste nó e selecione os convidados segurando dados que você não gostaria de reconstruir à mão. Uma tarefa que existe mas está desactivada não seleciona nada.",
|
||||
@@ -5300,10 +5353,10 @@
|
||||
"rationale": "Idade: tempo decorrido desde a última cópia armazenada. Limite utilizado: idade de referência com a qual essa cópia é comparada.",
|
||||
"summary": {
|
||||
"recent": "As {total} verificações de máquina/destino cumprem o critério de antiguidade indicado",
|
||||
"stale": "{count} of {total} guests have no backup from the last 30 days",
|
||||
"noBackups": "No stored backup matches a guest on this node",
|
||||
"attention": "{count} de {total} verificações de máquina/destino requerem revisão",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"stale": "{count} dos hóspedes do {total} não têm backup dos últimos 30 dias",
|
||||
"noBackups": "Nenhuma cópia de segurança armazenada corresponde a um convidado neste nó",
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
},
|
||||
"nextStep": {
|
||||
"stale": "Descubra por que o trabalho parou de produzir cópias para esses hóspedes: ele pode ter sido desativado, sua programação pode nunca disparar, ou suas corridas podem estar falhando. A verificação de resultados de execução relata como cada trabalho terminou pela última vez.",
|
||||
@@ -5317,10 +5370,10 @@
|
||||
"rationale": "A retenção tal como o Proxmox a resolve: definição da tarefa, depois do armazenamento, depois o valor por omissão do nó. A retenção aplicada por um servidor de backup não é legível a partir deste nó.",
|
||||
"summary": {
|
||||
"allDefined": "As {total} tarefas resolvem uma definição de retenção",
|
||||
"missing": "{count} of {total} enabled job(s) declare no retention",
|
||||
"notDeclared": "{count} de {total} tarefas guardam todas as cópias: não têm retenção declarada",
|
||||
"onServer": "{count} de {total} tarefas escrevem num servidor de backup, que as poda com as suas próprias tarefas",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"missing": "{count} do( s) trabalho( s) habilitado( s) {total} declaram não haver retenção",
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
},
|
||||
"nextStep": {
|
||||
"missing": "Defina uma retenção nesses trabalhos, ou no armazenamento para o qual eles escrevem. Proxmox toma a configuração do trabalho primeiro, depois o armazenamento, depois o padrão do nó.",
|
||||
@@ -5383,36 +5436,36 @@
|
||||
"summary": {
|
||||
"none": "Nada solicitou um reinício",
|
||||
"pending": "{count} elementos estão instalados e aguardam um reinício",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
},
|
||||
"enterprise_repo_without_subscription": {
|
||||
"title": "Enterprise repository",
|
||||
"rationale": "Referências a `enterprise.proxmox.com` em `/etc/apt/sources.list` e `sources.list.d`, face ao estado devolvido por `pvesubscription get`.",
|
||||
"summary": {
|
||||
"notEnabled": "The enterprise repository is not enabled",
|
||||
"subscribed": "The enterprise repository is backed by a subscription",
|
||||
"unsubscribed": "The enterprise repository is enabled without an active subscription",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"notEnabled": "O repositório da empresa não está habilitado",
|
||||
"subscribed": "O repositório da empresa é suportado por uma assinatura",
|
||||
"unsubscribed": "O repositório corporativo está habilitado sem uma assinatura ativa",
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
},
|
||||
"memory_overcommit": {
|
||||
"title": "Memory allocation",
|
||||
"rationale": "O teto `memory` de cada configuração de convidado face a MemTotal, com os convidados em execução contados à parte. Os contentores consomem até esse limite; as máquinas virtuais sem ballooning reservam-no.",
|
||||
"summary": {
|
||||
"withinRatio": "Guests are allocated {percent}% of host memory",
|
||||
"aboveRatio": "Guests are allocated {percent}% of host memory",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"withinRatio": "Os hóspedes recebem {percent}% da memória da máquina",
|
||||
"aboveRatio": "Os hóspedes recebem {percent}% da memória da máquina",
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
},
|
||||
"time_synchronisation": {
|
||||
"title": "Time synchronisation",
|
||||
"rationale": "NTP e NTPSynchronized tal como o `timedatectl` os reporta. A pertença ao cluster, a validação de certificados e a ordem dos registos dependem de relógios concordantes. Outro mecanismo pode estar a disciplinar o relógio.",
|
||||
"summary": {
|
||||
"synchronised": "The clock is synchronised with a time source",
|
||||
"disabled": "Time synchronisation is disabled",
|
||||
"notSynchronised": "Time synchronisation is enabled but the clock is not synchronised",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"synchronised": "O relógio está sincronizado com uma fonte de tempo",
|
||||
"notSynchronised": "A sincronização do tempo está activa mas o relógio não está sincronizado",
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
},
|
||||
"kernel_current": {
|
||||
@@ -5420,21 +5473,21 @@
|
||||
"rationale": "O kernel em execução face àquele que o anfitrião arrancaria a seguir, conforme o `proxmox-boot-tool` o reporta. Um kernel mais recente apenas instalado pode estar retido de propósito; uma diferença após reiniciar indica um arranque que não vingou.",
|
||||
"summary": {
|
||||
"current": "O kernel em execução {version} é o que o anfitrião arrancaria a seguir",
|
||||
"newerAvailable": "The host runs {running} while {newest} is installed",
|
||||
"newerSelected": "O anfitrião executa {running} e arrancaria {selected} no próximo reinício",
|
||||
"wouldDowngrade": "O anfitrião executa {running} mas arrancaria o mais antigo {selected} no próximo reinício",
|
||||
"bootTargetUnknown": "O anfitrião executa {version}; não foi possível ler o kernel escolhido para o próximo arranque",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"newerAvailable": "A máquina executa o {running} enquanto o {newest} está instalado",
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
},
|
||||
"security_updates": {
|
||||
"title": "Security updates",
|
||||
"rationale": "Pacotes pendentes cuja origem é um repositório de segurança, a partir de um `apt-get upgrade` simulado. O número reflete o que o apt reporta, não a gravidade do que cada pacote corrige.",
|
||||
"summary": {
|
||||
"none": "No package updates are pending",
|
||||
"noSecurity": "{total} update(s) pending, none from a security repository",
|
||||
"pending": "{count} of {total} pending update(s) come from a security repository",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"none": "Nenhuma atualização do pacote está pendente",
|
||||
"noSecurity": "Atualização do {total} pendente, nenhuma de um repositório de segurança",
|
||||
"pending": "O {count} do {total} ainda pendentes é proveniente de um repositório de segurança",
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
},
|
||||
"journal_size": {
|
||||
@@ -5442,10 +5495,10 @@
|
||||
"rationale": "O journal em disco face ao limite que se lhe aplica: SystemMaxUse quando está definido e, caso contrário, o valor por omissão do journald, um décimo do sistema de ficheiros onde reside.",
|
||||
"summary": {
|
||||
"bounded": "O journal ocupa {size}, dentro do seu limite efetivo",
|
||||
"large": "The journal holds {size} on disk",
|
||||
"nearCap": "O journal ocupa {size} e está a {percent}% do seu limite efetivo",
|
||||
"capUnknown": "O journal ocupa {size}; não foi possível determinar o seu limite efetivo",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"large": "O diário contém {size} no disco",
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
},
|
||||
"swap_configured": {
|
||||
@@ -5454,7 +5507,7 @@
|
||||
"summary": {
|
||||
"active": "{size} of swap is active",
|
||||
"none": "No swap area is active",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
},
|
||||
"filesystem_capacity": {
|
||||
@@ -5500,7 +5553,7 @@
|
||||
"summary": {
|
||||
"synchronised": "As {total} partições de arranque levam os mesmos kernels",
|
||||
"attention": "{count} de {total} partições de arranque requerem revisão",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
},
|
||||
"rationale": "As partições do sistema EFI proxmox-boot-tool reportam e os kernels que cada uma carrega. proxmox-boot-tool status pode montar temporariamente partições do sistema EFI; nenhuma inicialização é tentada."
|
||||
},
|
||||
@@ -5510,7 +5563,7 @@
|
||||
"summary": {
|
||||
"allRunning": "Os {total} serviços essenciais estão ativos e nenhuma unidade falhou",
|
||||
"attention": "{count} constatação(ões) entre as unidades",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
},
|
||||
"ha_state": {
|
||||
@@ -5519,7 +5572,7 @@
|
||||
"summary": {
|
||||
"managed": "Os {total} serviços geridos estão num estado assente em {nodes} nó(s)",
|
||||
"attention": "{count} constatação(ões) sobre {total} serviço(s) gerido(s)",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5528,27 +5581,27 @@
|
||||
"title": "Container privileges",
|
||||
"rationale": "A definição `unprivileged` de cada configuração de contentor. A sua ausência significa que o contentor partilha o espaço de nomes de utilizador do anfitrião, algo que certas cargas necessitam.",
|
||||
"summary": {
|
||||
"allUnprivileged": "All {total} containers are unprivileged",
|
||||
"privileged": "{count} of {total} containers run privileged",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"allUnprivileged": "Todos os recipientes {total} não são privilegiados",
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
},
|
||||
"qemu_without_agent": {
|
||||
"title": "Guest agent on virtual machines",
|
||||
"rationale": "A definição `agent` na configuração de cada máquina virtual. A definição indica que o agente está declarado, não que responda.",
|
||||
"summary": {
|
||||
"allHaveAgent": "All {total} virtual machines declare the guest agent",
|
||||
"missingAgent": "{count} of {total} virtual machines do not declare the guest agent",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
}
|
||||
"allHaveAgent": "Todas as máquinas virtuais {total} declaram o agente convidado",
|
||||
"missingAgent": "{count} das máquinas virtuais {total} não declaram o agente convidado",
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
},
|
||||
"title": "Agente convidado em máquinas virtuais"
|
||||
},
|
||||
"autostart": {
|
||||
"title": "Automatic start",
|
||||
"rationale": "A definição `onboot` de cada convidado, excluindo modelos e convidados geridos por HA. Se se espera que um convidado volte por si só, indica-o a política declarada.",
|
||||
"summary": {
|
||||
"allAutostart": "All {total} guests start with the host",
|
||||
"notAutostart": "{count} of {total} guests do not start with the host",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"allAutostart": "Todos os hóspedes do {total} começam com o anfitrião",
|
||||
"notAutostart": "{count} dos hóspedes do {total} não começam com a máquina",
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
},
|
||||
"stuck_snapshots": {
|
||||
@@ -5556,28 +5609,28 @@
|
||||
"rationale": "Estado e antiguidade dos snapshots e tarefas ativas. Uma operação recente ou sem data verificável não é considerada interrompida.",
|
||||
"summary": {
|
||||
"noSnapshots": "No guest holds snapshots",
|
||||
"allComplete": "The {total} snapshot(s) are complete",
|
||||
"stuck": "{count} of {total} snapshot(s) were left mid-operation",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"allComplete": "Os instantâneos {total} estão completos",
|
||||
"stuck": "{count} dos instantâneos {total} foram deixados no meio da operação",
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
},
|
||||
"cpu_host_type": {
|
||||
"title": "Virtual CPU model",
|
||||
"rationale": "O valor `cpu` de cada máquina virtual. `host` expõe o conjunto de instruções do processador físico, o que limita os nós para onde o convidado pode migrar. A incompatibilidade com um destino concreto não se determina aqui.",
|
||||
"summary": {
|
||||
"none": "None of the {total} virtual machines is pinned to the host processor",
|
||||
"pinned": "{count} of {total} virtual machines are pinned to the host processor",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"none": "Nenhuma das máquinas virtuais {total} está presa ao processador host",
|
||||
"pinned": "{count} de máquinas virtuais {total} são fixados ao processador host",
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
},
|
||||
"replication_state": {
|
||||
"title": "Replication",
|
||||
"rationale": "Tarefas de replicação a partir da API: número de falhas, último erro, última sincronização e o calendário que cada tarefa declara. As tarefas em pausa são assinaladas como tal.",
|
||||
"summary": {
|
||||
"healthy": "The {total} replication job(s) report no error",
|
||||
"failing": "{count} of {total} replication job(s) report an error",
|
||||
"statusUnavailable": "Replication jobs are defined but their status could not be read",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"healthy": "A tarefa de replicação do {total} não reporta nenhum erro",
|
||||
"failing": "{count} das tarefas de replicação do {total} reportam um erro",
|
||||
"statusUnavailable": "As tarefas de replicação estão definidas mas o seu estado não pôde ser lido",
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5589,39 +5642,39 @@
|
||||
"bothEnabled": "A ativação da firewall está configurada ao nível do centro de dados e do nó",
|
||||
"datacenterOff": "A firewall está desativada ao nível do centro de dados, pelo que as regras do nó não são aplicadas",
|
||||
"nodeOff": "A firewall está ativada ao nível do centro de dados, mas não neste nó",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
},
|
||||
"lynis_warnings": {
|
||||
"title": "Lynis warnings",
|
||||
"rationale": "Avisos da última auditoria do Lynis, cada um com o seu identificador de teste, e a idade dessa auditoria. Só é executada uma auditoria se o Lynis estiver instalado e não existir relatório completo. As sugestões não são incluídas.",
|
||||
"summary": {
|
||||
"none": "The last Lynis audit recorded no warnings",
|
||||
"found": "The last Lynis audit recorded {count} warning(s)",
|
||||
"incomplete": "The Lynis report is incomplete",
|
||||
"evaluationFailed": "The check could not be evaluated",
|
||||
"noneStale": "A última auditoria do Lynis não registou avisos, e o seu relatório tem {days} dia(s)",
|
||||
"foundStale": "A última auditoria do Lynis registou {count} aviso(s), e o seu relatório tem {days} dia(s)"
|
||||
"foundStale": "A última auditoria do Lynis registou {count} aviso(s), e o seu relatório tem {days} dia(s)",
|
||||
"none": "A última auditoria do Lynis não registrou avisos",
|
||||
"found": "A última auditoria de Lynis registrou avisos {count}",
|
||||
"incomplete": "O relatório Lynis está incompleto.",
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
},
|
||||
"certificate_expiry": {
|
||||
"title": "Certificate validity",
|
||||
"rationale": "A data de validade do certificado que o pveproxy serve a partir de /etc/pve/local. Um certificado próprio tem precedência sobre o que o Proxmox gera.",
|
||||
"summary": {
|
||||
"valid": "The certificate is valid for {days} more day(s)",
|
||||
"expiring": "The certificate expires in {days} day(s)",
|
||||
"expired": "The certificate expired {days} day(s) ago",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"valid": "O certificado é válido para {days} mais dias",
|
||||
"expiring": "O certificado expira em {days} dia(s)",
|
||||
"expired": "O certificado expirou {days} dias atrás",
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
},
|
||||
"ssh_root_login": {
|
||||
"title": "SSH root access",
|
||||
"rationale": "PermitRootLogin na configuração efetiva de `sshd -T`, com os métodos de autenticação com que se combina. O Proxmox é entregue com `yes`, que aceita palavra-passe.",
|
||||
"summary": {
|
||||
"password": "Root may sign in over SSH with a password",
|
||||
"keyOnly": "Root may sign in over SSH with a key only",
|
||||
"denied": "Root may not sign in over SSH",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"password": "Raiz pode entrar sobre SSH com uma senha",
|
||||
"keyOnly": "Raiz pode entrar sobre SSH com uma chave apenas",
|
||||
"denied": "A raiz não pode entrar sobre o SSH",
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5630,9 +5683,9 @@
|
||||
"title": "Volume assignment",
|
||||
"rationale": "Volumes de convidado no armazenamento local face às referências nas configurações atuais, pendentes e de snapshots. Backups, ISOs e modelos ficam fora da comparação. Um volume sem referência é um candidato a revisão.",
|
||||
"summary": {
|
||||
"none": "No orphaned volumes were found",
|
||||
"found": "Há {count} volumes sem referência nas configurações examinadas",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"none": "Não foram encontrados volumes órfãos",
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
},
|
||||
"zfs_arc_max": {
|
||||
@@ -5640,21 +5693,21 @@
|
||||
"rationale": "Valores efetivos de c_min, c_max e tamanho do ARC, o parâmetro de módulo carregado e as definições persistentes em /etc/modprobe.d. Um valor configurado a zero seleciona o valor por omissão do módulo; o ARC é um teto e a memória que ocupa é recuperável.",
|
||||
"summary": {
|
||||
"bounded": "O limite do ARC é {percent}% da memória do anfitrião, e a memória que ocupa é recuperável",
|
||||
"high": "The ARC may use {percent}% of host memory",
|
||||
"unset": "The ARC has no explicit limit set",
|
||||
"conflicting": "{count} definições do ARC não coincidem entre si",
|
||||
"pending": "Uma definição persistente do ARC difere do valor que o módulo em execução transporta",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"high": "O ARC pode usar {percent}% da memória da máquina",
|
||||
"unset": "O ARC não tem limite explícito definido",
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
},
|
||||
"zfs_scrub_age": {
|
||||
"title": "ZFS scrub",
|
||||
"rationale": "O último scrub concluído que o `zpool status` regista em cada pool. Um resilver não é um scrub. Uma pool criada há pouco ainda não teve ocasião de executar um.",
|
||||
"summary": {
|
||||
"recent": "The {total} pool(s) were scrubbed within the last 35 days",
|
||||
"overdue": "{count} of {total} pool(s) have not been scrubbed in 35 days",
|
||||
"neverScrubbed": "{count} pool(s) record no scrub",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"recent": "As piscinas {total} foram esfregadas nos últimos 35 dias",
|
||||
"overdue": "{count} da(s) piscina(s) {total} não foram esfregadas em 35 dias",
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
},
|
||||
"thin_pool_overprovisioning": {
|
||||
@@ -5664,7 +5717,7 @@
|
||||
"withinRatio": "Os {total} thin pools encontram-se abaixo dos limites de revisão aplicados",
|
||||
"aboveRatio": "{count} de {total} thin pools distribuem mais capacidade do que possuem",
|
||||
"pressure": "{pressure} de {total} thin pools estão perto de encher os seus dados ou metadados",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
},
|
||||
"connected_storage": {
|
||||
@@ -5673,7 +5726,7 @@
|
||||
"summary": {
|
||||
"available": "O PVE indica que os {total} armazenamentos estão disponíveis; os componentes internos remotos e o acesso de escrita não foram testados",
|
||||
"attention": "{count} de {total} armazenamentos requerem revisão",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
},
|
||||
"pool_integrity": {
|
||||
@@ -5691,7 +5744,7 @@
|
||||
"summary": {
|
||||
"healthy": "O Ceph reporta HEALTH_OK",
|
||||
"degraded": "O Ceph reporta {state}, com {count} verificação(ões) nomeada(s)",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
},
|
||||
"array_integrity": {
|
||||
@@ -5700,7 +5753,7 @@
|
||||
"summary": {
|
||||
"intact": "Os {total} arrays e mapas mantêm a sua redundância",
|
||||
"degraded": "{count} de {total} arrays ou mapas estão sem ela",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5712,7 +5765,7 @@
|
||||
"withinLife": "As {total} leituras de discos não excedem o limiar indicativo de cinco anos",
|
||||
"pastLife": "{count} de {total} leituras de discos excedem cinco anos de funcionamento",
|
||||
"noReadings": "Nenhum disco expõe contadores SMART utilizáveis ({skipped} sem leituras)",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
},
|
||||
"disk_errors": {
|
||||
@@ -5729,23 +5782,22 @@
|
||||
"title": "Bond members",
|
||||
"rationale": "O estado MII de cada membro do bond a partir de /proc/net/bonding e quantas ligações restam. Em active-backup, um membro de reserva figura como ativo e não transporta tráfego.",
|
||||
"summary": {
|
||||
"allUp": "All members of the {total} bond(s) are up",
|
||||
"membersDown": "{count} bond member(s) are not up",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"allUp": "Todos os membros da(s) ligação(ões) {total} estão em alta",
|
||||
"membersDown": "O( s) membro( s) de ligação do {count} não está( s) em espera",
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
},
|
||||
"bridge_without_ports": {
|
||||
"title": "Bridge ports",
|
||||
"rationale": "A configuração de portas de cada bridge. Uma bridge sem porta física serve uma rede interna ou encaminhada.",
|
||||
"summary": {
|
||||
"allConnected": "The {total} bridge(s) carry a port",
|
||||
"isolated": "{count} of {total} bridge(s) carry no port",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"allConnected": "A(s) ponte(s) {total} carrega(m) uma porta",
|
||||
"evaluationFailed": "A verificação não pôde ser avaliada"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"summaryFallback": "The check could not be evaluated",
|
||||
"acceptRisk": {
|
||||
"action": "Aceitar risco",
|
||||
"revoke": "Voltar a ativo",
|
||||
@@ -5779,17 +5831,15 @@
|
||||
"OK": "OK"
|
||||
},
|
||||
"viewSwitch": {
|
||||
"ariaLabel": "Switch between assessment and inventory",
|
||||
"assessment": "Assessment",
|
||||
"inventory": "Inventory",
|
||||
"policy": "Política",
|
||||
"changes": "Alterações"
|
||||
"changes": "Alterações",
|
||||
"ariaLabel": "Mudança entre avaliação e inventário"
|
||||
},
|
||||
"inventory": {
|
||||
"loading": "Loading inventory…",
|
||||
"failed": "The inventory could not be composed.",
|
||||
"collectedAt": "Composed on {when}",
|
||||
"unavailable": "Not read in this inventory",
|
||||
"unresolved": "path not resolved",
|
||||
"noUplink": "no uplink",
|
||||
"identity": "Node identity",
|
||||
@@ -5832,12 +5882,10 @@
|
||||
"protection": "Backup",
|
||||
"passthrough": "Passthrough",
|
||||
"noBackup": "No backup",
|
||||
"noBackupDetail": "No enabled backup job selects this guest.",
|
||||
"applications": "Applications",
|
||||
"versionUnknown": "version not detected",
|
||||
"passthroughTitle": "PCI passthrough",
|
||||
"iommuGroup": "IOMMU group {group}",
|
||||
"sharedGroup": "{count} more device(s) in the same group",
|
||||
"proxmenux": "ProxMenux optimizations",
|
||||
"latency": "Latência de rede",
|
||||
"subscriptionStatus": {
|
||||
@@ -5848,7 +5896,11 @@
|
||||
"suspended": "Suspensa",
|
||||
"new": "Aguarda ativação",
|
||||
"unknown": "Desconhecido"
|
||||
}
|
||||
},
|
||||
"failed": "O inventário não pôde ser composto.",
|
||||
"unavailable": "Não lido neste inventário",
|
||||
"noBackupDetail": "Nenhuma tarefa de backup ativada seleciona este convidado.",
|
||||
"sharedGroup": "{count} mais dispositivo( s) no mesmo grupo"
|
||||
},
|
||||
"profile": {
|
||||
"label": "Report",
|
||||
@@ -5871,7 +5923,6 @@
|
||||
"area": "Area",
|
||||
"inventoryAnnex": "Inventory annex",
|
||||
"scopeTitle": "Scope of this report",
|
||||
"scopeBody": "This report describes the Proxmox VE node named above, as observed from the node itself at the time stated. It does not cover the interior of the guests beyond what they declare, network equipment outside the host, physical infrastructure, or any dependency not visible from this node. Findings marked as not determined were not measured and are not evidence of absence.",
|
||||
"building": "A compor o relatório…",
|
||||
"node": "Nó",
|
||||
"profile": "Perfil",
|
||||
@@ -6020,11 +6071,12 @@
|
||||
"structureSubtitle": "Como {node} está construído e configurado",
|
||||
"postureTitle": "Posture",
|
||||
"posture": {
|
||||
"security": "Host exposure and access.",
|
||||
"backup": "Guest protection and whether it is real.",
|
||||
"capacity": "Room to grow and the wear on the disks."
|
||||
"security": "Exposição ao hospedeiro e acesso.",
|
||||
"backup": "Proteção de hóspedes e se é real.",
|
||||
"capacity": "Espaço para crescer e o desgaste nos discos."
|
||||
},
|
||||
"scopeReadOnly": "A avaliação inspeciona as configurações e a integridade do host. Pode escrever relatórios e logs; verificações de status de inicialização podem montar temporariamente partições do sistema EFI."
|
||||
"scopeReadOnly": "A avaliação inspeciona as configurações e a integridade do host. Pode escrever relatórios e logs; verificações de status de inicialização podem montar temporariamente partições do sistema EFI.",
|
||||
"scopeBody": "Este relatório descreve o nó Proxmox VE denominado acima, como observado a partir do próprio nó no momento indicado. Não cobre o interior dos hóspedes além do que eles declaram, equipamento de rede fora do host, infraestrutura física, ou qualquer dependência não visível deste nó. Os achados marcados como não determinados não foram medidos e não são evidência de ausência."
|
||||
},
|
||||
"results": "Resultados",
|
||||
"classifications": {
|
||||
@@ -6178,15 +6230,19 @@
|
||||
"notApplicableScope": "Nada no âmbito examinado a que esta verificação se aplique.",
|
||||
"lynis": {
|
||||
"title": "Run Lynis",
|
||||
"bodyNotRun": "Lynis is installed but has not been run yet. Running it now completes the security review, but the process can take a few minutes.",
|
||||
"bodyStale": "The Lynis report is {days} days old. You can run it now to refresh the data (it takes a little longer) or continue with the existing report.",
|
||||
"withLynis": "Run with Lynis",
|
||||
"withoutLynis": "Run without Lynis",
|
||||
"cancel": "Cancel"
|
||||
"cancel": "Cancel",
|
||||
"bodyNotRun": "Lynis está instalado, mas ainda não foi executado. Executá-lo agora completa a revisão de segurança, mas o processo pode demorar alguns minutos.",
|
||||
"bodyStale": "O relatório Lynis tem {days} dias. Você pode executá-lo agora para atualizar os dados (demora um pouco mais) ou continuar com o relatório existente."
|
||||
},
|
||||
"readOnlyNotice": "A avaliação inspeciona as configurações e a integridade do host. Pode escrever relatórios e logs; verificações de status de inicialização podem montar temporariamente partições do sistema EFI.",
|
||||
"noActionNeeded": "Nada para fazer. Este cheque encontrou o que espera encontrar.",
|
||||
"couldNotEvaluate": "Esta verificação não pôde ser avaliada, por isso não relata nada de qualquer forma. As provas registram o que não conseguiu ler."
|
||||
"couldNotEvaluate": "Esta verificação não pôde ser avaliada, por isso não relata nada de qualquer forma. As provas registram o que não conseguiu ler.",
|
||||
"neverRun": "Este hospedeiro ainda não foi avaliado.",
|
||||
"noFindings": "Nenhuma descoberta corresponde ao filtro actual.",
|
||||
"acceptedNotice": "O {count} aceitou o(s) risco(s) registado(s) nesta máquina.",
|
||||
"summaryFallback": "A verificação não pôde ser avaliada"
|
||||
},
|
||||
"runtime": {
|
||||
"notifications": {
|
||||
|
||||
@@ -1090,7 +1090,8 @@
|
||||
"backups": "Zálohy",
|
||||
"updates": "Aktualizácie",
|
||||
"firewall": "Firewall",
|
||||
"app": "Aplikácie"
|
||||
"app": "Aplikácie",
|
||||
"logs": "Logy"
|
||||
},
|
||||
"actions": {
|
||||
"start": "Spustiť",
|
||||
@@ -1190,6 +1191,44 @@
|
||||
"empty": "Zatiaľ tu nie sú žiadne záznamy.",
|
||||
"emptyHint": "Pravidlá s log: info alebo vyššie začnú tento prehľad napĺňať, keď príde sieťová prevádzka."
|
||||
},
|
||||
"consoleLog": {
|
||||
"title": "Výstup konzoly",
|
||||
"description": "Štandardný a chybový výstup hlavného procesu obrazu.",
|
||||
"stopped": "Kontajner je zastavený; log uchováva výstup z jeho predchádzajúcich behov.",
|
||||
"lastLines": "Posledných {count} riadkov",
|
||||
"follow": "Sledovať",
|
||||
"pause": "Pozastaviť",
|
||||
"refresh": "Obnoviť",
|
||||
"download": "Stiahnuť",
|
||||
"filter": "Filtrovať riadky",
|
||||
"loading": "Načítava sa výstup konzoly...",
|
||||
"empty": "Zatiaľ nie je zaznamenaný žiadny výstup.",
|
||||
"emptyHint": "Riadky sa tu zobrazia, keď kontajner zapisuje do svojej konzoly.",
|
||||
"noMatches": "Filtru nezodpovedá žiadny riadok.",
|
||||
"readFailed": "Log konzoly sa nepodarilo načítať",
|
||||
"notAvailableTitle": "Tento kontajner nemá log konzoly",
|
||||
"notAvailableHint": "Log konzoly sa nastaví, keď ProxMenux nainštaluje kontajner z jeho OCI obrazu."
|
||||
},
|
||||
"ociUpdates": {
|
||||
"notTracked": "Po zaregistrovaní aplikácie na karte Aplikácie sa tu sleduje jej obraz.",
|
||||
"installedImage": "Nainštalovaný obraz",
|
||||
"newImage": "K dispozícii je nový obraz {image}",
|
||||
"stackNote": "Súčasť aplikácie s viacerými kontajnermi (hlavný CT {primary}, {count} kontajnerov): aktualizácia sa týka všetkých.",
|
||||
"pendingNote": "Operácia na tomto kontajneri bola prerušená; Obnoviť otvorí jej obnovenie.",
|
||||
"update": "Aktualizovať",
|
||||
"recreate": "Znovu vytvoriť",
|
||||
"recover": "Obnoviť",
|
||||
"terminalTitleUpdate": "Aktualizovať OCI aplikáciu",
|
||||
"terminalTitleRecreate": "Znovu vytvoriť OCI aplikáciu",
|
||||
"terminalDescription": "Rovnaký postup ako OCI manager Apps → Spravovať nainštalované OCI aplikácie.",
|
||||
"keepBackup": "Ponechať zálohu vytvorenú pred aktualizáciou",
|
||||
"noKeepBackup": "Záloha vytvorená pred aktualizáciou sa neponecháva",
|
||||
"keepBackupHelp": "Každá aktualizácia zálohuje kontajner pred nahradením jeho obrazu, aby ho bolo možné obnoviť, ak aktualizácia zlyhá. S touto možnosťou sa táto záloha ponechá vo zvolenom úložisku; na Proxmox Backup Server sa pred aktualizáciou zapíše záloha.",
|
||||
"scheduleHelp": "Aktualizuje sa iba obraz, a to len keď jeho register zverejní nový.",
|
||||
"releaseDelayHelp": "Nový obraz sa nainštaluje až vtedy, keď je aspoň takto starý.",
|
||||
"ackExternal": "Adresáre hostiteľa sa zálohou neobnovia",
|
||||
"ackExternalHelp": "Tento kontajner používa adresáre hostiteľa. Plánovaná aktualizácia sa spustí iba s týmto potvrdením."
|
||||
},
|
||||
"options": {
|
||||
"title": "Možnosti",
|
||||
"snapshotBefore": "Snapshot pred použitím zmien",
|
||||
@@ -1450,6 +1489,14 @@
|
||||
"loadFailed": "Konfiguráciu hromadnej aktualizácie sa nepodarilo načítať."
|
||||
},
|
||||
"appEditor": {
|
||||
"methodOciImage": "OCI obraz (nainštalovaný ProxMenux)",
|
||||
"ociImageHelp": "Verzia a jej aktualizácie sa čítajú z obrazu, z ktorého bol tento kontajner vytvorený. Nainštaloval ho ProxMenux, takže nie je čo nastavovať: nainštalovaný obraz sa porovnáva s tým, ktorý jeho register zverejňuje dnes.",
|
||||
"ociAppVersion": "Aplikácia",
|
||||
"ociImage": "Obraz",
|
||||
"ociNewImage": "Nový obraz",
|
||||
"ociImageCurrent": "Verzia",
|
||||
"refreshData": "Obnoviť údaje",
|
||||
"refreshingData": "Obnovuje sa…",
|
||||
"dockerDetectedWithWorkloads": "Zistený Docker s {count} aplikáciami v kontajneroch",
|
||||
"dockerWorkloadsHeading": "Aplikácie v Dockeri",
|
||||
"runsInsideDocker": "Aktualizuje sa spolu s obrazom Docker",
|
||||
@@ -1508,7 +1555,6 @@
|
||||
"containerNameLabel": "Názov kontajnera",
|
||||
"containerNamePlaceholder": "napr. <your-container-name>",
|
||||
"ociLabelKeyLabel": "Kľúč OCI labelu",
|
||||
"ociLabelPlaceholder": "org.opencontainers.image.version",
|
||||
"pythonInterpreterLabel": "Cesta k Python interpreteru",
|
||||
"pythonInterpreterPlaceholder": "napr. /opt/<your-app>/venv/bin/python",
|
||||
"pipDistLabel": "Názov distribúcie (pip balík)",
|
||||
@@ -1652,7 +1698,8 @@
|
||||
"notifyUpstreamLabel": "Upozorniť ma, keď bude k dispozícii nová upstream verzia",
|
||||
"notifyUpstreamHelp": "Odošle `app_update_available` do kanálov povolených v Nastaveniach → Upozornenia. Vypnite, ak túto aplikáciu nie je možné aktualizovať na vašom boxe.",
|
||||
"excludeFromBadgeLabel": "Vylúčiť z počítadla aktualizácií LXC",
|
||||
"excludeFromBadgeHelp": "Nezapočítajte túto aplikáciu do odznaku súhrnných aktualizácií na karte zoznamu LXC.Užitočné, keď ste úmyselne pripnutý ku konkrétnej verzii (požiadavka na sledovanie, zmrazenie kompatibility).Nemá vplyv na vlastný stav karty Aplikácia ani na odchádzajúce upozornenie."
|
||||
"excludeFromBadgeHelp": "Nezapočítajte túto aplikáciu do odznaku súhrnných aktualizácií na karte zoznamu LXC.Užitočné, keď ste úmyselne pripnutý ku konkrétnej verzii (požiadavka na sledovanie, zmrazenie kompatibility).Nemá vplyv na vlastný stav karty Aplikácia ani na odchádzajúce upozornenie.",
|
||||
"ociLabelPlaceholder": "org.opencontainers.image.version"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
@@ -3320,7 +3367,14 @@
|
||||
"auditReports": "Správy — k dispozícii je úplný audit aj samostatné prehľady bezpečnosti, záloh a kapacity diskov. Každý začne stručným zhrnutím, ponúkne tlačiteľný inventár a dá sa vyexportovať do PDF. Pred bezpečnostnou kontrolou s Lynisom sa aplikácia opýta, aby bežná kontrola ostala rýchla.",
|
||||
"auditPolicyBaseline": "Pravidlá a porovnanie — nastavte, čo má server spĺňať: zálohy, firewall aj prihlásenie roota cez SSH. Jeden beh môžete označiť ako východiskový stav a neskôr jednoducho vidieť nové, vyriešené aj prijaté zistenia.",
|
||||
"groupedAppUpdates": "Zoskupené upozornenia na aktualizácie aplikácií — po kontrole príde jedno prehľadné upozornenie namiesto samostatnej správy pre každú aplikáciu. Aplikácie sú zoskupené podľa LXC a zobrazia sa nainštalované aj dostupné verzie.",
|
||||
"adminTokenScope": "Prístup správcu — otvorenie terminálu Monitoru a vypnutie overovania teraz vyžadujú token s úplnými právami správcu. Token iba na čítanie, napríklad pre monitorovaciu integráciu, tak zostáva bezpečne obmedzený (nahlásil @f3rs3n)."
|
||||
"adminTokenScope": "Prístup správcu — otvorenie terminálu Monitoru a vypnutie overovania teraz vyžadujú token s úplnými právami správcu. Token iba na čítanie, napríklad pre monitorovaciu integráciu, tak zostáva bezpečne obmedzený (nahlásil @f3rs3n).",
|
||||
"ociAppTab": "OCI kontajnery na karte Aplikácie — kontajner nainštalovaný cez OCI manager Apps sa rozpozná podľa záznamu o inštalácii: aplikácia a jej obraz, nový obraz zistený podľa digestu a odkaz na repozitár obrazu.",
|
||||
"ociUpdatesTab": "Aktualizácie OCI kontajnerov — Aktualizovať a Znovu vytvoriť otvoria rovnaký postup ako ponuka OCI, zálohu vytvorenú pred aktualizáciou možno ponechať v úložisku záloh a obraz možno aktualizovať podľa plánu.",
|
||||
"ociLogsTab": "Karta Logy pre OCI kontajnery — výstup konzoly aplikácie uložený na hostiteľovi a sledovaný naživo, s filtrom a stiahnutím. Konzola Proxmoxu týchto kontajnerov otvorí shell.",
|
||||
"appsUpdateShortcut": "Ikona aktualizácie na stránke Aplikácie otvorí kontajner priamo na jeho karte Aktualizácie.",
|
||||
"webhookHttps": "Upozornenia Proxmoxu sa dostanú do Monitora aj so zapnutým HTTPS — doručujú sa na výhradne lokálnu adresu a už nezlyhávajú na chybe certifikátu.",
|
||||
"persistentLogs": "Skončená vlna chýb v logoch sa už nehlási ako trvalá: vzor sa musí opakovať 15 minút a jeho upozornenie sa zatvorí samo (nahlásil @Joshua1264).",
|
||||
"mountsLanAddress": "Body pripojenia na LVM-thin a inom blokovom úložisku zobrazujú svoje využitie a aplikácie s viacerými kontajnermi sa otvárajú na svojej LAN adrese."
|
||||
}
|
||||
},
|
||||
"network": {
|
||||
@@ -4936,23 +4990,23 @@
|
||||
"Zobraziť všetky LXC kontajnery",
|
||||
"Spustiť LXC kontajner",
|
||||
"Zastaviť LXC kontajner",
|
||||
"Otvoriť shell v LXC kontajneri",
|
||||
"Otvoriť konzolu LXC kontajnera",
|
||||
"Zobraziť nastavenia kontajnera",
|
||||
"Zobraziť stav úložísk",
|
||||
"Zobraziť obsah úložiska",
|
||||
"Otestovať výkon Proxmox systému",
|
||||
"Zobraziť verziu Proxmox VE",
|
||||
"Zobraziť stav služby pve-cluster",
|
||||
"Skontrolovať stav klastra",
|
||||
"Zobraziť stav klastra",
|
||||
"Zobraziť uzly klastra",
|
||||
"Zobraziť stav ZFS poolu",
|
||||
"Zobraziť všetky ZFS pooly",
|
||||
"Zobraziť ZFS súborové systémy a zväzky",
|
||||
"Zobraziť všetky ZFS datasety",
|
||||
"Zobraziť podrobnosti o súboroch",
|
||||
"Prejsť do iného priečinka",
|
||||
"Vytvoriť priečinok",
|
||||
"Odstrániť priečinok aj s obsahom",
|
||||
"Kopírovať súbory",
|
||||
"Kopírovať súbory alebo priečinky",
|
||||
"Presunúť alebo premenovať súbory",
|
||||
"Zobraziť obsah súboru",
|
||||
"Hľadať text v súbore",
|
||||
@@ -5034,6 +5088,8 @@
|
||||
"customLinkNewTitle": "Nový webový odkaz",
|
||||
"customLinkEditTitle": "Upraviť webový odkaz",
|
||||
"customLinkEditAria": "Upraviť vlastný odkaz {name}",
|
||||
"openUpdatesAria": "Otvoriť kartu Aktualizácie pre {name}",
|
||||
"openUpdatesTitle": "K dispozícii je aktualizácia — otvoriť kartu Aktualizácie",
|
||||
"customLinkName": "Názov",
|
||||
"customLinkNamePlaceholder": "napr. Moja aplikácia",
|
||||
"customLinkUrl": "URL",
|
||||
|
||||
+196
-140
@@ -458,11 +458,11 @@
|
||||
"extendedNvmeHealth": "Utökad NVMe Health",
|
||||
"ssdWearLifetime": "SSD slitage och livstid",
|
||||
"nvmeHealthMetrics": "NVMe Health Metrics",
|
||||
"sasHealthMetrics": "SAS/SCSI Health Metrics",
|
||||
"smartAttributes": "SMART-attribut",
|
||||
"selfTestResult": "Självtestresultat",
|
||||
"lastSelfTestResult": "Senaste självtestresultat",
|
||||
"recommendations": "Rekommendationer"
|
||||
"recommendations": "Rekommendationer",
|
||||
"sasHealthMetrics": "SAS / SCSI Health Metrics"
|
||||
},
|
||||
"statusValues": {
|
||||
"ok": "OK",
|
||||
@@ -1069,7 +1069,8 @@
|
||||
"backups": "Säkerhetskopieringar",
|
||||
"updates": "Uppdateringar",
|
||||
"firewall": "Brandvägg",
|
||||
"app": "App"
|
||||
"app": "App",
|
||||
"logs": "Loggar"
|
||||
},
|
||||
"actions": {
|
||||
"start": "Start",
|
||||
@@ -1169,6 +1170,44 @@
|
||||
"empty": "Inga brandväggshändelser har registrerats ännu.",
|
||||
"emptyHint": "Regler med log: info eller högre kommer att fylla denna vy när paket anländer."
|
||||
},
|
||||
"consoleLog": {
|
||||
"title": "Konsolutdata",
|
||||
"description": "Standardutdata och standardfel från avbildens huvudprocess.",
|
||||
"stopped": "Containern är stoppad; loggen behåller utdata från tidigare körningar.",
|
||||
"lastLines": "Senaste {count} raderna",
|
||||
"follow": "Följ",
|
||||
"pause": "Pausa",
|
||||
"refresh": "Uppdatera",
|
||||
"download": "Ladda ned",
|
||||
"filter": "Filtrera rader",
|
||||
"loading": "Läser in konsolutdata...",
|
||||
"empty": "Ingen utdata registrerad ännu.",
|
||||
"emptyHint": "Rader visas här när containern skriver till sin konsol.",
|
||||
"noMatches": "Inga rader matchar filtret.",
|
||||
"readFailed": "Det gick inte att läsa konsolloggen",
|
||||
"notAvailableTitle": "Den här containern har ingen konsollogg",
|
||||
"notAvailableHint": "Konsolloggen konfigureras när ProxMenux installerar containern från dess OCI-avbild."
|
||||
},
|
||||
"ociUpdates": {
|
||||
"notTracked": "När applikationen registreras i fliken App följs dess avbild här.",
|
||||
"installedImage": "Installerad avbild",
|
||||
"newImage": "Ny avbild {image} tillgänglig",
|
||||
"stackNote": "Del av en applikation med flera containrar (huvud-CT {primary}, {count} containrar): uppdateringen omfattar alla.",
|
||||
"pendingNote": "En åtgärd på den här containern avbröts; Återställ öppnar dess återställning.",
|
||||
"update": "Uppdatera",
|
||||
"recreate": "Återskapa",
|
||||
"recover": "Återställ",
|
||||
"terminalTitleUpdate": "Uppdatera OCI-applikation",
|
||||
"terminalTitleRecreate": "Återskapa OCI-applikation",
|
||||
"terminalDescription": "Samma flöde som OCI manager Apps → Hantera installerade OCI-applikationer.",
|
||||
"keepBackup": "Behåll säkerhetskopian som tas före uppdateringen",
|
||||
"noKeepBackup": "Säkerhetskopian som tas före uppdateringen behålls inte",
|
||||
"keepBackupHelp": "Varje uppdatering säkerhetskopierar containern innan dess avbild ersätts, för att återställa den om uppdateringen misslyckas. Med det här alternativet behålls säkerhetskopian i den valda lagringen; på Proxmox Backup Server skrivs en säkerhetskopia före uppdateringen.",
|
||||
"scheduleHelp": "Endast avbilden uppdateras, och bara när dess register publicerar en ny.",
|
||||
"releaseDelayHelp": "En ny avbild installeras först när den är minst så här gammal.",
|
||||
"ackExternal": "Värdkataloger återställs inte av säkerhetskopian",
|
||||
"ackExternalHelp": "Den här containern använder värdkataloger. En schemalagd uppdatering körs bara när detta är bekräftat."
|
||||
},
|
||||
"options": {
|
||||
"title": "Alternativ",
|
||||
"snapshotBefore": "Ögonblicksbild innan applicering",
|
||||
@@ -1429,6 +1468,14 @@
|
||||
"loadFailed": "Det gick inte att läsa in massuppdateringskonfigurationen."
|
||||
},
|
||||
"appEditor": {
|
||||
"methodOciImage": "OCI-avbild (installerad av ProxMenux)",
|
||||
"ociImageHelp": "Versionen och dess uppdateringar läses från avbilden som containern skapades från. ProxMenux installerade den, så det finns inget att konfigurera: den installerade avbilden jämförs med den som registret publicerar i dag.",
|
||||
"ociAppVersion": "Applikation",
|
||||
"ociImage": "Avbild",
|
||||
"ociNewImage": "Ny avbild",
|
||||
"ociImageCurrent": "Version",
|
||||
"refreshData": "Uppdatera data",
|
||||
"refreshingData": "Uppdaterar…",
|
||||
"dockerDetectedWithWorkloads": "Docker hittades med {count} applikationer i containrar",
|
||||
"dockerWorkloadsHeading": "Applikationer i Docker",
|
||||
"runsInsideDocker": "Uppdateras med sin Docker-avbildning",
|
||||
@@ -1487,7 +1534,6 @@
|
||||
"containerNameLabel": "Behållarens namn",
|
||||
"containerNamePlaceholder": "t.ex. <ditt-behållarnamn>",
|
||||
"ociLabelKeyLabel": "OCI-etikettnyckel",
|
||||
"ociLabelPlaceholder": "org.opencontainers.image.version",
|
||||
"pythonInterpreterLabel": "Python-tolkväg",
|
||||
"pythonInterpreterPlaceholder": "t.ex. /opt/<din-app>/venv/bin/python",
|
||||
"pipDistLabel": "Distributionsnamn (pip-paket)",
|
||||
@@ -1534,11 +1580,8 @@
|
||||
"portHttps": "https",
|
||||
"portLogoLabel": "Logotyp URL för denna länk (valfritt)",
|
||||
"portLogoPlaceholder": "t.ex. https://example.com/logo.webp",
|
||||
"portCategoryPlaceholder": "Category for the Apps dashboard (optional)",
|
||||
"portCategoryNone": "No category",
|
||||
"portCategoryAddNew": "+ Add new category…",
|
||||
"portCategoryCustomPlaceholder": "Type a category and press Enter (Esc to cancel)",
|
||||
"portCustomUrlPlaceholder": "Custom URL (e.g. https://vault.example.com) — overrides IP:port",
|
||||
"removePortTooltip": "Ta bort porten",
|
||||
"detectMethodDpkg": "dpkg ·",
|
||||
"detectMethodApk": "apk ·",
|
||||
@@ -1631,7 +1674,11 @@
|
||||
"notifyUpstreamLabel": "Meddela mig när en ny uppströmsversion är tillgänglig",
|
||||
"notifyUpstreamHelp": "Skickar `app_update_available` till de kanaler som är aktiverade i Inställningar → Aviseringar. Stäng av om den här appen inte kan uppdateras på din box.",
|
||||
"excludeFromBadgeLabel": "Uteslut från LXC-uppdateringsräknaren",
|
||||
"excludeFromBadgeHelp": "Räkna inte den här appen i det samlade uppdateringsmärket på LXC-listkortet. Användbart när du är fäst till en specifik version med avsikt (spårningskrav, frysning av kompatibilitet).Påverkar inte appflikens eget tillstånd eller det utgående meddelandet."
|
||||
"excludeFromBadgeHelp": "Räkna inte den här appen i det samlade uppdateringsmärket på LXC-listkortet. Användbart när du är fäst till en specifik version med avsikt (spårningskrav, frysning av kompatibilitet).Påverkar inte appflikens eget tillstånd eller det utgående meddelandet.",
|
||||
"ociLabelPlaceholder": "org.opencontainers.image.version",
|
||||
"portCategoryPlaceholder": "Kategori för Apps dashboard (tillval)",
|
||||
"portCategoryCustomPlaceholder": "Skriv en kategori och tryck på Enter (Esc för att avbryta)",
|
||||
"portCustomUrlPlaceholder": "Anpassad URL (t.ex. https://vault.example.com) - åsidosätter IP:port"
|
||||
},
|
||||
"statusFilter": {
|
||||
"ariaLabel": "Filtrera virtuella maskiner och containrar",
|
||||
@@ -2515,10 +2562,10 @@
|
||||
"scope": {
|
||||
"label": "Token permissions",
|
||||
"readOnly": "Read-only",
|
||||
"readOnlyHint": "Reads metrics and status. Recommended for dashboards and integrations.",
|
||||
"fullAdmin": "Full admin",
|
||||
"fullAdminHint": "Full control, like your own session.",
|
||||
"fullAdminWarning": "A full-admin token can do everything you can: power off or reboot the host, run updates and open a terminal. Share it only with fully trusted integrations."
|
||||
"readOnlyHint": "Läser mätvärden och status. Rekommenderas för instrumentbrädor och integrationer.",
|
||||
"fullAdminHint": "Full kontroll, som din egen session.",
|
||||
"fullAdminWarning": "En full-admin-token kan göra allt du kan: Strö av eller starta om värden, kör uppdateringar och öppna en terminal. Dela det bara med fullt betrodda integrationer."
|
||||
}
|
||||
},
|
||||
"firewall": {
|
||||
@@ -3302,26 +3349,33 @@
|
||||
"gotIt": "Jag förstår!",
|
||||
"dontShowAgain": "Visa inte igen för den här versionen",
|
||||
"currentFeatures": {
|
||||
"appDetection": "Smarter app detection in the App tab: Docker is correctly promoted as the parent workload during cold start (Portainer/SearXNG no longer briefly show up as native apps), unregistered suggestions live in the startup cache, and 'Find applications' runs a fresh catalog-backed scan on demand.",
|
||||
"dockerUpdates": "The Updates tab now covers Docker end-to-end: Docker Engine and per-image update tracking follow the same 24-hour rolling cycle as OS packages, with a 'Check now' action for on-demand digest comparison — no more waiting for the daily collector.",
|
||||
"appCatalog": "Ny katalog för appdetektering med över 380 spårade arbetsuppgifter, genererad live från community-scripts via sju detektionsmetoder (fil, binär, dpkg, apk, Python, Docker exec, Docker label). Primära och reservdetektorer täcker både nya och historiska LXC-layouter.",
|
||||
"pushover": "Pushover joins Telegram, Gotify, Discord, Email and Apprise as a native notification channel — user/API key, device and sound selectors, priority 0 for regular messages, optional priority 1 for CRITICAL events. Suggested by @benginx (#308).",
|
||||
"appsDashboard": "Ny huvudflik Apps — en enda startpunkt för varje webblänk på noden. LXC-registrerade appar och användardefinierade Custom Web Links delar samma rutnät med kategori-taggar, sökning och direktlänk till gästens modal.",
|
||||
"lxcAppsUpdates": "App-fliken inuti varje LXC-modal registrerar installerade appar, fångar webblänkar och spårar uppströmsversioner. Omarbetad Updates-flik applicerar OS-paket och appuppdateringar med en enda knapp; Docker Engine och per-image följer samma 24-timmarscykel med en 'Kontrollera nu'-åtgärd på begäran.",
|
||||
"multilingual": "Monitorn talar nu 8 språk: engelska, spanska, tyska, franska, italienska, portugisiska, svenska och slovakiska. Ett stort tack till @vaso73 för att ha byggt i18n-grunden.",
|
||||
"nvidiaMultiGpu": "NVIDIA-driverns livscykel går över till ägarskap per exakt BDF, så att en multi-GPU-värd kan skicka ett kort till en VM och behålla det andra operativt på värden eller i LXC, plus en versionsväljare som är medveten om kärna, gren och GPU (#298).",
|
||||
"aiCustomEndpoint": "AI Assistant custom OpenAI endpoint — LiteLLM, LM Studio, LocalAI, vLLM, OmniRoute and any self-hosted proxy on private IPs, loopback or Docker networks are recognised when loading the model catalogue. The dropdown surfaces the server's error (or the underlying network reason) directly under the Load button (#325, reported by @jorgeffonte).",
|
||||
"secureGatewayArch": "Secure Gateway wizard — the Alpine template download, local template selection and pct create all match the host's real architecture, so x86_64 hosts receive amd64 containers and arm64 hosts receive arm64 containers (#324, reported by @N0X4DD0).",
|
||||
"atomicNotifications": "Notification events reserve their deduplication fingerprint atomically before AI processing and channel delivery, so concurrent collectors, completion callbacks or parallel Monitor processes cannot send the same event twice. The reservation is released when no channel succeeds, preserving retries.",
|
||||
"borgSshPort": "Borg remote target — the Add Borg destination dialog and the shell TUI accept a custom SSH port. BORG_RSH, the auto key install flow and the capacity probe all honour it. Fully backwards compatible with existing entries created without an explicit port (suggested by @songochain in discussion #236).",
|
||||
"githubToken": "Settings → GitHub API accepts an optional personal access token for release and tag checks when the anonymous quota is exhausted. The token is encrypted at rest and never returned to the browser; the rate-limit error is translated in every Monitor language (suggested by @SystemIdleProcess in discussion #306).",
|
||||
"replicationContext": "Native Proxmox replication failure notifications resolve the replication job ID, affected VM/LXC ID and guest name; the exact error block from Proxmox is preserved as the reason, and each replication job deduplicates independently (reported by Ale R.).",
|
||||
"auditAssessment": "Audit & Report — a new page that documents and assesses the node. The Assessment runs a catalogue of checks across security, backups, capacity, storage, network, hardware, guests and system, classifying each finding as critical, warning, observation or conformant and stating what it read rather than judging it.",
|
||||
"changeJournal": "Change journal — a Changes view that lists exactly what ProxMenux modified on this host: every configuration file, package and service it touched, with the prior state of each, deduplicated to a current-state view that shows the host as it stands now rather than a log of every run.",
|
||||
"auditReports": "Reports — a full audit plus focused Security review, Backup assurance and Capacity & wear reports, each opening on its own posture header, and a printable Inventory; all export to PDF. A security assessment asks before running Lynis so a run stays fast.",
|
||||
"auditPolicyBaseline": "Policy and baseline — declare what the host is expected to be (backup requirements, firewall, root SSH login) so findings grade against it, mark a run as the reference, and see what changed since, with new, resolved and accepted findings kept apart.",
|
||||
"groupedAppUpdates": "Grouped application update notifications — one complete message per scan instead of one per application, grouped by LXC with the installed and available versions.",
|
||||
"adminTokenScope": "Administrative scope — opening a Monitor terminal and disabling authentication now require a full-admin token, so a read-only API token issued to a monitoring integration stays read-only (reported by @f3rs3n)."
|
||||
"appDetection": "Smartare app detektion i fliken App: Docker är korrekt främjas som moder arbetsbelastning under kallstart (Portainer / SearXNG inte längre kort visas som inhemska appar), oregistrerade förslag lever i uppstartscache, och \"Find applikationer\" kör en ny katalogstödd skanning på begäran.",
|
||||
"dockerUpdates": "fliken Uppdateringar täcker nu Docker end-to-end: Docker Motor- och per-image-uppdateringsspårning följer samma 24-timmars rullcykel som OS-paket, med en \"Check now\" -åtgärd för on-demand digest jämförelse - inte mer väntar på den dagliga samlaren.",
|
||||
"pushover": "Pushover ansluter sig till Telegram, Gotify, Discord, Email and Apprise som en infödd meddelandekanal - användar / API-nyckel, enhet och ljudväljare, prioritet 0 för vanliga meddelanden, valfri prioritet 1 för CRITICAL-evenemang. Föreslås av @benginx (#308).",
|
||||
"aiCustomEndpoint": "AI Assistant anpassade OpenAI endpoint - LiteLLM, LM Studio, LocalAI, vLLM, OmniRoute och någon själv värd proxy på privata IPs, loopback eller Docker-nätverk är erkända när man laddar modellkatalogen. Avstängningen ytor serverns fel (eller den underliggande nätverksskäl) direkt under Load-knappen (#325, rapporterad av @jorgeffonte).",
|
||||
"secureGatewayArch": "Säker Gateway guide - Alpine mall nedladdning, lokal mallval och pct create alla matcha värdens verkliga arkitektur, så x86 64 värdar får amd64 behållare och arm64 värdar får arm64 behållare (#324, rapporterad av @N0X4D0).",
|
||||
"atomicNotifications": "Anmälningshändelser förbehåller sig sin deduplicering fingeravtryck atomiskt innan AI-behandling och kanalleverans, så samtidiga samlare, slutförande återkopplingar eller parallella övervakningsprocesser kan inte skicka samma händelse två gånger. Bokningen släpps när ingen kanal lyckas, bevara retries.",
|
||||
"borgSshPort": "Borg fjärrmål - Add Borg destination dialog och skalet TUI acceptera en anpassad SSH hamn. BORG RSH, auto key install flow och kapacitet sond alla hedra det. Fullt bakåtkompatibel med befintliga poster som skapats utan en explicit port (förslag av @songochain i diskussion #236).",
|
||||
"githubToken": "Inställningar → GitHub API accepterar en valfri personlig åtkomsttoken för release och tag kontroller när den anonyma kvoten är utmattad. Token krypteras i vila och återvände aldrig till webbläsaren; hastighetsfel översätts i varje Monitor-språk (föreslås av @SystemIdleProcess i diskussion #306).",
|
||||
"replicationContext": "Native Proxmox replikationsfelmeddelanden löser replikationsjobbet ID, påverkade VM / LXC ID och gästnamn; det exakta felblocket från Proxmox bevaras som orsaken, och varje replikationsjobb dedupliceras oberoende (rapporteras av Ale R.).",
|
||||
"auditAssessment": "Audit & Report – en ny sida som dokumenterar och bedömer noden. Bedömningen driver en katalog över kontroller över säkerhet, säkerhetskopior, kapacitet, lagring, nätverk, hårdvara, gäster och system, klassificera varje hitta som kritisk, varning, observation eller överensstämmelse och ange vad det läser snarare än att döma det.",
|
||||
"changeJournal": "Ändra tidskrift - en Ändringsvy som listar exakt vad ProxMenux modifierade på denna värd: varje konfigurationsfil, paket och tjänst som den rörde, med föregående tillstånd av varje, deduplicerad till en aktuell statsvy som visar värden som det står nu snarare än en logg på varje körning.",
|
||||
"auditReports": "Rapporter - en fullständig revision plus fokuserad säkerhetsgranskning, säkerhetskopiering och kapacitet & slitage rapporter, varje öppning på sin egen hållning rubrik, och en utskrivbar lager; all export till PDF. En säkerhetsbedömning frågar innan du kör Lynis så en körning stannar snabbt.",
|
||||
"auditPolicyBaseline": "Policy och baslinje - förklara vad värden förväntas vara (backup krav, brandvägg, rot SSH inloggning) så resultat betyg mot det, markera en körning som referens, och se vad som förändrats sedan, med nya, lösta och accepterade fynd hålls isär.",
|
||||
"groupedAppUpdates": "Grupperade programuppdateringsmeddelanden - ett komplett meddelande per skanning istället för en per applikation, grupperad av LXC med installerade och tillgängliga versioner.",
|
||||
"adminTokenScope": "Administrativa räckvidd - öppna en Monitor-terminal och inaktivera autentisering kräver nu en full-admin-token, så en lättläst API-token utfärdad till en övervakningsintegration förblir lättläst (rapporterad av @f3rs3n).",
|
||||
"ociAppTab": "OCI-containrar i fliken App — en container som installerats av OCI manager Apps känns igen från sin installationspost: applikationen och dess avbild, en ny avbild som upptäcks via digest och en länk till avbildens repository.",
|
||||
"ociUpdatesTab": "Uppdateringar för OCI-containrar — Uppdatera och Återskapa öppnar samma flöde som OCI-menyn, säkerhetskopian som tas före uppdateringen kan behållas i en lagring för säkerhetskopior och avbilden kan uppdateras enligt schema.",
|
||||
"ociLogsTab": "Fliken Logs för OCI-containrar — applikationens konsolutdata, sparad på värden och följd i realtid, med filter och nedladdning. Proxmox-konsolen för dessa containrar öppnar ett skal.",
|
||||
"appsUpdateShortcut": "Uppdateringsikonen på sidan Appar öppnar containern direkt på dess flik Uppdateringar.",
|
||||
"webhookHttps": "Proxmox-aviseringar når Monitor med HTTPS aktiverat — de levereras till en adress som bara är lokal och misslyckas inte längre på grund av ett certifikatfel.",
|
||||
"persistentLogs": "En avslutad skur av loggfel rapporteras inte längre som bestående: ett mönster måste fortsätta att dyka upp i 15 minuter, och dess varning stängs av sig själv (rapporterat av @Joshua1264).",
|
||||
"mountsLanAddress": "Monteringspunkter på LVM-thin och annan blocklagring visar sin användning, och program med flera containrar öppnas på sin LAN-adress."
|
||||
}
|
||||
},
|
||||
"network": {
|
||||
@@ -3546,7 +3600,6 @@
|
||||
"latencyHistory": "Latenshistorik (senaste {count} poster)",
|
||||
"methodology": "Metodik",
|
||||
"testMethod": "Testmetod",
|
||||
"icmpEchoRequest": "ICMP Echo Request (Ping)",
|
||||
"samplesPerTest": "Prover per test",
|
||||
"threeConsecutivePings": "3 plingar i följd",
|
||||
"targetIp": "Mål-IP",
|
||||
@@ -3558,7 +3611,8 @@
|
||||
"assessmentUnknown": "Det går inte att fastställa nätverksstatus.",
|
||||
"footerTitle": "ProxMenux Monitor - Nätverksprestandarapport",
|
||||
"generated": "Genererad",
|
||||
"reportId": "Rapport-ID"
|
||||
"reportId": "Rapport-ID",
|
||||
"icmpEchoRequest": "ICMP Echo Request (Ping)"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5027,23 +5081,20 @@
|
||||
"uncategorized": "Uncategorized",
|
||||
"openAriaLabel": "Open {name} in a new tab",
|
||||
"openGuestAriaLabel": "Öppna {name} ({type} {id})",
|
||||
"emptyTitle": "No apps with a web link yet.",
|
||||
"emptyHint": "Register a Web Link for any app (App tab of a CT) to see it here.",
|
||||
"customLinkAdd": "Add link",
|
||||
"editModeToggle": "Edit",
|
||||
"editModeDone": "Done",
|
||||
"customLinkNewTitle": "New web link",
|
||||
"customLinkEditTitle": "Edit web link",
|
||||
"customLinkEditAria": "Redigera den anpassade länken {name}",
|
||||
"openUpdatesAria": "Öppna fliken Uppdateringar för {name}",
|
||||
"openUpdatesTitle": "Uppdatering tillgänglig — öppna fliken Uppdateringar",
|
||||
"customLinkName": "Name",
|
||||
"customLinkNamePlaceholder": "e.g. My app",
|
||||
"customLinkUrl": "URL",
|
||||
"customLinkLogo": "Logo URL (optional)",
|
||||
"customLinkLogoPlaceholder": "e.g., https://example.com/logo.webp",
|
||||
"customLinkCategory": "Category (optional)",
|
||||
"customLinkBinding": "Bound to",
|
||||
"customLinkBindingNone": "Not bound to any guest",
|
||||
"customLinkBindingHelp": "Bind this link to a VM or CT to add its ID + name to the card and jump to the guest with one click.",
|
||||
"customLinkSave": "Save",
|
||||
"customLinkCreate": "Create",
|
||||
"customLinkCancel": "Cancel",
|
||||
@@ -5079,7 +5130,12 @@
|
||||
"remoteAccessVpn": "Remote Access & VPN",
|
||||
"webserversProxies": "Webservers & Proxies",
|
||||
"zigbeeZwaveMatter": "ZigBee, Z-Wave & Matter"
|
||||
}
|
||||
},
|
||||
"emptyTitle": "Inga appar med en webblänk ännu.",
|
||||
"emptyHint": "Registrera en webblänk för någon app (App-fliken på en CT) för att se den här.",
|
||||
"customLinkLogoPlaceholder": "e.g., https://example.com/logo.webp",
|
||||
"customLinkBindingNone": "Inte bunden till någon gäst",
|
||||
"customLinkBindingHelp": "Bind denna länk till en VM eller CT för att lägga till sitt ID +-namn till kortet och hoppa till gästen med ett klick."
|
||||
},
|
||||
"audit": {
|
||||
"presentation": {
|
||||
@@ -5234,13 +5290,10 @@
|
||||
"loading": "Loading assessment…",
|
||||
"run": "Run assessment",
|
||||
"running": "Assessing…",
|
||||
"neverRun": "This host has not been assessed yet.",
|
||||
"lastRun": "Last assessed on {when}",
|
||||
"stale": "{days} days ago",
|
||||
"unverifiedChecks": "Ej gjorda: {checks}. Var och en anger i sina belägg vad den inte kunde läsa.",
|
||||
"noFindings": "No findings match the current filter.",
|
||||
"affectedCount": "{count} affected",
|
||||
"acceptedNotice": "{count} accepted risk(s) recorded on this host.",
|
||||
"reviewOn": "Granska den: {when}",
|
||||
"reviewDue": "Dags att granska — beslutet gäller fortfarande",
|
||||
"reviewDueNotice": "{count} accepterade beslut väntar på granskning.",
|
||||
@@ -5272,7 +5325,7 @@
|
||||
"sources": "Källor och insamlingstider"
|
||||
},
|
||||
"errors": {
|
||||
"runFailed": "The assessment could not be started."
|
||||
"runFailed": "Bedömningen kunde inte påbörjas."
|
||||
},
|
||||
"checks": {
|
||||
"backup": {
|
||||
@@ -5285,7 +5338,7 @@
|
||||
"uncovered": "{count} av {total} gäster väljs inte av något aktiverat säkerhetskopieringsjobb",
|
||||
"excludedData": "Granska {count} undantag för diskar eller monteringspunkter",
|
||||
"uncoveredExpected": "{required} gäster som deklarerats behöva säkerhetskopia väljs inte av något aktiverat jobb",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
},
|
||||
"nextStep": {
|
||||
"noJobs": "Skapa ett backup jobb på denna nod och välj de gäster som håller data som du inte vill bygga för hand. Ett jobb som existerar men är funktionshindrat väljer ingenting.",
|
||||
@@ -5300,10 +5353,10 @@
|
||||
"rationale": "Ålder: tid som gått sedan den senaste lagrade säkerhetskopian. Använd gräns: referensåldern som kopian jämförs med.",
|
||||
"summary": {
|
||||
"recent": "Alla {total} gäst-/destinationskontroller uppfyller det angivna ålderskravet",
|
||||
"stale": "{count} of {total} guests have no backup from the last 30 days",
|
||||
"noBackups": "No stored backup matches a guest on this node",
|
||||
"attention": "{count} av {total} gäst-/destinationskontroller behöver granskas",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"stale": "{count} av {total} gäster har ingen backup från de senaste 30 dagarna",
|
||||
"noBackups": "Ingen lagrad backup matchar en gäst på denna nod",
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
},
|
||||
"nextStep": {
|
||||
"stale": "Ta reda på varför jobbet slutade producera kopior för dessa gäster: det kan ha varit inaktiverat, dess schema kan aldrig elda, eller dess körningar kan misslyckas. Löpresultaten kontrollerar hur varje jobb senast slutade.",
|
||||
@@ -5317,10 +5370,10 @@
|
||||
"rationale": "Lagringstiden som Proxmox löser upp den: jobbets inställning, sedan lagringens, sedan nodens standardvärde. Lagringstid som en säkerhetskopieringsserver tillämpar går inte att läsa från den här noden.",
|
||||
"summary": {
|
||||
"allDefined": "Alla {total} jobb löser upp en inställning för lagringstid",
|
||||
"missing": "{count} of {total} enabled job(s) declare no retention",
|
||||
"notDeclared": "{count} av {total} jobb behåller varje kopia: ingen lagringstid är deklarerad",
|
||||
"onServer": "{count} av {total} jobb skriver till en säkerhetskopieringsserver, som gallrar dem med egna jobb",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"missing": "{count} av {total} aktiverade jobb (er) förklarar ingen lagring",
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
},
|
||||
"nextStep": {
|
||||
"missing": "Ange en lagring på dessa jobb, eller på lagringen de skriver till. Proxmox tar jobbets inställning först, sedan lagringen, sedan noden standard.",
|
||||
@@ -5383,36 +5436,36 @@
|
||||
"summary": {
|
||||
"none": "Ingenting har begärt omstart",
|
||||
"pending": "{count} poster är installerade och väntar på omstart",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
},
|
||||
"enterprise_repo_without_subscription": {
|
||||
"title": "Enterprise repository",
|
||||
"rationale": "Referenser till `enterprise.proxmox.com` i `/etc/apt/sources.list` och `sources.list.d`, mot statusen från `pvesubscription get`.",
|
||||
"summary": {
|
||||
"notEnabled": "The enterprise repository is not enabled",
|
||||
"subscribed": "The enterprise repository is backed by a subscription",
|
||||
"unsubscribed": "The enterprise repository is enabled without an active subscription",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"notEnabled": "Företagsförvaret är inte aktiverat",
|
||||
"subscribed": "Företagsregister stöds av en prenumeration",
|
||||
"unsubscribed": "Företagsregister är aktiverat utan aktiv prenumeration",
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
},
|
||||
"memory_overcommit": {
|
||||
"title": "Memory allocation",
|
||||
"rationale": "Taket `memory` i varje gästkonfiguration mot MemTotal, med körande gäster räknade för sig. Containrar förbrukar upp till den gränsen; virtuella maskiner utan ballooning reserverar den.",
|
||||
"summary": {
|
||||
"withinRatio": "Guests are allocated {percent}% of host memory",
|
||||
"aboveRatio": "Guests are allocated {percent}% of host memory",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"withinRatio": "Gäster tilldelas {percent}% av värdminnet",
|
||||
"aboveRatio": "Gäster tilldelas {percent}% av värdminnet",
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
},
|
||||
"time_synchronisation": {
|
||||
"title": "Time synchronisation",
|
||||
"rationale": "NTP och NTPSynchronized som `timedatectl` rapporterar dem. Klustermedlemskap, certifikatvalidering och loggordning bygger på klockor som stämmer överens. En annan mekanism kan sköta klockan.",
|
||||
"summary": {
|
||||
"synchronised": "The clock is synchronised with a time source",
|
||||
"disabled": "Time synchronisation is disabled",
|
||||
"notSynchronised": "Time synchronisation is enabled but the clock is not synchronised",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"synchronised": "Klockan synkroniseras med en tidskälla",
|
||||
"notSynchronised": "Tidssynkronisering är aktiverad men klockan synkroniseras inte",
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
},
|
||||
"kernel_current": {
|
||||
@@ -5420,21 +5473,21 @@
|
||||
"rationale": "Kärnan som körs mot den värden skulle starta härnäst, som `proxmox-boot-tool` rapporterar den. En nyare kärna som bara är installerad kan hållas tillbaka med avsikt; en skillnad efter omstart betyder en start som inte tog.",
|
||||
"summary": {
|
||||
"current": "Kärnan {version} som körs är den värden skulle starta härnäst",
|
||||
"newerAvailable": "The host runs {running} while {newest} is installed",
|
||||
"newerSelected": "Värden kör {running} och skulle starta {selected} vid nästa omstart",
|
||||
"wouldDowngrade": "Värden kör {running} men skulle starta den äldre {selected} vid nästa omstart",
|
||||
"bootTargetUnknown": "Värden kör {version}; kärnan som valts för nästa start kunde inte läsas",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"newerAvailable": "Värden kör {running} medan {newest} är installerad",
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
},
|
||||
"security_updates": {
|
||||
"title": "Security updates",
|
||||
"rationale": "Väntande paket vars ursprung är ett säkerhetsarkiv, från en simulerad `apt-get upgrade`. Antalet speglar vad apt rapporterar, inte hur allvarligt det varje paket rättar är.",
|
||||
"summary": {
|
||||
"none": "No package updates are pending",
|
||||
"noSecurity": "{total} update(s) pending, none from a security repository",
|
||||
"pending": "{count} of {total} pending update(s) come from a security repository",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"none": "Inga paketuppdateringar väntar",
|
||||
"noSecurity": "{total} uppdatering (er) i väntan, ingen från ett säkerhetsförvar",
|
||||
"pending": "{count} av {total} pågående uppdateringar kommer från ett säkerhetsförvar",
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
},
|
||||
"journal_size": {
|
||||
@@ -5442,10 +5495,10 @@
|
||||
"rationale": "Journalen på disk mot det tak som gäller för den: SystemMaxUse där det är satt, annars journalds standard på en tiondel av filsystemet den ligger på.",
|
||||
"summary": {
|
||||
"bounded": "Journalen upptar {size}, inom sitt gällande tak",
|
||||
"large": "The journal holds {size} on disk",
|
||||
"nearCap": "Journalen upptar {size} och ligger på {percent}% av sitt gällande tak",
|
||||
"capUnknown": "Journalen upptar {size}; dess gällande tak kunde inte fastställas",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"large": "Tidskriften håller {size} på disk",
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
},
|
||||
"swap_configured": {
|
||||
@@ -5454,7 +5507,7 @@
|
||||
"summary": {
|
||||
"active": "{size} of swap is active",
|
||||
"none": "No swap area is active",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
},
|
||||
"filesystem_capacity": {
|
||||
@@ -5500,7 +5553,7 @@
|
||||
"summary": {
|
||||
"synchronised": "De {total} startpartitionerna bär samma kärnor",
|
||||
"attention": "{count} av {total} startpartitioner behöver ses över",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
},
|
||||
"rationale": "EFI-systempartitionerna proxmox-boot-tool rapporter och de kärnor som var och en bär. proxmox-boot-tool status kan tillfälligt montera EFI-systempartitioner; ingen start görs."
|
||||
},
|
||||
@@ -5510,7 +5563,7 @@
|
||||
"summary": {
|
||||
"allRunning": "De {total} väsentliga tjänsterna är aktiva och ingen enhet har misslyckats",
|
||||
"attention": "{count} iakttagelse(r) bland enheterna",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
},
|
||||
"ha_state": {
|
||||
@@ -5519,7 +5572,7 @@
|
||||
"summary": {
|
||||
"managed": "De {total} hanterade tjänsterna är i ett stabilt läge på {nodes} nod(er)",
|
||||
"attention": "{count} iakttagelse(r) för {total} hanterade tjänster",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5528,27 +5581,27 @@
|
||||
"title": "Container privileges",
|
||||
"rationale": "Inställningen `unprivileged` i varje containerkonfiguration. Att den saknas betyder att containern delar värdens användarnamnrymd, vilket vissa laster kräver.",
|
||||
"summary": {
|
||||
"allUnprivileged": "All {total} containers are unprivileged",
|
||||
"privileged": "{count} of {total} containers run privileged",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"allUnprivileged": "Alla {total} behållare är oprivilegierade",
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
},
|
||||
"qemu_without_agent": {
|
||||
"title": "Guest agent on virtual machines",
|
||||
"rationale": "Inställningen `agent` i varje virtuell maskins konfiguration. Inställningen säger att agenten är deklarerad, inte att den svarar.",
|
||||
"summary": {
|
||||
"allHaveAgent": "All {total} virtual machines declare the guest agent",
|
||||
"missingAgent": "{count} of {total} virtual machines do not declare the guest agent",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
}
|
||||
"allHaveAgent": "Alla {total} virtuella maskiner förklarar gästagenten",
|
||||
"missingAgent": "{count} av {total} virtuella maskiner förklarar inte gästagenten",
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
},
|
||||
"title": "Gästagent på virtuella maskiner"
|
||||
},
|
||||
"autostart": {
|
||||
"title": "Automatic start",
|
||||
"rationale": "Inställningen `onboot` för varje gäst, utom mallar och gäster som HA hanterar. Om en gäst förväntas komma tillbaka av sig själv framgår av den deklarerade policyn.",
|
||||
"summary": {
|
||||
"allAutostart": "All {total} guests start with the host",
|
||||
"notAutostart": "{count} of {total} guests do not start with the host",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"allAutostart": "Alla {total} gäster börjar med värden",
|
||||
"notAutostart": "{count} av {total} gäster börjar inte med värden",
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
},
|
||||
"stuck_snapshots": {
|
||||
@@ -5556,28 +5609,28 @@
|
||||
"rationale": "Ögonblicksbildernas tillstånd och ålder samt aktiva uppgifter. En färsk åtgärd eller en utan verifierbart datum betraktas inte som avbruten.",
|
||||
"summary": {
|
||||
"noSnapshots": "No guest holds snapshots",
|
||||
"allComplete": "The {total} snapshot(s) are complete",
|
||||
"stuck": "{count} of {total} snapshot(s) were left mid-operation",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"allComplete": "{total} snapshot(s) är kompletta",
|
||||
"stuck": "{count} av {total} snapshot(s) lämnades mitten av driften",
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
},
|
||||
"cpu_host_type": {
|
||||
"title": "Virtual CPU model",
|
||||
"rationale": "Värdet `cpu` för varje virtuell maskin. `host` exponerar den fysiska processorns instruktionsuppsättning, vilket begränsar vilka noder gästen kan migrera till. Oförenlighet med ett visst mål avgörs inte här.",
|
||||
"summary": {
|
||||
"none": "None of the {total} virtual machines is pinned to the host processor",
|
||||
"pinned": "{count} of {total} virtual machines are pinned to the host processor",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"none": "Ingen av {total} virtuella maskiner är fäst vid värdprocessorn",
|
||||
"pinned": "{count} av {total} virtuella maskiner är fästa på värdprocessorn",
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
},
|
||||
"replication_state": {
|
||||
"title": "Replication",
|
||||
"rationale": "Replikeringsjobb från API:et: antal fel, senaste fel, senaste synkronisering och den kalender varje jobb anger. Pausade jobb redovisas som sådana.",
|
||||
"summary": {
|
||||
"healthy": "The {total} replication job(s) report no error",
|
||||
"failing": "{count} of {total} replication job(s) report an error",
|
||||
"statusUnavailable": "Replication jobs are defined but their status could not be read",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"healthy": "{total} replikeringsjobb (er) rapporterar inga fel",
|
||||
"failing": "{count} av {total} replikeringsjobb (er) rapporterar ett fel",
|
||||
"statusUnavailable": "Replikationsjobb definieras men deras status kan inte läsas",
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5589,39 +5642,39 @@
|
||||
"bothEnabled": "Brandväggsaktivering är konfigurerad på datacenter- och nodnivå",
|
||||
"datacenterOff": "Brandväggen är avstängd på datacenternivå, så nodreglerna tillämpas inte",
|
||||
"nodeOff": "Brandväggen är aktiverad på datacenternivå men inte på den här noden",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
},
|
||||
"lynis_warnings": {
|
||||
"title": "Lynis warnings",
|
||||
"rationale": "Varningar från den senaste Lynis-granskningen, var och en med sin testidentifierare, och hur gammal granskningen är. En granskning körs bara om Lynis är installerat och ingen fullständig rapport finns. Förslag ingår inte.",
|
||||
"summary": {
|
||||
"none": "The last Lynis audit recorded no warnings",
|
||||
"found": "The last Lynis audit recorded {count} warning(s)",
|
||||
"incomplete": "The Lynis report is incomplete",
|
||||
"evaluationFailed": "The check could not be evaluated",
|
||||
"noneStale": "Den senaste Lynis-granskningen registrerade inga varningar, och dess rapport är {days} dag(ar) gammal",
|
||||
"foundStale": "Den senaste Lynis-granskningen registrerade {count} varning(ar), och dess rapport är {days} dag(ar) gammal"
|
||||
"foundStale": "Den senaste Lynis-granskningen registrerade {count} varning(ar), och dess rapport är {days} dag(ar) gammal",
|
||||
"none": "Den sista Lynis-revisionen registrerade inga varningar",
|
||||
"found": "Den sista Lynis-revisionen spelade in {count}-varning (er)",
|
||||
"incomplete": "Lynis-rapporten är ofullständig",
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
},
|
||||
"certificate_expiry": {
|
||||
"title": "Certificate validity",
|
||||
"rationale": "Utgångsdatum för certifikatet som pveproxy levererar från /etc/pve/local. Ett eget certifikat går före det Proxmox genererar.",
|
||||
"summary": {
|
||||
"valid": "The certificate is valid for {days} more day(s)",
|
||||
"expiring": "The certificate expires in {days} day(s)",
|
||||
"expired": "The certificate expired {days} day(s) ago",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"valid": "Intyget gäller för {days} fler dagar (er)",
|
||||
"expiring": "Certifikatet löper ut i {days}-dagar",
|
||||
"expired": "Certifikatet löpte ut {days}-dagar sedan",
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
},
|
||||
"ssh_root_login": {
|
||||
"title": "SSH root access",
|
||||
"rationale": "PermitRootLogin i den effektiva `sshd -T`-konfigurationen, med de autentiseringsmetoder den kombineras med. Proxmox levereras med `yes`, som accepterar lösenord.",
|
||||
"summary": {
|
||||
"password": "Root may sign in over SSH with a password",
|
||||
"keyOnly": "Root may sign in over SSH with a key only",
|
||||
"denied": "Root may not sign in over SSH",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"password": "Root kan logga in över SSH med ett lösenord",
|
||||
"keyOnly": "Rot kan logga in över SSH med en nyckel endast",
|
||||
"denied": "Rot får inte logga in över SSH",
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5630,9 +5683,9 @@
|
||||
"title": "Volume assignment",
|
||||
"rationale": "Gästvolymer på lokal lagring mot referenserna i aktuella, väntande och ögonblicksbildskonfigurationer. Säkerhetskopior, ISO-filer och mallar ligger utanför jämförelsen. En volym utan referens är en kandidat för granskning.",
|
||||
"summary": {
|
||||
"none": "No orphaned volumes were found",
|
||||
"found": "{count} volymer saknar referens i de granskade konfigurationerna",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"none": "Inga föräldralösa volymer hittades",
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
},
|
||||
"zfs_arc_max": {
|
||||
@@ -5640,21 +5693,21 @@
|
||||
"rationale": "Effektiva värden för c_min, c_max och ARC-storlek, den laddade modulparametern och de bestående inställningarna i /etc/modprobe.d. Ett konfigurerat nollvärde väljer modulens standard; ARC är ett tak och minnet under det är återvinningsbart.",
|
||||
"summary": {
|
||||
"bounded": "ARC-gränsen är {percent}% av värdens minne, och minnet under den är återvinningsbart",
|
||||
"high": "The ARC may use {percent}% of host memory",
|
||||
"unset": "The ARC has no explicit limit set",
|
||||
"conflicting": "{count} ARC-inställningar stämmer inte överens",
|
||||
"pending": "En bestående ARC-inställning skiljer sig från värdet den körande modulen bär",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"high": "ARC kan använda {percent}% av värdminnet",
|
||||
"unset": "ARC har ingen tydlig gränsuppsättning",
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
},
|
||||
"zfs_scrub_age": {
|
||||
"title": "ZFS scrub",
|
||||
"rationale": "Den senaste avslutade scrub som `zpool status` registrerar för varje pool. En resilver är inte en scrub. En nyligen skapad pool har ännu inte haft tillfälle till en.",
|
||||
"summary": {
|
||||
"recent": "The {total} pool(s) were scrubbed within the last 35 days",
|
||||
"overdue": "{count} of {total} pool(s) have not been scrubbed in 35 days",
|
||||
"neverScrubbed": "{count} pool(s) record no scrub",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"recent": "{total} pool(s) skrubbades under de senaste 35 dagarna",
|
||||
"overdue": "{count} av {total} pool(s) har inte skrubbats på 35 dagar",
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
},
|
||||
"thin_pool_overprovisioning": {
|
||||
@@ -5664,7 +5717,7 @@
|
||||
"withinRatio": "De {total} thin-poolerna ligger under de tillämpade granskningsgränserna",
|
||||
"aboveRatio": "{count} av {total} thin-pooler delar ut mer kapacitet än de har",
|
||||
"pressure": "{pressure} av {total} thin-pooler närmar sig att fylla data eller metadata",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
},
|
||||
"connected_storage": {
|
||||
@@ -5673,7 +5726,7 @@
|
||||
"summary": {
|
||||
"available": "PVE rapporterar alla {total} lagringar som tillgängliga; fjärrsystemens interna delar och skrivåtkomst testades inte",
|
||||
"attention": "{count} av {total} lagringar behöver granskas",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
},
|
||||
"pool_integrity": {
|
||||
@@ -5691,7 +5744,7 @@
|
||||
"summary": {
|
||||
"healthy": "Ceph rapporterar HEALTH_OK",
|
||||
"degraded": "Ceph rapporterar {state}, med {count} namngivna kontroller",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
},
|
||||
"array_integrity": {
|
||||
@@ -5700,7 +5753,7 @@
|
||||
"summary": {
|
||||
"intact": "De {total} uppsättningarna och kartorna behåller sin redundans",
|
||||
"degraded": "{count} av {total} uppsättningar eller kartor saknar den",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5712,7 +5765,7 @@
|
||||
"withinLife": "De {total} diskavläsningarna ligger under femårströskeln",
|
||||
"pastLife": "{count} av {total} diskavläsningar överskrider fem års drift",
|
||||
"noReadings": "Ingen disk rapporterar användbara SMART-värden ({skipped} utan avläsningar)",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
},
|
||||
"disk_errors": {
|
||||
@@ -5729,23 +5782,22 @@
|
||||
"title": "Bond members",
|
||||
"rationale": "MII-status för varje bond-medlem från /proc/net/bonding och hur många länkar som återstår. I active-backup rapporterar en reservmedlem som uppe och bär ingen trafik.",
|
||||
"summary": {
|
||||
"allUp": "All members of the {total} bond(s) are up",
|
||||
"membersDown": "{count} bond member(s) are not up",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"allUp": "Alla medlemmar av {total} obligationer är uppe",
|
||||
"membersDown": "{count} obligationsmedlem (er) är inte upp",
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
},
|
||||
"bridge_without_ports": {
|
||||
"title": "Bridge ports",
|
||||
"rationale": "Portkonfigurationen för varje bridge. En bridge utan fysisk port betjänar ett internt eller routat nät.",
|
||||
"summary": {
|
||||
"allConnected": "The {total} bridge(s) carry a port",
|
||||
"isolated": "{count} of {total} bridge(s) carry no port",
|
||||
"evaluationFailed": "The check could not be evaluated"
|
||||
"allConnected": "{total} bron bär en port",
|
||||
"evaluationFailed": "Kontrollen kunde inte utvärderas"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"summaryFallback": "The check could not be evaluated",
|
||||
"acceptRisk": {
|
||||
"action": "Acceptera risken",
|
||||
"revoke": "Återför till aktiva",
|
||||
@@ -5779,17 +5831,15 @@
|
||||
"OK": "OK"
|
||||
},
|
||||
"viewSwitch": {
|
||||
"ariaLabel": "Switch between assessment and inventory",
|
||||
"assessment": "Assessment",
|
||||
"inventory": "Inventory",
|
||||
"policy": "Policy",
|
||||
"changes": "Ändringar"
|
||||
"changes": "Ändringar",
|
||||
"ariaLabel": "Växla mellan bedömning och lager"
|
||||
},
|
||||
"inventory": {
|
||||
"loading": "Loading inventory…",
|
||||
"failed": "The inventory could not be composed.",
|
||||
"collectedAt": "Composed on {when}",
|
||||
"unavailable": "Not read in this inventory",
|
||||
"unresolved": "path not resolved",
|
||||
"noUplink": "no uplink",
|
||||
"identity": "Node identity",
|
||||
@@ -5832,12 +5882,10 @@
|
||||
"protection": "Backup",
|
||||
"passthrough": "Passthrough",
|
||||
"noBackup": "No backup",
|
||||
"noBackupDetail": "No enabled backup job selects this guest.",
|
||||
"applications": "Applications",
|
||||
"versionUnknown": "version not detected",
|
||||
"passthroughTitle": "PCI passthrough",
|
||||
"iommuGroup": "IOMMU group {group}",
|
||||
"sharedGroup": "{count} more device(s) in the same group",
|
||||
"proxmenux": "ProxMenux optimizations",
|
||||
"latency": "Nätverkslatens",
|
||||
"subscriptionStatus": {
|
||||
@@ -5848,7 +5896,11 @@
|
||||
"suspended": "Pausad",
|
||||
"new": "Väntar på aktivering",
|
||||
"unknown": "Okänd"
|
||||
}
|
||||
},
|
||||
"failed": "Inventeringen kunde inte komponeras.",
|
||||
"unavailable": "Läs inte i denna inventering",
|
||||
"noBackupDetail": "Inget aktiverat backup jobb väljer denna gäst.",
|
||||
"sharedGroup": "{count} fler enheter (er) i samma grupp"
|
||||
},
|
||||
"profile": {
|
||||
"label": "Report",
|
||||
@@ -5871,7 +5923,6 @@
|
||||
"area": "Area",
|
||||
"inventoryAnnex": "Inventory annex",
|
||||
"scopeTitle": "Scope of this report",
|
||||
"scopeBody": "This report describes the Proxmox VE node named above, as observed from the node itself at the time stated. It does not cover the interior of the guests beyond what they declare, network equipment outside the host, physical infrastructure, or any dependency not visible from this node. Findings marked as not determined were not measured and are not evidence of absence.",
|
||||
"building": "Rapporten sätts samman…",
|
||||
"node": "Nod",
|
||||
"profile": "Profil",
|
||||
@@ -6020,11 +6071,12 @@
|
||||
"structureSubtitle": "Hur {node} är byggd och konfigurerad",
|
||||
"postureTitle": "Posture",
|
||||
"posture": {
|
||||
"security": "Host exposure and access.",
|
||||
"backup": "Guest protection and whether it is real.",
|
||||
"capacity": "Room to grow and the wear on the disks."
|
||||
"security": "Värd exponering och åtkomst.",
|
||||
"backup": "Gästskydd och om det är verkligt.",
|
||||
"capacity": "Rum att växa och slitage på diskarna."
|
||||
},
|
||||
"scopeReadOnly": "Bedömningen inspekterar värdinställningar och hälsa. Den kan skriva rapporter och loggar; startstatuskontroller kan tillfälligt montera EFI-systempartitioner."
|
||||
"scopeReadOnly": "Bedömningen inspekterar värdinställningar och hälsa. Den kan skriva rapporter och loggar; startstatuskontroller kan tillfälligt montera EFI-systempartitioner.",
|
||||
"scopeBody": "Denna rapport beskriver Proxmox VE-noden som nämns ovan, som observerats från noden själv vid den tidpunkt som anges. Det täcker inte insidan av gästerna bortom vad de deklarerar, nätverksutrustning utanför värden, fysisk infrastruktur eller något beroende som inte är synligt från denna nod. Resultat som inte fastställts mättes inte och är inte bevis på frånvaro."
|
||||
},
|
||||
"results": "Resultat",
|
||||
"classifications": {
|
||||
@@ -6178,15 +6230,19 @@
|
||||
"notApplicableScope": "Inget i det granskade omfånget som den här kontrollen gäller.",
|
||||
"lynis": {
|
||||
"title": "Run Lynis",
|
||||
"bodyNotRun": "Lynis is installed but has not been run yet. Running it now completes the security review, but the process can take a few minutes.",
|
||||
"bodyStale": "The Lynis report is {days} days old. You can run it now to refresh the data (it takes a little longer) or continue with the existing report.",
|
||||
"withLynis": "Run with Lynis",
|
||||
"withoutLynis": "Run without Lynis",
|
||||
"cancel": "Cancel"
|
||||
"cancel": "Cancel",
|
||||
"bodyNotRun": "Lynis är installerad men har inte körts ännu. Kör det nu slutför säkerhetsgranskningen, men processen kan ta några minuter.",
|
||||
"bodyStale": "Lynis-rapporten är {days} dagar gammal. Du kan köra det nu för att uppdatera data (det tar lite längre) eller fortsätta med den befintliga rapporten."
|
||||
},
|
||||
"readOnlyNotice": "Bedömningen inspekterar värdinställningar och hälsa. Den kan skriva rapporter och loggar; startstatuskontroller kan tillfälligt montera EFI-systempartitioner.",
|
||||
"noActionNeeded": "Inget att göra. Denna kontroll fann vad den förväntar sig att hitta.",
|
||||
"couldNotEvaluate": "Denna kontroll kunde inte utvärderas, så det rapporterar ingenting heller. Beviset registrerar vad det inte kunde läsa."
|
||||
"couldNotEvaluate": "Denna kontroll kunde inte utvärderas, så det rapporterar ingenting heller. Beviset registrerar vad det inte kunde läsa.",
|
||||
"neverRun": "Denna värd har inte bedömts ännu.",
|
||||
"noFindings": "Inga resultat matchar det aktuella filtret.",
|
||||
"acceptedNotice": "{count} accepterade risker registrerade på denna värd.",
|
||||
"summaryFallback": "Kontrollen kunde inte utvärderas"
|
||||
},
|
||||
"runtime": {
|
||||
"notifications": {
|
||||
@@ -6298,8 +6354,8 @@
|
||||
},
|
||||
"migration_start": {
|
||||
"title": "{hostname}: Migrering startade — {vmname} ({vmid})",
|
||||
"body": "Live migration of {vmname} (ID: {vmid}) to node {target_node} has started.",
|
||||
"label": "Migreringen startade"
|
||||
"label": "Migreringen startade",
|
||||
"body": "Levande migration av {vmname} (ID: {vmid}) till nod {target_node} har börjat."
|
||||
},
|
||||
"migration_complete": {
|
||||
"title": "{hostname}: Migreringen slutförd — {vmname} ({vmid})",
|
||||
@@ -6468,8 +6524,8 @@
|
||||
},
|
||||
"node_disconnect": {
|
||||
"title": "{hostname}: Nod {node_name} frånkopplad",
|
||||
"body": "Node {node_name} has disconnected from the cluster.",
|
||||
"label": "Noden frånkopplad"
|
||||
"label": "Noden frånkopplad",
|
||||
"body": "Nod {node_name} har kopplats från klustret."
|
||||
},
|
||||
"node_reconnect": {
|
||||
"title": "{hostname}: Noden {node_name} återansluten",
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "ProxMenux-Monitor",
|
||||
"version": "1.2.6.1-beta",
|
||||
"version": "1.2.6.2-beta",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ProxMenux-Monitor",
|
||||
"version": "1.2.6.1-beta",
|
||||
"version": "1.2.6.2-beta",
|
||||
"dependencies": {
|
||||
"@hookform/resolvers": "^3.10.0",
|
||||
"@radix-ui/react-accordion": "1.2.2",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ProxMenux-Monitor",
|
||||
"version": "1.2.6.1-beta",
|
||||
"version": "1.2.6.2-beta",
|
||||
"description": "Proxmox System Monitoring Dashboard",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
@@ -136,6 +136,8 @@ cp "$SCRIPT_DIR/flask_proxmenux_routes.py" "$APP_DIR/usr/bin/" 2>/dev/null || ec
|
||||
cp "$SCRIPT_DIR/post_install_versions.py" "$APP_DIR/usr/bin/" 2>/dev/null || echo "⚠️ post_install_versions.py not found"
|
||||
cp "$SCRIPT_DIR/mount_monitor.py" "$APP_DIR/usr/bin/" 2>/dev/null || echo "⚠️ mount_monitor.py not found"
|
||||
cp "$SCRIPT_DIR/lxc_mount_points.py" "$APP_DIR/usr/bin/" 2>/dev/null || echo "⚠️ lxc_mount_points.py not found"
|
||||
cp "$SCRIPT_DIR/oci_console_logs.py" "$APP_DIR/usr/bin/" 2>/dev/null || echo "⚠️ oci_console_logs.py not found"
|
||||
cp "$SCRIPT_DIR/oci_instance_info.py" "$APP_DIR/usr/bin/" 2>/dev/null || echo "⚠️ oci_instance_info.py not found"
|
||||
cp "$SCRIPT_DIR/disk_temperature_history.py" "$APP_DIR/usr/bin/" 2>/dev/null || echo "⚠️ disk_temperature_history.py not found"
|
||||
cp "$SCRIPT_DIR/smartctl_resolver.py" "$APP_DIR/usr/bin/" 2>/dev/null || echo "⚠️ smartctl_resolver.py not found"
|
||||
cp "$SCRIPT_DIR/disk_identity.py" "$APP_DIR/usr/bin/" 2>/dev/null || echo "⚠️ disk_identity.py not found"
|
||||
|
||||
@@ -865,108 +865,28 @@ _PVE_OUR_HEADERS = {
|
||||
}
|
||||
|
||||
|
||||
def _ssl_cert_hostname(cert_path: str) -> str:
|
||||
"""Pull the most useful hostname out of an x509 cert.
|
||||
|
||||
Preference order: first DNS SAN → CN. Returns '' on any failure.
|
||||
Used to build a webhook URL that won't fail PVE's TLS verification
|
||||
(issue #239 — PVE has no `--insecure` flag and the user's ACME cert
|
||||
is bound to a hostname, not to `127.0.0.1`).
|
||||
"""
|
||||
try:
|
||||
import subprocess
|
||||
out = subprocess.run(
|
||||
['openssl', 'x509', '-in', cert_path, '-noout',
|
||||
'-ext', 'subjectAltName', '-subject'],
|
||||
capture_output=True, text=True, timeout=5,
|
||||
)
|
||||
if out.returncode != 0:
|
||||
return ''
|
||||
text = out.stdout or ''
|
||||
# SAN line example: " DNS:pve.example.com, DNS:pve, IP Address:..."
|
||||
import re
|
||||
for line in text.splitlines():
|
||||
m = re.search(r'DNS:([A-Za-z0-9.\-]+)', line)
|
||||
if m:
|
||||
return m.group(1)
|
||||
# CN fallback. "subject= CN = pve.example.com" or "...CN=pve.example.com"
|
||||
m = re.search(r'CN\s*=\s*([A-Za-z0-9.\-]+)', text)
|
||||
if m:
|
||||
return m.group(1)
|
||||
except Exception:
|
||||
pass
|
||||
return ''
|
||||
|
||||
|
||||
def _hostname_resolves_locally(hostname: str) -> bool:
|
||||
"""True when `hostname` resolves to one of this host's own IPs.
|
||||
|
||||
Anti-misconfig: refuse to build a webhook URL that points
|
||||
elsewhere (a stale DNS entry pointing at the previous host, a CN
|
||||
that names a different node in the cluster, etc.). PVE delivers
|
||||
webhooks from the same node, so the URL has to round-trip to
|
||||
ourselves.
|
||||
"""
|
||||
try:
|
||||
import socket
|
||||
import ipaddress
|
||||
target_ips = set()
|
||||
for info in socket.getaddrinfo(hostname, None):
|
||||
ip = info[4][0]
|
||||
target_ips.add(ipaddress.ip_address(ip).compressed)
|
||||
# Collect our own IPs from /proc/net/fib_trie isn't portable; use
|
||||
# psutil if available, otherwise fall back to socket on the
|
||||
# hostname itself.
|
||||
local_ips = {'127.0.0.1', '::1'}
|
||||
try:
|
||||
import psutil
|
||||
for _iface, addrs in psutil.net_if_addrs().items():
|
||||
for a in addrs:
|
||||
if a.family in (socket.AF_INET, socket.AF_INET6):
|
||||
local_ips.add(ipaddress.ip_address(a.address.split('%')[0]).compressed)
|
||||
except Exception:
|
||||
pass
|
||||
return bool(target_ips & local_ips)
|
||||
except Exception:
|
||||
return False
|
||||
# With HTTPS enabled, PVE delivers its notifications to a plain-HTTP listener
|
||||
# the Monitor opens on loopback only for this route (see flask_server). PVE's
|
||||
# webhook client validates certificates against the system CA store, which
|
||||
# does not hold a self-signed, ACME-staging or PVE-CA-signed Monitor
|
||||
# certificate, so an https target fails with "unable to get local issuer
|
||||
# certificate" on every notification.
|
||||
WEBHOOK_LOOPBACK_PORT = 8009
|
||||
|
||||
|
||||
def _pve_webhook_url() -> str:
|
||||
"""Return the URL we register with PVE as our webhook target.
|
||||
|
||||
Three branches:
|
||||
1. SSL off → http://127.0.0.1:8008 (always works, no cert).
|
||||
2. SSL on + cert hostname extractable and resolves locally →
|
||||
https://<cert-hostname>:8008. This is what PVE's TLS layer
|
||||
actually validates against. Without this, PVE rejects the
|
||||
self/ACME cert with "IP address mismatch" (issue #239).
|
||||
3. SSL on but hostname extraction/check failed → fall back to
|
||||
https://127.0.0.1:8008 and accept that the user may still
|
||||
hit the cert-mismatch error. We log so the operator can
|
||||
diagnose. Better than silently emitting a wrong URL.
|
||||
"""
|
||||
"""Return the URL we register with PVE as our webhook target: the
|
||||
Monitor itself over HTTP when SSL is off, and its loopback-only HTTP
|
||||
listener when SSL is on. Both stay on 127.0.0.1, so nothing crosses
|
||||
the network and no certificate is involved."""
|
||||
try:
|
||||
from auth_manager import load_ssl_config
|
||||
cfg = load_ssl_config() or {}
|
||||
if not cfg.get('enabled'):
|
||||
return 'http://127.0.0.1:8008/api/notifications/webhook'
|
||||
|
||||
cert_path = cfg.get('cert_path') or ''
|
||||
if cert_path:
|
||||
host = _ssl_cert_hostname(cert_path)
|
||||
if host and _hostname_resolves_locally(host):
|
||||
return f'https://{host}:8008/api/notifications/webhook'
|
||||
if host:
|
||||
print(
|
||||
f"[ProxMenux] webhook URL fallback to 127.0.0.1: "
|
||||
f"cert hostname '{host}' does not resolve to a local "
|
||||
f"IP — PVE will likely report a TLS verification "
|
||||
f"error. Fix by ensuring the FQDN resolves on this "
|
||||
f"host (e.g. /etc/hosts entry)."
|
||||
)
|
||||
return 'https://127.0.0.1:8008/api/notifications/webhook'
|
||||
if cfg.get('enabled'):
|
||||
return f'http://127.0.0.1:{WEBHOOK_LOOPBACK_PORT}/api/notifications/webhook'
|
||||
except Exception:
|
||||
return 'http://127.0.0.1:8008/api/notifications/webhook'
|
||||
pass
|
||||
return 'http://127.0.0.1:8008/api/notifications/webhook'
|
||||
|
||||
|
||||
# Backward-compat alias for callers that read this at import time. Most
|
||||
@@ -988,15 +908,48 @@ def _pve_read_file(path):
|
||||
return None, str(e)
|
||||
|
||||
|
||||
_PVE_BACKUPS_KEPT = 3
|
||||
|
||||
|
||||
def _pve_backup_file(path):
|
||||
"""Create timestamped backup if file exists. Never fails fatally."""
|
||||
"""Create timestamped backup if file exists. Never fails fatally.
|
||||
|
||||
The backups live next to the file, inside the cluster filesystem, whose
|
||||
size is limited: a copy identical to the newest one is not written again
|
||||
and only the newest few are kept. Restore uses the newest.
|
||||
"""
|
||||
import os, shutil
|
||||
from datetime import datetime
|
||||
try:
|
||||
if os.path.exists(path):
|
||||
if not os.path.exists(path):
|
||||
return
|
||||
directory, name = os.path.split(path)
|
||||
prefix = f"{name}.proxmenux_backup_"
|
||||
existing = sorted(
|
||||
(os.path.join(directory, f) for f in os.listdir(directory) if f.startswith(prefix)),
|
||||
key=os.path.getmtime, reverse=True,
|
||||
)
|
||||
with open(path, 'rb') as f:
|
||||
current = f.read()
|
||||
newest_matches = False
|
||||
if existing:
|
||||
try:
|
||||
with open(existing[0], 'rb') as f:
|
||||
newest_matches = f.read() == current
|
||||
except OSError:
|
||||
pass
|
||||
if not newest_matches:
|
||||
ts = datetime.now().strftime('%Y%m%d_%H%M%S')
|
||||
backup = f"{path}.proxmenux_backup_{ts}"
|
||||
shutil.copy2(path, backup)
|
||||
shutil.copy2(path, os.path.join(directory, prefix + ts))
|
||||
existing = sorted(
|
||||
(os.path.join(directory, f) for f in os.listdir(directory) if f.startswith(prefix)),
|
||||
key=os.path.getmtime, reverse=True,
|
||||
)
|
||||
for stale in existing[_PVE_BACKUPS_KEPT:]:
|
||||
try:
|
||||
os.remove(stale)
|
||||
except OSError:
|
||||
pass
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
@@ -703,6 +703,36 @@ def _warmup_lxc_ip_cache() -> int:
|
||||
return count
|
||||
|
||||
|
||||
def _lxc_isolated_ips(vmid):
|
||||
"""Static addresses on interfaces that have no way out of the host.
|
||||
|
||||
lxc-info lists a container's addresses without saying which interface
|
||||
carries each, so a container with a second network leg could be offered
|
||||
at an address nobody can open: a ProxMenux stack wires its members through
|
||||
a private bridge, and Paperless-ngx answered on 10.77.0.30 instead of its
|
||||
LAN address. The interface a reader reaches is the one with a route out —
|
||||
DHCP, or a static address with a gateway. A static address with no gateway
|
||||
is local to the host, and is kept only as a last resort.
|
||||
"""
|
||||
try:
|
||||
with open(f"/etc/pve/lxc/{int(vmid)}.conf", encoding="utf-8") as handle:
|
||||
text = handle.read()
|
||||
except (OSError, ValueError):
|
||||
return set()
|
||||
isolated = set()
|
||||
for line in text.splitlines():
|
||||
if line.startswith("["):
|
||||
break # snapshot sections describe past states, not this one
|
||||
match = re.match(r"net\d+:\s*(.*)", line)
|
||||
if not match:
|
||||
continue
|
||||
options = dict(part.split("=", 1) for part in match.group(1).split(",") if "=" in part)
|
||||
address = options.get("ip", "")
|
||||
if address and address not in ("dhcp", "manual") and "gw" not in options:
|
||||
isolated.add(address.split("/", 1)[0])
|
||||
return isolated
|
||||
|
||||
|
||||
def get_lxc_ip_from_lxc_info(vmid):
|
||||
"""Get LXC IP addresses using lxc-info command (for DHCP containers)
|
||||
Returns a dict with all IPs and classification"""
|
||||
@@ -730,6 +760,9 @@ def get_lxc_ip_from_lxc_info(vmid):
|
||||
else:
|
||||
# Real network IPs (192.168.x.x, 10.x.x.x, etc.)
|
||||
real_ips.append(ip)
|
||||
isolated = _lxc_isolated_ips(vmid)
|
||||
if isolated:
|
||||
real_ips.sort(key=lambda ip: ip in isolated)
|
||||
|
||||
return {
|
||||
'all_ips': ips,
|
||||
@@ -3394,7 +3427,7 @@ def get_available_updates():
|
||||
_system_info_cache['available_updates_stamp'] = stamp
|
||||
return available_updates
|
||||
|
||||
# AGREGANDO FUNCIÓN PARA PARSEAR PROCESOS DE INTEL_GPU_TOP (SIN -J)
|
||||
# Parse intel_gpu_top process output without -J.
|
||||
def get_intel_gpu_processes_from_text():
|
||||
"""Parse processes from intel_gpu_top text output (more reliable than JSON)"""
|
||||
try:
|
||||
@@ -3409,7 +3442,7 @@ def get_intel_gpu_processes_from_text():
|
||||
bufsize=1
|
||||
)
|
||||
except FileNotFoundError:
|
||||
# intel_gpu_top no está instalado, retornar lista vacía
|
||||
# intel_gpu_top is not installed; return an empty list
|
||||
return []
|
||||
|
||||
# Wait 2 seconds for intel_gpu_top to collect data
|
||||
@@ -5544,7 +5577,7 @@ def _get_proxmox_storage_uncached():
|
||||
for resource in resources:
|
||||
node = resource.get('node', '')
|
||||
|
||||
# Filtrar solo storage del nodo local
|
||||
# Keep only the local node storage
|
||||
if node != local_node:
|
||||
# print(f"[v0] Skipping storage {resource.get('storage')} from remote node: {node}")
|
||||
pass
|
||||
@@ -5563,7 +5596,7 @@ def _get_proxmox_storage_uncached():
|
||||
pass
|
||||
continue
|
||||
|
||||
# No filtrar storages no disponibles - mantenerlos para mostrar errores
|
||||
# Keep unavailable storages so their errors stay visible
|
||||
# Calcular porcentaje
|
||||
percent = (used / total * 100) if total > 0 else 0.0
|
||||
|
||||
@@ -7862,7 +7895,7 @@ def get_detailed_gpu_info(gpu):
|
||||
else:
|
||||
# print(f"[v0] WARNING: No valid JSON objects found", flush=True)
|
||||
pass
|
||||
# CHANGE: Evitar bloqueo al leer stderr - usar communicate() con timeout
|
||||
# communicate() with a timeout: reading stderr directly blocks
|
||||
try:
|
||||
# Use communicate() with timeout instead of read() to avoid blocking
|
||||
_, stderr_output = process.communicate(timeout=0.5)
|
||||
@@ -8342,8 +8375,7 @@ def get_detailed_gpu_info(gpu):
|
||||
# print(f"[v0] Parsing fdinfo with {len(fdinfo)} entries", flush=True)
|
||||
pass
|
||||
|
||||
# CHANGE: Corregir parseo de fdinfo con estructura anidada
|
||||
# fdinfo es un diccionario donde las claves son los PIDs (como strings)
|
||||
# fdinfo is nested: the keys are the PIDs, as strings
|
||||
for pid_str, proc_data in fdinfo.items():
|
||||
try:
|
||||
process_info = {
|
||||
@@ -13794,6 +13826,13 @@ def api_vm_apps_suggestions(vmid):
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
|
||||
@app.route('/api/vms/<int:vmid>/apps/adguard-setup', methods=['GET'])
|
||||
@require_auth
|
||||
def api_vm_apps_adguard_setup(vmid):
|
||||
import lxc_apps
|
||||
return jsonify({'available': lxc_apps.oci_adguard_setup_available(vmid)})
|
||||
|
||||
|
||||
@app.route('/api/vms/<int:vmid>/docker/inventory', methods=['GET'])
|
||||
@require_auth
|
||||
def api_vm_docker_inventory(vmid):
|
||||
@@ -14143,6 +14182,8 @@ def _lxc_update_target_labels(
|
||||
label = 'Applications'
|
||||
elif target == 'docker-engine':
|
||||
label = 'Docker Engine'
|
||||
elif target == 'oci_image':
|
||||
label = 'OCI image'
|
||||
elif target.startswith('app:'):
|
||||
app_item = apps.get(target.split(':', 1)[1]) or {}
|
||||
label = str(app_item.get('name') or 'Application')
|
||||
@@ -15107,7 +15148,7 @@ def api_vms_modal_cache_all():
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
|
||||
# CHANGE: Modificar el endpoint para incluir la información completa de IPs
|
||||
# The endpoint returns the complete IP information.
|
||||
@app.route('/api/vms/<int:vmid>', methods=['GET'])
|
||||
@require_auth
|
||||
def get_vm_config(vmid):
|
||||
@@ -15245,6 +15286,38 @@ def api_lxc_mount_points_runtime(vmid):
|
||||
return jsonify({"ok": False, "error": str(e)}), 500
|
||||
|
||||
|
||||
@app.route('/api/lxc/<int:vmid>/console-log', methods=['GET'])
|
||||
@require_auth
|
||||
def api_lxc_console_log(vmid):
|
||||
"""Console output of a native OCI container. Never cached: the first
|
||||
request returns the last `lines` lines, later ones pass back `offset`
|
||||
and `inode` to receive only what was appended since."""
|
||||
try:
|
||||
import oci_console_logs
|
||||
except ImportError as e:
|
||||
return jsonify({"ok": False, "error": f"helper unavailable: {e}"}), 503
|
||||
try:
|
||||
lines = request.args.get('lines', default=200, type=int)
|
||||
offset = request.args.get('offset', type=int)
|
||||
inode = request.args.get('inode', type=int)
|
||||
return jsonify(oci_console_logs.read(vmid, lines=lines, offset=offset, inode=inode))
|
||||
except Exception as e:
|
||||
return jsonify({"ok": False, "error": str(e)}), 500
|
||||
|
||||
|
||||
@app.route('/api/lxc/<int:vmid>/oci-instance', methods=['GET'])
|
||||
@require_auth
|
||||
def api_lxc_oci_instance(vmid):
|
||||
"""Whether the container was installed by OCI manager Apps, its stack,
|
||||
host directories and pending operation, read from its record. Never
|
||||
cached; it also says whether the console log exists (Logs tab)."""
|
||||
try:
|
||||
import oci_instance_info
|
||||
return jsonify(oci_instance_info.info(vmid))
|
||||
except Exception as e:
|
||||
return jsonify({"ok": False, "error": str(e)}), 500
|
||||
|
||||
|
||||
@app.route('/api/vms/<int:vmid>/logs', methods=['GET'])
|
||||
@require_auth
|
||||
def api_vm_logs(vmid):
|
||||
@@ -22191,6 +22264,41 @@ def _run_scheduled_update(vmid: int, sched: dict) -> dict:
|
||||
}
|
||||
|
||||
requested_target = sched.get("target") or "both"
|
||||
if requested_targets == ['oci_image']:
|
||||
# A container installed by OCI manager Apps is updated by replacing
|
||||
# its image, through the same flow as the OCI menu, unattended.
|
||||
command = ['bash', '/usr/local/share/proxmenux/scripts/oci/oci_manager_apps.sh',
|
||||
'manage', str(vmid), '--action', 'update', '--unattended']
|
||||
storage = (sched.get('backup_storage') or '').strip()
|
||||
if sched.get('backup') and storage:
|
||||
command += ['--keep-backup', storage]
|
||||
if sched.get('acknowledge_external_data'):
|
||||
command.append('--acknowledge-external-data')
|
||||
delay = int(sched.get('release_delay_days') or 0)
|
||||
if delay > 0:
|
||||
command += ['--min-image-age-days', str(delay)]
|
||||
try:
|
||||
proc = subprocess.run(command, stdin=subprocess.DEVNULL, capture_output=True, text=True,
|
||||
timeout=4 * 3600, env=dict(os.environ, TERM='dumb'))
|
||||
except subprocess.TimeoutExpired:
|
||||
reasons.append('the OCI image update did not finish in time')
|
||||
return finish('failure', 'oci_image', [])
|
||||
output = re.sub(r'\x1b\[[0-9;?]*[ -/]*[@-~]|\x1b[()][A-Z0-9]|\r', '', (proc.stdout or '') + (proc.stderr or ''))
|
||||
_append_lxc_update_log(log_path, output)
|
||||
if proc.returncode == 0:
|
||||
return finish('success', 'oci_image', ['oci_image'])
|
||||
if proc.returncode == 5:
|
||||
deferred_targets.append('oci_image')
|
||||
reasons.append(f'the new image is younger than {delay} days')
|
||||
return finish('deferred', 'oci_image', [])
|
||||
if proc.returncode == 4:
|
||||
reasons.append('the container has changes made outside ProxMenux; review them in OCI manager Apps')
|
||||
return finish('skipped', 'oci_image', [])
|
||||
if proc.returncode == 3:
|
||||
reasons.append('another OCI operation was running')
|
||||
return finish('skipped', 'oci_image', [])
|
||||
reasons.append('the OCI image update failed; the previous installation is restored when the update started')
|
||||
return finish('failure', 'oci_image', [])
|
||||
if not os.path.isfile(_APPLY_UPDATES_SCRIPT):
|
||||
reasons.append('update runner is not installed')
|
||||
return finish('skipped', requested_target, [])
|
||||
@@ -22774,6 +22882,18 @@ if __name__ == '__main__':
|
||||
print(f"[ProxMenux] SSL config error, falling back to HTTP: {e}")
|
||||
ssl_ctx = None
|
||||
|
||||
# With HTTPS on, PVE cannot validate the Monitor certificate against the
|
||||
# system CA store, so its webhook is delivered to this plain-HTTP
|
||||
# listener instead. It binds 127.0.0.1 only and answers nothing but the
|
||||
# webhook route.
|
||||
from flask_notification_routes import WEBHOOK_LOOPBACK_PORT
|
||||
|
||||
def _webhook_loopback_app(environ, start_response):
|
||||
if environ.get('PATH_INFO') == '/api/notifications/webhook':
|
||||
return app(environ, start_response)
|
||||
start_response('404 Not Found', [('Content-Type', 'text/plain')])
|
||||
return [b'Not found']
|
||||
|
||||
# Use gevent for SSL+WebSocket support, or fallback to Flask dev server
|
||||
gevent_available = False
|
||||
ssl_loaded = False
|
||||
@@ -22872,11 +22992,26 @@ if __name__ == '__main__':
|
||||
ssl_context=ssl_context
|
||||
)
|
||||
gevent_available = True
|
||||
try:
|
||||
webhook_server = pywsgi.WSGIServer(
|
||||
('127.0.0.1', WEBHOOK_LOOPBACK_PORT), _webhook_loopback_app, log=None)
|
||||
webhook_server.start()
|
||||
print(f"[ProxMenux] PVE webhook listener on 127.0.0.1:{WEBHOOK_LOOPBACK_PORT}")
|
||||
except Exception as _e:
|
||||
print(f"[ProxMenux] WARN: PVE webhook listener could not start on "
|
||||
f"127.0.0.1:{WEBHOOK_LOOPBACK_PORT} ({_e}); PVE notifications will not arrive", flush=True)
|
||||
server.serve_forever()
|
||||
except ImportError as e:
|
||||
print(f"[ProxMenux] gevent not available ({e})")
|
||||
# Fallback: Flask dev server with SSL - flask-sock handles WebSockets
|
||||
ssl_context = auth_manager.create_reloadable_ssl_context(ssl_cert, ssl_key)
|
||||
try:
|
||||
from werkzeug.serving import make_server
|
||||
_webhook_srv = make_server('127.0.0.1', WEBHOOK_LOOPBACK_PORT, _webhook_loopback_app, threaded=True)
|
||||
threading.Thread(target=_webhook_srv.serve_forever, daemon=True).start()
|
||||
print(f"[ProxMenux] PVE webhook listener on 127.0.0.1:{WEBHOOK_LOOPBACK_PORT}")
|
||||
except Exception as _e:
|
||||
print(f"[ProxMenux] WARN: PVE webhook listener could not start ({_e})", flush=True)
|
||||
print("[ProxMenux] Starting Flask server with SSL (using flask-sock for WebSockets)...")
|
||||
app.run(host='::', port=8008, debug=False, ssl_context=ssl_context, threaded=True)
|
||||
else:
|
||||
|
||||
@@ -199,7 +199,7 @@ def search_command():
|
||||
'command': stripped
|
||||
})
|
||||
|
||||
# Resetear descripciones para el siguiente comando
|
||||
# Reset the descriptions for the next command
|
||||
current_description = []
|
||||
|
||||
return jsonify({
|
||||
|
||||
@@ -4146,7 +4146,8 @@ class HealthMonitor:
|
||||
New thresholds:
|
||||
- CASCADE: ≥15 errors (increased from 10)
|
||||
- SPIKE: ≥5 errors AND 4x increase (more restrictive)
|
||||
- PERSISTENT: Same error in 3 consecutive checks
|
||||
- PERSISTENT: the same pattern seen in at least 3 checks whose
|
||||
occurrences span 15+ minutes, and still present in this check
|
||||
"""
|
||||
cache_key = 'logs_analysis'
|
||||
current_time = time.time()
|
||||
@@ -4193,6 +4194,8 @@ class HealthMonitor:
|
||||
|
||||
recent_patterns = defaultdict(int)
|
||||
previous_patterns = defaultdict(int)
|
||||
# Patterns present in this check; each counts one check once.
|
||||
seen_this_check = set()
|
||||
critical_errors_found = {} # To store unique critical error lines for persistence
|
||||
|
||||
for line in recent_lines:
|
||||
@@ -4363,10 +4366,15 @@ class HealthMonitor:
|
||||
else:
|
||||
self.persistent_log_patterns[pattern] = {
|
||||
'count': 1,
|
||||
'checks': 0,
|
||||
'first_seen': current_time,
|
||||
'last_seen': current_time,
|
||||
'sample': line.strip()[:200], # Original line for display
|
||||
}
|
||||
if pattern not in seen_this_check:
|
||||
seen_this_check.add(pattern)
|
||||
self.persistent_log_patterns[pattern]['checks'] = \
|
||||
self.persistent_log_patterns[pattern].get('checks', 0) + 1
|
||||
|
||||
for line in previous_lines:
|
||||
if not line.strip():
|
||||
@@ -4409,10 +4417,23 @@ class HealthMonitor:
|
||||
samples.append(clean[:120])
|
||||
return samples
|
||||
|
||||
# A pattern that stopped appearing is forgotten before the
|
||||
# evaluation, and its own warning (if it had one) is closed.
|
||||
patterns_to_remove = [
|
||||
p for p, data in self.persistent_log_patterns.items()
|
||||
if current_time - data['last_seen'] > 1800
|
||||
]
|
||||
for pattern in patterns_to_remove:
|
||||
del self.persistent_log_patterns[pattern]
|
||||
|
||||
# Persistent means recurring: present in this check, seen in at
|
||||
# least three checks, and with occurrences spanning 15 minutes.
|
||||
# A burst that ended is not persistent however long ago it began.
|
||||
persistent_errors = {}
|
||||
for pattern, data in self.persistent_log_patterns.items():
|
||||
time_span = current_time - data['first_seen']
|
||||
if data['count'] >= 3 and time_span >= 900: # 15 minutes
|
||||
span = data['last_seen'] - data['first_seen']
|
||||
if (pattern in seen_this_check and data.get('checks', 1) >= 3
|
||||
and data['count'] >= 3 and span >= 900):
|
||||
persistent_errors[pattern] = data['count']
|
||||
|
||||
# Record as warning if not already recorded
|
||||
@@ -4437,12 +4458,14 @@ class HealthMonitor:
|
||||
'dismissable': True, 'occurrences': data['count']}
|
||||
)
|
||||
|
||||
patterns_to_remove = [
|
||||
p for p, data in self.persistent_log_patterns.items()
|
||||
if current_time - data['last_seen'] > 1800
|
||||
]
|
||||
for pattern in patterns_to_remove:
|
||||
del self.persistent_log_patterns[pattern]
|
||||
# Close the per-pattern warnings of patterns that are no
|
||||
# longer persistent: the burst ended, or it was forgotten.
|
||||
for pattern in list(self.persistent_log_patterns.keys()) + patterns_to_remove:
|
||||
if pattern in persistent_errors:
|
||||
continue
|
||||
stale_key = f'log_persistent_{hashlib.md5(pattern.encode()).hexdigest()[:8]}'
|
||||
if health_persistence.is_error_active(stale_key, category='logs'):
|
||||
health_persistence.clear_error(stale_key)
|
||||
|
||||
# B5 fix: Cap size to prevent unbounded memory growth under high error load
|
||||
MAX_LOG_PATTERNS = 500
|
||||
|
||||
@@ -29,6 +29,7 @@ import datetime
|
||||
import copy
|
||||
import concurrent.futures
|
||||
import hashlib
|
||||
import ipaddress
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
@@ -36,6 +37,7 @@ import signal
|
||||
import shlex
|
||||
import socket
|
||||
import subprocess
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
import urllib.error
|
||||
@@ -62,7 +64,7 @@ _UPSTREAM_CACHE_TTL_SEC = 24 * 3600
|
||||
|
||||
_VALID_METHODS = ("dpkg", "apk", "file", "binary",
|
||||
"python_dist", "docker_label", "docker_exec",
|
||||
"command", "manual")
|
||||
"command", "manual", "oci_image")
|
||||
_DETECTOR_FIELDS = (
|
||||
"package", "file_path", "file_regex", "binary_path", "binary_args",
|
||||
"python_path", "distribution", "container_name", "label",
|
||||
@@ -93,7 +95,7 @@ _VALID_UPSTREAM_TYPES = ("github", "http_json", "docker_hub")
|
||||
# exposes and the freeform "custom" text field.
|
||||
_VALID_SCHEDULE_TARGETS = ("os", "app", "both")
|
||||
_SCHEDULE_TARGET_ID_RE = re.compile(
|
||||
r"^(?:os|apps|app:[A-Za-z0-9_-]{1,64}|docker-engine|docker-(?:compose|container):[A-Za-z0-9][A-Za-z0-9_.-]{0,127}|docker-unit:[a-f0-9]{20})$"
|
||||
r"^(?:os|apps|oci_image|app:[A-Za-z0-9_-]{1,64}|docker-engine|docker-(?:compose|container):[A-Za-z0-9][A-Za-z0-9_.-]{0,127}|docker-unit:[a-f0-9]{20})$"
|
||||
)
|
||||
_BULK_TARGET_ID_RE = re.compile(
|
||||
r"^(?:os|app:[A-Za-z0-9_-]{1,64}|docker-engine|docker-unit:[a-f0-9]{20})$"
|
||||
@@ -886,6 +888,10 @@ def validate_schedule(payload: Any) -> tuple[bool, Any]:
|
||||
"backup_storage": backup_storage,
|
||||
"restart": restart,
|
||||
"release_delay_days": release_delay_days,
|
||||
# Host directories of an OCI container are not reverted by its
|
||||
# backup; a scheduled image update runs only when this was
|
||||
# confirmed when the schedule was saved.
|
||||
"acknowledge_external_data": bool(payload.get("acknowledge_external_data")),
|
||||
}
|
||||
# Preserve `last_run_at` / `last_run_status` when the caller sent
|
||||
# them (typical when the scheduler writes back after firing);
|
||||
@@ -951,7 +957,12 @@ def validate_config(payload: dict) -> tuple[bool, Any]:
|
||||
if method:
|
||||
conf["installed_via"] = method
|
||||
|
||||
if method in ("dpkg", "apk"):
|
||||
if method == "oci_image":
|
||||
# Everything it needs is in the installation record ProxMenux wrote:
|
||||
# the image, the digest and the registry. There is no field to fill
|
||||
# and no upstream to configure.
|
||||
pass
|
||||
elif method in ("dpkg", "apk"):
|
||||
pkg = (payload.get("package") or "").strip()
|
||||
if not pkg or not _PACKAGE_RE.match(pkg):
|
||||
return _err("package is required (letters/digits/._+@:/ up to 127 chars)")
|
||||
@@ -1345,6 +1356,15 @@ def detect_installed_version(vmid, config: dict) -> tuple[Optional[str], Optiona
|
||||
# tag_regex is reused (backward-compat with older hints).
|
||||
pattern = config.get("installed_regex") or config.get("tag_regex") or r"(\d+[.\d]+)"
|
||||
|
||||
if method == "oci_image":
|
||||
result = _oci_image_versions(vmid, with_latest=False)
|
||||
if result.get("error"):
|
||||
return None, result["error"]
|
||||
# An image that states no application version is still an image with
|
||||
# a build date and a digest, which is what its updates are decided on.
|
||||
return (result.get("installed_version")
|
||||
or _oci_image_label(None, result.get("image_created"), result.get("installed_digest"))), None
|
||||
|
||||
if method == "dpkg":
|
||||
rc, out, err = _pct_exec(vmid, ["dpkg-query", "-W", "-f=${Version}", config["package"]])
|
||||
if rc != 0:
|
||||
@@ -3767,9 +3787,14 @@ def partition_scheduled_release_targets(
|
||||
# A delegated app has no updater of its own and never resolves a
|
||||
# release date, so including it would hold the whole schedule back
|
||||
# waiting for a date that will never arrive.
|
||||
# An application ProxMenux installed from an OCI image is updated by
|
||||
# replacing its image through the OCI engine's own transaction, not by
|
||||
# a helper or a command inside the guest, so a scripted plan has
|
||||
# nothing it could run for it.
|
||||
if (not app_id or app.get("managed_oci_app_id")
|
||||
or app.get("helper_slug") == "docker"
|
||||
or app.get("update_via") == "docker"):
|
||||
or app.get("update_via") == "docker"
|
||||
or app.get("installed_via") == "oci_image"):
|
||||
continue
|
||||
if not select_all_apps and app_id not in selected_app_ids:
|
||||
continue
|
||||
@@ -3962,13 +3987,20 @@ def _app_update_notification_payload(vmid, app: dict) -> Optional[dict]:
|
||||
return None
|
||||
state = app.get("state") or {}
|
||||
latest = state.get("latest_version")
|
||||
installed = state.get("installed_version")
|
||||
if app.get("installed_via") == "oci_image" and state.get("latest_digest"):
|
||||
# What is published is an image. Naming it by version, build date and
|
||||
# digest keeps two rebuilds of the same version from being taken for
|
||||
# one notification, and tells the reader what actually changed.
|
||||
latest = _oci_image_label(latest, state.get("latest_image_created"), state.get("latest_digest"))
|
||||
installed = _oci_image_label(installed, state.get("image_created"), state.get("installed_digest"))
|
||||
if not state.get("update_available") or not latest:
|
||||
return None
|
||||
return {
|
||||
"vmid": int(vmid),
|
||||
"ct_name": app.get("name") or f"CT-{vmid}",
|
||||
"app_name": app.get("name") or "app",
|
||||
"installed": state.get("installed_version") or "unknown",
|
||||
"installed": installed or "unknown",
|
||||
"latest": latest,
|
||||
"app_id": str(app.get("id") or ""),
|
||||
}
|
||||
@@ -4291,6 +4323,28 @@ def check_app(
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
|
||||
if app.get("installed_via") == "oci_image":
|
||||
result = _oci_image_versions(vmid, known=state)
|
||||
app["state"] = {
|
||||
"installed_version": result.get("installed_version"),
|
||||
"latest_version": result.get("latest_version"),
|
||||
"latest_published_at": None,
|
||||
"update_available": result.get("update_available"),
|
||||
"error": result.get("error"),
|
||||
"checked_at": _now_iso(),
|
||||
"installed_digest": result.get("installed_digest"),
|
||||
"latest_digest": result.get("latest_digest"),
|
||||
"image_created": result.get("image_created"),
|
||||
"latest_image_created": result.get("latest_image_created"),
|
||||
"image_reference": result.get("image_reference"),
|
||||
"image_repository": result.get("image_repository"),
|
||||
}
|
||||
sidecar["updated_at"] = _now_iso()
|
||||
_write_sidecar(vmid, sidecar)
|
||||
if notify and app["state"]["update_available"] and app["state"]["latest_version"]:
|
||||
_fire_update_notification(vmid, app)
|
||||
return sidecar
|
||||
|
||||
installed, inst_err, _healed = _detect_with_alt_healing(vmid, app)
|
||||
# Trigger the upstream fetch when ANY upstream source is
|
||||
# configured. The dispatcher inside `fetch_latest_upstream`
|
||||
@@ -4511,6 +4565,12 @@ def _summarise_app(app: dict) -> dict:
|
||||
# match this registered app against the CT's helper_slug and
|
||||
# display its installed/upstream versions.
|
||||
"helper_slug": app.get("helper_slug") or "",
|
||||
# OCI image identity, for the Updates tab of an OCI container.
|
||||
"image_reference": state.get("image_reference"),
|
||||
"image_created": state.get("image_created"),
|
||||
"installed_digest": state.get("installed_digest"),
|
||||
"latest_image_created": state.get("latest_image_created"),
|
||||
"latest_digest": state.get("latest_digest"),
|
||||
}
|
||||
|
||||
|
||||
@@ -5238,6 +5298,276 @@ def _helper_slug_meta(vmid) -> Optional[dict]:
|
||||
return None
|
||||
|
||||
|
||||
_OCI_INSTANCE_ROOT = "/usr/local/share/proxmenux/oci/instances"
|
||||
_OCI_CATALOG_INDEX = "/usr/local/share/proxmenux/oci/engine/catalog/index.json"
|
||||
_oci_catalog_cache: tuple[float, dict] | None = None
|
||||
|
||||
|
||||
def _oci_catalog_icons() -> dict:
|
||||
"""Current icon per catalog application, keyed by template id.
|
||||
|
||||
The installation record keeps a copy of the catalog entry as it stood on
|
||||
the day of the install, which freezes the icon along with everything else.
|
||||
Icons get corrected — most of the catalog used to point at a URL that
|
||||
answered 404 — so the panel reads the catalog and keeps the record as the
|
||||
fallback for an application the catalog no longer lists.
|
||||
"""
|
||||
global _oci_catalog_cache
|
||||
now = time.time()
|
||||
if _oci_catalog_cache and now - _oci_catalog_cache[0] < 600:
|
||||
return _oci_catalog_cache[1]
|
||||
icons: dict = {}
|
||||
try:
|
||||
with open(_OCI_CATALOG_INDEX, encoding="utf-8") as handle:
|
||||
for item in (json.load(handle) or {}).get("applications", []):
|
||||
icon = (item or {}).get("icon")
|
||||
if not isinstance(icon, str) or not icon.startswith("http"):
|
||||
continue
|
||||
# An installation records the template id; the catalog is keyed
|
||||
# by the application id and carries both.
|
||||
for key in (item.get("template_id"), item.get("id")):
|
||||
if key:
|
||||
icons.setdefault(key, icon)
|
||||
except (OSError, ValueError, TypeError):
|
||||
pass
|
||||
_oci_catalog_cache = (now, icons)
|
||||
return icons
|
||||
|
||||
|
||||
def _oci_localised(value) -> str:
|
||||
"""A catalog_ui text field, which is either a string or a locale map."""
|
||||
if isinstance(value, str):
|
||||
return value.strip()
|
||||
if isinstance(value, dict):
|
||||
for key in ("en_US", "en", *sorted(value)):
|
||||
text = value.get(key)
|
||||
if isinstance(text, str) and text.strip():
|
||||
return text.strip()
|
||||
return ""
|
||||
|
||||
|
||||
def _oci_name_from_image(reference: str | None) -> str:
|
||||
"""A presentable name for an image that carries no catalog entry.
|
||||
|
||||
A stack member records the image it runs and the role it plays, not a
|
||||
title: `nextcloud:latest` as the `application` of a Nextcloud stack.
|
||||
"""
|
||||
repository = str(reference or "").split("@", 1)[0]
|
||||
basename = repository.rsplit("/", 1)[-1].rsplit(":", 1)[0].strip()
|
||||
if not basename:
|
||||
return ""
|
||||
return " ".join(word.capitalize() for word in re.split(r"[-_.]+", basename) if word)
|
||||
|
||||
|
||||
def _oci_instance_meta(vmid) -> Optional[dict]:
|
||||
"""What ProxMenux itself recorded when it installed this container.
|
||||
|
||||
The sibling of `_helper_slug_meta`, and stronger evidence: a helper slug
|
||||
is a hint read back out of the guest, while this is the contract the
|
||||
installer wrote. It needs no `pct exec`, so it also answers for a stopped
|
||||
container, and it cannot mistake an incidental binary for the application
|
||||
— CT 152 runs Chromium and happens to have Docker inside, which the
|
||||
runtime probe reported as the only candidate.
|
||||
"""
|
||||
try:
|
||||
with open(f"{_OCI_INSTANCE_ROOT}/{int(vmid)}/oci-compose.json", encoding="utf-8") as handle:
|
||||
record = json.load(handle)
|
||||
except (OSError, ValueError, TypeError):
|
||||
return None
|
||||
if not isinstance(record, dict) or record.get("status") not in ("installed", "assembling"):
|
||||
return None
|
||||
template = record.get("template") or {}
|
||||
contract = template.get("container_contract") or {}
|
||||
image = contract.get("image") or {}
|
||||
observed_image = (record.get("observed") or {}).get("image") or {}
|
||||
# A stack member carries only its own image contract; the presentation
|
||||
# belongs to the stack it is part of, which records its title, site,
|
||||
# category and the endpoint the stack is reached on.
|
||||
stack = record.get("stack") if isinstance(record.get("stack"), dict) else {}
|
||||
stack_template = stack.get("template") if isinstance(stack.get("template"), dict) else {}
|
||||
role = str((record.get("stack_member") or {}).get("name") or "").strip()
|
||||
|
||||
member = record.get("stack_member") or {}
|
||||
is_primary = not stack_template or member.get("primary_vmid") in (None, record.get("vmid"))
|
||||
ui = template.get("catalog_ui") or stack_template.get("catalog_ui") or {}
|
||||
if not template.get("catalog_ui") and stack_template and is_primary:
|
||||
# Only the member the stack is reached on inherits the stack endpoint.
|
||||
# The cache and the database of a Nextcloud stack do not answer on its
|
||||
# web port, and offering it would register a service that is not there.
|
||||
template = {**stack_template, "id": template.get("id") or stack_template.get("id")}
|
||||
elif not template.get("catalog_ui") and stack_template:
|
||||
ui = {key: value for key, value in ui.items()
|
||||
if key in ("category", "category_label")}
|
||||
# `container_contract.ports` lists every port the image exposes; the
|
||||
# endpoint is the one the application is actually reached on, with its
|
||||
# scheme. Chromium exposes 3000 and 3001 and serves on 3001 over https.
|
||||
endpoint = next((e for e in (template.get("first_run") or {}).get("endpoints") or []
|
||||
if isinstance(e, dict) and e.get("port")), None) or ui.get("launch") or {}
|
||||
ports = []
|
||||
for entry in contract.get("ports") or []:
|
||||
try:
|
||||
port = int((entry or {}).get("container_port"))
|
||||
except (TypeError, ValueError):
|
||||
continue
|
||||
if 1 <= port <= 65535 and port not in ports:
|
||||
ports.append(port)
|
||||
template_id = str(template.get("id") or "").strip()
|
||||
catalog_icons = _oci_catalog_icons()
|
||||
logo = catalog_icons.get(template_id) or ""
|
||||
if not logo:
|
||||
# A stack or a one-off image has no catalog entry of its own, but the
|
||||
# image it runs usually does: the Nextcloud stack wears Nextcloud's.
|
||||
repository = str(image.get("reference") or "").split("@", 1)[0]
|
||||
basename = repository.rsplit("/", 1)[-1].rsplit(":", 1)[0].strip().lower()
|
||||
logo = catalog_icons.get(basename) or ""
|
||||
if not logo:
|
||||
logo = ui.get("icon") if isinstance(ui.get("icon"), str) else ""
|
||||
website = ui.get("website") if isinstance(ui.get("website"), str) else ""
|
||||
return {
|
||||
"template_id": template_id or None,
|
||||
"name": (_oci_localised(ui.get("title"))
|
||||
or _oci_name_from_image(image.get("reference"))
|
||||
or str(template.get("id") or "").strip() or None),
|
||||
"role": role or None,
|
||||
"logo": logo if logo.startswith(("http://", "https://")) else "",
|
||||
"website": website if website.startswith(("http://", "https://")) else "",
|
||||
"category": str(ui.get("category") or "").strip() or None,
|
||||
"category_label": str(ui.get("category_label") or "").strip() or None,
|
||||
"image_reference": str(image.get("reference") or "").strip() or None,
|
||||
# The repository of the image — its GitHub project, or its page on the
|
||||
# registry for an official image — which is where its updates come from.
|
||||
"repository": (str(ui.get("repository") or "").strip()
|
||||
or str((template.get("source") or {}).get("repository") or "").strip() or None),
|
||||
"endpoint_port": endpoint.get("port") if isinstance(endpoint.get("port"), int) else None,
|
||||
"endpoint_scheme": str(endpoint.get("scheme") or "").strip().lower() or None,
|
||||
"endpoint_path": str(endpoint.get("path") or "").strip() or None,
|
||||
"ports": ports,
|
||||
# The exact image this container was created from. Its digest is what
|
||||
# an update is decided on; the version label is only for reading.
|
||||
"installed_digest": str(observed_image.get("manifest_digest") or "").strip() or None,
|
||||
"architecture": str(observed_image.get("architecture") or "").strip() or None,
|
||||
}
|
||||
|
||||
|
||||
def oci_adguard_setup_available(vmid) -> bool:
|
||||
"""Probe only this OCI application's setup endpoint, without caching it."""
|
||||
meta = _oci_instance_meta(vmid)
|
||||
if not meta or meta.get('template_id') != 'image-adguard-home':
|
||||
return False
|
||||
try:
|
||||
result = subprocess.run(['lxc-info', '-n', str(int(vmid)), '-iH'],
|
||||
capture_output=True, text=True, timeout=3, check=True)
|
||||
ip = next(str(ipaddress.IPv4Address(value.strip()))
|
||||
for value in result.stdout.splitlines()
|
||||
if value.strip() and ipaddress.ip_address(value.strip()).version == 4)
|
||||
with socket.create_connection((ip, 3000), timeout=1) as connection:
|
||||
connection.settimeout(1)
|
||||
connection.sendall(b'GET / HTTP/1.0\r\nHost: localhost\r\n\r\n')
|
||||
return connection.recv(32).startswith(b'HTTP/')
|
||||
except (OSError, ValueError, StopIteration, subprocess.SubprocessError):
|
||||
return False
|
||||
|
||||
|
||||
_OCI_REMOTE_DIR = "/usr/local/share/proxmenux/oci/engine/remote"
|
||||
|
||||
|
||||
def _oci_state_module():
|
||||
"""The OCI engine's own reader of image versions.
|
||||
|
||||
Reused rather than copied: it resolves the platform manifest, reads the
|
||||
version the image states in its environment before the label it may
|
||||
have inherited from its base, and it is the same code the engine
|
||||
installs and updates with, so the panel and the updater cannot disagree
|
||||
about what an image is.
|
||||
"""
|
||||
if _OCI_REMOTE_DIR not in sys.path:
|
||||
sys.path.insert(0, _OCI_REMOTE_DIR)
|
||||
import oci_installation_state
|
||||
return oci_installation_state
|
||||
|
||||
|
||||
def _oci_repository(reference: str) -> str:
|
||||
repository = reference.split("@", 1)[0]
|
||||
if ":" in repository.rsplit("/", 1)[-1]:
|
||||
repository = repository.rsplit(":", 1)[0]
|
||||
return repository
|
||||
|
||||
|
||||
def _oci_resolve(module, reference: str, architecture: str) -> dict:
|
||||
# One retry: an anonymous registry answers the occasional request with an
|
||||
# error that the next one does not repeat.
|
||||
try:
|
||||
return module.resolve_candidate(reference, architecture)
|
||||
except RuntimeError:
|
||||
time.sleep(2)
|
||||
return module.resolve_candidate(reference, architecture)
|
||||
|
||||
|
||||
def _oci_image_versions(vmid, known: Optional[dict] = None, with_latest: bool = True) -> dict:
|
||||
"""Installed and published version of a container ProxMenux installed.
|
||||
|
||||
Nothing is inferred. The installation record names the image and the
|
||||
exact digest the container was created from; the registry says which
|
||||
digest the same tag points at today. An update is available when those
|
||||
two differ — the version strings only say which one it is, and they are
|
||||
not compared, because a rebuild can keep its number and a build id such
|
||||
as ``b1ee1dc8-ls55`` has no order to compare.
|
||||
|
||||
The installed version is read by digest, which never changes, so a
|
||||
previous answer for the same digest is reused instead of asked again.
|
||||
"""
|
||||
meta = _oci_instance_meta(vmid)
|
||||
if not meta or not meta.get("image_reference") or not meta.get("installed_digest"):
|
||||
return {"error": "no OCI installation record for this container"}
|
||||
reference = meta["image_reference"]
|
||||
architecture = meta.get("architecture") or "amd64"
|
||||
installed_digest = meta["installed_digest"]
|
||||
result: dict = {"installed_digest": installed_digest, "image_reference": reference,
|
||||
"image_repository": meta.get("repository")}
|
||||
try:
|
||||
module = _oci_state_module()
|
||||
except Exception as exc:
|
||||
return {**result, "error": f"OCI engine unavailable: {exc}"}
|
||||
|
||||
known = known or {}
|
||||
if (known.get("installed_digest") == installed_digest
|
||||
and (known.get("installed_version") or known.get("image_created"))):
|
||||
result["installed_version"] = known.get("installed_version")
|
||||
result["image_created"] = known.get("image_created")
|
||||
else:
|
||||
try:
|
||||
installed = _oci_resolve(
|
||||
module, f"{_oci_repository(reference)}@{installed_digest}", architecture)
|
||||
result["installed_version"] = installed.get("version")
|
||||
result["image_created"] = installed.get("created")
|
||||
except Exception as exc:
|
||||
return {**result, "error": f"could not read the installed image: {exc}"}
|
||||
if not with_latest:
|
||||
return result
|
||||
try:
|
||||
latest = _oci_resolve(module, reference, architecture)
|
||||
except Exception as exc:
|
||||
return {**result, "error": f"could not read {reference} from its registry: {exc}"}
|
||||
latest_digest = latest.get("manifest_digest")
|
||||
# The image decides. An application whose version did not move can still
|
||||
# have a new image — a rebuild on a patched base — and that is an update
|
||||
# for a container whose application only changes when its image does.
|
||||
replaced = bool(latest_digest) and latest_digest != installed_digest
|
||||
result.update(latest_digest=latest_digest, latest_version=latest.get("version"),
|
||||
latest_image_created=latest.get("created"), update_available=replaced)
|
||||
return result
|
||||
|
||||
|
||||
def _oci_image_label(version: Optional[str], created: Optional[str], digest: Optional[str]) -> str:
|
||||
"""One image, as a line a reader can compare: version, build date, digest."""
|
||||
parts = [version] if version else []
|
||||
if created:
|
||||
parts.append(str(created)[:10])
|
||||
if digest:
|
||||
parts.append(str(digest).split(":", 1)[-1][:8])
|
||||
return " · ".join(parts) or "unknown"
|
||||
|
||||
|
||||
def _catalog_lookup(slug: str) -> Optional[dict]:
|
||||
"""Fetch the community-scripts catalog entry for a slug.
|
||||
Returns {name, updateable, default_port, logo} or None.
|
||||
@@ -5292,6 +5622,7 @@ def get_suggestions(vmid, force: bool = False) -> dict:
|
||||
if p in _KNOWN_WEB_PORTS:
|
||||
web_hint = "/"
|
||||
break
|
||||
oci_meta = _oci_instance_meta(vmid)
|
||||
meta = _helper_slug_meta(vmid) or {}
|
||||
slug = meta.get("slug")
|
||||
# Suppress base-OS helper slugs from the suggestion pipeline.
|
||||
@@ -5318,7 +5649,10 @@ def get_suggestions(vmid, force: bool = False) -> dict:
|
||||
detector.get("installed_via") in ("docker_label", "docker_exec")
|
||||
for detector in primary_matches
|
||||
)
|
||||
if "docker" in detected_map and primary_is_docker_workload:
|
||||
# An OCI container installed by ProxMenux is the application named in its
|
||||
# own record. Promoting a probed binary over that would offer Docker for a
|
||||
# Chromium container just because the image ships a docker client.
|
||||
if "docker" in detected_map and primary_is_docker_workload and not oci_meta:
|
||||
slug = "docker"
|
||||
meta = {"slug": "docker", "name": "Docker"}
|
||||
# Tracking hint pipeline: catalog + curated hints merged.
|
||||
@@ -5560,6 +5894,47 @@ def get_suggestions(vmid, force: bool = False) -> dict:
|
||||
"tracking_suggestion": det_tracking,
|
||||
})
|
||||
|
||||
if oci_meta:
|
||||
# The record states what this container runs, so a probe finding is
|
||||
# noise: CT 152 runs Chromium and ships a docker client, and offering
|
||||
# to register Docker there invites the user to track the wrong thing.
|
||||
extras = []
|
||||
# Recorded facts replace every probed guess: the name, the logo, the
|
||||
# site and the endpoint the application is served on. The version is
|
||||
# not filled here — the image has no detector among the guest-side
|
||||
# methods — so the entry registers without version tracking until the
|
||||
# OCI detector exists.
|
||||
name_sug = oci_meta["name"] or name_sug
|
||||
logo_url = oci_meta["logo"] or logo_url
|
||||
category_suggestion = oci_meta["category_label"] or suggest_category_for(slug)
|
||||
if oci_meta["endpoint_port"]:
|
||||
default_ports = [oci_meta["endpoint_port"]]
|
||||
ports = [oci_meta["endpoint_port"]] + [p for p in (oci_meta["ports"] or ports)
|
||||
if p != oci_meta["endpoint_port"]]
|
||||
elif oci_meta["ports"]:
|
||||
default_ports = list(oci_meta["ports"])
|
||||
web_hint = oci_meta["endpoint_path"] or web_hint
|
||||
if oci_meta["template_id"] == "image-adguard-home":
|
||||
# The first-run endpoint disappears once setup switches to :80.
|
||||
default_ports = [80]
|
||||
ports = [80, 3000]
|
||||
# Version tracking comes with the registration. Its updates are
|
||||
# decided by the image, which always has a build date and a digest,
|
||||
# so it applies even to an image that states no application version.
|
||||
versions = _oci_image_versions(vmid, with_latest=False)
|
||||
if not versions.get("error"):
|
||||
tracking = {
|
||||
"installed_via": "oci_image",
|
||||
"detected_version": versions.get("installed_version") or _oci_image_label(
|
||||
None, versions.get("image_created"), versions.get("installed_digest")),
|
||||
"detector_verified": True,
|
||||
"detector_source": "oci_instance_record",
|
||||
"logo": logo_url or None,
|
||||
"website": oci_meta["website"] or None,
|
||||
}
|
||||
else:
|
||||
category_suggestion = suggest_category_for(slug)
|
||||
|
||||
return {
|
||||
"name_suggestion": name_sug,
|
||||
"helper_slug": slug,
|
||||
@@ -5568,9 +5943,20 @@ def get_suggestions(vmid, force: bool = False) -> dict:
|
||||
"tracking_suggestion": tracking,
|
||||
"default_ports": default_ports,
|
||||
"logo_url": logo_url or None,
|
||||
# Identity of a ProxMenux OCI install: the scheme the endpoint is
|
||||
# served on, the image it was created from, and the upstream source.
|
||||
"oci_instance": {
|
||||
"template_id": oci_meta["template_id"],
|
||||
"image_reference": oci_meta["image_reference"],
|
||||
"repository": oci_meta["repository"],
|
||||
"scheme": oci_meta["endpoint_scheme"],
|
||||
"port": oci_meta["endpoint_port"],
|
||||
"path": oci_meta["endpoint_path"],
|
||||
"website": oci_meta["website"],
|
||||
} if oci_meta else None,
|
||||
# Categoría preset for the primary detection — same lookup as
|
||||
# get_catalog_entry so the Register button pre-selects it.
|
||||
"category": suggest_category_for(slug),
|
||||
"category": category_suggestion,
|
||||
"extras": extras,
|
||||
"docker_workloads": sorted(docker_workloads, key=lambda item: item["name"].lower()),
|
||||
"docker_web_links": docker_web_links,
|
||||
|
||||
@@ -304,21 +304,56 @@ def _df_via_host_pid(host_pid: str, ct_target: str) -> dict[str, Optional[int]]:
|
||||
["df", "-B1", "--output=size,used,avail", full],
|
||||
capture_output=True, text=True, timeout=_STAT_TIMEOUT,
|
||||
)
|
||||
except subprocess.TimeoutExpired:
|
||||
# A filesystem that does not answer df will not answer statfs
|
||||
# either; asking again would only double the wait.
|
||||
return empty
|
||||
except OSError:
|
||||
return empty
|
||||
if proc.returncode == 0:
|
||||
lines = [ln for ln in proc.stdout.strip().splitlines() if ln.strip()]
|
||||
parts = lines[-1].split() if len(lines) >= 2 else []
|
||||
if len(parts) >= 3:
|
||||
try:
|
||||
return {
|
||||
"total_bytes": int(parts[0]),
|
||||
"used_bytes": int(parts[1]),
|
||||
"available_bytes": int(parts[2]),
|
||||
}
|
||||
except ValueError:
|
||||
pass
|
||||
return _statfs_via_host(full)
|
||||
|
||||
|
||||
def _statfs_via_host(full: str) -> dict[str, Optional[int]]:
|
||||
"""Capacity of a path read from its filesystem rather than the mount table.
|
||||
|
||||
df names a path by finding the mount that holds it in the host's own
|
||||
table, and a volume of a native OCI container is not in that table: df
|
||||
answers "no file systems processed" and the tab showed no usage for any
|
||||
of its volumes. statfs asks the filesystem of the path directly and
|
||||
returns the same three figures df prints. It is only reached when df
|
||||
completes without an answer, so every mount df can measure keeps the
|
||||
value it had.
|
||||
"""
|
||||
empty = {"total_bytes": None, "used_bytes": None, "available_bytes": None}
|
||||
try:
|
||||
proc = subprocess.run(
|
||||
["stat", "-f", "-c", "%S %b %f %a", full],
|
||||
capture_output=True, text=True, timeout=_STAT_TIMEOUT,
|
||||
)
|
||||
if proc.returncode != 0:
|
||||
return empty
|
||||
lines = [ln for ln in proc.stdout.strip().splitlines() if ln.strip()]
|
||||
if len(lines) < 2:
|
||||
return empty
|
||||
parts = lines[-1].split()
|
||||
if len(parts) < 3:
|
||||
return empty
|
||||
return {
|
||||
"total_bytes": int(parts[0]),
|
||||
"used_bytes": int(parts[1]),
|
||||
"available_bytes": int(parts[2]),
|
||||
}
|
||||
block, total, free, available = (int(value) for value in proc.stdout.split())
|
||||
except (subprocess.TimeoutExpired, OSError, ValueError):
|
||||
return empty
|
||||
if block <= 0 or total <= 0:
|
||||
return empty
|
||||
return {
|
||||
"total_bytes": total * block,
|
||||
"used_bytes": (total - free) * block,
|
||||
"available_bytes": available * block,
|
||||
}
|
||||
|
||||
|
||||
def _df_via_pct_exec(vmid: str, ct_target: str,
|
||||
|
||||
@@ -97,8 +97,7 @@ class RateLimiter:
|
||||
# Counter of events dropped while over the rate limit. Surfaced via
|
||||
# `consume_drop_count()` so the dispatch loop can periodically log
|
||||
# "X events suppressed by rate-limit" instead of letting them
|
||||
# disappear silently. Audit Tier 6 — `RateLimiter` descarta
|
||||
# silenciosamente eventos sobre el límite.
|
||||
# disappear silently.
|
||||
self._dropped: int = 0
|
||||
|
||||
def allow(self) -> bool:
|
||||
|
||||
@@ -2502,8 +2502,7 @@ class TaskWatcher:
|
||||
# Manual starts (onboot=0) within the grace period also bypass the
|
||||
# aggregator: a user manually starting a VM right after boot wants
|
||||
# the individual confirmation, not their action silently rolled into
|
||||
# the autostart summary. Audit Tier 6 — `system_startup` aggregation
|
||||
# puede tragar VM starts manuales del usuario durante grace period.
|
||||
# the autostart summary.
|
||||
_STARTUP_EVENTS = {'vm_start', 'ct_start'}
|
||||
if event_type in _STARTUP_EVENTS and not is_error and not is_warning:
|
||||
if _shared_state.is_startup_period():
|
||||
|
||||
@@ -1353,8 +1353,7 @@ TEMPLATES = {
|
||||
# `system-mail` event, and the Monitor forwards it to every enabled
|
||||
# channel. Most operators want smartd alerts but NOT noisy cron
|
||||
# output — without a visible toggle the only fix is editing
|
||||
# /etc/aliases or removing MAILTO from the cron job. Audit Tier 6
|
||||
# — `system_mail` toggle no visible en UI / reportado por usuario.
|
||||
# /etc/aliases or removing MAILTO from the cron job.
|
||||
},
|
||||
'apt_listchanges': {
|
||||
'title': '{hostname}: {pve_title}',
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
"""Console output of a native OCI container, read from the host.
|
||||
|
||||
ProxMenux creates every OCI container with `lxc.console.logfile` pointing at
|
||||
`/var/log/proxmenux/oci/<vmid>.console.log`: liblxc copies the stdout and
|
||||
stderr of the image's entrypoint there, the way `docker logs` keeps them. The
|
||||
file already exists on the host, so nothing here runs inside the container.
|
||||
|
||||
The path is derived from the VMID and confirmed against the container's own
|
||||
configuration; no caller can name a file. Reads are bounded — the last lines
|
||||
on first open, then only what was appended since the offset the viewer holds —
|
||||
and a file that got shorter or was replaced (logrotate's copytruncate, a
|
||||
container rebuilt by an update) resets the viewer instead of returning garbage.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
LOG_DIR = "/var/log/proxmenux/oci"
|
||||
TAIL_READ_LIMIT = 2 * 1024 * 1024 # bytes scanned to find the last lines
|
||||
FOLLOW_READ_LIMIT = 512 * 1024 # bytes returned per follow request
|
||||
MAX_LINES = 2000
|
||||
|
||||
# CSI sequences (colours, cursor), OSC sequences (window titles) and the lone
|
||||
# ESC-letter codes some programs emit. Stripped, never rendered: the text goes
|
||||
# to the page as text.
|
||||
_ANSI_RE = re.compile(r"\x1b\[[0-9;?]*[ -/]*[@-~]|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)|\x1b[@-Z\\-_]")
|
||||
_CONTROL_RE = re.compile(r"[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]")
|
||||
|
||||
|
||||
def log_path(vmid: int) -> str:
|
||||
return os.path.join(LOG_DIR, f"{int(vmid)}.console.log")
|
||||
|
||||
|
||||
def configured_log(vmid: int) -> str | None:
|
||||
"""The console log the container declares, when it is the ProxMenux one."""
|
||||
try:
|
||||
with open(f"/etc/pve/lxc/{int(vmid)}.conf", encoding="utf-8") as handle:
|
||||
for line in handle:
|
||||
if line.startswith("["):
|
||||
break
|
||||
if line.startswith("lxc.console.logfile:"):
|
||||
value = line.split(":", 1)[1].strip()
|
||||
return value if value == log_path(vmid) else None
|
||||
except (OSError, ValueError):
|
||||
return None
|
||||
return None
|
||||
|
||||
|
||||
def terminal_state(vmid: int) -> dict:
|
||||
"""Whether the Proxmox console of the container opens a shell."""
|
||||
mode = "tty"
|
||||
try:
|
||||
with open(f"/etc/pve/lxc/{int(vmid)}.conf", encoding="utf-8") as handle:
|
||||
for line in handle:
|
||||
if line.startswith("["):
|
||||
break
|
||||
if line.startswith("cmode:"):
|
||||
mode = line.split(":", 1)[1].strip()
|
||||
except (OSError, ValueError):
|
||||
pass
|
||||
return {"cmode": mode, "shell": mode == "shell"}
|
||||
|
||||
|
||||
def clean(text: str) -> list[str]:
|
||||
"""Readable lines from raw console output.
|
||||
|
||||
CRLF becomes a line end. A lone carriage return is how a progress bar
|
||||
redraws itself in place, so only what was written after the last one on a
|
||||
line is kept — the state the terminal would have shown.
|
||||
"""
|
||||
text = _ANSI_RE.sub("", text).replace("\r\n", "\n")
|
||||
lines = []
|
||||
for raw in text.split("\n"):
|
||||
if "\r" in raw:
|
||||
raw = raw.rsplit("\r", 1)[-1]
|
||||
lines.append(_CONTROL_RE.sub("", raw))
|
||||
return lines
|
||||
|
||||
|
||||
def _read_tail(handle, size: int, lines: int) -> tuple[list[str], bool]:
|
||||
start = max(0, size - TAIL_READ_LIMIT)
|
||||
handle.seek(start)
|
||||
data = handle.read(size - start).decode("utf-8", errors="replace")
|
||||
result = clean(data)
|
||||
if start > 0 and result:
|
||||
result = result[1:] # the first line was cut by the read window
|
||||
if result and result[-1] == "":
|
||||
result = result[:-1]
|
||||
head_cut = start > 0 or len(result) > lines
|
||||
return result[-lines:], head_cut
|
||||
|
||||
|
||||
def read(vmid: int, lines: int = 200, offset: int | None = None, inode: int | None = None) -> dict:
|
||||
"""The last `lines` lines, or what was appended after `offset`.
|
||||
|
||||
`lines=0` reads nothing: it only says whether the container has a
|
||||
console log, which is what decides if the viewer is offered at all.
|
||||
"""
|
||||
lines = max(0, min(int(lines), MAX_LINES))
|
||||
path = configured_log(vmid)
|
||||
base = {"ok": True, "vmid": int(vmid), **terminal_state(vmid)}
|
||||
if not path:
|
||||
return {**base, "enabled": False, "lines": [], "size": 0, "offset": 0, "inode": None}
|
||||
try:
|
||||
stat = os.stat(path)
|
||||
except OSError:
|
||||
return {**base, "enabled": True, "path": path, "lines": [], "size": 0, "offset": 0, "inode": None}
|
||||
size = stat.st_size
|
||||
base.update(enabled=True, path=path, size=size, inode=stat.st_ino)
|
||||
if lines == 0 and offset is None:
|
||||
return {**base, "lines": [], "offset": size}
|
||||
with open(path, "rb") as handle:
|
||||
replaced = inode is not None and inode != stat.st_ino
|
||||
if offset is None or replaced or offset > size:
|
||||
# First open, or the file the viewer followed is gone: rotated by
|
||||
# copytruncate, or recreated with the container.
|
||||
result, head_cut = _read_tail(handle, size, max(lines, 1))
|
||||
return {**base, "lines": result, "offset": size, "reset": offset is not None,
|
||||
"head_truncated": head_cut}
|
||||
handle.seek(offset)
|
||||
chunk = handle.read(min(size - offset, FOLLOW_READ_LIMIT))
|
||||
# Only whole lines are returned; an unfinished last line is left for the
|
||||
# next read, where it arrives complete.
|
||||
cut = chunk.rfind(b"\n")
|
||||
if cut < 0:
|
||||
return {**base, "lines": [], "offset": offset, "reset": False}
|
||||
complete = chunk[:cut + 1]
|
||||
result = clean(complete.decode("utf-8", errors="replace"))
|
||||
if result and result[-1] == "":
|
||||
result = result[:-1]
|
||||
return {**base, "lines": result, "offset": offset + len(complete), "reset": False}
|
||||
@@ -0,0 +1,62 @@
|
||||
"""What the VM & LXC modal needs to know about an OCI instance.
|
||||
|
||||
Read-only view of the installation record OCI manager Apps keeps for every
|
||||
container it created: whether the container is one, whether it belongs to a
|
||||
multi-container application, whether it uses host directories (which its
|
||||
backup does not revert) and whether an operation is pending. Nothing here
|
||||
changes the record or runs inside the container.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
|
||||
import oci_console_logs
|
||||
|
||||
ROOT = "/usr/local/share/proxmenux/oci/instances"
|
||||
|
||||
|
||||
def _record(vmid: int) -> dict | None:
|
||||
path = os.path.join(ROOT, str(int(vmid)), "oci-compose.json")
|
||||
try:
|
||||
with open(path, encoding="utf-8") as handle:
|
||||
record = json.load(handle)
|
||||
except (OSError, ValueError):
|
||||
return None
|
||||
return record if isinstance(record, dict) else None
|
||||
|
||||
|
||||
def _host_dirs(record: dict) -> bool:
|
||||
mounts = (record.get("deployment") or {}).get("mounts") or []
|
||||
return any(isinstance(m, dict) and m.get("type") == "host-bind" for m in mounts)
|
||||
|
||||
|
||||
def info(vmid: int) -> dict:
|
||||
vmid = int(vmid)
|
||||
result = {
|
||||
"vmid": vmid,
|
||||
"oci_instance": False,
|
||||
"console_log": oci_console_logs.configured_log(vmid) is not None,
|
||||
"stack": False,
|
||||
"primary_vmid": vmid,
|
||||
"members": [],
|
||||
"host_directories": False,
|
||||
"pending": False,
|
||||
}
|
||||
record = _record(vmid)
|
||||
if record is None:
|
||||
return result
|
||||
primary_id = int((record.get("stack_member") or {}).get("primary_vmid") or vmid)
|
||||
primary = record if primary_id == vmid else (_record(primary_id) or {})
|
||||
members = [int(m["vmid"]) for m in (primary.get("stack") or {}).get("members") or []
|
||||
if isinstance(m, dict) and str(m.get("vmid", "")).isdigit()]
|
||||
records = [record] if not members else [r for r in (_record(m) for m in members) if r]
|
||||
result.update(
|
||||
oci_instance=True,
|
||||
stack=bool(members) or bool(record.get("stack_member")),
|
||||
primary_vmid=primary_id,
|
||||
members=members,
|
||||
host_directories=any(_host_dirs(r) for r in records),
|
||||
pending=bool(record.get("pending_transaction") or primary.get("pending_stack_transaction")),
|
||||
)
|
||||
return result
|
||||
@@ -0,0 +1,217 @@
|
||||
import importlib.util
|
||||
import json
|
||||
import shutil
|
||||
import socket
|
||||
import ssl
|
||||
import subprocess
|
||||
import tempfile
|
||||
import threading
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from unittest import mock
|
||||
|
||||
|
||||
MODULE_PATH = Path(__file__).resolve().parents[1] / "auth_manager.py"
|
||||
SPEC = importlib.util.spec_from_file_location("auth_manager_ssl_under_test", MODULE_PATH)
|
||||
auth_manager = importlib.util.module_from_spec(SPEC)
|
||||
SPEC.loader.exec_module(auth_manager)
|
||||
|
||||
|
||||
class _FakeSslSocket:
|
||||
def __init__(self, context):
|
||||
self.context = context
|
||||
|
||||
|
||||
class ProxmoxCertificateHotReloadTests(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
if shutil.which("openssl") is None:
|
||||
raise unittest.SkipTest("openssl is required for TLS fixture generation")
|
||||
cls.fixture_dir = tempfile.TemporaryDirectory()
|
||||
fixture_path = Path(cls.fixture_dir.name)
|
||||
cls.pairs = []
|
||||
for name in ("original", "renewed"):
|
||||
cert_path = fixture_path / f"{name}.pem"
|
||||
key_path = fixture_path / f"{name}.key"
|
||||
subprocess.run(
|
||||
[
|
||||
"openssl", "req", "-x509", "-newkey", "rsa:2048",
|
||||
"-nodes", "-days", "1", "-subj", f"/CN={name}.test",
|
||||
"-keyout", str(key_path), "-out", str(cert_path),
|
||||
],
|
||||
check=True,
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL,
|
||||
)
|
||||
cls.pairs.append((cert_path, key_path))
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.fixture_dir.cleanup()
|
||||
|
||||
def setUp(self):
|
||||
self.temp_dir = tempfile.TemporaryDirectory()
|
||||
self.addCleanup(self.temp_dir.cleanup)
|
||||
temp_path = Path(self.temp_dir.name)
|
||||
self.active_cert = temp_path / "pveproxy-ssl.pem"
|
||||
self.active_key = temp_path / "pveproxy-ssl.key"
|
||||
self.ssl_config = temp_path / "ssl_config.json"
|
||||
self._install_pair(0)
|
||||
self._write_config("proxmox")
|
||||
|
||||
self.patch = mock.patch.multiple(
|
||||
auth_manager,
|
||||
SSL_CONFIG_FILE=self.ssl_config,
|
||||
PROXMOX_CUSTOM_CERT_PATH=str(self.active_cert),
|
||||
PROXMOX_CUSTOM_KEY_PATH=str(self.active_key),
|
||||
PROXMOX_CERT_PATH=str(temp_path / "missing-pve-ssl.pem"),
|
||||
PROXMOX_KEY_PATH=str(temp_path / "missing-pve-ssl.key"),
|
||||
)
|
||||
self.patch.start()
|
||||
self.addCleanup(self.patch.stop)
|
||||
self.addCleanup(self._reset_runtime)
|
||||
|
||||
def _reset_runtime(self):
|
||||
with auth_manager._SSL_RUNTIME_LOCK:
|
||||
auth_manager._SSL_RUNTIME_CONTEXT = None
|
||||
auth_manager._SSL_RUNTIME_FINGERPRINT = ""
|
||||
auth_manager._SSL_RUNTIME_CERT_PATH = ""
|
||||
auth_manager._SSL_RUNTIME_KEY_PATH = ""
|
||||
auth_manager._SSL_RUNTIME_SOURCE = "none"
|
||||
auth_manager._SSL_RUNTIME_LAST_REFRESH_ERROR = ""
|
||||
|
||||
def _install_pair(self, index):
|
||||
cert_path, key_path = self.pairs[index]
|
||||
shutil.copyfile(cert_path, self.active_cert)
|
||||
shutil.copyfile(key_path, self.active_key)
|
||||
|
||||
def _write_config(self, source):
|
||||
self.ssl_config.write_text(json.dumps({
|
||||
"enabled": True,
|
||||
"cert_path": str(self.active_cert),
|
||||
"key_path": str(self.active_key),
|
||||
"source": source,
|
||||
}))
|
||||
|
||||
def _create_context(self):
|
||||
return auth_manager.create_reloadable_ssl_context(
|
||||
str(self.active_cert), str(self.active_key)
|
||||
)
|
||||
|
||||
def test_unchanged_pair_does_not_rebuild_the_context(self):
|
||||
context = self._create_context()
|
||||
ssl_socket = _FakeSslSocket(context)
|
||||
|
||||
with mock.patch.object(
|
||||
auth_manager,
|
||||
"reload_server_ssl_context",
|
||||
wraps=auth_manager.reload_server_ssl_context,
|
||||
) as reload_mock:
|
||||
context.sni_callback(ssl_socket, "proxmenux.test", context)
|
||||
|
||||
reload_mock.assert_not_called()
|
||||
self.assertIs(ssl_socket.context, context)
|
||||
|
||||
def test_valid_renewed_pair_is_activated_during_the_handshake(self):
|
||||
context = self._create_context()
|
||||
previous_fingerprint = auth_manager._SSL_RUNTIME_FINGERPRINT
|
||||
self._install_pair(1)
|
||||
ssl_socket = _FakeSslSocket(context)
|
||||
|
||||
context.sni_callback(ssl_socket, "proxmenux.test", context)
|
||||
|
||||
self.assertNotEqual(previous_fingerprint, auth_manager._SSL_RUNTIME_FINGERPRINT)
|
||||
self.assertIs(ssl_socket.context, auth_manager._SSL_RUNTIME_CONTEXT)
|
||||
self.assertIsNot(ssl_socket.context, context)
|
||||
self.assertEqual(auth_manager._SSL_RUNTIME_LAST_REFRESH_ERROR, "")
|
||||
|
||||
def test_mismatched_pair_keeps_the_previous_context(self):
|
||||
context = self._create_context()
|
||||
previous_fingerprint = auth_manager._SSL_RUNTIME_FINGERPRINT
|
||||
shutil.copyfile(self.pairs[1][0], self.active_cert)
|
||||
ssl_socket = _FakeSslSocket(context)
|
||||
|
||||
context.sni_callback(ssl_socket, "proxmenux.test", context)
|
||||
|
||||
self.assertEqual(previous_fingerprint, auth_manager._SSL_RUNTIME_FINGERPRINT)
|
||||
self.assertIs(auth_manager._SSL_RUNTIME_CONTEXT, context)
|
||||
self.assertIs(ssl_socket.context, context)
|
||||
self.assertTrue(auth_manager._SSL_RUNTIME_LAST_REFRESH_ERROR)
|
||||
|
||||
def test_custom_certificate_source_is_not_examined_automatically(self):
|
||||
self._write_config("custom")
|
||||
context = self._create_context()
|
||||
previous_fingerprint = auth_manager._SSL_RUNTIME_FINGERPRINT
|
||||
self._install_pair(1)
|
||||
ssl_socket = _FakeSslSocket(context)
|
||||
|
||||
context.sni_callback(ssl_socket, "proxmenux.test", context)
|
||||
|
||||
self.assertEqual(previous_fingerprint, auth_manager._SSL_RUNTIME_FINGERPRINT)
|
||||
self.assertIs(ssl_socket.context, context)
|
||||
|
||||
def test_first_real_tls_connection_receives_the_renewed_certificate(self):
|
||||
server_context = self._create_context()
|
||||
self._install_pair(1)
|
||||
server_socket, client_socket = socket.socketpair()
|
||||
server_socket.settimeout(5)
|
||||
client_socket.settimeout(5)
|
||||
server_error = []
|
||||
|
||||
def serve_once():
|
||||
try:
|
||||
with server_context.wrap_socket(server_socket, server_side=True) as tls_socket:
|
||||
tls_socket.recv(1)
|
||||
except Exception as error: # pragma: no cover - asserted below
|
||||
server_error.append(error)
|
||||
|
||||
thread = threading.Thread(target=serve_once)
|
||||
thread.start()
|
||||
client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
||||
client_context.check_hostname = False
|
||||
client_context.verify_mode = ssl.CERT_NONE
|
||||
with client_context.wrap_socket(
|
||||
client_socket, server_hostname="proxmenux.test"
|
||||
) as tls_client:
|
||||
received_der = tls_client.getpeercert(binary_form=True)
|
||||
tls_client.sendall(b"x")
|
||||
thread.join(timeout=5)
|
||||
|
||||
self.assertFalse(thread.is_alive())
|
||||
self.assertEqual(server_error, [])
|
||||
renewed_pem = self.pairs[1][0].read_text()
|
||||
self.assertEqual(received_der, ssl.PEM_cert_to_DER_cert(renewed_pem))
|
||||
|
||||
def test_tls_connection_without_sni_also_receives_the_renewed_certificate(self):
|
||||
server_context = self._create_context()
|
||||
self._install_pair(1)
|
||||
server_socket, client_socket = socket.socketpair()
|
||||
server_socket.settimeout(5)
|
||||
client_socket.settimeout(5)
|
||||
server_error = []
|
||||
|
||||
def serve_once():
|
||||
try:
|
||||
with server_context.wrap_socket(server_socket, server_side=True) as tls_socket:
|
||||
tls_socket.recv(1)
|
||||
except Exception as error: # pragma: no cover - asserted below
|
||||
server_error.append(error)
|
||||
|
||||
thread = threading.Thread(target=serve_once)
|
||||
thread.start()
|
||||
client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
||||
client_context.check_hostname = False
|
||||
client_context.verify_mode = ssl.CERT_NONE
|
||||
with client_context.wrap_socket(client_socket) as tls_client:
|
||||
received_der = tls_client.getpeercert(binary_form=True)
|
||||
tls_client.sendall(b"x")
|
||||
thread.join(timeout=5)
|
||||
|
||||
self.assertFalse(thread.is_alive())
|
||||
self.assertEqual(server_error, [])
|
||||
renewed_pem = self.pairs[1][0].read_text()
|
||||
self.assertEqual(received_der, ssl.PEM_cert_to_DER_cert(renewed_pem))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,69 @@
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from unittest import mock
|
||||
|
||||
|
||||
SCRIPTS_DIR = Path(__file__).resolve().parents[1]
|
||||
if str(SCRIPTS_DIR) not in sys.path:
|
||||
sys.path.insert(0, str(SCRIPTS_DIR))
|
||||
|
||||
import lxc_apps # noqa: E402
|
||||
|
||||
|
||||
class ScheduledUpdateRecordTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.temp_dir = tempfile.TemporaryDirectory()
|
||||
self.addCleanup(self.temp_dir.cleanup)
|
||||
self.apps_dir_patch = mock.patch.object(
|
||||
lxc_apps, '_APPS_DIR', self.temp_dir.name,
|
||||
)
|
||||
self.apps_dir_patch.start()
|
||||
self.addCleanup(self.apps_dir_patch.stop)
|
||||
self.vmid = 9911
|
||||
self.assertTrue(lxc_apps._write_sidecar(self.vmid, {
|
||||
'vmid': self.vmid,
|
||||
'apps': [],
|
||||
'schedule': {'enabled': True, 'cron': '0 3 * * *'},
|
||||
}))
|
||||
|
||||
def test_record_keeps_log_and_reboot_evidence(self):
|
||||
self.assertTrue(lxc_apps.record_schedule_run(
|
||||
self.vmid,
|
||||
'success',
|
||||
'both',
|
||||
log_name='../9911-scheduled-' + ('a' * 32) + '.log',
|
||||
reboot_required=True,
|
||||
reboot_packages=['linux-image-amd64', 'libc6'],
|
||||
))
|
||||
schedule = lxc_apps._read_sidecar(self.vmid)['schedule']
|
||||
self.assertEqual(
|
||||
schedule['last_run_log'],
|
||||
'9911-scheduled-' + ('a' * 32) + '.log',
|
||||
)
|
||||
self.assertTrue(schedule['last_run_reboot_required'])
|
||||
self.assertEqual(
|
||||
schedule['last_run_reboot_packages'],
|
||||
['linux-image-amd64', 'libc6'],
|
||||
)
|
||||
|
||||
def test_lifecycle_clear_preserves_run_and_log(self):
|
||||
lxc_apps.record_schedule_run(
|
||||
self.vmid,
|
||||
'success',
|
||||
'os',
|
||||
log_name='9911-scheduled-' + ('b' * 32) + '.log',
|
||||
reboot_required=True,
|
||||
reboot_packages=['linux-image-amd64'],
|
||||
)
|
||||
self.assertTrue(lxc_apps.clear_schedule_reboot_required(self.vmid))
|
||||
schedule = lxc_apps._read_sidecar(self.vmid)['schedule']
|
||||
self.assertFalse(schedule['last_run_reboot_required'])
|
||||
self.assertNotIn('last_run_reboot_packages', schedule)
|
||||
self.assertEqual(schedule['last_run_status'], 'success')
|
||||
self.assertIn('last_run_log', schedule)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,160 @@
|
||||
import sqlite3
|
||||
import sys
|
||||
import tempfile
|
||||
import threading
|
||||
import time
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from unittest import mock
|
||||
|
||||
|
||||
SCRIPTS_DIR = Path(__file__).resolve().parents[1]
|
||||
if str(SCRIPTS_DIR) not in sys.path:
|
||||
sys.path.insert(0, str(SCRIPTS_DIR))
|
||||
|
||||
import notification_manager # noqa: E402
|
||||
from notification_events import NotificationEvent # noqa: E402
|
||||
|
||||
|
||||
class RecordingChannel:
|
||||
def __init__(self, results=None):
|
||||
self.results = list(results or [True])
|
||||
self.calls = 0
|
||||
self.lock = threading.Lock()
|
||||
|
||||
def send(self, title, body, severity, data):
|
||||
with self.lock:
|
||||
self.calls += 1
|
||||
success = self.results.pop(0) if self.results else True
|
||||
time.sleep(0.1)
|
||||
return {'success': success, 'error': '' if success else 'temporary failure'}
|
||||
|
||||
|
||||
class NotificationDeliveryDedupTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.temp_dir = tempfile.TemporaryDirectory()
|
||||
self.addCleanup(self.temp_dir.cleanup)
|
||||
self.db_path = Path(self.temp_dir.name) / 'health_monitor.db'
|
||||
conn = sqlite3.connect(str(self.db_path))
|
||||
conn.execute('''
|
||||
CREATE TABLE notification_last_sent (
|
||||
fingerprint TEXT PRIMARY KEY,
|
||||
last_sent_ts INTEGER NOT NULL,
|
||||
count INTEGER DEFAULT 1
|
||||
)
|
||||
''')
|
||||
conn.execute('''
|
||||
CREATE TABLE notification_history (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
event_type TEXT NOT NULL,
|
||||
channel TEXT NOT NULL,
|
||||
title TEXT,
|
||||
message TEXT,
|
||||
severity TEXT,
|
||||
sent_at TEXT NOT NULL,
|
||||
success INTEGER DEFAULT 1,
|
||||
error_message TEXT,
|
||||
source TEXT DEFAULT 'server'
|
||||
)
|
||||
''')
|
||||
conn.commit()
|
||||
conn.close()
|
||||
self.db_patch = mock.patch.object(
|
||||
notification_manager, 'DB_PATH', self.db_path,
|
||||
)
|
||||
self.db_patch.start()
|
||||
self.addCleanup(self.db_patch.stop)
|
||||
self.ai_context_patch = mock.patch.object(
|
||||
notification_manager, 'enrich_context_for_ai', return_value='',
|
||||
)
|
||||
self.ai_context_patch.start()
|
||||
self.addCleanup(self.ai_context_patch.stop)
|
||||
self.ai_rewrite_patch = mock.patch.object(
|
||||
notification_manager, '_format_with_ai_bounded', return_value=None,
|
||||
)
|
||||
self.ai_rewrite_patch.start()
|
||||
self.addCleanup(self.ai_rewrite_patch.stop)
|
||||
|
||||
def _manager(self, channel):
|
||||
manager = notification_manager.NotificationManager()
|
||||
manager._enabled = True
|
||||
manager._config = {
|
||||
'email.enabled': 'true',
|
||||
'email.rich_format': 'false',
|
||||
'ai_enabled': 'false',
|
||||
}
|
||||
manager._channels = {'email': channel}
|
||||
return manager
|
||||
|
||||
@staticmethod
|
||||
def _event():
|
||||
return NotificationEvent(
|
||||
event_type='lxc_update_applied',
|
||||
severity='INFO',
|
||||
data={
|
||||
'hostname': 'pve-test',
|
||||
'vmid': 210,
|
||||
'ct_name': 'docker-frontend',
|
||||
'target': 'Docker Engine',
|
||||
'result': 'succeeded',
|
||||
'duration': '10s',
|
||||
'details': 'Update completed',
|
||||
},
|
||||
source='manual',
|
||||
entity='ct',
|
||||
entity_id='210:same-run',
|
||||
)
|
||||
|
||||
def test_concurrent_managers_deliver_same_fingerprint_once(self):
|
||||
channel = RecordingChannel()
|
||||
managers = [self._manager(channel), self._manager(channel)]
|
||||
barrier = threading.Barrier(3)
|
||||
|
||||
def dispatch(manager):
|
||||
barrier.wait()
|
||||
manager._dispatch_event(self._event())
|
||||
|
||||
threads = [
|
||||
threading.Thread(target=dispatch, args=(manager,))
|
||||
for manager in managers
|
||||
]
|
||||
for thread in threads:
|
||||
thread.start()
|
||||
barrier.wait()
|
||||
for thread in threads:
|
||||
thread.join(timeout=5)
|
||||
|
||||
self.assertEqual(channel.calls, 1)
|
||||
conn = sqlite3.connect(str(self.db_path))
|
||||
history_count = conn.execute(
|
||||
'SELECT COUNT(*) FROM notification_history WHERE success = 1'
|
||||
).fetchone()[0]
|
||||
claim_count = conn.execute(
|
||||
'SELECT COUNT(*) FROM notification_delivery_claims'
|
||||
).fetchone()[0]
|
||||
conn.close()
|
||||
self.assertEqual(history_count, 1)
|
||||
self.assertEqual(claim_count, 0)
|
||||
|
||||
def test_failed_delivery_releases_claim_for_retry(self):
|
||||
channel = RecordingChannel([False, True])
|
||||
manager = self._manager(channel)
|
||||
|
||||
manager._dispatch_event(self._event())
|
||||
manager._dispatch_event(self._event())
|
||||
|
||||
self.assertEqual(channel.calls, 2)
|
||||
conn = sqlite3.connect(str(self.db_path))
|
||||
successes = conn.execute(
|
||||
'SELECT success FROM notification_history ORDER BY id'
|
||||
).fetchall()
|
||||
claim_count = conn.execute(
|
||||
'SELECT COUNT(*) FROM notification_delivery_claims'
|
||||
).fetchone()[0]
|
||||
conn.close()
|
||||
self.assertEqual(successes, [(0,), (1,)])
|
||||
self.assertEqual(claim_count, 0)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,114 @@
|
||||
import json
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from queue import Queue
|
||||
from unittest import mock
|
||||
|
||||
|
||||
SCRIPTS_DIR = Path(__file__).resolve().parents[1]
|
||||
if str(SCRIPTS_DIR) not in sys.path:
|
||||
sys.path.insert(0, str(SCRIPTS_DIR))
|
||||
|
||||
import notification_events # noqa: E402
|
||||
import notification_templates # noqa: E402
|
||||
import post_install_versions # noqa: E402
|
||||
|
||||
|
||||
class NotificationUpdatePolicyTests(unittest.TestCase):
|
||||
def test_apt_listchanges_system_mail_has_its_own_update_event(self):
|
||||
watcher = notification_events.ProxmoxHookWatcher(Queue())
|
||||
classified = watcher._classify_pve(
|
||||
"system-mail",
|
||||
"info",
|
||||
"Novedades de apt-listchanges para amd",
|
||||
"zfs-linux recommends that all users update absolute paths",
|
||||
)
|
||||
self.assertEqual(classified, ("apt_listchanges", "node", ""))
|
||||
|
||||
def test_regular_system_mail_remains_available(self):
|
||||
watcher = notification_events.ProxmoxHookWatcher(Queue())
|
||||
with mock.patch.object(notification_events, "_record_smartd_observation_impl"):
|
||||
classified = watcher._classify_pve(
|
||||
"system-mail",
|
||||
"warning",
|
||||
"SMART error (CurrentPendingSector) detected on host",
|
||||
"Device: /dev/sda",
|
||||
)
|
||||
self.assertEqual(classified, ("system_mail", "node", ""))
|
||||
|
||||
def test_apt_listchanges_body_is_preserved_and_attributed(self):
|
||||
watcher = notification_events.ProxmoxHookWatcher(Queue())
|
||||
upstream = (
|
||||
"zfs-linux (2.2.4-2) unstable; urgency=medium\n\n"
|
||||
" Package-maintainer recommendation.\n\n"
|
||||
" -- Maintainer <maintainer@example.com>"
|
||||
)
|
||||
result = watcher.process_webhook({
|
||||
"title": "apt-listchanges: News for host",
|
||||
"message": upstream,
|
||||
"severity": "info",
|
||||
"fields": {"type": "system-mail", "hostname": "pve-test"},
|
||||
})
|
||||
self.assertTrue(result["accepted"])
|
||||
event = watcher._queue.get_nowait()
|
||||
self.assertEqual(event.event_type, "apt_listchanges")
|
||||
self.assertEqual(event.data["reason"], upstream)
|
||||
|
||||
rendered = notification_templates.render_template(
|
||||
event.event_type,
|
||||
event.data,
|
||||
)
|
||||
self.assertIn("not a ProxMenux recommendation", rendered["body_text"])
|
||||
self.assertIn(upstream, rendered["body_text"])
|
||||
|
||||
def test_smaller_pending_subset_does_not_notify_again(self):
|
||||
updates = [
|
||||
{"key": "persistent_network", "available_version": "1.2"},
|
||||
]
|
||||
notified = {
|
||||
"log2ram": {"1.4"},
|
||||
"persistent_network": {"1.2"},
|
||||
}
|
||||
self.assertEqual(
|
||||
notification_events._new_post_install_update_versions(updates, notified),
|
||||
{},
|
||||
)
|
||||
|
||||
def test_new_version_of_existing_tool_is_detected(self):
|
||||
updates = [
|
||||
{"key": "persistent_network", "available_version": "1.3"},
|
||||
]
|
||||
notified = {"persistent_network": {"1.2"}}
|
||||
self.assertEqual(
|
||||
notification_events._new_post_install_update_versions(updates, notified),
|
||||
{"persistent_network": "1.3"},
|
||||
)
|
||||
|
||||
def test_notified_versions_share_the_existing_snapshot_file(self):
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
snapshot_path = Path(temporary) / "updates_available.json"
|
||||
cache = {
|
||||
"scanned_at": 123.0,
|
||||
"updates": [
|
||||
{"key": "log2ram", "available_version": "1.4"},
|
||||
],
|
||||
}
|
||||
with mock.patch.object(post_install_versions, "_UPDATES_JSON", snapshot_path), \
|
||||
mock.patch.object(post_install_versions, "_cache", cache):
|
||||
post_install_versions.save_notified_versions(
|
||||
{"log2ram": {"1.3", "1.4"}}
|
||||
)
|
||||
self.assertEqual(
|
||||
post_install_versions.load_notified_versions(),
|
||||
{"log2ram": {"1.3", "1.4"}},
|
||||
)
|
||||
payload = json.loads(snapshot_path.read_text(encoding="utf-8"))
|
||||
self.assertEqual(payload["scanned_at"], 123.0)
|
||||
self.assertEqual(payload["updates"], cache["updates"])
|
||||
self.assertEqual(payload["notified_versions"]["log2ram"], ["1.3", "1.4"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,37 @@
|
||||
import sys
|
||||
from pathlib import Path
|
||||
import unittest
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
SCRIPTS = Path(__file__).resolve().parents[1]
|
||||
sys.path.insert(0, str(SCRIPTS))
|
||||
import lxc_apps
|
||||
|
||||
|
||||
class AdguardSetupTests(unittest.TestCase):
|
||||
def test_non_adguard_is_not_probed(self):
|
||||
with patch.object(lxc_apps, '_oci_instance_meta', return_value={'template_id': 'image-frigate'}), \
|
||||
patch.object(lxc_apps.subprocess, 'run') as run:
|
||||
self.assertFalse(lxc_apps.oci_adguard_setup_available(190))
|
||||
run.assert_not_called()
|
||||
|
||||
def test_setup_returns_true_only_for_http_response(self):
|
||||
process = MagicMock(stdout='192.168.0.42\n')
|
||||
connection = MagicMock()
|
||||
connection.__enter__.return_value.recv.return_value = b'HTTP/1.1 302 Found\r\n'
|
||||
with patch.object(lxc_apps, '_oci_instance_meta', return_value={'template_id': 'image-adguard-home'}), \
|
||||
patch.object(lxc_apps.subprocess, 'run', return_value=process), \
|
||||
patch.object(lxc_apps.socket, 'create_connection', return_value=connection) as connect:
|
||||
self.assertTrue(lxc_apps.oci_adguard_setup_available(190))
|
||||
connect.assert_called_once_with(('192.168.0.42', 3000), timeout=1)
|
||||
|
||||
def test_closed_setup_port_is_not_offered(self):
|
||||
process = MagicMock(stdout='192.168.0.42\n')
|
||||
with patch.object(lxc_apps, '_oci_instance_meta', return_value={'template_id': 'image-adguard-home'}), \
|
||||
patch.object(lxc_apps.subprocess, 'run', return_value=process), \
|
||||
patch.object(lxc_apps.socket, 'create_connection', side_effect=OSError):
|
||||
self.assertFalse(lxc_apps.oci_adguard_setup_available(190))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Regression tests based on LeidenSpain's real LXC OOM block."""
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
||||
|
||||
from proxmox_known_errors import ( # noqa: E402
|
||||
analyze_oom_event,
|
||||
format_oom_diagnosis,
|
||||
get_error_context,
|
||||
)
|
||||
|
||||
|
||||
LXC_OOM = """
|
||||
apt-get invoked oom-killer: gfp_mask=0x101cca, order=3, oom_score_adj=0
|
||||
memory: usage 131056kB, limit 131072kB, failcnt 1922
|
||||
swap: usage 0kB, limit 0kB, failcnt 0
|
||||
Memory cgroup stats for /lxc/108:
|
||||
oom-kill:constraint=CONSTRAINT_MEMCG,nodemask=(null),cpuset=ns,mems_allowed=0,oom_memcg=/lxc/108,task_memcg=/lxc/108/ns/.lxc,task=apt-get,pid=1183877,uid=100000
|
||||
Memory cgroup out of memory: Killed process 1183877 (apt-get) total-vm:79700kB, anon-rss:65056kB
|
||||
"""
|
||||
|
||||
|
||||
class OomDiagnosticsTest(unittest.TestCase):
|
||||
def test_lxc_memcg_scope_and_limits(self):
|
||||
result = analyze_oom_event(LXC_OOM)
|
||||
self.assertIsNotNone(result)
|
||||
self.assertEqual(result['scope'], 'lxc')
|
||||
self.assertEqual(result['ctid'], '108')
|
||||
self.assertEqual(result['constraint'], 'CONSTRAINT_MEMCG')
|
||||
self.assertEqual(result['memory_usage_kib'], 131056)
|
||||
self.assertEqual(result['memory_limit_kib'], 131072)
|
||||
self.assertEqual(result['swap_limit_kib'], 0)
|
||||
self.assertEqual(result['victim_process'], 'apt-get')
|
||||
self.assertEqual(result['victim_pid'], '1183877')
|
||||
|
||||
def test_diagnosis_does_not_blame_host(self):
|
||||
diagnosis = format_oom_diagnosis(analyze_oom_event(LXC_OOM))
|
||||
self.assertIn('LXC 108', diagnosis)
|
||||
self.assertIn('not a host-wide OOM', diagnosis)
|
||||
self.assertIn('128.0 MiB used of 128.0 MiB', diagnosis)
|
||||
self.assertIn('Killed process: apt-get', diagnosis)
|
||||
|
||||
def test_known_error_context_includes_event_evidence(self):
|
||||
context = get_error_context(LXC_OOM, category='memory', detail_level='detailed')
|
||||
self.assertIn('Event analysis:', context)
|
||||
self.assertIn('LXC 108 memory cgroup', context)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,8 +1,89 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"observed_at": "2026-08-21",
|
||||
"notes": "Runtime-verified detectors for the LXC app catalog. Every entry is a detector proven to work on a real container, either in maintainer testing or a reviewed community confirmation. Contribution rules \u2014 accept ONLY: `detector` (required, with installed_via + method-specific fields + repo/tag_regex), optional `alt_detectors` (cross-method fallbacks), optional `file_fallbacks` (same-method secondary paths). REJECT anything that identifies a host: no IP addresses, no VMIDs, no hostnames, no `evidence` blocks with those fields. Report reproduction context in the PR description instead \u2014 the committed JSON must stay generic.",
|
||||
"observed_at": "2026-09-24",
|
||||
"notes": "Runtime-verified detectors for the LXC app catalog. Every entry is a detector proven to work on a real container, either in maintainer testing or a reviewed community confirmation. Contribution rules — accept ONLY: `detector` (required, with installed_via + method-specific fields + repo/tag_regex), optional `alt_detectors` (cross-method fallbacks), optional `file_fallbacks` (same-method secondary paths). REJECT anything that identifies a host: no IP addresses, no VMIDs, no hostnames, no `evidence` blocks with those fields. Report reproduction context in the PR description instead — the committed JSON must stay generic.",
|
||||
"apps": {
|
||||
"adguard": {
|
||||
"detector": {
|
||||
"installed_via": "binary",
|
||||
"binary_path": "/opt/AdGuardHome/AdGuardHome",
|
||||
"repo": "AdguardTeam/AdGuardHome",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
}
|
||||
},
|
||||
"agentdvr": {
|
||||
"detector": {
|
||||
"installed_via": "file",
|
||||
"file_path": "/root/.agentdvr",
|
||||
"file_regex": "Agent_[^/]+_([0-9]+(?:_[0-9]+){3})\\.zip",
|
||||
"repo": "ispysoftware/agent-install-scripts",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+(?:\\.\\d+){3})"
|
||||
}
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"operational": true,
|
||||
"name": "Audiobookshelf",
|
||||
"install_scope": [
|
||||
"community-script",
|
||||
"manual-if-same-package"
|
||||
],
|
||||
"evidence": [
|
||||
"community-confirmed:github-discussion-306"
|
||||
],
|
||||
"detector": {
|
||||
"installed_via": "dpkg",
|
||||
"package": "audiobookshelf",
|
||||
"repo": "advplyr/audiobookshelf",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "(?i)(?:v|release[-_/]?)?(\\d+(?:\\.\\d+){1,3}(?:[-+._][0-9A-Za-z.-]+)?)"
|
||||
}
|
||||
},
|
||||
"changedetection": {
|
||||
"operational": true,
|
||||
"name": "Changedetection.io",
|
||||
"install_scope": [
|
||||
"community-script",
|
||||
"manual"
|
||||
],
|
||||
"evidence": [
|
||||
"community-confirmed:github-discussion-306"
|
||||
],
|
||||
"detector": {
|
||||
"installed_via": "command",
|
||||
"command_argv": [
|
||||
"/opt/changedetection/.venv/bin/changedetection.io",
|
||||
"--version"
|
||||
],
|
||||
"installed_regex": "v?(\\d+\\.\\d+\\.\\d+)",
|
||||
"repo": "dgtlmoon/changedetection.io",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
},
|
||||
"default_ports": [
|
||||
5000
|
||||
],
|
||||
"website": "https://changedetection.io/"
|
||||
},
|
||||
"dispatcharr": {
|
||||
"operational": true,
|
||||
"name": "Dispatcharr",
|
||||
"install_scope": [
|
||||
"community-script"
|
||||
],
|
||||
"evidence": [
|
||||
"community-confirmed:github-discussion-306"
|
||||
],
|
||||
"detector": {
|
||||
"installed_via": "file",
|
||||
"file_path": "/root/.dispatcharr",
|
||||
"file_regex": "(\\d+\\.\\d+\\.\\d+)",
|
||||
"repo": "Dispatcharr/Dispatcharr",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
}
|
||||
},
|
||||
"docker": {
|
||||
"operational": true,
|
||||
"install_scope": [
|
||||
@@ -20,6 +101,249 @@
|
||||
"tag_regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
}
|
||||
},
|
||||
"docmost": {
|
||||
"detector": {
|
||||
"installed_via": "file",
|
||||
"file_path": "/opt/docmost/package.json",
|
||||
"file_regex": "\"version\"\\s*:\\s*\"(\\d+\\.\\d+\\.\\d+)\"",
|
||||
"repo": "docmost/docmost",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
},
|
||||
"file_fallbacks": [
|
||||
{
|
||||
"path": "/root/.docmost",
|
||||
"regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
}
|
||||
]
|
||||
},
|
||||
"gitea": {
|
||||
"operational": true,
|
||||
"name": "Gitea",
|
||||
"install_scope": [
|
||||
"community-script",
|
||||
"manual-if-same-package"
|
||||
],
|
||||
"evidence": [
|
||||
"community-confirmed:github-discussion-306"
|
||||
],
|
||||
"detector": {
|
||||
"installed_via": "apk",
|
||||
"package": "gitea",
|
||||
"repo": "go-gitea/gitea",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
}
|
||||
},
|
||||
"grafana": {
|
||||
"operational": false,
|
||||
"detector": {
|
||||
"installed_via": "docker_exec",
|
||||
"container_name": "grafana",
|
||||
"binary_path": "grafana",
|
||||
"binary_args": [
|
||||
"server",
|
||||
"-v"
|
||||
],
|
||||
"repo": "grafana/grafana",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
}
|
||||
},
|
||||
"immich": {
|
||||
"detector": {
|
||||
"installed_via": "file",
|
||||
"file_path": "/root/.immich",
|
||||
"file_regex": "(?i)(?:v|release[-_/]?)?(\\d+(?:\\.\\d+){1,3}(?:[-+._][0-9A-Za-z.-]+)?)",
|
||||
"repo": "immich-app/immich",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "(?i)(?:v|release[-_/]?)?(\\d+(?:\\.\\d+){1,3}(?:[-+._][0-9A-Za-z.-]+)?)"
|
||||
},
|
||||
"alt_detectors": [
|
||||
{
|
||||
"installed_via": "docker_label",
|
||||
"container_name": "immich_server",
|
||||
"label": "org.opencontainers.image.version"
|
||||
}
|
||||
]
|
||||
},
|
||||
"jellyfin": {
|
||||
"detector": {
|
||||
"installed_via": "dpkg",
|
||||
"package": "jellyfin",
|
||||
"repo": "jellyfin/jellyfin",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "(?i)(?:v|release[-_/]?)?(\\d+(?:\\.\\d+){1,3}(?:[-+._][0-9A-Za-z.-]+)?)"
|
||||
}
|
||||
},
|
||||
"kavita": {
|
||||
"operational": true,
|
||||
"name": "Kavita",
|
||||
"install_scope": [
|
||||
"community-script"
|
||||
],
|
||||
"evidence": [
|
||||
"community-confirmed:github-discussion-306"
|
||||
],
|
||||
"detector": {
|
||||
"installed_via": "file",
|
||||
"file_path": "/root/.kavita",
|
||||
"file_regex": "(\\d+\\.\\d+\\.\\d+)",
|
||||
"repo": "Kareadita/Kavita",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
}
|
||||
},
|
||||
"lazylibrarian": {
|
||||
"operational": true,
|
||||
"name": "LazyLibrarian",
|
||||
"install_scope": [
|
||||
"community-script"
|
||||
],
|
||||
"detector": {
|
||||
"installed_via": "command",
|
||||
"command_argv": [
|
||||
"git",
|
||||
"-C",
|
||||
"/opt/LazyLibrarian",
|
||||
"rev-parse",
|
||||
"HEAD"
|
||||
],
|
||||
"installed_regex": "([0-9a-fA-F]{40})",
|
||||
"upstream_type": "http_json",
|
||||
"upstream_url": "https://gitlab.com/api/v4/projects/LazyLibrarian%2FLazyLibrarian/repository/commits/master",
|
||||
"upstream_json_path": "id",
|
||||
"tag_regex": "([0-9a-fA-F]{40})"
|
||||
},
|
||||
"default_ports": [
|
||||
5299
|
||||
],
|
||||
"website": "https://lazylibrarian.gitlab.io/"
|
||||
},
|
||||
"netalertx": {
|
||||
"name": "NetAlertX",
|
||||
"install_scope": [
|
||||
"docker"
|
||||
],
|
||||
"detector": {
|
||||
"installed_via": "docker_label",
|
||||
"container_name": "netalertx",
|
||||
"label": "org.opencontainers.image.version",
|
||||
"repo": "netalertx/NetAlertX",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+(?:\\.\\d+){1,3})"
|
||||
}
|
||||
},
|
||||
"nginxproxymanager": {
|
||||
"detector": {
|
||||
"installed_via": "file",
|
||||
"file_path": "/opt/nginxproxymanager/backend/package.json",
|
||||
"file_regex": "\"version\"\\s*:\\s*\"(\\d+\\.\\d+\\.\\d+)\"",
|
||||
"repo": "NginxProxyManager/nginx-proxy-manager",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
},
|
||||
"file_fallbacks": [
|
||||
{
|
||||
"path": "/app/package.json",
|
||||
"regex": "\"version\"\\s*:\\s*\"(\\d+\\.\\d+\\.\\d+)\""
|
||||
},
|
||||
{
|
||||
"path": "/root/.nginxproxymanager",
|
||||
"regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
}
|
||||
]
|
||||
},
|
||||
"odoo": {
|
||||
"detector": {
|
||||
"installed_via": "dpkg",
|
||||
"package": "odoo",
|
||||
"tag_regex": "(\\d+\\.\\d+(?:\\.\\d+)?)"
|
||||
},
|
||||
"alt_detectors": [
|
||||
{
|
||||
"installed_via": "binary",
|
||||
"binary_path": "/usr/bin/odoo"
|
||||
}
|
||||
]
|
||||
},
|
||||
"openwebui": {
|
||||
"operational": true,
|
||||
"detector": {
|
||||
"installed_via": "python_dist",
|
||||
"python_path": "/root/.local/share/uv/tools/open-webui/bin/python",
|
||||
"distribution": "open-webui",
|
||||
"repo": "open-webui/open-webui",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
}
|
||||
},
|
||||
"pairdrop": {
|
||||
"detector": {
|
||||
"installed_via": "file",
|
||||
"file_path": "/opt/pairdrop/package.json",
|
||||
"file_regex": "\"version\"\\s*:\\s*\"(\\d+\\.\\d+\\.\\d+)\"",
|
||||
"repo": "schlagmichdoch/PairDrop",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
},
|
||||
"file_fallbacks": [
|
||||
{
|
||||
"path": "/root/.pairdrop",
|
||||
"regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
}
|
||||
]
|
||||
},
|
||||
"paperless-ngx": {
|
||||
"operational": false,
|
||||
"detector": {
|
||||
"installed_via": "docker_label",
|
||||
"container_name": "paperless-webserver-1",
|
||||
"label": "org.opencontainers.image.version",
|
||||
"repo": "paperless-ngx/paperless-ngx",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
},
|
||||
"alt_detectors": [
|
||||
{
|
||||
"installed_via": "file",
|
||||
"file_path": "/opt/paperless/src/paperless/version.py",
|
||||
"file_regex": "__version__[^\\n=]*=\\s*\\((\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\)"
|
||||
}
|
||||
]
|
||||
},
|
||||
"peanut": {
|
||||
"operational": true,
|
||||
"name": "PeaNUT",
|
||||
"install_scope": [
|
||||
"community-script"
|
||||
],
|
||||
"detector": {
|
||||
"installed_via": "file",
|
||||
"file_path": "/opt/peanut/package.json",
|
||||
"file_regex": "\"version\"\\s*:\\s*\"v?(\\d+\\.\\d+\\.\\d+)\"",
|
||||
"upstream_type": "github",
|
||||
"repo": "Brandawg93/PeaNUT",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
},
|
||||
"default_ports": [
|
||||
8080
|
||||
],
|
||||
"website": "https://github.com/Brandawg93/PeaNUT"
|
||||
},
|
||||
"plex": {
|
||||
"operational": true,
|
||||
"detector": {
|
||||
"installed_via": "dpkg",
|
||||
"package": "plexmediaserver",
|
||||
"installed_regex": "(\\d+\\.\\d+\\.\\d+\\.\\d+)",
|
||||
"upstream_type": "http_json",
|
||||
"upstream_url": "https://plex.tv/api/downloads/5.json?channel=8",
|
||||
"upstream_json_path": "computer.Linux.version",
|
||||
"tag_regex": "(\\d+\\.\\d+\\.\\d+\\.\\d+)"
|
||||
}
|
||||
},
|
||||
"portainer": {
|
||||
"operational": true,
|
||||
"name": "Portainer",
|
||||
@@ -44,76 +368,25 @@
|
||||
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/portainer.webp",
|
||||
"website": "https://www.portainer.io/"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"operational": true,
|
||||
"name": "Audiobookshelf",
|
||||
"install_scope": [
|
||||
"community-script",
|
||||
"manual-if-same-package"
|
||||
],
|
||||
"evidence": [
|
||||
"community-confirmed:github-discussion-306"
|
||||
],
|
||||
"prometheus": {
|
||||
"operational": false,
|
||||
"detector": {
|
||||
"installed_via": "docker_exec",
|
||||
"container_name": "prometheus",
|
||||
"binary_path": "/bin/prometheus",
|
||||
"binary_args": [
|
||||
"--version"
|
||||
],
|
||||
"repo": "prometheus/prometheus",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
}
|
||||
},
|
||||
"proxmox-backup-server": {
|
||||
"detector": {
|
||||
"installed_via": "dpkg",
|
||||
"package": "audiobookshelf",
|
||||
"repo": "advplyr/audiobookshelf",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "(?i)(?:v|release[-_/]?)?(\\d+(?:\\.\\d+){1,3}(?:[-+._][0-9A-Za-z.-]+)?)"
|
||||
}
|
||||
},
|
||||
"gitea": {
|
||||
"operational": true,
|
||||
"name": "Gitea",
|
||||
"install_scope": [
|
||||
"community-script",
|
||||
"manual-if-same-package"
|
||||
],
|
||||
"evidence": [
|
||||
"community-confirmed:github-discussion-306"
|
||||
],
|
||||
"detector": {
|
||||
"installed_via": "apk",
|
||||
"package": "gitea",
|
||||
"repo": "go-gitea/gitea",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
}
|
||||
},
|
||||
"dispatcharr": {
|
||||
"operational": true,
|
||||
"name": "Dispatcharr",
|
||||
"install_scope": [
|
||||
"community-script"
|
||||
],
|
||||
"evidence": [
|
||||
"community-confirmed:github-discussion-306"
|
||||
],
|
||||
"detector": {
|
||||
"installed_via": "file",
|
||||
"file_path": "/root/.dispatcharr",
|
||||
"file_regex": "(\\d+\\.\\d+\\.\\d+)",
|
||||
"repo": "Dispatcharr/Dispatcharr",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
}
|
||||
},
|
||||
"kavita": {
|
||||
"operational": true,
|
||||
"name": "Kavita",
|
||||
"install_scope": [
|
||||
"community-script"
|
||||
],
|
||||
"evidence": [
|
||||
"community-confirmed:github-discussion-306"
|
||||
],
|
||||
"detector": {
|
||||
"installed_via": "file",
|
||||
"file_path": "/root/.kavita",
|
||||
"file_regex": "(\\d+\\.\\d+\\.\\d+)",
|
||||
"repo": "Kareadita/Kavita",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
"package": "proxmox-backup-server",
|
||||
"tag_regex": "(\\d+\\.\\d+\\.\\d+)"
|
||||
}
|
||||
},
|
||||
"qbittorrent": {
|
||||
@@ -125,6 +398,19 @@
|
||||
"tag_regex": "(?i)(?:release-)?(\\d+\\.\\d+\\.\\d+)"
|
||||
}
|
||||
},
|
||||
"searxng": {
|
||||
"operational": true,
|
||||
"install_scope": [
|
||||
"community-script",
|
||||
"manual-if-same-venv"
|
||||
],
|
||||
"detector": {
|
||||
"installed_via": "python_dist",
|
||||
"python_path": "/usr/local/searxng/searx-pyenv/bin/python",
|
||||
"distribution": "searxng",
|
||||
"installed_regex": "(\\d+\\.\\d+\\.\\d+\\+[0-9a-f]+)"
|
||||
}
|
||||
},
|
||||
"tandoor": {
|
||||
"detector": {
|
||||
"installed_via": "file",
|
||||
@@ -141,77 +427,20 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"openwebui": {
|
||||
"operational": true,
|
||||
"detector": {
|
||||
"installed_via": "python_dist",
|
||||
"python_path": "/root/.local/share/uv/tools/open-webui/bin/python",
|
||||
"distribution": "open-webui",
|
||||
"repo": "open-webui/open-webui",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
}
|
||||
},
|
||||
"proxmox-backup-server": {
|
||||
"detector": {
|
||||
"installed_via": "dpkg",
|
||||
"package": "proxmox-backup-server",
|
||||
"tag_regex": "(\\d+\\.\\d+\\.\\d+)"
|
||||
}
|
||||
},
|
||||
"jellyfin": {
|
||||
"detector": {
|
||||
"installed_via": "dpkg",
|
||||
"package": "jellyfin",
|
||||
"repo": "jellyfin/jellyfin",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "(?i)(?:v|release[-_/]?)?(\\d+(?:\\.\\d+){1,3}(?:[-+._][0-9A-Za-z.-]+)?)"
|
||||
}
|
||||
},
|
||||
"adguard": {
|
||||
"detector": {
|
||||
"installed_via": "binary",
|
||||
"binary_path": "/opt/AdGuardHome/AdGuardHome",
|
||||
"repo": "AdguardTeam/AdGuardHome",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
}
|
||||
},
|
||||
"nginxproxymanager": {
|
||||
"technitiumdns": {
|
||||
"name": "Technitium DNS Server",
|
||||
"detector": {
|
||||
"installed_via": "file",
|
||||
"file_path": "/opt/nginxproxymanager/backend/package.json",
|
||||
"file_regex": "\"version\"\\s*:\\s*\"(\\d+\\.\\d+\\.\\d+)\"",
|
||||
"repo": "NginxProxyManager/nginx-proxy-manager",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
"file_path": "/root/.technitium",
|
||||
"file_regex": "(\\d+(?:\\.\\d+){1,3})",
|
||||
"upstream_type": "http_json",
|
||||
"upstream_url": "https://go.technitium.com/?id=42",
|
||||
"upstream_json_path": "updateVersion"
|
||||
},
|
||||
"file_fallbacks": [
|
||||
{
|
||||
"path": "/app/package.json",
|
||||
"regex": "\"version\"\\s*:\\s*\"(\\d+\\.\\d+\\.\\d+)\""
|
||||
},
|
||||
{
|
||||
"path": "/root/.nginxproxymanager",
|
||||
"regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
}
|
||||
]
|
||||
},
|
||||
"pairdrop": {
|
||||
"detector": {
|
||||
"installed_via": "file",
|
||||
"file_path": "/opt/pairdrop/package.json",
|
||||
"file_regex": "\"version\"\\s*:\\s*\"(\\d+\\.\\d+\\.\\d+)\"",
|
||||
"repo": "schlagmichdoch/PairDrop",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
},
|
||||
"file_fallbacks": [
|
||||
{
|
||||
"path": "/root/.pairdrop",
|
||||
"regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
}
|
||||
]
|
||||
"default_ports": [
|
||||
5380
|
||||
],
|
||||
"website": "https://technitium.com/dns/"
|
||||
},
|
||||
"traefik": {
|
||||
"operational": true,
|
||||
@@ -259,189 +488,6 @@
|
||||
"installed_regex": "(?im)^Vaultwarden\\s+v?(\\d+\\.\\d+\\.\\d+)"
|
||||
}
|
||||
]
|
||||
},
|
||||
"docmost": {
|
||||
"detector": {
|
||||
"installed_via": "file",
|
||||
"file_path": "/opt/docmost/package.json",
|
||||
"file_regex": "\"version\"\\s*:\\s*\"(\\d+\\.\\d+\\.\\d+)\"",
|
||||
"repo": "docmost/docmost",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
},
|
||||
"file_fallbacks": [
|
||||
{
|
||||
"path": "/root/.docmost",
|
||||
"regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
}
|
||||
]
|
||||
},
|
||||
"agentdvr": {
|
||||
"detector": {
|
||||
"installed_via": "file",
|
||||
"file_path": "/root/.agentdvr",
|
||||
"file_regex": "Agent_[^/]+_([0-9]+(?:_[0-9]+){3})\\.zip",
|
||||
"repo": "ispysoftware/agent-install-scripts",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+(?:\\.\\d+){3})"
|
||||
}
|
||||
},
|
||||
"odoo": {
|
||||
"detector": {
|
||||
"installed_via": "dpkg",
|
||||
"package": "odoo",
|
||||
"tag_regex": "(\\d+\\.\\d+(?:\\.\\d+)?)"
|
||||
},
|
||||
"alt_detectors": [
|
||||
{
|
||||
"installed_via": "binary",
|
||||
"binary_path": "/usr/bin/odoo"
|
||||
}
|
||||
]
|
||||
},
|
||||
"paperless-ngx": {
|
||||
"operational": false,
|
||||
"detector": {
|
||||
"installed_via": "docker_label",
|
||||
"container_name": "paperless-webserver-1",
|
||||
"label": "org.opencontainers.image.version",
|
||||
"repo": "paperless-ngx/paperless-ngx",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
},
|
||||
"alt_detectors": [
|
||||
{
|
||||
"installed_via": "file",
|
||||
"file_path": "/opt/paperless/src/paperless/version.py",
|
||||
"file_regex": "__version__[^\\n=]*=\\s*\\((\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\)"
|
||||
}
|
||||
]
|
||||
},
|
||||
"plex": {
|
||||
"operational": true,
|
||||
"detector": {
|
||||
"installed_via": "dpkg",
|
||||
"package": "plexmediaserver",
|
||||
"installed_regex": "(\\d+\\.\\d+\\.\\d+\\.\\d+)",
|
||||
"upstream_type": "http_json",
|
||||
"upstream_url": "https://plex.tv/api/downloads/5.json?channel=8",
|
||||
"upstream_json_path": "computer.Linux.version",
|
||||
"tag_regex": "(\\d+\\.\\d+\\.\\d+\\.\\d+)"
|
||||
}
|
||||
},
|
||||
"prometheus": {
|
||||
"operational": false,
|
||||
"detector": {
|
||||
"installed_via": "docker_exec",
|
||||
"container_name": "prometheus",
|
||||
"binary_path": "/bin/prometheus",
|
||||
"binary_args": [
|
||||
"--version"
|
||||
],
|
||||
"repo": "prometheus/prometheus",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
}
|
||||
},
|
||||
"grafana": {
|
||||
"operational": false,
|
||||
"detector": {
|
||||
"installed_via": "docker_exec",
|
||||
"container_name": "grafana",
|
||||
"binary_path": "grafana",
|
||||
"binary_args": [
|
||||
"server",
|
||||
"-v"
|
||||
],
|
||||
"repo": "grafana/grafana",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
}
|
||||
},
|
||||
"searxng": {
|
||||
"operational": true,
|
||||
"install_scope": [
|
||||
"community-script",
|
||||
"manual-if-same-venv"
|
||||
],
|
||||
"detector": {
|
||||
"installed_via": "python_dist",
|
||||
"python_path": "/usr/local/searxng/searx-pyenv/bin/python",
|
||||
"distribution": "searxng",
|
||||
"installed_regex": "(\\d+\\.\\d+\\.\\d+\\+[0-9a-f]+)"
|
||||
}
|
||||
},
|
||||
"technitiumdns": {
|
||||
"name": "Technitium DNS Server",
|
||||
"detector": {
|
||||
"installed_via": "file",
|
||||
"file_path": "/root/.technitium",
|
||||
"file_regex": "(\\d+(?:\\.\\d+){1,3})",
|
||||
"upstream_type": "http_json",
|
||||
"upstream_url": "https://go.technitium.com/?id=42",
|
||||
"upstream_json_path": "updateVersion"
|
||||
},
|
||||
"default_ports": [
|
||||
5380
|
||||
],
|
||||
"website": "https://technitium.com/dns/"
|
||||
},
|
||||
"netalertx": {
|
||||
"name": "NetAlertX",
|
||||
"install_scope": [
|
||||
"docker"
|
||||
],
|
||||
"detector": {
|
||||
"installed_via": "docker_label",
|
||||
"container_name": "netalertx",
|
||||
"label": "org.opencontainers.image.version",
|
||||
"repo": "netalertx/NetAlertX",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+(?:\\.\\d+){1,3})"
|
||||
}
|
||||
},
|
||||
"immich": {
|
||||
"detector": {
|
||||
"installed_via": "file",
|
||||
"file_path": "/root/.immich",
|
||||
"file_regex": "(?i)(?:v|release[-_/]?)?(\\d+(?:\\.\\d+){1,3}(?:[-+._][0-9A-Za-z.-]+)?)",
|
||||
"repo": "immich-app/immich",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "(?i)(?:v|release[-_/]?)?(\\d+(?:\\.\\d+){1,3}(?:[-+._][0-9A-Za-z.-]+)?)"
|
||||
},
|
||||
"alt_detectors": [
|
||||
{
|
||||
"installed_via": "docker_label",
|
||||
"container_name": "immich_server",
|
||||
"label": "org.opencontainers.image.version"
|
||||
}
|
||||
]
|
||||
},
|
||||
"changedetection": {
|
||||
"operational": true,
|
||||
"name": "Changedetection.io",
|
||||
"install_scope": [
|
||||
"community-script",
|
||||
"manual"
|
||||
],
|
||||
"evidence": [
|
||||
"community-confirmed:github-discussion-306"
|
||||
],
|
||||
"detector": {
|
||||
"installed_via": "command",
|
||||
"command_argv": [
|
||||
"/opt/changedetection/.venv/bin/changedetection.io",
|
||||
"--version"
|
||||
],
|
||||
"installed_regex": "v?(\\d+\\.\\d+\\.\\d+)",
|
||||
"repo": "dgtlmoon/changedetection.io",
|
||||
"github_source": "releases",
|
||||
"tag_regex": "v?(\\d+\\.\\d+\\.\\d+)"
|
||||
},
|
||||
"default_ports": [
|
||||
5000
|
||||
],
|
||||
"website": "https://changedetection.io/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+34
-34
@@ -120,11 +120,11 @@
|
||||
"ACL Status:": "ACL-Status:",
|
||||
"ACL permissions applied for local access for user:": "ACL-Berechtigungen für lokalen Zugriff für Benutzer angewendet:",
|
||||
"ADVANCED SETTINGS COMPLETE": "ERWEITERTE EINSTELLUNGEN ABGESCHLOSSEN",
|
||||
"AI / Coding & Dev-Tools": "KI / Codierung und Entwicklungstools",
|
||||
"AI / Coding & Dev-Tools": "KI, Programmierung und Entwicklung",
|
||||
"ALL DATA ON": "ALLE DATEN EIN",
|
||||
"ALL DATA ON THIS DISK WILL BE PERMANENTLY LOST!": "ALLE DATEN AUF DIESER Diskette gehen dauerhaft verloren!",
|
||||
"ALL Utilities": "ALLE Dienstprogramme",
|
||||
"ALLOWED_HOSTS cannot contain line breaks": "ALLOWED HOSTS kann keine Zeilenumbrüche enthalten",
|
||||
"ALLOWED_HOSTS cannot contain line breaks": "ALLOWED_HOSTS kann keine Zeilenumbrüche enthalten",
|
||||
"AList initial login": "AList Erstanmeldung",
|
||||
"AMD CPU detected": "AMD-CPU erkannt",
|
||||
"AMD CPU fixes applied successfully": "AMD-CPU-Korrekturen erfolgreich angewendet",
|
||||
@@ -185,7 +185,7 @@
|
||||
"Actual device path on the host": "Tatsächlicher Gerätepfad auf dem Host",
|
||||
"Adaptation file too large": "Anpassungsdatei zu groß",
|
||||
"Adaptation file with unexpected permissions or owner": "Anpassungsdatei mit unerwarteten Berechtigungen oder Besitzer",
|
||||
"Adblock & DNS": "Adblock & DNS",
|
||||
"Adblock & DNS": "Adblock und DNS",
|
||||
"Add Audio Passthrough": "Fügen Sie Audio-Passthrough hinzu",
|
||||
"Add CIFS storage:": "CIFS-Speicher hinzufügen:",
|
||||
"Add Controller or NVMe (PCI passthrough)": "Controller oder NVMe hinzufügen (PCI-Passthrough)",
|
||||
@@ -439,7 +439,7 @@
|
||||
"Auth key is required.": "Authentifizierungsschlüssel ist erforderlich.",
|
||||
"Auth:": "Authentifizierung:",
|
||||
"Authentication": "Authentifizierung",
|
||||
"Authentication & Security": "Authentifizierung & Sicherheit",
|
||||
"Authentication & Security": "Authentifizierung und Sicherheit",
|
||||
"Authentication Error": "Authentifizierungsfehler",
|
||||
"Authentication failed.": "Die Authentifizierung ist fehlgeschlagen.",
|
||||
"Authentication required:": "Authentifizierung erforderlich:",
|
||||
@@ -463,7 +463,7 @@
|
||||
"Automatic private network allocation requires a /24 subnet": "Automatische private Netzwerkzuweisung requires a /24 Subnetz",
|
||||
"Automatic video library manager for TV Shows": "Automatischer Videobibliotheksmanager für TV-Shows",
|
||||
"Automatic/Unattended": "Automatisch/unbeaufsichtigt",
|
||||
"Automation & Scheduling": "Automatisierung & Terminplanung",
|
||||
"Automation & Scheduling": "Automatisierung und Zeitplanung",
|
||||
"Available": "Verfügbar",
|
||||
"Available Borg archives (newest first):": "Verfügbare Borg-Archive (neueste zuerst):",
|
||||
"Available Borg targets:": "Verfügbare Borg-Ziele:",
|
||||
@@ -500,7 +500,7 @@
|
||||
"Backend:": "Backend:",
|
||||
"Background archive extraction for Arr download queues. No web interface.": "Hintergrund-Archivextraktion für Arr-Download-Warteschlangen. Kein Webinterface.",
|
||||
"Backup — VM and CT backups": "Backup – VM- und CT-Backups",
|
||||
"Backup & Recovery": "Backup & Recovery",
|
||||
"Backup & Recovery": "Sicherung und Wiederherstellung",
|
||||
"Backup Created": "Backup erstellt",
|
||||
"Backup ID (group name in PBS):": "Backup-ID (Gruppenname in PBS):",
|
||||
"Backup ID for this job:": "Backup-ID für diesen Job:",
|
||||
@@ -603,11 +603,11 @@
|
||||
"Broken gasket-dkms package state recovered.": "Der Status des defekten „gasket-dkms“-Pakets wurde wiederhergestellt.",
|
||||
"Browse Your Life in Images": "Durchsuchen Sie Ihr Leben in Bildern",
|
||||
"Browse manually (advanced)...": "Manuell durchsuchen (erweitert)...",
|
||||
"Browsers & Web Desktops": "Browser & Web Desktops",
|
||||
"Browsers & Web Desktops": "Browser und Web-Desktops",
|
||||
"Build and install the gasket and apex kernel modules (DKMS)": "gasket- und apex-Kernelmodule erstellen und installieren (DKMS)",
|
||||
"Build dependencies installed.": "Build-Abhängigkeiten installiert.",
|
||||
"Build your personal knowledge base with TriliumNext Notes": "Erstellen Sie Ihre persönliche Wissensbasis mit TriliumNext Notes",
|
||||
"Business & ERP": "Business & ERP",
|
||||
"Business & ERP": "Unternehmen und ERP",
|
||||
"CHANGES APPLIED SUCCESSFULLY": "ÄNDERUNGEN WURDEN ERFOLGREICH ANGEWENDET",
|
||||
"CIFS Client Tools: AVAILABLE": "CIFS-Client-Tools: VERFÜGBAR",
|
||||
"CIFS Client Tools: NOT AVAILABLE - installing...": "CIFS-Client-Tools: NICHT VERFÜGBAR – Installation...",
|
||||
@@ -869,7 +869,7 @@
|
||||
"Commenting legacy ceph.list (if present)...": "Kommentieren der alten ceph.list (falls vorhanden) ...",
|
||||
"Common Issues Check": "Überprüfen Sie häufige Probleme",
|
||||
"Common root for the published views": "Gemeinsame Wurzel für die veröffentlichten Ansichten",
|
||||
"Communication & Community": "Kommunikation & Community",
|
||||
"Communication & Community": "Kommunikation und Community",
|
||||
"Community Scripts": "Community-Skripte",
|
||||
"Community single-container Home Assistant OS image": "Einbehälter-Bild in der Gemeinschaft Home Assistant OS",
|
||||
"Compatibility check": "Kompatibilitätsprüfung",
|
||||
@@ -1084,7 +1084,7 @@
|
||||
"Container will pick up the mount on next start": "Der Container holt das Reittier beim nächsten Start ab",
|
||||
"Container with ID": "Container mit ID",
|
||||
"Container:": "Container:",
|
||||
"Containers & Docker": "Container & Docker",
|
||||
"Containers & Docker": "Container und Docker",
|
||||
"Containers returned to their previous state": "Container in ihren vorherigen Zustand zurückgekehrt",
|
||||
"Containers that are removed:": "Entfernte Behälter:",
|
||||
"Containers that will be created (one LXC per service, on a private network):": "Container, die erstellt werden (ein LXC pro Dienst, in einem privaten Netzwerk):",
|
||||
@@ -1157,7 +1157,7 @@
|
||||
"Coral M.2 Apex configuration added - device ready": "Coral M.2 Apex-Konfiguration hinzugefügt – Gerät bereit",
|
||||
"Coral M.2 Apex configuration added - device will be available after reboot": "Coral M.2 Apex-Konfiguration hinzugefügt – Gerät ist nach dem Neustart verfügbar",
|
||||
"Coral M.2 Apex detected, configuring...": "Coral M.2 Apex erkannt, konfiguriert...",
|
||||
"Coral PCIe/M.2 node (e.g. /dev/apex_0)": "Coral PCIe/M.2-Knoten (z. B. /dev/apex 0)",
|
||||
"Coral PCIe/M.2 node (e.g. /dev/apex_0)": "Coral PCIe/M.2-Knoten (z. B. /dev/apex_0)",
|
||||
"Coral TPU Installation": "Coral-TPU-Installation",
|
||||
"Coral TPU Uninstall": "Coral TPU-Deinstallation",
|
||||
"Coral TPU device nodes detected with correct group (apex).": "Coral TPU-Geräteknoten wurden mit der richtigen Gruppe (Apex) erkannt.",
|
||||
@@ -1345,7 +1345,7 @@
|
||||
"Creating the container...": "Erstellen des Containers...",
|
||||
"Creating the initial administrator...": "Erstellen des ersten Administrators...",
|
||||
"Creating the temporary data container": "Erstellen des temporären Datencontainers",
|
||||
"Creative & Design": "Kreativ & Design",
|
||||
"Creative & Design": "Kreativität und Design",
|
||||
"Credentials are correct": "Die Anmeldedaten sind korrekt",
|
||||
"Credentials cleared. jwt_secret and API tokens preserved.": "Anmeldedaten gelöscht. jwt_secret und API-Token bleiben erhalten.",
|
||||
"Credentials file created securely.": "Anmeldeinformationsdatei sicher erstellt.",
|
||||
@@ -1694,7 +1694,7 @@
|
||||
"Docker Mods are only offered for compatible LinuxServer images": "Docker Mods werden nur für kompatible LinuxServer Images angeboten",
|
||||
"Docker Volume Backup": "Docker Volume Backup",
|
||||
"Docker/CLI not available yet or no valid answer": "Docker/CLI noch nicht verfügbar oder keine gültige Antwort",
|
||||
"Documents & Notes": "Dokumente & Notizen",
|
||||
"Documents & Notes": "Dokumente und Notizen",
|
||||
"Documents volume size in GB": "Dokumentenvolumen in GB",
|
||||
"Dokuwiki is a simple to use and highly versatile Open Source wiki software that doesn't require a database. It is loved by users for its clean and readable syntax. The ease of maintenance, backup and integration makes it an administrator's favorite. Built in access controls and authentication connectors make DokuWiki especially useful in the enterprise context and the large number of plugins contributed by its vibrant community allow for a broad range of use cases beyond a traditional wiki.": "Dokuwiki ist eine einfach zu bedienende und äußerst vielseitige Open-Source-Wiki-Software, die keine Datenbank requi ist. Es wird von den Benutzern für seine saubere und lesbare Syntax geliebt. Die einfache Wartung, Sicherung und Integration macht es zum Favoriten des Administrators. Integrierte Zugangskontrollen und Authentifizierungskonnektoren machen DokuWiki besonders nützlich im Unternehmenskontext und die große Anzahl von Plugins, die von der lebendigen Community beigetragen werden, ermöglichen eine breite Palette von Anwendungsfällen jenseits eines traditionellen Wikis.",
|
||||
"Dolphin Emulator lets you play GameCube and Wii games with various graphical enhancements and other features are available to improve your game experience.": "Mit Dolphin Emulator können Sie GameCube- und Wii-Spiele mit verschiedenen grafischen Verbesserungen spielen, und es stehen weitere Funktionen zur Verfügung, um Ihr Spielerlebnis zu verbessern.",
|
||||
@@ -1731,7 +1731,7 @@
|
||||
"Dry run completed; the container and the mounts were not changed.": "Trockenlauf abgeschlossen; der Behälter und die Halterungen wurden nicht verändert.",
|
||||
"DuckDNS subdomain without .duckdns.org (comma separated for several)": "DuckDNS Subdomain ohne .duckdns.org (Komma für mehrere getrennt)",
|
||||
"DuckDNS token from your account at duckdns.org": "DuckDNS-Token von Ihrem Konto bei duckdns.org",
|
||||
"DuckDNS updates the subdomain every 5 minutes. Without UPDATE_IP, DuckDNS itself detects the public IPv4 address of the request.": "DuckDNS aktualisiert die Subdomain alle 5 Minuten. Ohne UPDATE IP erkennt DuckDNS selbst die öffentliche IPv4-Adresse der Anfrage.",
|
||||
"DuckDNS updates the subdomain every 5 minutes. Without UPDATE_IP, DuckDNS itself detects the public IPv4 address of the request.": "DuckDNS aktualisiert die Subdomain alle 5 Minuten. Ohne UPDATE_IP erkennt DuckDNS selbst die öffentliche IPv4-Adresse der Anfrage.",
|
||||
"DuckStation is a PS1 Emulator aiming for the best accuracy and game support.": "DuckStation ist ein PS1-Emulator, der auf die beste accuracy- und Spielunterstützung abzielt.",
|
||||
"Duckdns is a free service which will point a DNS (sub domains of duckdns.org) to an IP of your choice. The service is completely free, and doesn't require reactivation or forum posts to maintain its existence.": "Duckdns ist ein kostenloser Dienst, der ein DNS (Subdomains von duckdns.org) auf eine IP Ihrer Wahl verweist. Der Dienst ist völlig kostenlos und require Reaktivierung oder Forenbeiträge, um seine Existenz zu erhalten.",
|
||||
"Dumping AMD GPU ROM BIOS via sysfs...": "Das AMD-GPU-ROM-BIOS wird über sysfs gelöscht ...",
|
||||
@@ -2230,7 +2230,7 @@
|
||||
"FileBrowser Quantum": "FileBrowser Quantum",
|
||||
"FileBrowser Quantum (new installation)": "FileBrowser Quantum (Neuinstallation)",
|
||||
"FileDrop is a free, open source file sharing service": "FileDrop ist ein kostenloser Open Source File Sharing Service",
|
||||
"Files & Downloads": "Dateien & Downloads",
|
||||
"Files & Downloads": "Dateien und Downloads",
|
||||
"Files volume size in GB": "Dateivolumengröße in GB",
|
||||
"Filesystem": "Dateisystem",
|
||||
"Filesystem Tools Required": "Dateisystem-Tools erforderlich",
|
||||
@@ -2239,7 +2239,7 @@
|
||||
"Final cleanup of the stack operation completed": "Endgültige Bereinigung des Stacks operation abgeschlossen",
|
||||
"Final confirmation": "Endgültige Bestätigung",
|
||||
"Final storage health/status check": "Endgültige Überprüfung des Speicherzustands/-status",
|
||||
"Finance & Budgeting": "Finanzen & Budgeting",
|
||||
"Finance & Budgeting": "Finanzen und Budget",
|
||||
"Find your device using https://finds.synology.com": "Finden Sie Ihr Gerät über https://finds.synology.com",
|
||||
"Fingerprint:": "Fingerabdruck:",
|
||||
"Firefly, the easiest using of WireGuard VPN server, plus version of wg-easy.": "Firefly, die einfachste Verwendung von WireGuard VPN-Server, plus Version von wg-easy.",
|
||||
@@ -2387,7 +2387,7 @@
|
||||
"GRUB_CMDLINE_LINUX_DEFAULT not found in GRUB config": "GRUB_CMDLINE_LINUX_DEFAULT wurde in der GRUB-Konfiguration nicht gefunden",
|
||||
"GUI mode (if available)": "GUI-Modus (falls verfügbar)",
|
||||
"GZDoom is a feature centric port for all Doom engine games, based on ZDoom, adding an OpenGL renderer and powerful scripting capabilities.": "GZDoom ist ein funktionsorientierter Port für alle Doom-Engine-Spiele, basierend auf ZDoom, der einen OpenGL-Renderer und leistungsstarke Skriptfunktionen hinzufügt.",
|
||||
"Gaming & Leisure": "Gaming & Leisure",
|
||||
"Gaming & Leisure": "Spiele und Freizeit",
|
||||
"Gateway is not installed.": "Gateway ist nicht installiert.",
|
||||
"Gateway removed.": "Gateway entfernt.",
|
||||
"Gateway restarted.": "Gateway neu gestartet.",
|
||||
@@ -2527,7 +2527,7 @@
|
||||
"Host GPU detected": "Host-GPU erkannt",
|
||||
"Host GPU is already bound to vfio-pci. Host reconfiguration/reboot should not be required for this VM-to-VM reassignment.": "Die Host-GPU ist bereits an vfio-pci gebunden. Für diese VM-zu-VM-Neuzuweisung sollte keine Host-Neukonfiguration/Neustart erforderlich sein.",
|
||||
"Host IP": "Host-IP",
|
||||
"Host Management": "Host Management",
|
||||
"Host Management": "Host-Verwaltung",
|
||||
"Host Mount Path": "Host-Mount-Pfad",
|
||||
"Host NFS/Samba as Proxmox Storage (pvesm)": "NFS/Samba als Proxmox-Speicher hosten (pvesm)",
|
||||
"Host Path": "Hostpfad",
|
||||
@@ -2795,7 +2795,7 @@
|
||||
"Initiator IQN is authorised on the target": "Der Initiator-IQN ist auf dem Ziel autorisiert",
|
||||
"Initiator IQN:": "Initiator-IQN:",
|
||||
"Inkscape is professional quality vector graphics software which runs on Linux, Mac OS X and Windows desktop computers.": "Inkscape ist professionelle Qualitätsvektor-Grafiksoftware, die auf Linux, Mac OS X und Windows Desktop-Computern läuft.",
|
||||
"Inside the LXC, create the administrator: console kimai:user:create YOUR_USERNAME YOUR_EMAIL ROLE_SUPER_ADMIN": "Erstellen Sie im LXC den Administrator: Konsole kimai:user:creat YOUR USERNAME YOUR EMAIL ROLE SUPER ADMIN",
|
||||
"Inside the LXC, create the administrator: console kimai:user:create YOUR_USERNAME YOUR_EMAIL ROLE_SUPER_ADMIN": "Erstellen Sie im LXC den Administrator: Konsole kimai:user:creat YOUR_USERNAME YOUR_EMAIL ROLE_SUPER_ADMIN",
|
||||
"Inspect disks before any action": "Überprüfen Sie die Datenträger vor jeder Aktion",
|
||||
"Inspect host device nodes": "Untersuchen Sie die Host-Geräteknoten",
|
||||
"Inspect passthrough/kernel events": "Überprüfen Sie Passthrough-/Kernel-Ereignisse",
|
||||
@@ -3087,7 +3087,7 @@
|
||||
"Invalid volume size": "Ungültige Volumengröße",
|
||||
"Invalid volume size:": "Ungültige Volumengröße:",
|
||||
"Invalid volume target": "Ungültiges Volumenziel",
|
||||
"IoT & Smart Home": "IoT & Smart Home",
|
||||
"IoT & Smart Home": "IoT und Smart Home",
|
||||
"Is the value a password or secret?": "Ist der Wert ein Passwort oder ein Geheimnis?",
|
||||
"Issue": "Ausgabe",
|
||||
"Issues found": "Probleme gefunden",
|
||||
@@ -3386,7 +3386,7 @@
|
||||
"Max user watches configured": "Maximale Benutzerüberwachungen konfiguriert",
|
||||
"Maximum auto-repair attempts reached (3). Please review the log and run any remaining commands manually.": "Maximale Anzahl automatischer Reparaturversuche erreicht (3). Bitte überprüfen Sie das Protokoll und führen Sie alle verbleibenden Befehle manuell aus.",
|
||||
"May need to restart terminal": "Möglicherweise muss das Terminal neu gestartet werden",
|
||||
"Media & Streaming": "Medien & Streaming",
|
||||
"Media & Streaming": "Medien und Streaming",
|
||||
"Media discovery and request management for Jellyfin, Plex and Emby.": "Media Discovery und Request Management für Jellyfin, Plex und Emby.",
|
||||
"Media library transcoding and health checking, with an internal worker node.": "Medienbibliothek Transcodierung und Gesundheitsüberprüfung, mit einem internen Mitarbeiterknoten.",
|
||||
"Media server": "Medienserver",
|
||||
@@ -3442,7 +3442,7 @@
|
||||
"Monitor progress:": "Fortschritt überwachen:",
|
||||
"Monitor, analyze, and alert on network performance.": "Überwachen, analysieren und alarmieren Sie die Netzwerkleistung.",
|
||||
"Monitoring": "Überwachung",
|
||||
"Monitoring & Analytics": "Monitoring & Analytics",
|
||||
"Monitoring & Analytics": "Überwachung und Auswertung",
|
||||
"Most common cause: the archive is corrupted (interrupted write, partial copy, or storage issue).": "Häufigste Ursache: Das Archiv ist beschädigt (unterbrochener Schreibvorgang, teilweises Kopieren oder Speicherproblem).",
|
||||
"Mount Added Successfully:": "Mount erfolgreich hinzugefügt:",
|
||||
"Mount CIFS share:": "CIFS-Freigabe bereitstellen:",
|
||||
@@ -3652,7 +3652,7 @@
|
||||
"NVMe health status: WARNING (critical_warning =": "NVMe-Gesundheitsstatus: WARNUNG (critical_warning =",
|
||||
"NVMe skipped (to add as PCIe use 'Add Controller or NVMe PCIe to VM'):": "NVMe übersprungen (zum Hinzufügen als PCIe verwenden Sie „Controller oder NVMe PCIe zur VM hinzufügen“):",
|
||||
"NVMe-specific SMART log": "NVMe-spezifisches SMART-Protokoll",
|
||||
"NVR & Cameras": "NVR & Kameras",
|
||||
"NVR & Cameras": "NVR und Kameras",
|
||||
"NVR with optional VA-API video acceleration and hardware object detectors": "NVR mit optionaler VA-API Videobeschleunigung und Hardwareobjektdetektoren",
|
||||
"NZBGet web interface": "NZBGet Web-Schnittstelle",
|
||||
"Name": "Name",
|
||||
@@ -3664,7 +3664,7 @@
|
||||
"Name of this wallabag instance, shown in the interface and in 2FA codes": "Name dieser wallabag-Instanz, angezeigt in der Schnittstelle und in 2FA-Codes",
|
||||
"Name or part of the description of the application": "Name oder Teil der Beschreibung des Antrags",
|
||||
"Name:": "Name:",
|
||||
"Named accounts need private mode. Stop the container, set public: false in /config/config.js, start it again and create each user with: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>": "Benannte Konten benötigen einen privaten Modus. Stoppen Sie den Container, setzen Sie public: false in /config/config.js, starten Sie ihn erneut und erstellen Sie jeden Benutzer mit: pct exec <CTID> -- env THELOUNGE HOME=/config s6-setuidgid abc thelounge add <user>",
|
||||
"Named accounts need private mode. Stop the container, set public: false in /config/config.js, start it again and create each user with: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>": "Benannte Konten benötigen einen privaten Modus. Stoppen Sie den Container, setzen Sie public: false in /config/config.js, starten Sie ihn erneut und erstellen Sie jeden Benutzer mit: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>",
|
||||
"Neither /etc/kernel/cmdline nor /etc/default/grub found.": "Weder /etc/kernel/cmdline noch /etc/default/grub gefunden.",
|
||||
"Nesting feature enabled": "Verschachtelungsfunktion aktiviert",
|
||||
"NetBIOS Service: RUNNING": "NetBIOS-Dienst: LÄUFT",
|
||||
@@ -3674,7 +3674,7 @@
|
||||
"Netbox is an IP address management (IPAM) and data center infrastructure management (DCIM) tool. Initially conceived by the network engineering team at DigitalOcean, NetBox was developed specifically to address the needs of network and infrastructure engineers. It is intended to function as a domain-specific source of truth for network operations.": "Netbox ist ein IP-Adressmanagement (IPAM) und ein Data Center Infrastructure Management (DCIM). Ursprünglich vom Netzwerk-Engineering-Team von DigitalOcean konzipiert, wurde NetBox speziell für die Bedürfnisse von Netzwerk- und Infrastrukturingenieuren entwickelt. Es soll als domänenspezifische Wahrheitsquelle für Netzwerk-operationen fungieren.",
|
||||
"Network": "Netzwerk",
|
||||
"Network :": "Netzwerk:",
|
||||
"Network & Firewall": "Netzwerk & Firewall",
|
||||
"Network & Firewall": "Netzwerk und Firewall",
|
||||
"Network (interfaces, DNS)": "Netzwerk (Schnittstellen, DNS)",
|
||||
"Network Bridge": "Netzwerkbrücke",
|
||||
"Network Commands": "Netzwerkbefehle",
|
||||
@@ -4045,7 +4045,7 @@
|
||||
"OCI containers require Proxmox VE 9.1 or later.": "OCI-Container erfordern Proxmox VE 9.1 oder höher.",
|
||||
"OCI management": "OCI-Verwaltung",
|
||||
"OCI management could not be completed. Check the backend status; no additional cleanup has been authorized.": "Das OCI-Management konnte nicht abgeschlossen werden. Überprüfen Sie den Backend-Status; es wurde keine zusätzliche Bereinigung autorisiert.",
|
||||
"OCI manager Apps (beta)": "OCI Manager Apps (Beta)",
|
||||
"OCI manager Apps (beta)": "OCI manager Apps (beta)",
|
||||
"OCI manager Apps is a beta: if something does not work as expected, please report it on GitHub with the application name.": "OCI Manager Apps ist eine Beta: Wenn etwas nicht wie erwartet funktioniert, melden Sie es bitte auf GitHub mit dem Anwendungsnamen.",
|
||||
"OCI metadata integrity mismatch": "OCI Unstimmigkeiten bei Metadaten",
|
||||
"OCI metadata too large": "OCI-Metadaten zu groß",
|
||||
@@ -4377,7 +4377,7 @@
|
||||
"Postfix configuration": "Postfix-Konfiguration",
|
||||
"PostgreSQL": "PostgreSQL",
|
||||
"PostgreSQL URL without an associated service:": "PostgreSQL URL ohne zugehörigen Dienst:",
|
||||
"PostgreSQL creates the database named in POSTGRES_DB on the first start. The installer default is postgresql.": "PostgreSQL erstellt beim ersten Start die in POSTGRES DB genannte Datenbank. Der Installer ist standardmäßig postgresql.",
|
||||
"PostgreSQL creates the database named in POSTGRES_DB on the first start. The installer default is postgresql.": "PostgreSQL erstellt beim ersten Start die in POSTGRES_DB genannte Datenbank. Der Installer ist standardmäßig postgresql.",
|
||||
"PostgreSQL is an advanced, enterprise-class, and open-source relational database system. PostgreSQL supports both SQL (relational) and JSON (non-relational) querying.": "PostgreSQL ist ein fortschrittliches, Enterprise-Klasse und Open-Source relationale Datenbanksystem. PostgreSQL unterstützt sowohl SQL (relational) als auch JSON (non-relational) Abfragen.",
|
||||
"PostgreSQL requires a password": "PostgreSQL requires ein Passwort",
|
||||
"PostgreSQL volume size in GB": "PostgreSQL Volumengröße in GB",
|
||||
@@ -4460,7 +4460,7 @@
|
||||
"Process may take several minutes depending on container size": "Der Vorgang kann je nach Behältergröße mehrere Minuten dauern",
|
||||
"Process may take several minutes for large containers": "Bei großen Behältern kann der Vorgang mehrere Minuten dauern",
|
||||
"Processes using NVIDIA:": "Prozesse mit NVIDIA:",
|
||||
"Productivity & Workflows": "Produktivität & Workflows",
|
||||
"Productivity & Workflows": "Produktivität und Arbeitsabläufe",
|
||||
"Profile": "Profil",
|
||||
"Profile:": "Profil:",
|
||||
"Projectsend is a self-hosted application that lets you upload files and assign them to specific clients that you create yourself. Secure, private and easy. No more depending on external services or e-mail to send those files.": "Projectsend ist eine selbst gehostete Anwendung, mit der Sie Dateien hochladen und bestimmten Clients zuweisen können, die Sie selbst erstellen. Sicher, privat und einfach. Nicht mehr abhängig von externen Diensten oder E-Mail, um diese Dateien zu senden.",
|
||||
@@ -4541,7 +4541,7 @@
|
||||
"Pwndrop is a self-deployable file hosting service for sending out red teaming payloads or securely sharing your private files over HTTP and WebDAV.": "Pwndrop ist ein selbst einsetzbarer Dateihosting-Service zum Senden von roten Teaming-Nutzlasten oder zum sicheren Teilen Ihrer privaten Dateien über HTTP und WebDAV.",
|
||||
"PyCharm offers out-of-the-box support for Python, databases, Jupyter, Git, Conda, PyTorch, TensorFlow, Hugging Face, Django, Flask, FastAPI, and more.": "PyCharm bietet Out-of-the-Box-Unterstützung für Python, Datenbanken, Jupyter, Git, Conda, PyTorch, TensorFlow, Hugging Face, Django, Flask, FastAPI und mehr.",
|
||||
"Pydio Cells needs an external MySQL or MariaDB database. The setup wizard asks for its address, database name and user on the first start.": "Pydio Cells benötigt eine externe MySQL- oder MariaDB-Datenbank. Der Setup-Assistent fragt beim ersten Start nach Adresse, Datenbankname und Benutzer.",
|
||||
"Pydio Cells redirects to the address given in EXTERNALURL. If the container changes address, edit lxc.environment.runtime: EXTERNALURL and SERVER_IP in /etc/pve/lxc/<CTID>.conf with the container stopped, and delete /config/keys/cert.crt to regenerate the certificate.": "Pydio Cells leitet an die in EXTERNALURL angegebene Adresse weiter. Wenn der Container die Adresse ändert, bearbeiten Sie lxc.environment.runtime: EXTERNALURL und SERVER IP in /etc/pve/lxc/<CTID>.conf mit dem gestoppten Container und löschen Sie /config/keys/cert.crt, um das Zertifikat zu regenerieren.",
|
||||
"Pydio Cells redirects to the address given in EXTERNALURL. If the container changes address, edit lxc.environment.runtime: EXTERNALURL and SERVER_IP in /etc/pve/lxc/<CTID>.conf with the container stopped, and delete /config/keys/cert.crt to regenerate the certificate.": "Pydio Cells leitet an die in EXTERNALURL angegebene Adresse weiter. Wenn der Container die Adresse ändert, bearbeiten Sie lxc.environment.runtime: EXTERNALURL und SERVER_IP in /etc/pve/lxc/<CTID>.conf mit dem gestoppten Container und löschen Sie /config/keys/cert.crt, um das Zertifikat zu regenerieren.",
|
||||
"Pydio-cells is the nextgen file sharing platform for organizations. It is a full rewrite of the Pydio project using the Go language following a micro-service architecture.": "Pydio-cells ist die Nextgen File-Sharing-Plattform für Unternehmen. Es ist eine vollständige Neufassung des Pydio-Projekts mit der Go-Sprache nach einer Micro-Service-Architektur.",
|
||||
"QDirStat Qt-based directory statistics: KDirStat without any KDE -- from the author of the original KDirStat.": "QDirStat Qt-basierte Verzeichnisstatistik: KDirStat ohne KDE - vom Autor des ursprünglichen KDirStat.",
|
||||
"Quick health check (PASSED / FAILED)": "Schneller Gesundheitscheck (bestanden / nicht bestanden)",
|
||||
@@ -4686,7 +4686,7 @@
|
||||
"Remapped users:": "Neu zugeordnete Benutzer:",
|
||||
"Reminder: You must install the QEMU Guest Agent inside the Windows VM": "Erinnerung: Sie müssen den QEMU-Gastagenten in der Windows-VM installieren",
|
||||
"Remmina is a remote desktop client written in GTK, aiming to be useful for system administrators and travellers, who need to work with lots of remote computers in front of either large or tiny screens. Remmina supports multiple network protocols, in an integrated and consistent user interface. Currently RDP, VNC, SPICE, SSH and EXEC are supported.": "Remmina ist ein Remote-Desktop-Client, der in GTK geschrieben ist und für Systemadministratoren und Reisende nützlich sein soll, die mit vielen Remote-Computern vor großen oder kleinen Bildschirmen arbeiten müssen. Remmina unterstützt mehrere Netzwerkprotokolle in einer integrierten und konsistenten Benutzeroberfläche. Derzeit werden RDP, VNC, SPICE, SSH und EXEC unterstützt.",
|
||||
"Remote Access & VPN": "Remote Access und VPN",
|
||||
"Remote Access & VPN": "Fernzugriff und VPN",
|
||||
"Remote dry run completed; no container was created.": "Ferntrockenlauf abgeschlossen; kein Container wurde erstellt.",
|
||||
"Remote repository path:": "Remote-Repository-Pfad:",
|
||||
"Remote server via SSH (recommended — off-host, dedup across machines)": "Remote-Server über SSH (empfohlen – Off-Host, maschinenübergreifende Deduplizierung)",
|
||||
@@ -5955,7 +5955,7 @@
|
||||
"The imported Compose requests privileged, but the official jlesage/handbrake documentation does not require it; ProxMenux keeps the LXC unprivileged.": "Die importierte Compose verlangt privilegiert, aber die offizielle jlesage/handbrake Dokumentation require es nicht; ProxMenux hält die LXC unprivilegiert.",
|
||||
"The imported OCI groups are not numeric": "Importierte OCI-Gruppen sind nicht numerisch",
|
||||
"The imported OCI user or group is not numeric": "Der importierte OCI-Benutzer oder -Gruppe ist nicht numerisch",
|
||||
"The initial user name and password stay written in /etc/pve/lxc/<CTID>.conf as INIT_USERNAME and INIT_PASSWORD. They can be removed after the first login, with the container stopped.": "Der ursprüngliche Benutzername und das Passwort bleiben in /etc/pve/lxc/<CTID>.conf als INIT USERNAME und INIT PASSWORD geschrieben. Sie können nach dem ersten Login entfernt werden, wenn der Container angehalten wird.",
|
||||
"The initial user name and password stay written in /etc/pve/lxc/<CTID>.conf as INIT_USERNAME and INIT_PASSWORD. They can be removed after the first login, with the container stopped.": "Der ursprüngliche Benutzername und das Passwort bleiben in /etc/pve/lxc/<CTID>.conf als INIT_USERNAME und INIT_PASSWORD geschrieben. Sie können nach dem ersten Login entfernt werden, wenn der Container angehalten wird.",
|
||||
"The installation asks which one to use for these paths.": "Die Installation fragt, welche für diese Pfade verwendet werden soll.",
|
||||
"The installation ended with exit code": "Die Installation endete mit Exit-Code",
|
||||
"The installation requires a server restart to apply changes. Do you want to restart now?": "Die Installation erfordert einen Serverneustart, um die Änderungen zu übernehmen. Möchten Sie jetzt neu starten?",
|
||||
@@ -6074,7 +6074,7 @@
|
||||
"The rootfs is not managed by Proxmox": "Die Rootfs werden nicht von Proxmox verwaltet",
|
||||
"The rootfs is not mounted": "Die Rootfs sind nicht montiert",
|
||||
"The same GPU cannot be used by two VMs at the same time.": "Die gleiche GPU kann nicht von zwei VMs gleichzeitig verwendet werden.",
|
||||
"The same connection can be given as container variables instead of the file: UN_SONARR_0_URL and UN_SONARR_0_API_KEY, or the UN_RADARR_0_ equivalents.": "Die gleiche Verbindung kann als Containervariablen anstelle der Datei angegeben werden: UN SONARR 0 URL und UN SONARR 0 API KEY oder die UN RADARR 0 equivalents.",
|
||||
"The same connection can be given as container variables instead of the file: UN_SONARR_0_URL and UN_SONARR_0_API_KEY, or the UN_RADARR_0_ equivalents.": "Die gleiche Verbindung kann als Containervariablen anstelle der Datei angegeben werden: UN_SONARR_0_URL und UN_SONARR_0_API_KEY oder die UN RADARR 0 equivalents.",
|
||||
"The saved MOTD state is invalid; no changes were made": "Der gespeicherte MOTD-Status ist ungültig;Es wurden keine Änderungen vorgenommen",
|
||||
"The saved OCI record is incomplete or has an unexpected format.": "Der gespeicherte OCI-Datensatz ist unvollständig oder hat ein unerwartetes Format.",
|
||||
"The saved projection does not match the native evidence": "Die gespeicherte Projektion stimmt nicht mit dem nativen Beweis überein",
|
||||
@@ -6822,7 +6822,7 @@
|
||||
"Web interface to manage devices running Tasmota firmware.": "Web-Schnittstelle zur Verwaltung von Geräten mit Tasmota-Firmware.",
|
||||
"WebCord can be summarized as a pack of security and privacy hardenings, Discord features reimplementations, Electron / Chromium / Discord bugs workarounds, stylesheets, internal pages and wrapped https://discord.com page, designed to conform with ToS as much as it is possible (or hide the changes that might violate it from Discord's eyes).": "WebCord kann als ein Paket von Sicherheits- und Datenschutz-Härtungen, Discord-Features-Reimplementierungen, Electron / Chromium / Discord-Bugs-Workarounds, Stylesheets, interne Seiten und verpackte https://discord.com-Seite zusammengefasst werden, die so weit wie möglich mit ToS konform sind (oder die Änderungen, die es verletzen könnten, vor Discords Augen verbergen).",
|
||||
"Webgrabplus is a multi-site incremental xmltv epg grabber. It collects tv-program guide data from selected tvguide sites for your favourite channels.": "Webgrabplus ist ein multi-site inkrementeller xmltv epg grabber. Es sammelt tv-programm-guide-daten von ausgewählten tvguide-seiten für ihre lieblingskanäle.",
|
||||
"Webservers & Proxies": "Webserver & Proxies",
|
||||
"Webservers & Proxies": "Webserver und Proxys",
|
||||
"Website": "Webseite",
|
||||
"Webstation is a web native emulation focused LXQt desktop based on Ubuntu.": "Webstation ist ein Web-nativer Emulations-fokussierter LXQt-Desktop auf Basis von Ubuntu.",
|
||||
"Webtop - Alpine, Ubuntu, Fedora, and Arch based containers containing full desktop environments in officially supported flavors accessible via any modern web browser.": "Webtop - Alpine, Ubuntu, Fedora und Arch-basierte Container mit vollständigen Desktop-Umgebungen in offiziell unterstützten Geschmacksrichtungen, die über jeden modernen Webbrowser zugänglich sind.",
|
||||
@@ -6855,7 +6855,7 @@
|
||||
"WireGuard® is an extremely simple yet fast and modern VPN that utilizes state-of-the-art cryptography. It aims to be faster, simpler, leaner, and more useful than IPsec, while avoiding the massive headache. It intends to be considerably more performant than OpenVPN. WireGuard is designed as a general purpose VPN for running on embedded interfaces and super computers alike, fit for many different circumstances. Initially released for the Linux kernel, it is now cross-platform (Windows, macOS, BSD, iOS, Android) and widely deployable. It is currently under heavy development, but already it might be regarded as the most secure, easiest to use, and simplest VPN solution in the industry.": "WireGuard® ist ein extrem einfaches, aber schnelles und modernes VPN, das modernste Kryptographie nutzt. Es zielt darauf ab, schneller, einfacher, schlanker und nützlicher als IPsec zu sein, während die massiven Kopfschmerzen vermieden werden. Es soll deutlich performanter sein als OpenVPN. WireGuard ist als Allzweck-VPN für den Betrieb auf eingebetteten Schnittstellen und Supercomputern konzipiert, die für viele verschiedene Umstände geeignet sind. Ursprünglich für den Linux-Kernel veröffentlicht, ist er jetzt plattformübergreifend (Windows, macOS, BSD, iOS, Android) und weit verbreitet einsetzbar. Es befindet sich derzeit in der entwicklung, aber es könnte bereits als die sicherste, einfachste und einfachste vpn-lösung in der branche angesehen werden.",
|
||||
"Wired NICs in backup missing on target:": "Kabelgebundene Netzwerkkarten im Backup fehlen auf dem Ziel:",
|
||||
"Wireshark is the world’s foremost and widely-used network protocol analyzer. It lets you see what’s happening on your network at a microscopic level and is the de facto (and often de jure) standard across many commercial and non-profit enterprises, government agencies, and educational institutions. Wireshark development thrives thanks to the volunteer contributions of networking experts around the globe and is the continuation of a project started by Gerald Combs in 1998.": "Wireshark ist der weltweit führende und weit verbreitete Netzwerkprotokollanalysator. Es lässt Sie sehen, was in Ihrem Netzwerk auf einer mikroskopischen Ebene passiert und ist der De-facto- (und oft de jure-) Standard in vielen kommerziellen und gemeinnützigen Unternehmen, Regierungsbehörden und Bildungseinrichtungen. Die Entwicklung von Wireshark gedeiht dank der freiwilligen Beiträge von Netzwerkexperten auf der ganzen Welt und ist die Fortsetzung eines von Gerald Combs 1998 gestarteten Projekts.",
|
||||
"With dns validation, the DNSPLUGIN variable names the provider plugin. The advanced installation asks for it; otherwise add the line lxc.environment.runtime: DNSPLUGIN=<plugin> to /etc/pve/lxc/<CTID>.conf with the container stopped.": "Bei der dns-Validierung benennt die DNSPLUGIN-Variable das Provider-Plugin. Die erweiterte Installation fragt danach; andernfalls fügen Sie die Zeile lxc.environment hinzu. Laufzeit: DNSPLUGIN=<plugin> zu /etc/pve/lxc/<CTID>.conf mit angehaltenem Container.",
|
||||
"With dns validation, the DNSPLUGIN variable names the provider plugin. The advanced installation asks for it; otherwise add the line lxc.environment.runtime: DNSPLUGIN=<plugin> to /etc/pve/lxc/<CTID>.conf with the container stopped.": "Bei der dns-Validierung benennt die DNSPLUGIN-Variable das Provider-Plugin. Die erweiterte Installation fragt danach; andernfalls fügen Sie die Zeile lxc.environment.runtime: DNSPLUGIN=<plugin> zu /etc/pve/lxc/<CTID>.conf hinzu, wenn der Container angehalten wird.",
|
||||
"With dns validation, write the provider credentials in /config/dns-conf/<plugin>.ini inside the container and restart it.": "Schreiben Sie mit der dns-Validierung den Provider credentials in /config/dns-conf/<plugin>.ini in den Container und starten Sie ihn neu.",
|
||||
"With http validation, port 80 of the router must be forwarded to port 80 of this container.": "Bei der http-Validierung muss Port 80 des Routers an Port 80 dieses Containers weitergeleitet werden.",
|
||||
"With warnings": "Mit Warnungen",
|
||||
|
||||
+179
-136
@@ -80,7 +80,7 @@
|
||||
"A new kernel is staged for the next boot:": "Se prepara un nuevo kernel para el siguiente arranque:",
|
||||
"A newer version is available:": "Hay una versión más nueva disponible:",
|
||||
"A pending operation exists for": "Existe una operación pendiente",
|
||||
"A pending stack assembly already exists; it is not overwritten": "Ya existe un montaje de pila pendiente; no está sobrescrito",
|
||||
"A pending stack assembly already exists; it is not overwritten": "Ya existe un ensamblado de pila pendiente; no se sobrescribe",
|
||||
"A previous NVIDIA refresh is pending review": "Un refresco previo de NVIDIA está pendiente de revisión",
|
||||
"A previous VFIO passthrough configuration was detected for the following NVIDIA GPU(s):": "Se detectó una configuración de paso a través de VFIO anterior para las siguientes GPU NVIDIA:",
|
||||
"A privacy-first, open-source platform for knowledge management and collaboration.": "Una plataforma de código abierto para la gestión del conocimiento y la colaboración.",
|
||||
@@ -120,7 +120,7 @@
|
||||
"ACL Status:": "Estado de ACL:",
|
||||
"ACL permissions applied for local access for user:": "Permisos ACL aplicados para el acceso local del usuario:",
|
||||
"ADVANCED SETTINGS COMPLETE": "CONFIGURACIÓN AVANZADA COMPLETA",
|
||||
"AI / Coding & Dev-Tools": "AI / Coding & Dev-Tools",
|
||||
"AI / Coding & Dev-Tools": "IA, programación y desarrollo",
|
||||
"ALL DATA ON": "TODOS LOS DATOS SOBRE",
|
||||
"ALL DATA ON THIS DISK WILL BE PERMANENTLY LOST!": "¡TODOS LOS DATOS DE ESTE DISCO SE PERDERÁN PERMANENTEMENTE!",
|
||||
"ALL Utilities": "TODAS las utilidades",
|
||||
@@ -207,6 +207,8 @@
|
||||
"Add a Coral PCIe/M.2 device?": "¿Añada un dispositivo Coral PCIe/M.2?",
|
||||
"Add a custom data path?": "¿Añadir una ruta de datos personalizada?",
|
||||
"Add an extra custom path": "Añadir una ruta personalizada adicional",
|
||||
"Add another extra path to this stack": "Añadir otra ruta adicional a esta pila",
|
||||
"Add extra paths to this stack": "Añadir rutas adicionales a esta pila",
|
||||
"Add as IDE": "Agregar como IDE",
|
||||
"Add as SATA": "Agregar como SATA",
|
||||
"Add as SCSI": "Agregar como SCSI",
|
||||
@@ -352,7 +354,7 @@
|
||||
"Another OCI operation is using the instance registry. Wait for it to finish and open this menu again; no container is modified.": "Otra operación OCI está utilizando el registro de instancias. Espere a que termine y abra este menú de nuevo; no se modifica ningún contenedor.",
|
||||
"Another OCI operation is using the registry. This operation was not started.": "Otro operación OCI está utilizando el registro. Esta operación no se inició.",
|
||||
"Another instance uses": "Otro caso utiliza",
|
||||
"Another stack operation is pending": "Otra pila operación está pendiente",
|
||||
"Another stack operation is pending": "Hay otra operación de pila pendiente",
|
||||
"Application": "Aplicación",
|
||||
"Application responding:": "Solicitud de respuesta:",
|
||||
"Application responding; checking its stability...": "Aplicación respondiendo; comprobando su estabilidad...",
|
||||
@@ -439,7 +441,7 @@
|
||||
"Auth key is required.": "Se requiere clave de autenticación.",
|
||||
"Auth:": "Autenticación:",
|
||||
"Authentication": "Autenticación",
|
||||
"Authentication & Security": "Autenticación y Seguridad",
|
||||
"Authentication & Security": "Autenticación y seguridad",
|
||||
"Authentication Error": "Error de autenticación",
|
||||
"Authentication failed.": "La autenticación falló.",
|
||||
"Authentication required:": "Se requiere autenticación:",
|
||||
@@ -463,7 +465,7 @@
|
||||
"Automatic private network allocation requires a /24 subnet": "Asignación automática de red privada requiere una subred /24",
|
||||
"Automatic video library manager for TV Shows": "Gestor automático de la biblioteca de vídeo para TV Shows",
|
||||
"Automatic/Unattended": "Automático/desatendido",
|
||||
"Automation & Scheduling": "Automatización y Programación de tareas",
|
||||
"Automation & Scheduling": "Automatización y programación",
|
||||
"Available": "Disponible",
|
||||
"Available Borg archives (newest first):": "Archivos Borg disponibles (los más nuevos primero):",
|
||||
"Available Borg targets:": "Objetivos Borg disponibles:",
|
||||
@@ -500,7 +502,7 @@
|
||||
"Backend:": "Parte trasera:",
|
||||
"Background archive extraction for Arr download queues. No web interface.": "Extracción de archivos de fondo para las colas de descarga Arr. No hay interfaz web.",
|
||||
"Backup — VM and CT backups": "Copia de seguridad: copias de seguridad de VM y CT",
|
||||
"Backup & Recovery": "Backups y Recuperación",
|
||||
"Backup & Recovery": "Backups y recuperación",
|
||||
"Backup Created": "Copia de seguridad creada",
|
||||
"Backup ID (group name in PBS):": "ID del backup (nombre del grupo en PBS):",
|
||||
"Backup ID for this job:": "ID del backup para este trabajo:",
|
||||
@@ -561,7 +563,7 @@
|
||||
"Beta (develop branch)": "Beta (rama de desarrollo)",
|
||||
"Beta version:": "Versión beta:",
|
||||
"Binary not found in extracted content.": "Binario no encontrado en el contenido extraído.",
|
||||
"Bind mount added:": "Montaje de enlace agregado:",
|
||||
"Bind mount added:": "Montaje bind añadido:",
|
||||
"Bind mounts are not included in vzdump": "Los bind mounts no están incluidos en vzdump",
|
||||
"Bitcoin Knots can be used as a desktop client for regular payments or as a full node server utility for merchants and other payment services.": "Bitcoin Knots se puede utilizar como cliente de escritorio para pagos regulares o como un servidor de nodos completo para comerciantes y otros servicios de pago.",
|
||||
"Blacklist nouveau driver": "Poner el controlador nouveau en la lista negra",
|
||||
@@ -603,7 +605,7 @@
|
||||
"Broken gasket-dkms package state recovered.": "Se ha recuperado el estado dañado del paquete gasket-dkms.",
|
||||
"Browse Your Life in Images": "Explore su vida en imágenes",
|
||||
"Browse manually (advanced)...": "Navegar manualmente (avanzado)...",
|
||||
"Browsers & Web Desktops": "Navegadores y Escritorios web",
|
||||
"Browsers & Web Desktops": "Navegadores y escritorios web",
|
||||
"Build and install the gasket and apex kernel modules (DKMS)": "Compilar e instalar los módulos del kernel gasket y apex (DKMS)",
|
||||
"Build dependencies installed.": "Construya dependencias instaladas.",
|
||||
"Build your personal knowledge base with TriliumNext Notes": "Construya su base de conocimiento personal con Trilium",
|
||||
@@ -755,7 +757,7 @@
|
||||
"Checking the image compatibility:": "Verificación de la compatibilidad de la imagen:",
|
||||
"Checking the image in the registry...": "Revisando la imagen en el registro...",
|
||||
"Checking the interrupted operation...": "Revisando la interrumpida operación...",
|
||||
"Checking the interrupted stack operation...": "Revisando la pila interrumpida operación...",
|
||||
"Checking the interrupted stack operation...": "Revisando la operación de pila interrumpida...",
|
||||
"Checking the new image without starting it:": "Comprobando la nueva imagen sin comenzarla:",
|
||||
"Checking the remote...": "Revisando el control remoto...",
|
||||
"Checking the restored installation": "Comprobación de la instalación restaurada",
|
||||
@@ -869,7 +871,7 @@
|
||||
"Commenting legacy ceph.list (if present)...": "Comentando ceph.list heredado (si está presente)...",
|
||||
"Common Issues Check": "Verificación de problemas comunes",
|
||||
"Common root for the published views": "Raíz común para las vistas publicadas",
|
||||
"Communication & Community": "Comunicación y Comunidad",
|
||||
"Communication & Community": "Comunicación y comunidad",
|
||||
"Community Scripts": "Scripts comunitarios",
|
||||
"Community single-container Home Assistant OS image": "Comunidad Imagen de un solo contenedor Home Assistant OS",
|
||||
"Compatibility check": "verificación de compatibilidad",
|
||||
@@ -1041,7 +1043,7 @@
|
||||
"Consider security implications for production environments": "Considere las implicaciones de seguridad para los entornos de producción.",
|
||||
"Consider visiting the repository and supporting the project.": "considere visitar el repositorio y apoyar el proyecto.",
|
||||
"Console log:": "Registro de consolas:",
|
||||
"Container": "Recipiente",
|
||||
"Container": "Contenedor",
|
||||
"Container — LXC root directories": "Contenedor: directorios raíz de LXC",
|
||||
"Container ID": "ID del contenedor",
|
||||
"Container ID not defined. Make sure to select a container first.": "ID de contenedor no definido. Asegúrese de seleccionar un contenedor primero.",
|
||||
@@ -1050,10 +1052,10 @@
|
||||
"Container Path": "Ruta del contenedor",
|
||||
"Container Path:": "Ruta del contenedor:",
|
||||
"Container Status": "Estado del contenedor",
|
||||
"Container checked": "Control de contenedores",
|
||||
"Container checked": "Contenedor comprobado",
|
||||
"Container configuration not found": "Configuración del contenedor no encontrada",
|
||||
"Container configured (not started):": "Container configurado (no iniciado):",
|
||||
"Container converted to privileged": "Container convertido a privilegiado",
|
||||
"Container configured (not started):": "Contenedor configurado (no iniciado):",
|
||||
"Container converted to privileged": "Contenedor convertido a privilegiado",
|
||||
"Container created:": "Container created:",
|
||||
"Container did not become ready in time. Skipping driver installation.": "El contenedor no estuvo listo a tiempo. Saltarse la instalación del controlador.",
|
||||
"Container did not start in time.": "El contenedor no arrancó a tiempo.",
|
||||
@@ -1083,11 +1085,12 @@
|
||||
"Container volume (included in backups)": "Volumen de contenedor (incluido en backups)",
|
||||
"Container will pick up the mount on next start": "El contenedor recogerá la montura en el próximo inicio.",
|
||||
"Container with ID": "Contenedor con identificación",
|
||||
"Container:": "Recipiente:",
|
||||
"Container:": "Contenedor:",
|
||||
"Containers & Docker": "Contenedores y Docker",
|
||||
"Containers returned to their previous state": "Los contenedores regresaron a su estado anterior",
|
||||
"Containers that are removed:": "Contenedores que se eliminan:",
|
||||
"Containers that will be created (one LXC per service, on a private network):": "Contenedores que se crearán (un LXC por servicio, en una red privada):",
|
||||
"Containers that will receive this path": "Contenedores que recibirán esta ruta",
|
||||
"Containers:": "Containers:",
|
||||
"Contains files": "Contiene archivos",
|
||||
"Contains:": "Contiene:",
|
||||
@@ -1157,7 +1160,7 @@
|
||||
"Coral M.2 Apex configuration added - device ready": "Configuración de Coral M.2 Apex agregada: dispositivo listo",
|
||||
"Coral M.2 Apex configuration added - device will be available after reboot": "Se agregó la configuración de Coral M.2 Apex: el dispositivo estará disponible después del reinicio",
|
||||
"Coral M.2 Apex detected, configuring...": "Coral M.2 Apex detectado, configurando...",
|
||||
"Coral PCIe/M.2 node (e.g. /dev/apex_0)": "Nodo Coral PCIe/M.2 (por ejemplo, /dev/apex 0)",
|
||||
"Coral PCIe/M.2 node (e.g. /dev/apex_0)": "Nodo Coral PCIe/M.2 (por ejemplo, /dev/apex_0)",
|
||||
"Coral TPU Installation": "Instalación de TPU Coral",
|
||||
"Coral TPU Uninstall": "Desinstalación de Coral TPU",
|
||||
"Coral TPU device nodes detected with correct group (apex).": "Nodos del dispositivo Coral TPU detectados con el grupo correcto (ápice).",
|
||||
@@ -1179,7 +1182,7 @@
|
||||
"Core is still on the initial installation page": "Core sigue en la página de instalación inicial",
|
||||
"Core packages": "Paquetes principales",
|
||||
"Cores": "Núcleos",
|
||||
"Corrupted gzip layer": "Capa de gzip corregida",
|
||||
"Corrupted gzip layer": "Capa gzip corrupta",
|
||||
"Could not add": "No se pudo agregar",
|
||||
"Could not add disk": "No se pudo agregar el disco",
|
||||
"Could not add the device to the container:": "No podía añadir el dispositivo al contenedor:",
|
||||
@@ -1235,7 +1238,7 @@
|
||||
"Could not install sshpass automatically (no internet?). Falling back to manual paste mode — you'll see the line to copy onto the server next.": "No se pudo instalar sshpass automáticamente (¿no hay Internet?).Volviendo al modo de pegado manual, verá la línea para copiar en el servidor a continuación.",
|
||||
"Could not install the NVIDIA Container Toolkit signing key.": "No se pudo instalar la clave de firma de NVIDIA Container Toolkit.",
|
||||
"Could not install the required packages:": "No podía instalar los paquetes necesarios:",
|
||||
"Could not install the stack startup hook": "No podía instalar el gancho de arranque de pila",
|
||||
"Could not install the stack startup hook": "No se pudo instalar el hook de arranque de la pila",
|
||||
"Could not install vzdump hook in /etc/vzdump.conf": "No se pudo instalar el gancho vzdump en /etc/vzdump.conf",
|
||||
"Could not load shared functions. Script cannot continue.": "No se pudieron cargar funciones compartidas. El guión no puede continuar.",
|
||||
"Could not load the host kernel module:": "No podía cargar el módulo del kernel host:",
|
||||
@@ -1243,7 +1246,7 @@
|
||||
"Could not mount": "No se pudo montar",
|
||||
"Could not mount ISO on device": "No se pudo montar ISO en el dispositivo",
|
||||
"Could not mount the container filesystem:": "No se pudo montar el sistema de archivos de contenedores:",
|
||||
"Could not obtain an intact image after two attempts": "No podía obtener una imagen intacta después de dos intentos",
|
||||
"Could not obtain an intact image after two attempts": "No se pudo obtener una imagen íntegra tras dos intentos",
|
||||
"Could not parse OVF file, or no disk image references found.": "No se pudo analizar el archivo OVF o no se encontraron referencias de imágenes de disco.",
|
||||
"Could not prepare on-boot restore service. Nothing new was scheduled.": "No se pudo preparar el servicio de restauración en el arranque. No se ha programado nada nuevo.",
|
||||
"Could not prepare the NVIDIA driver links": "No podía preparar los enlaces de controladores NVIDIA",
|
||||
@@ -1258,7 +1261,7 @@
|
||||
"Could not remount automatically. Try manually or check credentials.": "No se pudo volver a montar automáticamente. Pruebe manualmente o verifique las credenciales.",
|
||||
"Could not remove VM automatically. Run manually:": "No se pudo eliminar la VM automáticamente. Ejecutar manualmente:",
|
||||
"Could not remove previous DKMS tree at": "No se pudo eliminar el árbol DKMS anterior en",
|
||||
"Could not reserve a private network for the stack": "No podía reservar una red privada para la pila",
|
||||
"Could not reserve a private network for the stack": "No se pudo reservar una red privada para la pila",
|
||||
"Could not resolve the Compose user:": "No podía resolver el usuario de Compose:",
|
||||
"Could not resolve the OCI manifest of the image:": "No podía resolver el manifiesto de la imagen de la OCI:",
|
||||
"Could not resolve the OCI manifest:": "No podía resolver el manifiesto de la OCI:",
|
||||
@@ -1345,7 +1348,7 @@
|
||||
"Creating the container...": "Creando el contenedor...",
|
||||
"Creating the initial administrator...": "Crear el administrador inicial...",
|
||||
"Creating the temporary data container": "Creación del contenedor de datos temporales",
|
||||
"Creative & Design": "Creatividad y Diseño",
|
||||
"Creative & Design": "Creatividad y diseño",
|
||||
"Credentials are correct": "Las credenciales son correctas",
|
||||
"Credentials cleared. jwt_secret and API tokens preserved.": "Credenciales borradas. Se conservan los tokens jwt_secret y API.",
|
||||
"Credentials file created securely.": "Archivo de credenciales creado de forma segura.",
|
||||
@@ -1450,7 +1453,7 @@
|
||||
"Data size:": "Tamaño de datos:",
|
||||
"Data that is deleted with them:": "Datos que se eliminan con ellos:",
|
||||
"Data volume size in GB": "Tamaño del volumen de datos en GB",
|
||||
"Data volumes protected": "Volumen de datos protegidos",
|
||||
"Data volumes protected": "Volúmenes de datos protegidos",
|
||||
"Data wipe complete.": "Borrado de datos completo.",
|
||||
"Data wiped from": "Datos borrados de",
|
||||
"Database management in a single PHP file": "Gestión de bases de datos en un solo archivo PHP",
|
||||
@@ -1474,7 +1477,7 @@
|
||||
"Default Login Credentials:": "Credenciales de inicio de sesión predeterminadas:",
|
||||
"Default Port": "Puerto predeterminado",
|
||||
"Default Proxmox logo applied": "Logotipo predeterminado de Proxmox aplicado",
|
||||
"Default is none (video-only passthrough). Use SPACE to toggle selections.": "El valor predeterminado es ninguno (transmisión de solo video). Utilice la ESPACIO para alternar selecciones.",
|
||||
"Default is none (video-only passthrough). Use SPACE to toggle selections.": "El valor predeterminado es ninguno (transmisión de solo video). Utilice ESPACIO para alternar selecciones.",
|
||||
"Default journald configuration restored": "Configuración de diario predeterminada restaurada",
|
||||
"Default location is /mnt/<name>. The share will be mounted here on the host with open permissions so an unprivileged LXC can bind-mount and write to it. For LXC access, bind-mount this path with the LXC Mount Manager.": "La ubicación predeterminada es /mnt/<nombre>. El recurso compartido se montará aquí en el host con permisos abiertos para que un LXC sin privilegios pueda vincularlo, montarlo y escribir en él. Para acceder a LXC, vincule esta ruta con LXC Mount Manager.",
|
||||
"Default location is /mnt/<name>. The share will be mounted here on the host. Use this path in /etc/fstab. For LXC access, bind-mount this path with the LXC Mount Manager.": "La ubicación predeterminada es /mnt/<nombre>. El recurso compartido se montará aquí en el host. Utilice esta ruta en /etc/fstab. Para acceder a LXC, vincule esta ruta con LXC Mount Manager.",
|
||||
@@ -1694,7 +1697,7 @@
|
||||
"Docker Mods are only offered for compatible LinuxServer images": "Docker Mods solo se ofrecen para imágenes compatibles de LinuxServer",
|
||||
"Docker Volume Backup": "Docker Volume Backup",
|
||||
"Docker/CLI not available yet or no valid answer": "Docker/CLI aún no está disponible o no hay respuesta válida",
|
||||
"Documents & Notes": "Documentos y Notas",
|
||||
"Documents & Notes": "Documentos y notas",
|
||||
"Documents volume size in GB": "Tamaño del volumen de documentos en GB",
|
||||
"Dokuwiki is a simple to use and highly versatile Open Source wiki software that doesn't require a database. It is loved by users for its clean and readable syntax. The ease of maintenance, backup and integration makes it an administrator's favorite. Built in access controls and authentication connectors make DokuWiki especially useful in the enterprise context and the large number of plugins contributed by its vibrant community allow for a broad range of use cases beyond a traditional wiki.": "Dokuwiki es un software de wiki de código abierto muy versátil que no requiere una base de datos. Es amado por los usuarios por su sintaxis limpia y legible. La facilidad de mantenimiento, backup e integración lo convierte en el favorito del administrador. Construidos en controles de acceso y conectores de autenticación hacen de DokuWiki especialmente útil en el contexto empresarial y el gran número de plugins aportados por su vibrante comunidad permiten una amplia gama de casos de uso más allá de un wiki tradicional.",
|
||||
"Dolphin Emulator lets you play GameCube and Wii games with various graphical enhancements and other features are available to improve your game experience.": "Dolphin Emulator le permite jugar juegos de GameCube y Wii con diversas mejoras gráficas y otras características están disponibles para mejorar su experiencia de juego.",
|
||||
@@ -1719,7 +1722,7 @@
|
||||
"Downloading amdgpu_top": "Descargando amdgpu_top",
|
||||
"Downloading official installer...": "Descargando el instalador oficial...",
|
||||
"Downloading pre-existing encrypted backups from this host will fail unless you kept a copy of the current key.": "la descarga de copias de seguridad cifradas preexistentes desde este host fallará a menos que conserve una copia de la clave actual.",
|
||||
"Downloading the image:": "Descargar la imagen:",
|
||||
"Downloading the image:": "Descargando la imagen:",
|
||||
"Downloading the latest Fastfetch release...": "Descargando la última versión de Fastfetch...",
|
||||
"Driver blacklist entries removed": "Se eliminaron las entradas de la lista negra de controladores",
|
||||
"Driver blacklist removed for": "Lista negra de controladores eliminada para",
|
||||
@@ -1731,7 +1734,7 @@
|
||||
"Dry run completed; the container and the mounts were not changed.": "Correción seca completada; el contenedor y las monturas no se cambiaron.",
|
||||
"DuckDNS subdomain without .duckdns.org (comma separated for several)": "Subdominio DuckDNS sin .duckdns.org (comma separado para varios)",
|
||||
"DuckDNS token from your account at duckdns.org": "DuckDNS token desde tu cuenta en duckdns.org",
|
||||
"DuckDNS updates the subdomain every 5 minutes. Without UPDATE_IP, DuckDNS itself detects the public IPv4 address of the request.": "DuckDNS actualiza el subdominio cada 5 minutos. Sin UPDATE IP, DuckDNS detecta la dirección IPv4 pública de la solicitud.",
|
||||
"DuckDNS updates the subdomain every 5 minutes. Without UPDATE_IP, DuckDNS itself detects the public IPv4 address of the request.": "DuckDNS actualiza el subdominio cada 5 minutos. Sin UPDATE_IP, DuckDNS detecta la dirección IPv4 pública de la solicitud.",
|
||||
"DuckStation is a PS1 Emulator aiming for the best accuracy and game support.": "DuckStation es un emulador PS1 que busca el mejor accuracy y soporte para juegos.",
|
||||
"Duckdns is a free service which will point a DNS (sub domains of duckdns.org) to an IP of your choice. The service is completely free, and doesn't require reactivation or forum posts to maintain its existence.": "Duckdns es un servicio gratuito que señalará un DNS (sub dominios de duckdns.org) a un IP de su elección. El servicio es totalmente gratuito, y no requiere reactivación o publicaciones de foro para mantener su existencia.",
|
||||
"Dumping AMD GPU ROM BIOS via sysfs...": "Volviendo la BIOS de la ROM de la GPU AMD a través de sysfs...",
|
||||
@@ -1743,7 +1746,7 @@
|
||||
"Duplicated VMID in the Proxmox inventory": "VMID duplicado en el inventario de Proxmox",
|
||||
"Duplicated native directive:": "Directiva nativa duplicada:",
|
||||
"Duplicated native option": "Opción nativa duplicada",
|
||||
"Duplicated or invalid stack VMID": "Montaje duplicado o inválido VMID",
|
||||
"Duplicated or invalid stack VMID": "VMID de pila duplicado o no válido",
|
||||
"Duplicati is a backup client that securely stores encrypted, incremental, compressed backups on local storage, cloud storage services and remote file servers. It works with standard protocols like FTP, SSH, WebDAV as well as popular services like Microsoft OneDrive, Amazon S3, Google Drive, box.com, Mega, B2, and many others.": "Duplicati es un cliente de backup que almacena de forma segura backups cifradas, incrementales y comprimidas en almacenamiento local, servicios de almacenamiento en la nube y servidores de archivos remotos. Funciona con protocolos estándar como FTP, SSH, WebDAV y servicios populares como Microsoft OneDrive, Amazon S3, Google Drive, box.com, Mega, B2, y muchos otros.",
|
||||
"Duplicati web interface (password only)": "Interfaz web Duplicati (sólo contraseña)",
|
||||
"Duration": "Duración",
|
||||
@@ -2230,16 +2233,16 @@
|
||||
"FileBrowser Quantum": "FileBrowser Quantum",
|
||||
"FileBrowser Quantum (new installation)": "FileBrowser Quantum (nueva instalación)",
|
||||
"FileDrop is a free, open source file sharing service": "FileDrop es un servicio gratuito de intercambio de archivos de código abierto",
|
||||
"Files & Downloads": "Archivos y Descargas",
|
||||
"Files & Downloads": "Archivos y descargas",
|
||||
"Files volume size in GB": "Tamaño del volumen de archivos en GB",
|
||||
"Filesystem": "Sistema de archivos",
|
||||
"Filesystem Tools Required": "Herramientas del sistema de archivos necesarias",
|
||||
"Filesystem:": "Sistema de archivos:",
|
||||
"Final Confirmation": "Confirmación final",
|
||||
"Final cleanup of the stack operation completed": "Limpieza final de la pila operación completado",
|
||||
"Final cleanup of the stack operation completed": "Limpieza final de la operación de pila completada",
|
||||
"Final confirmation": "Confirmación final",
|
||||
"Final storage health/status check": "Comprobación final del estado/salud del almacenamiento",
|
||||
"Finance & Budgeting": "Finanzas y Presupuestos",
|
||||
"Finance & Budgeting": "Finanzas y presupuestos",
|
||||
"Find your device using https://finds.synology.com": "Encuentre su dispositivo usando https://finds.synology.com",
|
||||
"Fingerprint:": "Huella digital:",
|
||||
"Firefly, the easiest using of WireGuard VPN server, plus version of wg-easy.": "Firefly, el uso más fácil del servidor WireGuard VPN, además de la versión de wg-easy.",
|
||||
@@ -2387,7 +2390,7 @@
|
||||
"GRUB_CMDLINE_LINUX_DEFAULT not found in GRUB config": "GRUB_CMDLINE_LINUX_DEFAULT no se encuentra en la configuración de GRUB",
|
||||
"GUI mode (if available)": "Modo GUI (si está disponible)",
|
||||
"GZDoom is a feature centric port for all Doom engine games, based on ZDoom, adding an OpenGL renderer and powerful scripting capabilities.": "GZDoom es un puerto centrico característica para todos los juegos de motores Doom, basado en ZDoom, añadiendo un renderizador OpenGL y potentes capacidades de scripting.",
|
||||
"Gaming & Leisure": "Juegos y Ocio",
|
||||
"Gaming & Leisure": "Juegos y ocio",
|
||||
"Gateway is not installed.": "La puerta de enlace no está instalada.",
|
||||
"Gateway removed.": "Puerta de enlace eliminada.",
|
||||
"Gateway restarted.": "La puerta de enlace se reinició.",
|
||||
@@ -2520,14 +2523,14 @@
|
||||
"Host Config Backup / Restore": "Copia de seguridad/restauración de la configuración del host",
|
||||
"Host Config Restore": "Restauración de configuración del host",
|
||||
"Host DVB tuners": "Sintonizadores DVB de host",
|
||||
"Host Directory": "Directorio de host",
|
||||
"Host Directory to LXC Mount Point": "Directorio de host para el punto de montaje LXC",
|
||||
"Host Directory:": "Directorio de host:",
|
||||
"Host Directory": "Directorio del host",
|
||||
"Host Directory to LXC Mount Point": "Directorio del host a punto de montaje LXC",
|
||||
"Host Directory:": "Directorio del host:",
|
||||
"Host GPU binding changed — reboot required.": "Se cambió el enlace de la GPU del host: es necesario reiniciar.",
|
||||
"Host GPU detected": "GPU del host detectada",
|
||||
"Host GPU is already bound to vfio-pci. Host reconfiguration/reboot should not be required for this VM-to-VM reassignment.": "La GPU del host ya está vinculada a vfio-pci. No debería ser necesario reconfigurar/reiniciar el host para esta reasignación de VM a VM.",
|
||||
"Host IP": "IP del host",
|
||||
"Host Management": "Host Management",
|
||||
"Host Management": "Gestión del host",
|
||||
"Host Mount Path": "Ruta de montaje del host",
|
||||
"Host NFS/Samba as Proxmox Storage (pvesm)": "Aloje NFS/Samba como almacenamiento en Proxmox (pvesm)",
|
||||
"Host Path": "Ruta del host",
|
||||
@@ -2559,7 +2562,7 @@
|
||||
"Host directory access for unprivileged containers has been prepared above": "El acceso al directorio de host para contenedores sin privilegios se preparó anteriormente",
|
||||
"Host directory kept, with its content:": "El directorio host se mantiene, con su contenido:",
|
||||
"Host directory permissions updated — unprivileged containers can now access it": "Permisos del directorio de host actualizados: los contenedores sin privilegios ahora pueden acceder a él",
|
||||
"Host directory:": "Directorio de host:",
|
||||
"Host directory:": "Directorio del host:",
|
||||
"Host fstab CIFS Mounts:": "Montajes CIFS del host fstab:",
|
||||
"Host fstab CIFS mounts (not registered with pvesm):": "Montajes CIFS del host fstab (no registrados con pvesm):",
|
||||
"Host fstab CIFS mounts:": "Montajes CIFS del host fstab:",
|
||||
@@ -2669,8 +2672,8 @@
|
||||
"If notifications are enabled (Telegram/Discord/ntfy/...), you will receive a \"Host restore finished\" message when all background tasks complete.": "si las notificaciones están habilitadas (Telegram/Discord/ntfy/...), recibirá un mensaje de \"Restauración del host finalizada\" cuando se completen todas las tareas en segundo plano.",
|
||||
"If passthrough fails on Windows: install RadeonResetBugFix.": "Si el paso a través falla en Windows: instale RadeonResetBugFix.",
|
||||
"If path not accessible (ZFS/BTRFS):": "Si la ruta no es accesible (ZFS/BTRFS):",
|
||||
"If pvesm path returned a DEVICE (LVM):": "Si la ruta pvesm devolvió un DISPOSITIVO (LVM):",
|
||||
"If pvesm path returned a DIRECTORY (ZFS/BTRFS):": "Si la ruta pvesm devolvió un DIRECTORIO (ZFS/BTRFS):",
|
||||
"If pvesm path returned a DEVICE (LVM):": "Si pvesm path devolvió un DISPOSITIVO (LVM):",
|
||||
"If pvesm path returned a DIRECTORY (ZFS/BTRFS):": "Si pvesm path devolvió un DIRECTORIO (ZFS/BTRFS):",
|
||||
"If repositories error:": "Si hay error en los repositorios:",
|
||||
"If the host freezes, remove hostpci entries from": "Si el host se congela, elimine las entradas hostpci de",
|
||||
"If this happens, you can restore the backup from the 'Subscription Banner Removal' option in 'Uninstall optimizations'.": "Si esto sucede, puede restaurar la copia de seguridad desde la opción 'Eliminación del banner de suscripción' en 'Optimizaciones de desinstalación'.",
|
||||
@@ -2697,7 +2700,7 @@
|
||||
"Image downloaded": "Imagen descargada",
|
||||
"Image file not found:": "Archivo de imagen no encontrado:",
|
||||
"Image imported:": "Imagen importada:",
|
||||
"Image integrity verified": "Verificación de la integridad de la imagen",
|
||||
"Image integrity verified": "Integridad de la imagen verificada",
|
||||
"Image not allowed for the host monitor profile": "Imagen no permitida para el perfil del monitor host",
|
||||
"Image reference (for example ghcr.io/user/application:latest)": "Referencia de imagen (por ejemplo ghcr.io/user/application:latest)",
|
||||
"Image that is not in the catalog": "Imagen que no está en el catálogo",
|
||||
@@ -2755,7 +2758,7 @@
|
||||
"Incompatible instance directory": "Directorio de instancias incompatibles",
|
||||
"Incompatible instance record": "Registro de instancia incompatible",
|
||||
"Incompatible record": "Registro incompatible",
|
||||
"Incompatible stack assembly": "Montaje de pila incompatible",
|
||||
"Incompatible stack assembly": "Ensamblado de pila incompatible",
|
||||
"Incompatible version": "versión incompatible",
|
||||
"Incomplete NVIDIA identity": "Identidad incompleta NVIDIA",
|
||||
"Incomplete NVIDIA inventory": "Incompleto inventario de NVIDIA",
|
||||
@@ -2768,11 +2771,11 @@
|
||||
"Incomplete or incompatible Proxmox inventory": "Incompleto o incompatible Proxmox inventario",
|
||||
"Incomplete primary network": "Red primaria incompleta",
|
||||
"Incomplete stack order": "Orden de pila incompleta",
|
||||
"Incomplete stack removed": "Montaje completo eliminado",
|
||||
"Incomplete stack removed": "Pila incompleta eliminada",
|
||||
"Inconsistent adaptation profile and recipe": "Perfil de adaptación inconsistente y receta",
|
||||
"Inconsistent host monitor profile": "Perfil de monitor de host inconsistente",
|
||||
"Inconsistent stack identity": "Identidad de pila inconsistente",
|
||||
"Inconsistent stack membership for": "Miembro de pila inconsistente para",
|
||||
"Inconsistent stack membership for": "Pertenencia a la pila inconsistente para",
|
||||
"Increase container RAM temporarily to": "Aumente temporalmente la RAM del contenedor para",
|
||||
"Increase file and process limits for advanced workloads": "Aumente los límites de archivos y procesos para cargas de trabajo avanzadas",
|
||||
"Increase various system limits": "Aumentar varios límites del sistema",
|
||||
@@ -2795,7 +2798,7 @@
|
||||
"Initiator IQN is authorised on the target": "El iniciador IQN está autorizado en el objetivo.",
|
||||
"Initiator IQN:": "IQN del iniciador:",
|
||||
"Inkscape is professional quality vector graphics software which runs on Linux, Mac OS X and Windows desktop computers.": "Inkscape es un software de gráficos vectoriales de calidad profesional que funciona en Linux, Mac OS X y Windows computadoras de escritorio.",
|
||||
"Inside the LXC, create the administrator: console kimai:user:create YOUR_USERNAME YOUR_EMAIL ROLE_SUPER_ADMIN": "Dentro del LXC, crea el administrador: consola kimai:user:crear Your USERNAME Your EMAIL ROLE SUPER ADMIN",
|
||||
"Inside the LXC, create the administrator: console kimai:user:create YOUR_USERNAME YOUR_EMAIL ROLE_SUPER_ADMIN": "Dentro del LXC, crea el administrador: consola kimai:user:crear Your USERNAME Your EMAIL ROLE_SUPER_ADMIN",
|
||||
"Inspect disks before any action": "Inspeccionar los discos antes de cualquier acción.",
|
||||
"Inspect host device nodes": "Inspeccionar los nodos del dispositivo host",
|
||||
"Inspect passthrough/kernel events": "Inspeccionar eventos de transferencia/kernel",
|
||||
@@ -2843,7 +2846,7 @@
|
||||
"Install this image?": "¿Instalar esta imagen?",
|
||||
"Install with Cloud-Init script": "Instalar con el script Cloud-Init",
|
||||
"Install with ISO from UUP Dump": "Instalar con ISO desde UUP Dump",
|
||||
"Install with advanced settings": "Instalar con configuración avanzada",
|
||||
"Install with advanced settings": "Instalar con la configuración avanzada",
|
||||
"Install with default settings": "Instalar con la configuración predeterminada",
|
||||
"Install with personal ISO": "Instalar con ISO personal",
|
||||
"Install with this configuration?": "¿Instalar con esta configuración?",
|
||||
@@ -2924,9 +2927,9 @@
|
||||
"Installing selected utilities": "Instalación de utilidades seleccionadas",
|
||||
"Installing system utilities...": "Instalando utilidades del sistema...",
|
||||
"Installing the new image": "Instalación de la nueva imagen",
|
||||
"Installing the new image...": "Instalar la nueva imagen...",
|
||||
"Installing the new image:": "Instalar la nueva imagen:",
|
||||
"Installing the stack startup hook...": "Instalar el gancho de arranque de la pila...",
|
||||
"Installing the new image...": "Instalando la nueva imagen...",
|
||||
"Installing the new image:": "Instalando la nueva imagen:",
|
||||
"Installing the stack startup hook...": "Instalando el hook de arranque de la pila...",
|
||||
"Installing zfs-auto-snapshot package...": "Instalando el paquete zfs-auto-snapshot...",
|
||||
"Installs essential packages if missing": "Instala paquetes esenciales si faltan",
|
||||
"Insufficient Disk Space": "Espacio en disco insuficiente",
|
||||
@@ -2965,9 +2968,9 @@
|
||||
"Internal subnet of the tunnel (change it only if it clashes)": "Subnet interno del túnel (cambiarlo sólo si choca)",
|
||||
"Interrupted operation": "Operación interrumpida",
|
||||
"Interrupted operation:": "Interrupted operación:",
|
||||
"Interrupted stack operation found": "Montaje interrumpido operación encontrado",
|
||||
"Interrupted stack operation found": "Se ha encontrado una operación de pila interrumpida",
|
||||
"Invalid 'proxmox-ve' candidate (not 9.x or none). Please verify your repository configuration and network, then retry.": "Candidato 'proxmox-ve' no válido (ni 9.x ni ninguno). Verifique la configuración y la red de su repositorio y luego vuelva a intentarlo.",
|
||||
"Invalid ALLOWED_HOSTS value": "Valor inválido ALLOWED HOSTS",
|
||||
"Invalid ALLOWED_HOSTS value": "Valor inválido ALLOWED_HOSTS",
|
||||
"Invalid Home Assistant OS check timeout": "Inválido Home Assistant OS check timeout",
|
||||
"Invalid ID": "ID no válida",
|
||||
"Invalid Intel render path": "Ruta de renderización Intel no válida",
|
||||
@@ -3067,13 +3070,13 @@
|
||||
"Invalid service check arguments": "Inválidos argumentos de verificación de servicios",
|
||||
"Invalid service check timeout": "Hora de facturación de servicio inválido",
|
||||
"Invalid shared path": "Ruta compartida no válida",
|
||||
"Invalid shutdown timeout": "Hora de apagado inválido",
|
||||
"Invalid shutdown timeout": "Tiempo de espera de apagado no válido",
|
||||
"Invalid size. Please enter a number in MB (e.g., 128, 256, 512).": "Tamaño no válido. Ingrese un número en MB (por ejemplo, 128, 256, 512).",
|
||||
"Invalid stack contract": "Contrato de pila inválido",
|
||||
"Invalid stack journal": "Revista de pilas inválidas",
|
||||
"Invalid stack members": "Miembros de pila inválidos",
|
||||
"Invalid stack name": "Nombre de pila inválido",
|
||||
"Invalid stack operation": "Apilación inválida operación",
|
||||
"Invalid stack contract": "Contrato de pila no válido",
|
||||
"Invalid stack journal": "Diario de pila no válido",
|
||||
"Invalid stack members": "Miembros de pila no válidos",
|
||||
"Invalid stack name": "Nombre de pila no válido",
|
||||
"Invalid stack operation": "Operación de pila no válida",
|
||||
"Invalid storage ID. Use only letters, numbers, hyphens and underscores.": "ID de almacenamiento no válido. Utilice únicamente letras, números, guiones y guiones bajos.",
|
||||
"Invalid suite application": "Aplicación de suite inválida",
|
||||
"Invalid sysctl value:": "Valor sysctl inválido:",
|
||||
@@ -3087,7 +3090,7 @@
|
||||
"Invalid volume size": "Tamaño del volumen inválido",
|
||||
"Invalid volume size:": "Tamaño de volumen inválido:",
|
||||
"Invalid volume target": "Destino de volumen no válido",
|
||||
"IoT & Smart Home": "IoT & Smart Home",
|
||||
"IoT & Smart Home": "IoT y domótica",
|
||||
"Is the value a password or secret?": "¿Es el valor una contraseña o secreto?",
|
||||
"Issue": "Asunto",
|
||||
"Issues found": "Problemas encontrados",
|
||||
@@ -3181,7 +3184,7 @@
|
||||
"Kometa reads its configuration from /config/config.yml and the container only ships /config/config.yml.template. Copy the template to config.yml, fill in the required Plex and TMDb connections, then restart the container.": "Kometa lee su configuración desde /config/config.yml y el contenedor sólo barcos /config/config.yml.template. Copiar la plantilla para config.yml, rellenar las conexiones necesario Plex y TMDb, luego reiniciar el contenedor.",
|
||||
"Komga is a media server for your comics, mangas, BDs, magazines and eBooks.": "Komga es un servidor multimedia para tus cómics, mangas, BDs, revistas y eBooks.",
|
||||
"Krita is a professional FREE and open source painting program. It is made by artists that want to see affordable art tools for everyone.": "Krita es un programa de pintura profesional GRATIS y de código abierto. Está hecho por artistas que quieren ver herramientas de arte asequibles para todos.",
|
||||
"LAN access to the kept containers (stack configuration incomplete):": "Acceso LAN a los contenedores guardados (incompleto de configuración de almacenamiento):",
|
||||
"LAN access to the kept containers (stack configuration incomplete):": "Acceso LAN a los contenedores conservados (configuración de la pila incompleta):",
|
||||
"LAN address applied to the application URLs": "Dirección LAN aplicada a las URL de la aplicación",
|
||||
"LLM App Development Platform": "Plataforma de desarrollo de aplicaciones LLM",
|
||||
"LM Studio can run local AI models like gpt-oss, Llama, Gemma, Qwen, and DeepSeek privately on your computer.": "LM Studio puede ejecutar modelos locales de IA como gpt-oss, Llama, Gemma, Qwen y DeepSeek en privado en su computadora.",
|
||||
@@ -3386,7 +3389,7 @@
|
||||
"Max user watches configured": "Número máximo de relojes de usuario configurados",
|
||||
"Maximum auto-repair attempts reached (3). Please review the log and run any remaining commands manually.": "Se alcanzó el número máximo de intentos de reparación automática (3). Revise el registro y ejecute los comandos restantes manualmente.",
|
||||
"May need to restart terminal": "Puede que sea necesario reiniciar el terminal",
|
||||
"Media & Streaming": "Multimedia y Streaming",
|
||||
"Media & Streaming": "Multimedia y streaming",
|
||||
"Media discovery and request management for Jellyfin, Plex and Emby.": "descubrimiento de medios y gestión de solicitudes para Jellyfin, Plex y Emby.",
|
||||
"Media library transcoding and health checking, with an internal worker node.": "Transcodificación de la biblioteca de medios y control de salud, con un nodo de trabajador interno.",
|
||||
"Media server": "Servidor multimedia",
|
||||
@@ -3401,7 +3404,7 @@
|
||||
"Memory settings optimized successfully": "Configuración de memoria optimizada con éxito",
|
||||
"Memory:": "Memoria:",
|
||||
"Memos is a lightweight, self-hosted memo hub. Open Source and Free forever.": "Memos es un centro de memo liviano y auto hospedado. Fuente Abierta y Libre para siempre.",
|
||||
"Messaging & Notifications": "Mensajería y Notificaciones",
|
||||
"Messaging & Notifications": "Mensajería y notificaciones",
|
||||
"Messaging & Queues": "Mensajería y Colas",
|
||||
"Messenger for the Decentralized Web": "Messenger para la Web descentralizada",
|
||||
"Method:": "Método:",
|
||||
@@ -3442,9 +3445,9 @@
|
||||
"Monitor progress:": "Supervisar el progreso:",
|
||||
"Monitor, analyze, and alert on network performance.": "Monitorear, analizar y alertar sobre el rendimiento de la red.",
|
||||
"Monitoring": "Monitorización",
|
||||
"Monitoring & Analytics": "Monitorización y Analítica",
|
||||
"Monitoring & Analytics": "Monitorización y analítica",
|
||||
"Most common cause: the archive is corrupted (interrupted write, partial copy, or storage issue).": "causa más común: el archivo está dañado (escritura interrumpida, copia parcial o problema de almacenamiento).",
|
||||
"Mount Added Successfully:": "Montaje agregado con éxito:",
|
||||
"Mount Added Successfully:": "Montaje añadido correctamente:",
|
||||
"Mount CIFS share:": "Monte el recurso compartido CIFS:",
|
||||
"Mount Configuration Summary:": "Resumen de configuración de montaje:",
|
||||
"Mount Details:": "Detalles de montaje:",
|
||||
@@ -3515,7 +3518,7 @@
|
||||
"Move that copy offsite (USB, password manager, another host). Delete it from this path when done.": "mueva esa copia fuera del sitio (USB, administrador de contraseñas, otro host).Elimínelo de esta ruta cuando haya terminado.",
|
||||
"Move to target VM (remove from source VM config)": "Mover a la VM de destino (eliminar de la configuración de la VM de origen)",
|
||||
"Moving the data volumes aside": "Mover los volúmenes de datos a un lado",
|
||||
"Moving the data volumes aside...": "Mover los volúmenes de datos a un lado...",
|
||||
"Moving the data volumes aside...": "Apartando los volúmenes de datos...",
|
||||
"Multi-container application (experimental)": "Aplicación multicontenedor (experimental)",
|
||||
"Multi-line variables are not supported": "No se admiten variables multilíneas",
|
||||
"Multiple networks or external networks are not yet supported": "Aún no se admiten múltiples redes o redes externas",
|
||||
@@ -3652,7 +3655,7 @@
|
||||
"NVMe health status: WARNING (critical_warning =": "Estado de salud de NVMe: ADVERTENCIA (advertencia_crítica =",
|
||||
"NVMe skipped (to add as PCIe use 'Add Controller or NVMe PCIe to VM'):": "NVMe omitido (para agregar como PCIe use 'Agregar controlador o NVMe PCIe a VM'):",
|
||||
"NVMe-specific SMART log": "Registro SMART específico de NVMe",
|
||||
"NVR & Cameras": "NVR y Cámaras",
|
||||
"NVR & Cameras": "NVR y cámaras",
|
||||
"NVR with optional VA-API video acceleration and hardware object detectors": "NVR con detectores opcionales de vídeo VA-API y detectores de objetos de hardware",
|
||||
"NZBGet web interface": "Interfaz web NZBGet",
|
||||
"Name": "Nombre",
|
||||
@@ -3674,7 +3677,7 @@
|
||||
"Netbox is an IP address management (IPAM) and data center infrastructure management (DCIM) tool. Initially conceived by the network engineering team at DigitalOcean, NetBox was developed specifically to address the needs of network and infrastructure engineers. It is intended to function as a domain-specific source of truth for network operations.": "Netbox es una herramienta de gestión de direcciones IP (IPAM) y gestión de infraestructuras del centro de datos (DCIM). Inicialmente concebido por el equipo de ingeniería de red en DigitalOcean, NetBox fue desarrollado específicamente para atender las necesidades de los ingenieros de red e infraestructura. Está destinado a funcionar como una fuente de verdad específica para la red operations.",
|
||||
"Network": "Red",
|
||||
"Network :": "Red :",
|
||||
"Network & Firewall": "Red y Cortafuegos",
|
||||
"Network & Firewall": "Red y cortafuegos",
|
||||
"Network (interfaces, DNS)": "Red (interfaces, DNS)",
|
||||
"Network Bridge": "Puente de red",
|
||||
"Network Commands": "Comandos de red",
|
||||
@@ -3932,7 +3935,7 @@
|
||||
"No jobs": "Sin trabajos",
|
||||
"No language selected.": "No se seleccionó ningún idioma.",
|
||||
"No local disk storage configured.": "No hay almacenamiento en disco local configurado.",
|
||||
"No main sources.list present (skipped)": "No hay ninguna lista de fuentes principales presente (omitida)",
|
||||
"No main sources.list present (skipped)": "No hay sources.list principal (omitido)",
|
||||
"No matching PVE vzdump jobs were found for the PBS backend.": "No se encontraron trabajos PVE vzdump coincidentes para el backend de PBS.",
|
||||
"No matching PVE vzdump jobs were found for the local archive backend.": "No se encontraron trabajos PVE vzdump coincidentes para el backend del archivo local.",
|
||||
"No mount point was specified.": "No se especificó ningún punto de montaje.",
|
||||
@@ -4045,7 +4048,7 @@
|
||||
"OCI containers require Proxmox VE 9.1 or later.": "Los contenedores OCI requieren Proxmox VE 9.1 o posterior.",
|
||||
"OCI management": "Gestión OCI",
|
||||
"OCI management could not be completed. Check the backend status; no additional cleanup has been authorized.": "La gestión OCI no pudo completarse. Comprueba el estado del backend; no se ha autorizado ninguna limpieza adicional.",
|
||||
"OCI manager Apps (beta)": "Aplicaciones de administrador de OCI (beta)",
|
||||
"OCI manager Apps (beta)": "OCI manager Apps (beta)",
|
||||
"OCI manager Apps is a beta: if something does not work as expected, please report it on GitHub with the application name.": "OCI manager Apps es una beta: si algo no funciona como esperabas, repórtalo en GitHub con el nombre de la aplicación.",
|
||||
"OCI metadata integrity mismatch": "Desigualdad de la integridad de los metadatos de la OCI",
|
||||
"OCI metadata too large": "OCI metadatos demasiado grandes",
|
||||
@@ -4101,7 +4104,7 @@
|
||||
"Only removes storage definition, not remote data.": "Solo elimina la definición de almacenamiento, no los datos remotos.",
|
||||
"Only run this if you used LVM (step 6b):": "Ejecute esto solo si usó LVM (paso 6b):",
|
||||
"Only the host backup hook is removed — PVE vzdump jobs targeting this storage stay intact.": "solo se elimina el enlace de copia de seguridad del host; las tareas de PVE vzdump destinados a este almacenamiento permanecen intactos.",
|
||||
"Only the image reference, with no Compose file": "Sólo la referencia de la imagen, sin archivo Compose",
|
||||
"Only the image reference, with no Compose file": "Solo la referencia de la imagen, sin archivo Compose",
|
||||
"Open": "Abierto",
|
||||
"Open Source realtime backend in 1 file": "Open Source en tiempo real backend en 1 archivo",
|
||||
"Open rwx + default inheritance for new files": "Abra rwx + herencia predeterminada para archivos nuevos",
|
||||
@@ -4169,7 +4172,7 @@
|
||||
"Original ZFS ARC config restored from .bak": "Configuración original de ZFS ARC restaurada desde .bak",
|
||||
"Original bashrc restored": "Bashrc original restaurado.",
|
||||
"Original logrotate configuration restored": "Configuración original de logrotate restaurada",
|
||||
"Orphan stack contract archived:": "Contrato de pila de huérfano archivado:",
|
||||
"Orphan stack contract archived:": "Contrato de pila huérfano archivado:",
|
||||
"Oscam is an Open Source Conditional Access Module software used for descrambling DVB transmissions using smart cards. It's both a server and a client.": "Oscam es un software de módulos de acceso condicional de código abierto utilizado para descifrar transmissions DVB utilizando tarjetas inteligentes. Es un servidor y un cliente.",
|
||||
"Other Prebuilt Linux VMs": "Otras máquinas virtuales Linux prediseñadas",
|
||||
"Output archive:": "Archivo de salida:",
|
||||
@@ -4268,8 +4271,8 @@
|
||||
"Password to access the aMule web interface": "Contraseña para acceder a la interfaz web aMule",
|
||||
"Passwords do not match. Please try again.": "Las contraseñas no coinciden. Por favor inténtalo de nuevo.",
|
||||
"Paste it here and press Ctrl+D on an empty line.": "Pégalo aquí y pulsa Ctrl+D en una línea vacía.",
|
||||
"Paste its Compose file in the terminal": "Pega su archivo Compose en la terminal",
|
||||
"Paste its docker run command in the terminal": "Pega su comando docker run en la terminal",
|
||||
"Paste its Compose file in the terminal": "Pegar su archivo Compose en la terminal",
|
||||
"Paste its docker run command in the terminal": "Pegar su comando docker run en la terminal",
|
||||
"Paste the UUP Dump URL here": "Pegue la URL del volcado UUP aquí",
|
||||
"Patching source for kernel compatibility...": "Fuente de parcheo para compatibilidad del kernel...",
|
||||
"Path does not exist.": "La ruta no existe.",
|
||||
@@ -4377,7 +4380,7 @@
|
||||
"Postfix configuration": "Configuración de sufijo",
|
||||
"PostgreSQL": "PostgreSQL",
|
||||
"PostgreSQL URL without an associated service:": "URL de PostgreSQL sin un servicio asociado:",
|
||||
"PostgreSQL creates the database named in POSTGRES_DB on the first start. The installer default is postgresql.": "PostgreSQL crea la base de datos llamada en POSTGRES DB en el primer comienzo. El instalador predeterminado es postgresql.",
|
||||
"PostgreSQL creates the database named in POSTGRES_DB on the first start. The installer default is postgresql.": "PostgreSQL crea la base de datos llamada en POSTGRES_DB en el primer comienzo. El instalador predeterminado es postgresql.",
|
||||
"PostgreSQL is an advanced, enterprise-class, and open-source relational database system. PostgreSQL supports both SQL (relational) and JSON (non-relational) querying.": "PostgreSQL es un sistema de bases de datos relacionales avanzado, de clase empresarial y de código abierto. PostgreSQL soporta tanto SQL (relacional) como JSON (no-relacional) querying.",
|
||||
"PostgreSQL requires a password": "PostgreSQL requires una contraseña",
|
||||
"PostgreSQL volume size in GB": "Tamaño del volumen de PostgreSQL en GB",
|
||||
@@ -4406,7 +4409,7 @@
|
||||
"Press Ctrl+C to stop the server and return to menu.": "Presione Ctrl+C para detener el servidor y regresar al menú.",
|
||||
"Press ENTER to continue...": "Presione ENTER para continuar...",
|
||||
"Press ENTER to return to the menu...": "Presione ENTER para regresar al menú...",
|
||||
"Press ENTER to return...": "Presione ENTRAR para regresar...",
|
||||
"Press ENTER to return...": "Presione ENTER para regresar...",
|
||||
"Press Enter to close...": "Presione Entrar para cerrar...",
|
||||
"Press Enter to continue": "Presione Entrar para continuar",
|
||||
"Press Enter to continue...": "Presione Entrar para continuar...",
|
||||
@@ -4460,7 +4463,7 @@
|
||||
"Process may take several minutes depending on container size": "El proceso puede tardar varios minutos dependiendo del tamaño del contenedor.",
|
||||
"Process may take several minutes for large containers": "El proceso puede tardar varios minutos para contenedores grandes.",
|
||||
"Processes using NVIDIA:": "Procesos usando NVIDIA:",
|
||||
"Productivity & Workflows": "Productividad y Flujos de trabajo",
|
||||
"Productivity & Workflows": "Productividad y flujos de trabajo",
|
||||
"Profile": "Perfil",
|
||||
"Profile:": "Perfil:",
|
||||
"Projectsend is a self-hosted application that lets you upload files and assign them to specific clients that you create yourself. Secure, private and easy. No more depending on external services or e-mail to send those files.": "Projectsend es una aplicación autoalojada que le permite subir archivos y asignarlos a clientes específicos que usted crea. Seguro, privado y fácil. No más dependiendo de servicios externos o correo electrónico para enviar esos archivos.",
|
||||
@@ -4541,7 +4544,7 @@
|
||||
"Pwndrop is a self-deployable file hosting service for sending out red teaming payloads or securely sharing your private files over HTTP and WebDAV.": "Pwndrop es un servicio de hospedaje de archivos autodesplegable para enviar descargas de equipo rojo o compartir de forma segura sus archivos privados sobre HTTP y WebDAV.",
|
||||
"PyCharm offers out-of-the-box support for Python, databases, Jupyter, Git, Conda, PyTorch, TensorFlow, Hugging Face, Django, Flask, FastAPI, and more.": "PyCharm ofrece soporte fuera de la caja para Python, bases de datos, Jupyter, Git, Conda, PyTorch, TensorFlow, Hugging Face, Django, Flask, FastAPI, y más.",
|
||||
"Pydio Cells needs an external MySQL or MariaDB database. The setup wizard asks for its address, database name and user on the first start.": "Pydio Cells necesita una base de datos MySQL externa o MariaDB. El asistente de configuración pide su dirección, nombre de la base de datos y usuario en el primer comienzo.",
|
||||
"Pydio Cells redirects to the address given in EXTERNALURL. If the container changes address, edit lxc.environment.runtime: EXTERNALURL and SERVER_IP in /etc/pve/lxc/<CTID>.conf with the container stopped, and delete /config/keys/cert.crt to regenerate the certificate.": "Pydio Cells redirige a la dirección dada en EXTERNALURL. Si el contenedor cambia la dirección, edite lxc.environment.runtime: EXTERNALURL y SERVER IP en /etc/pve/lxc/Seguido CTID ratio.conf con el contenedor detenido, y elimine /config/keys/cert.crt para regenerar el certificado.",
|
||||
"Pydio Cells redirects to the address given in EXTERNALURL. If the container changes address, edit lxc.environment.runtime: EXTERNALURL and SERVER_IP in /etc/pve/lxc/<CTID>.conf with the container stopped, and delete /config/keys/cert.crt to regenerate the certificate.": "Pydio Cells redirige a la dirección dada en EXTERNALURL. Si el contenedor cambia la dirección, edite lxc.environment.runtime: EXTERNALURL y SERVER_IP en /etc/pve/lxc/Seguido CTID ratio.conf con el contenedor detenido, y elimine /config/keys/cert.crt para regenerar el certificado.",
|
||||
"Pydio-cells is the nextgen file sharing platform for organizations. It is a full rewrite of the Pydio project using the Go language following a micro-service architecture.": "Pydio-cells es la plataforma de intercambio de archivos de Nextgen para organizaciones. Es una reescritura completa del proyecto Pydio usando el lenguaje Go siguiendo una arquitectura de microservicio.",
|
||||
"QDirStat Qt-based directory statistics: KDirStat without any KDE -- from the author of the original KDirStat.": "QDirStat Estadísticas de directorios basadas en Qt: KDirStat sin ningún KDE -- del autor del original KDirStat.",
|
||||
"Quick health check (PASSED / FAILED)": "Chequeo de salud rápido (APROBADO / FALLADO)",
|
||||
@@ -4576,7 +4579,7 @@
|
||||
"Re-enter the BORG REPOKEY passphrase to confirm:": "Vuelva a ingresar la frase de contraseña de BORG REPOKEY para confirmar:",
|
||||
"Re-running pre-check after repairs...": "Volviendo a ejecutar la verificación previa después de las reparaciones...",
|
||||
"Reachable": "Accesible",
|
||||
"Read its Compose file from a file of this host": "Lea su archivo Compose desde un archivo de este host",
|
||||
"Read its Compose file from a file of this host": "Leer su archivo Compose desde un archivo de este host",
|
||||
"Read the link with pct console CTID on the Proxmox host, or from the Console panel of the container in the Proxmox web interface, then open the https://playit.gg/claim/ address it shows in a browser and sign in to playit.gg. Ctrl+a q leaves pct console.": "Lea el enlace con la consola pct CTID en el host Proxmox, o desde el panel Console del contenedor en la interfaz web Proxmox, a continuación, abra la dirección https://playit.gg/claim/ que muestra en un navegador y regístrese para playit.gg. Ctrl+a q deja la consola pct.",
|
||||
"Read-Only": "Sólo lectura",
|
||||
"Read-Only access": "Acceso de sólo lectura",
|
||||
@@ -4739,7 +4742,7 @@
|
||||
"Remove subscription banner": "Eliminar banner de suscripción",
|
||||
"Remove the unprivileged flag from configuration:": "Elimine la bandera sin privilegios de la configuración:",
|
||||
"Remove unused packages and their config": "Eliminar paquetes no utilizados y su configuración.",
|
||||
"Remove: delete the application and its containers": "Eliminar: eliminar la aplicación y sus contenedores",
|
||||
"Remove: delete the application and its containers": "Eliminar: la aplicación y sus contenedores",
|
||||
"Removed": "Remoto",
|
||||
"Removed KVM MSR options from configuration": "Se eliminaron las opciones de KVM MSR de la configuración.",
|
||||
"Removed Mount:": "Montaje eliminado:",
|
||||
@@ -4791,7 +4794,7 @@
|
||||
"Removing storage from Proxmox...": "Eliminando almacenamiento de Proxmox...",
|
||||
"Removing system limits optimizations...": "Eliminando optimizaciones de límites del sistema...",
|
||||
"Removing the containers...": "Removiendo los contenedores...",
|
||||
"Removing the incomplete stack...": "La eliminación de la pila incompleta...",
|
||||
"Removing the incomplete stack...": "Eliminando la pila incompleta...",
|
||||
"Removing the previous container": "Remoción del contenedor anterior",
|
||||
"Removing utilities installed by ProxMenux...": "Eliminando utilidades instaladas por ProxMenux...",
|
||||
"Removing zfs-auto-snapshot...": "Eliminando zfs-auto-snapshot...",
|
||||
@@ -4880,8 +4883,8 @@
|
||||
"Restoring the original rpcbind service state...": "Restaurando el estado original del servicio rpcbind...",
|
||||
"Restoring the previous Rclone configuration...": "Restaurar la configuración anterior de Rclone...",
|
||||
"Restoring the previous backup...": "Restaurar el backup anterior...",
|
||||
"Restoring the previous state of the stack...": "Restaurar el estado anterior de la pila...",
|
||||
"Restoring the stack records...": "Restaurar los registros de la pila...",
|
||||
"Restoring the previous state of the stack...": "Restaurando el estado anterior de la pila...",
|
||||
"Restoring the stack records...": "Restaurando los registros de la pila...",
|
||||
"Results will be saved automatically to:": "Los resultados se guardarán automáticamente en:",
|
||||
"Results will be saved to:": "Los resultados se guardarán en:",
|
||||
"Retention": "Retención",
|
||||
@@ -5043,8 +5046,8 @@
|
||||
"Save this Borg target so you don't need to enter the details again?": "¿Guardar este objetivo Borg para no tener que volver a introducir los detalles?",
|
||||
"Saved record removed": "Se elimina el registro guardado",
|
||||
"Saving the new configuration": "Salvando la nueva configuración",
|
||||
"Saving the new configuration...": "Salvando la nueva configuración...",
|
||||
"Saving the stack records...": "Salvando los registros de la pila...",
|
||||
"Saving the new configuration...": "Guardando la nueva configuración...",
|
||||
"Saving the stack records...": "Guardando los registros de la pila...",
|
||||
"Scan storage for new content": "Escanear el almacenamiento en busca de contenido nuevo",
|
||||
"Scanning available physical disks...": "Escaneando discos físicos disponibles...",
|
||||
"Scanning network for NFS servers...": "Escaneando la red en busca de servidores NFS...",
|
||||
@@ -5143,6 +5146,7 @@
|
||||
"Select archive to restore": "Seleccione el archivo para restaurar",
|
||||
"Select at least one path to continue.": "seleccione al menos una ruta para continuar.",
|
||||
"Select at least one suite application": "Seleccione al menos una aplicación de suite",
|
||||
"Select at least one stack container": "Seleccione al menos un contenedor de la pila",
|
||||
"Select authentication mode:": "Seleccione el modo de autenticación:",
|
||||
"Select authentication type:": "Seleccione el tipo de autenticación:",
|
||||
"Select available Controllers/NVMe to add:": "Seleccione Controladores/NVMe disponibles para agregar:",
|
||||
@@ -5341,7 +5345,7 @@
|
||||
"Shared host data is not reverted by the backups. Continue?": "Los datos de host compartidos no son revertidos por los backups. ¿Continúa?",
|
||||
"Shared host directories (not included in Proxmox backups)": "Directorios de host compartidos (no incluidos en backups de Proxmox)",
|
||||
"Shared host directory": "Directorio compartido del host",
|
||||
"Shared host directory (not included in Proxmox backups)": "Directorio de host compartido (no incluido en backups de Proxmox)",
|
||||
"Shared host directory (not included in Proxmox backups)": "Directorio del host compartido (no incluido en los backups de Proxmox)",
|
||||
"Shared host files are kept as they are; the backup does not restore their content.": "Los archivos de host compartidos se guardan como están; el backup no restaura su contenido.",
|
||||
"Shared host media directory": "Directorio multimedia compartido del host",
|
||||
"Shared memory size for the GPU workload in MB": "Tamaño de memoria compartido para el volumen de trabajo de GPU en MB",
|
||||
@@ -5466,20 +5470,20 @@
|
||||
"Stable (main branch)": "Estable (rama principal)",
|
||||
"Stable monitor service normalized.": "Servicio de monitor estable normalizado.",
|
||||
"Stack": "Pila",
|
||||
"Stack adapter not recognized by the translator": "Adaptador Stack no reconocido por el traductor",
|
||||
"Stack backups are missing; a partial restore is not allowed": "Faltan backups; no se permite una restauración parcial",
|
||||
"Stack checked:": "Se ha comprobado:",
|
||||
"Stack members are missing; recreate them after verifying their volumes": "Los miembros de Stack están desaparecidos; recrearlos después de verificar sus volúmenes",
|
||||
"Stack members are updated together with their stack": "Los miembros de Stack se actualizan junto con su pila",
|
||||
"Stack adapter not recognized by the translator": "Adaptador de pila no reconocido por el traductor",
|
||||
"Stack backups are missing; a partial restore is not allowed": "Faltan backups de la pila; no se permite una restauración parcial",
|
||||
"Stack checked:": "Pila comprobada:",
|
||||
"Stack members are missing; recreate them after verifying their volumes": "Faltan miembros de la pila; recréelos después de verificar sus volúmenes",
|
||||
"Stack members are updated together with their stack": "Los miembros de una pila se actualizan junto con su pila",
|
||||
"Stack name": "Nombre de la pila",
|
||||
"Stack records restored": "Registros recuperados",
|
||||
"Stack records saved": "Registros guardados",
|
||||
"Stack records saved; no container was reinstalled.": "Registros guardados; no se reinstaló ningún contenedor.",
|
||||
"Stack recovery completed; every member is back to its previous installation.": "Recuperación de etapas completada; cada miembro está de vuelta a su instalación anterior.",
|
||||
"Stack startup hook installed": "Gancho de arranque de Stack instalado",
|
||||
"Stack stopped": "Stack paró",
|
||||
"Stack update completed. Data kept.": "Actualización finalizada. Datos guardados.",
|
||||
"Stack:": "Stack:",
|
||||
"Stack records restored": "Registros de la pila restaurados",
|
||||
"Stack records saved": "Registros de la pila guardados",
|
||||
"Stack records saved; no container was reinstalled.": "Registros de la pila guardados; no se reinstaló ningún contenedor.",
|
||||
"Stack recovery completed; every member is back to its previous installation.": "Recuperación de la pila completada; cada miembro ha vuelto a su instalación anterior.",
|
||||
"Stack startup hook installed": "Hook de arranque de la pila instalado",
|
||||
"Stack stopped": "Pila detenida",
|
||||
"Stack update completed. Data kept.": "Actualización de la pila completada. Datos conservados.",
|
||||
"Stack:": "Pila:",
|
||||
"Staging directory:": "Directorio temporal:",
|
||||
"Staging ready.": "Preparación completada.",
|
||||
"Staging source:": "Origen de la preparación:",
|
||||
@@ -5514,9 +5518,9 @@
|
||||
"Start uploading to PBS — sets a recovery passphrase": "comience a cargar en PBS: establece una frase de contraseña de recuperación",
|
||||
"Start when finished": "Iniciar al terminar",
|
||||
"Start with Proxmox": "Iniciar con Proxmox",
|
||||
"Starting": "Empezando",
|
||||
"Starting Borg backup...": "Iniciando copia de seguridad de Borg...",
|
||||
"Starting CT": "TC inicial",
|
||||
"Starting": "Iniciando",
|
||||
"Starting Borg backup...": "Iniciando el backup de Borg...",
|
||||
"Starting CT": "Iniciando el CT",
|
||||
"Starting LXC Privileged to Unprivileged conversion process...": "Iniciando el proceso de conversión de LXC privilegiado a no privilegiado...",
|
||||
"Starting LXC Unprivileged to Privileged conversion process...": "Iniciando el proceso de conversión de LXC sin privilegios a privilegiados...",
|
||||
"Starting NVIDIA installer. This may take several minutes...": "Iniciando el instalador de NVIDIA. Esto puede tardar varios minutos...",
|
||||
@@ -5525,22 +5529,22 @@
|
||||
"Starting ProxMenux update...": "Iniciando actualización de ProxMenux...",
|
||||
"Starting Proxmox storage integration...": "Iniciando la integración del almacenamiento de Proxmox...",
|
||||
"Starting Proxmox system repair...": "Iniciando la reparación del sistema Proxmox...",
|
||||
"Starting Rclone and waiting for the FUSE mount...": "Empezando Rclone y esperando el montaje FUSE...",
|
||||
"Starting Rclone and waiting for the FUSE mount...": "Iniciando Rclone y esperando el montaje FUSE...",
|
||||
"Starting SMART long self-test...": "Iniciando la autoprueba larga SMART...",
|
||||
"Starting SMART short self-test...": "Iniciando la autoprueba corta SMART...",
|
||||
"Starting container": "Contenedor inicial",
|
||||
"Starting container...": "Contenedor inicial...",
|
||||
"Starting direct conversion of container": "Iniciar la conversión directa del contenedor",
|
||||
"Starting gateway...": "Iniciando puerta de enlace...",
|
||||
"Starting container": "Iniciando el contenedor",
|
||||
"Starting container...": "Iniciando el contenedor...",
|
||||
"Starting direct conversion of container": "Iniciando la conversión directa del contenedor",
|
||||
"Starting gateway...": "Iniciando la puerta de enlace...",
|
||||
"Starting installation...": "Iniciando instalación...",
|
||||
"Starting installer...": "Iniciando el instalador...",
|
||||
"Starting privileged container...": "Iniciando contenedor privilegiado...",
|
||||
"Starting privileged container...": "Iniciando el contenedor privilegiado...",
|
||||
"Starting rpcbind service...": "Iniciando el servicio rpcbind...",
|
||||
"Starting the container...": "Comenzando el contenedor...",
|
||||
"Starting the main container and its dependencies...": "Comenzando el contenedor principal y sus dependencias...",
|
||||
"Starting the service:": "Inicio del servicio:",
|
||||
"Starting unprivileged container...": "Iniciando contenedor sin privilegios...",
|
||||
"Startup: coordinated by the stack startup hook": "Inicio: coordinado por el gancho de arranque de pila",
|
||||
"Starting the container...": "Iniciando el contenedor...",
|
||||
"Starting the main container and its dependencies...": "Iniciando el contenedor principal y sus dependencias...",
|
||||
"Starting the service:": "Iniciando el servicio:",
|
||||
"Starting unprivileged container...": "Iniciando el contenedor sin privilegios...",
|
||||
"Startup: coordinated by the stack startup hook": "Arranque: coordinado por el hook de arranque de la pila",
|
||||
"Startup: independent, without hookscript": "Inicio: independiente, sin gancho",
|
||||
"Static IP": "IP estática",
|
||||
"Static IPv4 address": "Dirección IPv4 estática",
|
||||
@@ -5578,7 +5582,7 @@
|
||||
"Stopping the container before applying configuration...": "Deteniendo el contenedor antes de aplicar la configuración...",
|
||||
"Stopping the container before conversion...": "Deteniendo el contenedor antes de la conversión...",
|
||||
"Stopping the container...": "Deteniendo el contenedor...",
|
||||
"Stopping the stack...": "Detener la pila...",
|
||||
"Stopping the stack...": "Deteniendo la pila...",
|
||||
"Storage": "Almacenamiento",
|
||||
"Storage & Share Manager": "Almacenamiento y Gestor de recursos compartidos",
|
||||
"Storage Added:": "Almacenamiento agregado:",
|
||||
@@ -5830,6 +5834,7 @@
|
||||
"The command works out a value by running another command:": "El comando obtiene un valor ejecutando otro comando:",
|
||||
"The compatibility check raised failures that may break the system after restore.": "La verificación de compatibilidad generó fallas que pueden dañar el sistema después de la restauración.",
|
||||
"The configuration changed after the backup was restored; the recovery is not confirmed": "La configuración cambió después de la restauración del backup; la recuperación no se confirma",
|
||||
"The console of the container could not be configured": "No se pudo configurar la consola del contenedor",
|
||||
"The configuration changed after the new container was validated": "La configuración cambió después de validar el nuevo contenedor",
|
||||
"The configuration changed during the NVIDIA refresh": "La configuración cambió durante la actualización de NVIDIA",
|
||||
"The configuration evidence does not match": "La evidencia de configuración no coincide",
|
||||
@@ -5879,7 +5884,7 @@
|
||||
"The data and document volumes need at least 8 GB": "Los volúmenes de datos y documentos necesitan al menos 8 GB",
|
||||
"The database server must accept connections from the IP address of this container, with a user that is not limited to localhost.": "El servidor de bases de datos debe aceptar conexiones desde la dirección IP de este contenedor, con un usuario que no se limita a localhost.",
|
||||
"The dedicated adapter still requires replaying its rootfs changes": "El adaptador dedicado todavía requiere replaying its rootfs changes",
|
||||
"The dependency hook and the stack recipe differ": "El gancho de dependencia y la receta de pila difieren",
|
||||
"The dependency hook and the stack recipe differ": "El hook de dependencias y la receta de la pila no coinciden",
|
||||
"The dependency hook was modified; review it before updating": "El gancho de dependencia fue modificado; revisarlo antes de actualizarlo",
|
||||
"The developer-friendly cloud platform for building and running LLM agents for AI-native applications.": "La plataforma de nube amigable con el desarrollador para construir y ejecutar agentes LLM para aplicaciones nativas de AI.",
|
||||
"The device directory does not exist:": "El directorio del dispositivo no existe:",
|
||||
@@ -5942,7 +5947,7 @@
|
||||
"The image did not grant the application user access to the devices; check its native init. Host permissions were not relaxed.": "La imagen no concedió el acceso del usuario de la aplicación a los dispositivos; comprobar su entrada nativa. Los permisos del host no se relajaron.",
|
||||
"The image did not pass the integrity check": "La imagen no pasó el control de integridad",
|
||||
"The image does not declare support for this architecture:": "La imagen no declara soporte para esta arquitectura:",
|
||||
"The image download did not complete correctly; downloading it again...": "La descarga de la imagen no se completó correctamente; descargarlo de nuevo...",
|
||||
"The image download did not complete correctly; downloading it again...": "La descarga de la imagen no se completó correctamente; descargándola de nuevo...",
|
||||
"The image expects files that are given to it one by one:": "La imagen espera archivos que se le dan uno por uno:",
|
||||
"The image is already up to date; nothing was changed.": "La imagen ya está actualizada; nada cambió.",
|
||||
"The image is in its registry, for one architecture.": "La imagen está en su registro, para una arquitectura.",
|
||||
@@ -5955,7 +5960,7 @@
|
||||
"The imported Compose requests privileged, but the official jlesage/handbrake documentation does not require it; ProxMenux keeps the LXC unprivileged.": "El Compose importado solicita privilegiado, pero la documentación oficial jlesage/handbrake no lo requiere; ProxMenux mantiene el LXC sin privilegios.",
|
||||
"The imported OCI groups are not numeric": "Los grupos OCI importados no son numéricos",
|
||||
"The imported OCI user or group is not numeric": "El usuario o grupo OCI importado no es numérico",
|
||||
"The initial user name and password stay written in /etc/pve/lxc/<CTID>.conf as INIT_USERNAME and INIT_PASSWORD. They can be removed after the first login, with the container stopped.": "El nombre de usuario inicial y la contraseña permanecen escritos en /etc/pve/lxc/según INIT USERNAME e INIT PASSWORD. Se pueden quitar después de la primera entrada, con el contenedor detenido.",
|
||||
"The initial user name and password stay written in /etc/pve/lxc/<CTID>.conf as INIT_USERNAME and INIT_PASSWORD. They can be removed after the first login, with the container stopped.": "El nombre de usuario inicial y la contraseña permanecen escritos en /etc/pve/lxc/según INIT_USERNAME e INIT_PASSWORD. Se pueden quitar después de la primera entrada, con el contenedor detenido.",
|
||||
"The installation asks which one to use for these paths.": "La instalación pregunta cuál usar para estas rutas.",
|
||||
"The installation ended with exit code": "La instalación terminó con código de salida",
|
||||
"The installation requires a server restart to apply changes. Do you want to restart now?": "La instalación requiere reiniciar el servidor para aplicar los cambios. ¿Quieres reiniciar ahora?",
|
||||
@@ -5981,7 +5986,7 @@
|
||||
"The main member must stop first and start last": "El miembro principal debe parar primero y comenzar el último",
|
||||
"The main member of the stack is missing": "Falta el miembro principal de la pila",
|
||||
"The manifest does not match its digest": "El manifiesto no coincide con su digestión",
|
||||
"The member journal belongs to another stack operation": "El diario miembro pertenece a otra pila operación",
|
||||
"The member journal belongs to another stack operation": "El diario del miembro pertenece a otra operación de pila",
|
||||
"The member journal is outside the registry": "La revista miembro está fuera del registro",
|
||||
"The mount evidence does not match the verified directories": "La evidencia de montaje no coincide con los directorios verificados",
|
||||
"The mount source or options were not kept": "La fuente de montaje o las opciones no se guardaron",
|
||||
@@ -6035,7 +6040,7 @@
|
||||
"The prepared directory escapes the rootfs:": "El directorio preparado escapa a los rootfs:",
|
||||
"The preselected VMID does not exist on this host:": "El VMID preseleccionado no existe en este host:",
|
||||
"The previous native backup will be restored. Shared host directories are not reverted. Displaced disks are kept.": "El backup nativo anterior será restaurado. Los directorios de host compartidos no son revertidos. Se guardan discos desplazados.",
|
||||
"The previous stack contract is not safe; review it before reusing it": "El contrato de pila anterior no es seguro; revisarlo antes de reutilizarlo",
|
||||
"The previous stack contract is not safe; review it before reusing it": "El contrato de pila anterior no es seguro; revíselo antes de reutilizarlo",
|
||||
"The previous stack contract is not valid; it is not archived automatically": "El contrato de pila anterior no es válido; no se archiva automáticamente",
|
||||
"The previous stack contract still has containers or VMs:": "El contrato de pila anterior todavía tiene contenedores o VMs:",
|
||||
"The private address is already assigned to another container:": "La dirección privada ya está asignada a otro contenedor:",
|
||||
@@ -6069,12 +6074,12 @@
|
||||
"The requested machine learning GPU profile is not working; it is not replaced by CPU": "El perfil GPU de aprendizaje automático solicitado no funciona; no es reemplazado por CPU",
|
||||
"The restored service did not pass its health check": "El servicio restaurado no aprobó su cheque de salud",
|
||||
"The restored service stopped; the recovery is not confirmed": "El servicio restaurado se detuvo; la recuperación no se confirma",
|
||||
"The reviewed Tandoor stack does not require a privileged LXC.": "La pila Tandoor revisada no requiere un privilegiado LXC.",
|
||||
"The reviewed Tandoor stack does not require a privileged LXC.": "La pila de Tandoor revisada no requiere un LXC privilegiado.",
|
||||
"The rootfs capture only belongs to the running installation": "La captura de rootfs sólo pertenece a la instalación de ejecución",
|
||||
"The rootfs is not managed by Proxmox": "Los rootfs no son gestionados por Proxmox",
|
||||
"The rootfs is not mounted": "Los rootfs no se montan",
|
||||
"The same GPU cannot be used by two VMs at the same time.": "Dos máquinas virtuales no pueden utilizar la misma GPU al mismo tiempo.",
|
||||
"The same connection can be given as container variables instead of the file: UN_SONARR_0_URL and UN_SONARR_0_API_KEY, or the UN_RADARR_0_ equivalents.": "La misma conexión se puede administrar como variables contenedor en lugar del archivo: UN SONARR 0 URL y UN SONARR 0 API KEY, o UN RADARR 0 equivalents.",
|
||||
"The same connection can be given as container variables instead of the file: UN_SONARR_0_URL and UN_SONARR_0_API_KEY, or the UN_RADARR_0_ equivalents.": "La misma conexión se puede administrar como variables contenedor en lugar del archivo: UN_SONARR_0_URL y UN_SONARR_0_API_KEY, o UN RADARR 0 equivalents.",
|
||||
"The saved MOTD state is invalid; no changes were made": "el estado MOTD guardado no es válido;no se hicieron cambios",
|
||||
"The saved OCI record is incomplete or has an unexpected format.": "El registro OCI guardado es incompleto o tiene un formato inesperado.",
|
||||
"The saved projection does not match the native evidence": "La proyección salva no coincide con la evidencia nativa",
|
||||
@@ -6146,11 +6151,11 @@
|
||||
"The stack member has no declared adaptation profile": "El miembro de la pila no tiene perfil de adaptación declarado",
|
||||
"The stack name only accepts lowercase letters, numbers and hyphens": "El nombre de la pila solo acepta letras minúsculas, números y guiones",
|
||||
"The stack needs member adaptations or a verification of missing volumes": "La pila necesita adaptaciones de los miembros o una verificación de volúmenes perdidos",
|
||||
"The stack operation had already finished": "La pila operación ya había terminado",
|
||||
"The stack operation has not finished yet": "La pila operación no ha terminado todavía",
|
||||
"The stack operation stopped halfway. Select the stack again in the OCI management menu to recover it.": "La pila operación se detuvo a mitad de camino. Seleccione la pila de nuevo en el menú de gestión de OCI para recuperarla.",
|
||||
"The stack registry is incomplete; review the private contracts.": "El registro de pilas es incompleto; revisar los contratos privados.",
|
||||
"The stack startup hook was not found": "El gancho de arranque de pila no fue encontrado",
|
||||
"The stack operation had already finished": "La operación de pila ya había terminado",
|
||||
"The stack operation has not finished yet": "La operación de pila todavía no ha terminado",
|
||||
"The stack operation stopped halfway. Select the stack again in the OCI management menu to recover it.": "La operación de pila se detuvo a medias. Seleccione la pila de nuevo en el menú de gestión OCI para recuperarla.",
|
||||
"The stack registry is incomplete; review the private contracts.": "El registro de pilas está incompleto; revise los contratos privados.",
|
||||
"The stack startup hook was not found": "No se encontró el hook de arranque de la pila",
|
||||
"The stack update was saved.": "La actualización de la pila fue guardada.",
|
||||
"The startup differs from the declared Nextcloud adapter": "La startup difiere del adaptador Nextcloud declarado",
|
||||
"The startup differs from the declared adapter": "La startup difiere del adaptador declarado",
|
||||
@@ -6335,7 +6340,7 @@
|
||||
"Transaction log:": "Registro de transacciones:",
|
||||
"Translation files:": "Archivos de traducción:",
|
||||
"Transmission is designed for easy, powerful use. Transmission has the features you want from a BitTorrent client: encryption, a web interface, peer exchange, magnet links, DHT, µTP, UPnP and NAT-PMP port forwarding, webseed support, watch directories, tracker editing, global and per-torrent speed limits, and more.": "Transmission está diseñado para un uso fácil y potente. Transmission tiene las características que desea de un cliente BitTorrent: cifrado, una interfaz web, intercambio de pares, enlaces magnéticos, DHT, μTP, UPnP y NAT-PMP, soporte web, directorios de reloj, edición de rastreadores, límites de velocidad globales y per-torrent, y más.",
|
||||
"Tried pvesm path and manual detection methods": "Ruta pvesm probada y métodos de detección manual",
|
||||
"Tried pvesm path and manual detection methods": "Se probó pvesm path y métodos de detección manual",
|
||||
"Trust this certificate and save it for scheduled backups?": "¿Confiar en este certificado y guardarlo para copias de seguridad programadas?",
|
||||
"Try Again": "Intentar otra vez",
|
||||
"Try a different search term.": "Pruebe con un término de búsqueda diferente.",
|
||||
@@ -6430,14 +6435,14 @@
|
||||
"Unmounting": "Desmontaje",
|
||||
"Unmounting disk...": "Desmontando disco...",
|
||||
"Unpackerr configured": "Unpackerr configurado",
|
||||
"Unpackerr has no web interface and extracts nothing until it is pointed at a Starr application. Uncomment the [sonarr.0] or [radarr.0] section in /config/unpackerr.conf inside the container, set its url and api_key, then restart the container.": "Unpackerr no tiene interfaz web y no extrae nada hasta que se apunta a una aplicación Starr. Descomponer la sección [sonarr.0] o [radarr.0] en /config/unpackerr.conf dentro del contenedor, establecer su url y api key, luego reiniciar el recipiente.",
|
||||
"Unpackerr has no web interface and extracts nothing until it is pointed at a Starr application. Uncomment the [sonarr.0] or [radarr.0] section in /config/unpackerr.conf inside the container, set its url and api_key, then restart the container.": "Unpackerr no tiene interfaz web y no extrae nada hasta que se apunta a una aplicación Starr. Descomentar la sección [sonarr.0] o [radarr.0] en /config/unpackerr.conf dentro del contenedor, establecer su url y api_key, y reiniciar el contenedor.",
|
||||
"Unpackerr requires Sonarr, Radarr or Lidarr in this suite": "Unpackerr requiere Sonarr, Radarr o Lidarr en esta suite",
|
||||
"Unpackerr stopped during its first start": "Unpackerr se detuvo durante su primer inicio",
|
||||
"Unprivileged": "Sin privilegios",
|
||||
"Unprivileged Container Access": "Acceso a contenedores sin privilegios",
|
||||
"Unprivileged container": "Contenedor sin privilegios",
|
||||
"Unprivileged container selected:": "Contenedor sin privilegios seleccionado:",
|
||||
"Unprivileged container — UID offset:": "Contenedor sin privilegios: compensación de UID:",
|
||||
"Unprivileged container — UID offset:": "Contenedor sin privilegios — desplazamiento de UID:",
|
||||
"Unprivileged containers map their UIDs to high host UIDs (e.g. 100000+), which appear as 'others' on the host filesystem.": "Los contenedores sin privilegios asignan sus UID a UID de host altos (por ejemplo, 100000+), que aparecen como \"otros\" en el sistema de archivos del host.",
|
||||
"Unprivileged: Limited access (more secure)": "Sin privilegios: acceso limitado (más seguro)",
|
||||
"Unreachable": "Inalcanzable",
|
||||
@@ -6465,7 +6470,7 @@
|
||||
"Unsafe registry directory": "Directorio de registros inseguros",
|
||||
"Unsafe registry lock": "Cierre de registro inseguro",
|
||||
"Unsafe rootfs for the capture": "rootfs inseguros para la captura",
|
||||
"Unsafe stack assembly": "Montaje de pila inseguro",
|
||||
"Unsafe stack assembly": "Ensamblado de pila inseguro",
|
||||
"Unsafe volume path": "Vía de volumen inseguro",
|
||||
"Unsupported CPU allocation mode:": "Modo de asignación de CPU no compatible:",
|
||||
"Unsupported GID strategy:": "Estrategia GID sin apoyo:",
|
||||
@@ -6498,7 +6503,7 @@
|
||||
"Unsupported volume options:": "Opciones de volumen no admitidas:",
|
||||
"Untrusted or modified NVIDIA hook": "Gancho NVIDIA sin confianza o modificado",
|
||||
"Unused image removed from the cache:": "Imagen no utilizada extraída del caché:",
|
||||
"Unused images removed from the cache:": "Imágenes no utilizadas eliminadas del caché:",
|
||||
"Unused images removed from the cache:": "Imágenes sin uso eliminadas de la caché:",
|
||||
"Update": "Actualización",
|
||||
"Update Available": "Actualización disponible",
|
||||
"Update Ceph repository (Only if using Ceph):": "Actualice el repositorio de Ceph (solo si usa Ceph):",
|
||||
@@ -6516,7 +6521,7 @@
|
||||
"Update and upgrade all system packages": "Actualizar y actualizar todos los paquetes del sistema.",
|
||||
"Update and upgrade system": "Actualizar el sistema",
|
||||
"Update cancelled by user": "Actualización cancelada por el usuario",
|
||||
"Update completed. Data kept.": "Actualización completada. Datos guardados.",
|
||||
"Update completed. Data kept.": "Actualización completada. Datos conservados.",
|
||||
"Update completed. Press Enter to continue...": "Actualización completada. Presione Entrar para continuar...",
|
||||
"Update every container of the application": "Actualizar cada contenedor de la aplicación",
|
||||
"Update kernel to compatible version": "Actualizar el kernel a una versión compatible",
|
||||
@@ -6537,7 +6542,7 @@
|
||||
"Updates file is empty or unreadable.": "El archivo de actualizaciones está vacío o es ilegible.",
|
||||
"Updating": "Actualización",
|
||||
"Updating APT package lists...": "Actualizando listas de paquetes APT...",
|
||||
"Updating Debian Bookworm → Trixie in sources.list...": "Actualizando Debian Bookworm → Trixie en fuentes.list...",
|
||||
"Updating Debian Bookworm → Trixie in sources.list...": "Actualizando Debian Bookworm → Trixie en sources.list...",
|
||||
"Updating Figurine binary...": "Actualizando el binario de Figurine...",
|
||||
"Updating Lynis to the latest version...": "Actualizando Lynis a la última versión...",
|
||||
"Updating PVE application manager...": "Actualizando el administrador de aplicaciones PVE...",
|
||||
@@ -6574,7 +6579,7 @@
|
||||
"Use Custom backup and uncheck the conflicting path from the list": "use una copia de seguridad personalizada y desmarque la ruta conflictiva de la lista",
|
||||
"Use Default Settings?": "¿Usar configuración predeterminada?",
|
||||
"Use Download first if you want to save a copy of the current key. Continue?": "use Descargar primero si desea guardar una copia de la clave actual.¿Continuar?",
|
||||
"Use SPACE to select, ENTER to confirm": "Utilice ESPACIO para seleccionar, ENTRAR para confirmar",
|
||||
"Use SPACE to select, ENTER to confirm": "Utilice ESPACIO para seleccionar, ENTER para confirmar",
|
||||
"Use SPACE to select/deselect, ENTER to confirm": "Utilice ESPACIO para seleccionar/deseleccionar, ENTER para confirmar",
|
||||
"Use SSH or terminal access (SSH recommended)": "Utilice SSH o acceso a terminal (se recomienda SSH)",
|
||||
"Use Spacebar to select.": "use la barra espaciadora para seleccionar.",
|
||||
@@ -6631,7 +6636,7 @@
|
||||
"Using default Proxmox logo...": "Usando el logotipo predeterminado de Proxmox...",
|
||||
"Using existing encryption key:": "Usando la clave de cifrado existente:",
|
||||
"Using the image verified by the transaction": "Utilizando la imagen verificada por la transacción",
|
||||
"Using the verified image from the cache": "Utilizando la imagen verificada del cache",
|
||||
"Using the verified image from the cache": "Usando la imagen verificada de la caché",
|
||||
"Utilities": "Utilidades",
|
||||
"Utilities Installation Menu": "Menú de instalación de utilidades",
|
||||
"Utilities Menu": "Menú de utilidades",
|
||||
@@ -6822,7 +6827,7 @@
|
||||
"Web interface to manage devices running Tasmota firmware.": "Interfaz web para gestionar dispositivos que ejecutan el firmware de Tasmota.",
|
||||
"WebCord can be summarized as a pack of security and privacy hardenings, Discord features reimplementations, Electron / Chromium / Discord bugs workarounds, stylesheets, internal pages and wrapped https://discord.com page, designed to conform with ToS as much as it is possible (or hide the changes that might violate it from Discord's eyes).": "WebCord se puede resumir como un paquete de endurecimientos de seguridad y privacidad, Discord características reimplementaciones, Electron / Chromium / Discord bugs workarounds, hojas de estilo, páginas internas y envueltas https://discord.com página, diseñado para conformarse con ToS tanto como sea posible (o ocultar los cambios que podrían violarlo de los ojos de Discord).",
|
||||
"Webgrabplus is a multi-site incremental xmltv epg grabber. It collects tv-program guide data from selected tvguide sites for your favourite channels.": "Webgrabplus es un multi-sitio incremental xmltv epg grabber. Recopila datos de guía de tv-program de sitios seleccionados de tvguide para sus canales favoritos.",
|
||||
"Webservers & Proxies": "Servidores web y Proxies",
|
||||
"Webservers & Proxies": "Servidores web y proxies",
|
||||
"Website": "Sitio web",
|
||||
"Webstation is a web native emulation focused LXQt desktop based on Ubuntu.": "Webstation es una emulación nativa web centrada en el escritorio LXQt basado en Ubuntu.",
|
||||
"Webtop - Alpine, Ubuntu, Fedora, and Arch based containers containing full desktop environments in officially supported flavors accessible via any modern web browser.": "Webtop - Contenedores alpinos, Ubuntu, Fedora y Arch que contienen entornos completos de escritorio en sabores oficialmente compatibles accesibles a través de cualquier navegador web moderno.",
|
||||
@@ -6855,7 +6860,7 @@
|
||||
"WireGuard® is an extremely simple yet fast and modern VPN that utilizes state-of-the-art cryptography. It aims to be faster, simpler, leaner, and more useful than IPsec, while avoiding the massive headache. It intends to be considerably more performant than OpenVPN. WireGuard is designed as a general purpose VPN for running on embedded interfaces and super computers alike, fit for many different circumstances. Initially released for the Linux kernel, it is now cross-platform (Windows, macOS, BSD, iOS, Android) and widely deployable. It is currently under heavy development, but already it might be regarded as the most secure, easiest to use, and simplest VPN solution in the industry.": "WireGuard® es un VPN extremadamente sencillo pero rápido y moderno que utiliza la criptografía de última generación. Su objetivo es ser más rápido, más simple, más inclinado y más útil que IPsec, evitando al mismo tiempo el dolor de cabeza masivo. Tiene la intención de ser considerablemente más performante que OpenVPN. WireGuard está diseñado como una VPN de propósito general para ejecutar en interfaces incrustadas y super ordenadores por igual, encajan para muchas circunstancias diferentes. Inicialmente lanzado para el kernel de Linux, ahora es multiplataforma (Windows, macOS, BSD, iOS, Android) y ampliamente implementable. Actualmente está en desarrollo pesado, pero ya podría considerarse como la solución VPN más segura, fácil de usar y más simple de la industria.",
|
||||
"Wired NICs in backup missing on target:": "Faltan NIC cableadas en la copia de seguridad en el objetivo:",
|
||||
"Wireshark is the world’s foremost and widely-used network protocol analyzer. It lets you see what’s happening on your network at a microscopic level and is the de facto (and often de jure) standard across many commercial and non-profit enterprises, government agencies, and educational institutions. Wireshark development thrives thanks to the volunteer contributions of networking experts around the globe and is the continuation of a project started by Gerald Combs in 1998.": "Wireshark es el analizador de protocolo de red más importante y ampliamente utilizado del mundo. Le permite ver lo que está sucediendo en su red a nivel microscópico y es el estándar de facto (y a menudo de jure) en muchas empresas comerciales y sin fines de lucro, agencias gubernamentales e instituciones educativas. El desarrollo de Wireshark prospera gracias a las contribuciones voluntarias de expertos en redes en todo el mundo y es la continuación de un proyecto iniciado por Gerald Combs en 1998.",
|
||||
"With dns validation, the DNSPLUGIN variable names the provider plugin. The advanced installation asks for it; otherwise add the line lxc.environment.runtime: DNSPLUGIN=<plugin> to /etc/pve/lxc/<CTID>.conf with the container stopped.": "Con dns validation, la variable DNSPLUGIN nombra el plugin del proveedor. La instalación avanzada lo pide; de lo contrario, agregue la línea lxc.environment. tiempo de ejecución: DNSPLUGIN= obedeciópluginilo a /etc/pve/lxc/ se hizo referencia aCTID ratio.conf con el contenedor detenido.",
|
||||
"With dns validation, the DNSPLUGIN variable names the provider plugin. The advanced installation asks for it; otherwise add the line lxc.environment.runtime: DNSPLUGIN=<plugin> to /etc/pve/lxc/<CTID>.conf with the container stopped.": "Con dns validation, la variable DNSPLUGIN nombra el plugin del proveedor. La instalación avanzada lo pide; de lo contrario, añadir la línea lxc.environment.runtime: DNSPLUGIN=<plugin> a /etc/pve/lxc/<CTID>.conf con el contenedor detenido.",
|
||||
"With dns validation, write the provider credentials in /config/dns-conf/<plugin>.ini inside the container and restart it.": "Con la validación dns, escriba el proveedor credentials en /config/dns-conf/iereplugin Principe.ini dentro del contenedor y reiniciarlo.",
|
||||
"With http validation, port 80 of the router must be forwarded to port 80 of this container.": "Con validación http, el puerto 80 del router debe ser enviado al puerto 80 de este contenedor.",
|
||||
"With warnings": "Con advertencias",
|
||||
@@ -7321,7 +7326,7 @@
|
||||
"skipped (already exist)": "omitido (ya existe)",
|
||||
"smbclient command is not working properly.": "El comando smbclient no funciona correctamente.",
|
||||
"smbclient command not found after installation.": "El comando smbclient no se encuentra después de la instalación.",
|
||||
"sources.list update skipped (no change)": "Actualización de fuentes.list omitida (sin cambios)",
|
||||
"sources.list update skipped (no change)": "Actualización de sources.list omitida (sin cambios)",
|
||||
"sources.list updated to Trixie": "fuentes.lista actualizada a Trixie",
|
||||
"ssh-keygen failed. Cannot create a new SSH key.": "ssh-keygen falló. No se puede crear una nueva clave SSH.",
|
||||
"stale entry/entries for interfaces no longer present": "entrada obsoleta/entradas para interfaces que ya no están presentes",
|
||||
@@ -7341,7 +7346,7 @@
|
||||
"switch_gpu_mode.sh was not found.": "No se encontró switch_gpu_mode.sh.",
|
||||
"sysfs ROM dump failed — trying ACPI VFCT table...": "Error en el volcado de ROM de sysfs: al intentar la tabla ACPI VFCT...",
|
||||
"syslog-ng allows you to flexibly collect, parse, classify, rewrite and correlate logs from across your infrastructure and store or route them to log analysis tools.": "syslog-ng le permite recoger flexiblemente, parse, clasificar, reescribir y correlacionar los registros de toda su infraestructura y almacenar o encaminarlos a herramientas de análisis de registros.",
|
||||
"systemctl restart networking failed:": "El reinicio de red systemctl falló:",
|
||||
"systemctl restart networking failed:": "systemctl restart networking falló:",
|
||||
"systemd OnCalendar expression": "expresión systemd OnCalendar",
|
||||
"the API key was not generated on the first start": "la clave de API no se generó en el primer comienzo",
|
||||
"the container has its own address, so the port Docker published on the host is not needed": "el contenedor tiene su propia dirección, por lo que el puerto Docker publicado en el host no es necesario",
|
||||
@@ -7432,5 +7437,43 @@
|
||||
"⚠ Disk data will NOT be erased.": "⚠ Los datos del disco NO se borrarán.",
|
||||
"⚠ Disk will be unmounted and removed from /etc/fstab.": "⚠ El disco se desmontará y se eliminará de /etc/fstab.",
|
||||
"⚠ The /etc/fstab entry will be removed.": "⚠ Se eliminará la entrada /etc/fstab.",
|
||||
"⚠ The disk will be unmounted.": "⚠ El disco se desmontará."
|
||||
"⚠ The disk will be unmounted.": "⚠ El disco se desmontará.",
|
||||
"Review external OCI changes": "Revisar cambios externos de OCI",
|
||||
"These Proxmox resources were added outside ProxMenux:": "Se añadieron estos recursos en Proxmox fuera de ProxMenux:",
|
||||
"They will be added to oci-compose before continuing. Unsupported or changed resources are not imported.": "Se añadirán al oci-compose antes de continuar. No se importarán recursos incompatibles o modificados.",
|
||||
"Include these resources in oci-compose?": "¿Incorporar estos recursos al oci-compose?",
|
||||
"Only an installed standalone OCI instance can adopt external changes": "Solo una instancia OCI independiente e instalada puede incorporar cambios externos",
|
||||
"The container identity changed; nothing was adopted": "Ha cambiado la identidad del contenedor; no se ha incorporado nada",
|
||||
"These manual changes cannot be adopted safely:": "Estos cambios manuales no se pueden incorporar con seguridad:",
|
||||
"The added disk needs a whole-GiB size recorded by Proxmox": "El disco añadido necesita un tamaño en GiB enteros registrado por Proxmox",
|
||||
"The added disk size is not a whole GiB": "El tamaño del disco añadido no equivale a un GiB entero",
|
||||
"Incomplete mount configuration": "Configuración incompleta del punto de montaje",
|
||||
"Unsupported mount options": "Opciones de montaje no admitidas",
|
||||
"Invalid read-only option": "Opción de solo lectura no válida",
|
||||
"Host directories cannot be included in vzdump": "Los directorios del host no pueden incluirse en vzdump",
|
||||
"Only backed-up Proxmox volumes can be adopted": "Solo se pueden incorporar volúmenes de Proxmox incluidos en las copias de seguridad",
|
||||
"Invalid Proxmox volume ID": "Identificador de volumen de Proxmox no válido",
|
||||
"The disk does not belong to this CT; automatic adoption is unsafe": "El disco no pertenece a este CT; incorporarlo automáticamente no es seguro",
|
||||
"Incomplete device configuration": "Configuración incompleta del dispositivo",
|
||||
"Unsupported device options": "Opciones de dispositivo no admitidas",
|
||||
"Only Intel/AMD DRM, Coral and USB nodes can be adopted automatically": "Solo se pueden incorporar automáticamente dispositivos DRM Intel/AMD, Coral y USB",
|
||||
"Device GID does not match the host": "El GID del dispositivo no coincide con el del host",
|
||||
"Invalid device permissions": "Permisos del dispositivo no válidos",
|
||||
"Invalid device UID": "UID del dispositivo no válido",
|
||||
"The OCI contract changed while reviewing; nothing was adopted": "El contrato OCI cambió durante la revisión; no se ha incorporado nada",
|
||||
"The LXC changed while reviewing; nothing was adopted": "El LXC cambió durante la revisión; no se ha incorporado nada",
|
||||
"The proposed changes no longer match; nothing was adopted": "Los cambios propuestos ya no coinciden; no se ha incorporado nada",
|
||||
"The LXC changed during verification; nothing was adopted": "El LXC cambió durante la verificación; no se ha incorporado nada",
|
||||
"A multi-container application is not recreated: its containers are updated together.": "Una aplicación multicontenedor no se recrea: sus contenedores se actualizan juntos.",
|
||||
"A scheduled run cannot answer:": "Una ejecución programada no puede responder:",
|
||||
"Only the update of the image runs unattended.": "Solo la actualización de la imagen se ejecuta de forma desatendida.",
|
||||
"This container is not a registered OCI instance.": "Este contenedor no es una instancia OCI registrada.",
|
||||
"The new image is more recent than the minimum age set for scheduled updates; it is not installed yet.": "La imagen nueva es más reciente que la antigüedad mínima fijada para las actualizaciones programadas; todavía no se instala.",
|
||||
"Invalid storage name": "Nombre de almacenamiento no válido",
|
||||
"Backup kept in": "Backup conservado en",
|
||||
"Creating a backup in": "Creando un backup en",
|
||||
"Backup created in": "Backup creado en",
|
||||
"The backup storage does not exist:": "El almacenamiento de backups no existe:",
|
||||
"The storage does not accept backups:": "El almacenamiento no admite backups:",
|
||||
"Invalid action": "Acción no válida"
|
||||
}
|
||||
|
||||
+29
-30
@@ -120,11 +120,11 @@
|
||||
"ACL Status:": "Statut de la liste de contrôle d'accès :",
|
||||
"ACL permissions applied for local access for user:": "Autorisations ACL appliquées pour l'accès local pour l'utilisateur :",
|
||||
"ADVANCED SETTINGS COMPLETE": "PARAMÈTRES AVANCÉS TERMINÉS",
|
||||
"AI / Coding & Dev-Tools": "AI / Codage & Outils Dev",
|
||||
"AI / Coding & Dev-Tools": "IA, programmation et développement",
|
||||
"ALL DATA ON": "TOUTES LES DONNÉES SUR",
|
||||
"ALL DATA ON THIS DISK WILL BE PERMANENTLY LOST!": "TOUTES LES DONNÉES SUR CE DISQUE SERONT PERMANENTES DÉFINITIVEMENT !",
|
||||
"ALL Utilities": "TOUS les utilitaires",
|
||||
"ALLOWED_HOSTS cannot contain line breaks": "ALLOWED HOSTS ne peut pas contenir les ruptures de ligne",
|
||||
"ALLOWED_HOSTS cannot contain line breaks": "ALLOWED_HOSTS ne peut pas contenir les ruptures de ligne",
|
||||
"AList initial login": "Connexion initiale AList",
|
||||
"AMD CPU detected": "Processeur AMD détecté",
|
||||
"AMD CPU fixes applied successfully": "Correctifs du processeur AMD appliqués avec succès",
|
||||
@@ -185,7 +185,7 @@
|
||||
"Actual device path on the host": "Chemin réel du périphérique sur l'hôte",
|
||||
"Adaptation file too large": "Dossier d'adaptation trop grand",
|
||||
"Adaptation file with unexpected permissions or owner": "Fichier d'adaptation avec permissions inattendues ou propriétaire",
|
||||
"Adblock & DNS": "Adblock & DNS",
|
||||
"Adblock & DNS": "Adblock et DNS",
|
||||
"Add Audio Passthrough": "Ajouter un relais audio",
|
||||
"Add CIFS storage:": "Ajoutez un stockage CIFS :",
|
||||
"Add Controller or NVMe (PCI passthrough)": "Ajouter un contrôleur ou NVMe (passthrough PCI)",
|
||||
@@ -463,7 +463,7 @@
|
||||
"Automatic private network allocation requires a /24 subnet": "Allocation de réseau privé automatique requires un sous-réseau /24",
|
||||
"Automatic video library manager for TV Shows": "Gestionnaire automatique de bibliothèque vidéo pour TV Shows",
|
||||
"Automatic/Unattended": "Automatique/sans surveillance",
|
||||
"Automation & Scheduling": "Automatisation et calendrier",
|
||||
"Automation & Scheduling": "Automatisation et planification",
|
||||
"Available": "Disponible",
|
||||
"Available Borg archives (newest first):": "Archives Borg disponibles (les plus récentes en premier) :",
|
||||
"Available Borg targets:": "Cibles Borg disponibles :",
|
||||
@@ -500,7 +500,7 @@
|
||||
"Backend:": "Back-end :",
|
||||
"Background archive extraction for Arr download queues. No web interface.": "Extraction des archives de fond pour les files de téléchargement Arr. Pas d'interface web.",
|
||||
"Backup — VM and CT backups": "Sauvegarde – Sauvegardes VM et CT",
|
||||
"Backup & Recovery": "Sauvegarde et récupération",
|
||||
"Backup & Recovery": "Sauvegarde et restauration",
|
||||
"Backup Created": "Sauvegarde créée",
|
||||
"Backup ID (group name in PBS):": "ID de sauvegarde (nom du groupe dans PBS) :",
|
||||
"Backup ID for this job:": "ID de sauvegarde pour ce travail :",
|
||||
@@ -603,11 +603,11 @@
|
||||
"Broken gasket-dkms package state recovered.": "L'état défectueux du paquet gasket-dkms a été réparé.",
|
||||
"Browse Your Life in Images": "Parcourez votre vie en images",
|
||||
"Browse manually (advanced)...": "Parcourir manuellement (avancé)...",
|
||||
"Browsers & Web Desktops": "Navigateurs et bureaux Web",
|
||||
"Browsers & Web Desktops": "Navigateurs et bureaux web",
|
||||
"Build and install the gasket and apex kernel modules (DKMS)": "Compiler et installer les modules noyau gasket et apex (DKMS)",
|
||||
"Build dependencies installed.": "Dépendances de build installées.",
|
||||
"Build your personal knowledge base with TriliumNext Notes": "Construisez votre base de connaissances personnelles avec TriliumNext Notes",
|
||||
"Business & ERP": "Affaires & ERP",
|
||||
"Business & ERP": "Entreprise et ERP",
|
||||
"CHANGES APPLIED SUCCESSFULLY": "MODIFICATIONS APPLIQUÉES AVEC SUCCÈS",
|
||||
"CIFS Client Tools: AVAILABLE": "Outils clients CIFS : DISPONIBLES",
|
||||
"CIFS Client Tools: NOT AVAILABLE - installing...": "Outils client CIFS : NON DISPONIBLE - installation...",
|
||||
@@ -869,7 +869,7 @@
|
||||
"Commenting legacy ceph.list (if present)...": "Commentaire de l'héritage ceph.list (si présent)...",
|
||||
"Common Issues Check": "Vérification des problèmes courants",
|
||||
"Common root for the published views": "Source commune des vues publiées",
|
||||
"Communication & Community": "Communication & Communauté",
|
||||
"Communication & Community": "Communication et communauté",
|
||||
"Community Scripts": "Scripts communautaires",
|
||||
"Community single-container Home Assistant OS image": "Image OS communautaire monoconteneur Home Assistant",
|
||||
"Compatibility check": "Vérification de compatibilité",
|
||||
@@ -1041,7 +1041,7 @@
|
||||
"Consider security implications for production environments": "Tenir compte des implications en matière de sécurité pour les environnements de production",
|
||||
"Consider visiting the repository and supporting the project.": "pensez à visiter le référentiel et à soutenir le projet.",
|
||||
"Console log:": "Registre de la console & #160;:",
|
||||
"Container": "Récipient",
|
||||
"Container": "Conteneur",
|
||||
"Container — LXC root directories": "Conteneur — Répertoires racine LXC",
|
||||
"Container ID": "ID du conteneur",
|
||||
"Container ID not defined. Make sure to select a container first.": "ID de conteneur non défini. Assurez-vous de sélectionner d'abord un conteneur.",
|
||||
@@ -1083,8 +1083,8 @@
|
||||
"Container volume (included in backups)": "Volume des conteneurs (inclus dans les sauvegardes)",
|
||||
"Container will pick up the mount on next start": "Le conteneur récupérera la monture au prochain démarrage",
|
||||
"Container with ID": "Conteneur avec ID",
|
||||
"Container:": "Récipient:",
|
||||
"Containers & Docker": "Conteneurs & Docker",
|
||||
"Container:": "Conteneur :",
|
||||
"Containers & Docker": "Conteneurs et Docker",
|
||||
"Containers returned to their previous state": "Conteneurs retournés à leur état précédent",
|
||||
"Containers that are removed:": "Conteneurs enlevés:",
|
||||
"Containers that will be created (one LXC per service, on a private network):": "Conteneurs qui seront créés (un LXC par service, sur un réseau privé):",
|
||||
@@ -1157,7 +1157,7 @@
|
||||
"Coral M.2 Apex configuration added - device ready": "Configuration Coral M.2 Apex ajoutée - appareil prêt",
|
||||
"Coral M.2 Apex configuration added - device will be available after reboot": "Configuration Coral M.2 Apex ajoutée - l'appareil sera disponible après le redémarrage",
|
||||
"Coral M.2 Apex detected, configuring...": "Coral M.2 Apex détecté, configuration...",
|
||||
"Coral PCIe/M.2 node (e.g. /dev/apex_0)": "Coral PCIe/M.2 noeud (par exemple /dev/apex 0)",
|
||||
"Coral PCIe/M.2 node (e.g. /dev/apex_0)": "Coral PCIe/M.2 noeud (par exemple /dev/apex_0)",
|
||||
"Coral TPU Installation": "Installation du TPU Coral",
|
||||
"Coral TPU Uninstall": "Désinstallation de Coral TPU",
|
||||
"Coral TPU device nodes detected with correct group (apex).": "Nœuds de périphérique Coral TPU détectés avec le groupe correct (apex).",
|
||||
@@ -1345,7 +1345,7 @@
|
||||
"Creating the container...": "Créer le conteneur...",
|
||||
"Creating the initial administrator...": "Création de l'administrateur initial...",
|
||||
"Creating the temporary data container": "Création du conteneur temporaire de données",
|
||||
"Creative & Design": "Création & Design",
|
||||
"Creative & Design": "Création et design",
|
||||
"Credentials are correct": "Les informations d'identification sont correctes",
|
||||
"Credentials cleared. jwt_secret and API tokens preserved.": "Informations d'identification effacées. Jwt_secret et jetons API préservés.",
|
||||
"Credentials file created securely.": "Fichier d’informations d’identification créé en toute sécurité.",
|
||||
@@ -2230,7 +2230,7 @@
|
||||
"FileBrowser Quantum": "FileBrowser Quantum",
|
||||
"FileBrowser Quantum (new installation)": "FileBrowser Quantum (nouvelle installation)",
|
||||
"FileDrop is a free, open source file sharing service": "FileDrop est un service gratuit de partage de fichiers open source",
|
||||
"Files & Downloads": "Fichiers & téléchargements",
|
||||
"Files & Downloads": "Fichiers et téléchargements",
|
||||
"Files volume size in GB": "Taille du volume des fichiers en GB",
|
||||
"Filesystem": "Système de fichiers",
|
||||
"Filesystem Tools Required": "Outils de système de fichiers requis",
|
||||
@@ -2239,7 +2239,7 @@
|
||||
"Final cleanup of the stack operation completed": "Nettoyage final de la pile operation terminée",
|
||||
"Final confirmation": "Confirmation finale",
|
||||
"Final storage health/status check": "Vérification finale de l’état/de l’état du stockage",
|
||||
"Finance & Budgeting": "Finances & Budgeting",
|
||||
"Finance & Budgeting": "Finances et budget",
|
||||
"Find your device using https://finds.synology.com": "Trouvez votre appareil en utilisant https://finds.synology.com",
|
||||
"Fingerprint:": "Empreinte digitale :",
|
||||
"Firefly, the easiest using of WireGuard VPN server, plus version of wg-easy.": "Firefly, la plus simple utilisation du serveur VPN WireGuard, plus la version de wg-easy.",
|
||||
@@ -2387,7 +2387,7 @@
|
||||
"GRUB_CMDLINE_LINUX_DEFAULT not found in GRUB config": "GRUB_CMDLINE_LINUX_DEFAULT introuvable dans la configuration GRUB",
|
||||
"GUI mode (if available)": "Mode GUI (si disponible)",
|
||||
"GZDoom is a feature centric port for all Doom engine games, based on ZDoom, adding an OpenGL renderer and powerful scripting capabilities.": "GZDoom est un port centré pour tous les jeux de moteurs Doom, basé sur ZDoom, ajoutant un rendu OpenGL et de puissantes capacités de script.",
|
||||
"Gaming & Leisure": "Jeu & Leisure",
|
||||
"Gaming & Leisure": "Jeux et loisirs",
|
||||
"Gateway is not installed.": "La passerelle n'est pas installée.",
|
||||
"Gateway removed.": "Passerelle supprimée.",
|
||||
"Gateway restarted.": "La passerelle a redémarré.",
|
||||
@@ -2541,7 +2541,7 @@
|
||||
"Host already in VFIO mode — skipping host reconfiguration for VM reassignment": "Hôte déjà en mode VFIO : ignorer la reconfiguration de l'hôte pour la réaffectation de la VM",
|
||||
"Host audio devices": "Appareils audio d'accueil",
|
||||
"Host backup attached to PVE job": "Sauvegarde de l'hôte attachée au travail PVE",
|
||||
"Host data is not restored by the backup; confirm it with --acknowledge-external-data": "Les données de l'hôte ne sont pas restaurées par la sauvegarde; confirmez-le avec --acknow-external-data",
|
||||
"Host data is not restored by the backup; confirm it with --acknowledge-external-data": "Les données de l'hôte ne sont pas restaurées par la sauvegarde; confirmez-le avec --acknowledge-external-data",
|
||||
"Host device for /dev/kvm": "Appareil d'accueil pour /dev/kvm",
|
||||
"Host device for /dev/net/tun": "Appareil hôte pour /dev/net/tun",
|
||||
"Host device for /dev/ttyUSB0": "Appareil hôte pour /dev/ttyUSB0",
|
||||
@@ -2795,7 +2795,7 @@
|
||||
"Initiator IQN is authorised on the target": "L'IQN initiateur est autorisé sur la cible",
|
||||
"Initiator IQN:": "IQN initiateur :",
|
||||
"Inkscape is professional quality vector graphics software which runs on Linux, Mac OS X and Windows desktop computers.": "Inkscape est un logiciel graphique vectoriel de qualité professionnelle qui fonctionne sur les ordinateurs de bureau Linux, Mac OS X et Windows.",
|
||||
"Inside the LXC, create the administrator: console kimai:user:create YOUR_USERNAME YOUR_EMAIL ROLE_SUPER_ADMIN": "À l'intérieur du LXC, créez l'administrateur: console kimai:utilisateur:créez VOTRE USERNAME VOTRE ROLE SUPER ADMIN",
|
||||
"Inside the LXC, create the administrator: console kimai:user:create YOUR_USERNAME YOUR_EMAIL ROLE_SUPER_ADMIN": "À l'intérieur du LXC, créez l'administrateur: console kimai:utilisateur:créez VOTRE USERNAME VOTRE ROLE_SUPER_ADMIN",
|
||||
"Inspect disks before any action": "Inspecter les disques avant toute action",
|
||||
"Inspect host device nodes": "Inspecter les nœuds du périphérique hôte",
|
||||
"Inspect passthrough/kernel events": "Inspecter les événements de relais/noyau",
|
||||
@@ -3087,7 +3087,7 @@
|
||||
"Invalid volume size": "Volume non valide",
|
||||
"Invalid volume size:": "Volume non valide:",
|
||||
"Invalid volume target": "Cible de volume non valable",
|
||||
"IoT & Smart Home": "IoT et maison intelligente",
|
||||
"IoT & Smart Home": "IoT et maison connectée",
|
||||
"Is the value a password or secret?": "La valeur est-elle un mot de passe ou un secret ?",
|
||||
"Issue": "Problème",
|
||||
"Issues found": "Problèmes trouvés",
|
||||
@@ -3386,7 +3386,7 @@
|
||||
"Max user watches configured": "Nombre maximum de montres utilisateur configurées",
|
||||
"Maximum auto-repair attempts reached (3). Please review the log and run any remaining commands manually.": "Nombre maximal de tentatives de réparation automatique atteint (3). Veuillez consulter le journal et exécuter manuellement les commandes restantes.",
|
||||
"May need to restart terminal": "Il faudra peut-être redémarrer le terminal",
|
||||
"Media & Streaming": "Médias & Streaming",
|
||||
"Media & Streaming": "Médias et streaming",
|
||||
"Media discovery and request management for Jellyfin, Plex and Emby.": "Découverte des médias et gestion des demandes pour Jellyfin, Plex et Emby.",
|
||||
"Media library transcoding and health checking, with an internal worker node.": "Transcodage de la médiathèque et contrôle de la santé, avec un noeud de travail interne.",
|
||||
"Media server": "Serveur multimédia",
|
||||
@@ -3652,7 +3652,7 @@
|
||||
"NVMe health status: WARNING (critical_warning =": "État de santé NVMe : AVERTISSEMENT (critical_warning =",
|
||||
"NVMe skipped (to add as PCIe use 'Add Controller or NVMe PCIe to VM'):": "NVMe ignoré (pour ajouter en tant que PCIe, utilisez « Ajouter un contrôleur ou NVMe PCIe à la VM ») :",
|
||||
"NVMe-specific SMART log": "Journal SMART spécifique à NVMe",
|
||||
"NVR & Cameras": "NVR & Caméras",
|
||||
"NVR & Cameras": "NVR et caméras",
|
||||
"NVR with optional VA-API video acceleration and hardware object detectors": "NVR avec accélération vidéo VA-API en option et détecteurs d'objets matériels",
|
||||
"NZBGet web interface": "Interface web NZBGet",
|
||||
"Name": "Dénomination",
|
||||
@@ -3664,7 +3664,7 @@
|
||||
"Name of this wallabag instance, shown in the interface and in 2FA codes": "Nom de cette instance wallabag, affichée dans l'interface et dans les codes 2FA",
|
||||
"Name or part of the description of the application": "Nom ou partie de la description de la demande",
|
||||
"Name:": "Nom:",
|
||||
"Named accounts need private mode. Stop the container, set public: false in /config/config.js, start it again and create each user with: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>": "Les comptes nommés nécessitent un mode privé. Arrêter le conteneur, définir public: false in /config/config.js, recommencer et créer chaque utilisateur avec: pct exec <CTID> -- env THELOUNGE HOME=/config s6-setuidgid abc thelounge ajouter <user>",
|
||||
"Named accounts need private mode. Stop the container, set public: false in /config/config.js, start it again and create each user with: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>": "Les comptes nommés nécessitent un mode privé. Arrêter le conteneur, définir public: false in /config/config.js, recommencer et créer chaque utilisateur avec: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge ajouter <user>",
|
||||
"Neither /etc/kernel/cmdline nor /etc/default/grub found.": "Ni /etc/kernel/cmdline ni /etc/default/grub n'ont été trouvés.",
|
||||
"Nesting feature enabled": "Fonction d'imbrication activée",
|
||||
"NetBIOS Service: RUNNING": "Service NetBIOS : EN EXÉCUTION",
|
||||
@@ -3674,7 +3674,7 @@
|
||||
"Netbox is an IP address management (IPAM) and data center infrastructure management (DCIM) tool. Initially conceived by the network engineering team at DigitalOcean, NetBox was developed specifically to address the needs of network and infrastructure engineers. It is intended to function as a domain-specific source of truth for network operations.": "Netbox est un outil de gestion des adresses IP (IPAM) et de gestion de l'infrastructure des centres de données (DCIM). Initialement conçu par l'équipe d'ingénierie du réseau de DigitalOcean, NetBox a été développé spécifiquement pour répondre aux besoins des ingénieurs du réseau et de l'infrastructure. Il est destiné à fonctionner comme une source de vérité spécifique au domaine pour le réseau operations.",
|
||||
"Network": "Réseau",
|
||||
"Network :": "Réseau :",
|
||||
"Network & Firewall": "Réseau & Pare-feu",
|
||||
"Network & Firewall": "Réseau et pare-feu",
|
||||
"Network (interfaces, DNS)": "Réseau (interfaces, DNS)",
|
||||
"Network Bridge": "Pont réseau",
|
||||
"Network Commands": "Commandes réseau",
|
||||
@@ -4377,7 +4377,7 @@
|
||||
"Postfix configuration": "Configuration de Postfix",
|
||||
"PostgreSQL": "PostgreSQL",
|
||||
"PostgreSQL URL without an associated service:": "URL PostgreSQL sans service associé:",
|
||||
"PostgreSQL creates the database named in POSTGRES_DB on the first start. The installer default is postgresql.": "PostgreSQL crée la base de données nommée dans POSTGRES DB au premier démarrage. Par défaut, l'installation est postgresql.",
|
||||
"PostgreSQL creates the database named in POSTGRES_DB on the first start. The installer default is postgresql.": "PostgreSQL crée la base de données nommée dans POSTGRES_DB au premier démarrage. Par défaut, l'installation est postgresql.",
|
||||
"PostgreSQL is an advanced, enterprise-class, and open-source relational database system. PostgreSQL supports both SQL (relational) and JSON (non-relational) querying.": "PostgreSQL est un système de base de données relationnelles avancé, de classe entreprise et open-source. PostgreSQL prend en charge les requêtes SQL (relational) et JSON (non-relational).",
|
||||
"PostgreSQL requires a password": "PostgreSQL requires un mot de passe",
|
||||
"PostgreSQL volume size in GB": "Taille du volume PostgreSQL en GB",
|
||||
@@ -4541,7 +4541,7 @@
|
||||
"Pwndrop is a self-deployable file hosting service for sending out red teaming payloads or securely sharing your private files over HTTP and WebDAV.": "Pwndrop est un service d'hébergement de fichiers autodéployable pour envoyer des équipes rouges ou partager vos fichiers privés en toute sécurité via HTTP et WebDAV.",
|
||||
"PyCharm offers out-of-the-box support for Python, databases, Jupyter, Git, Conda, PyTorch, TensorFlow, Hugging Face, Django, Flask, FastAPI, and more.": "PyCharm offre une prise en charge hors de la boîte pour Python, bases de données, Jupyter, Git, Conde, PyTorch, TensorFlow, Hugging Face, Django, Flask, FastAPI, et plus encore.",
|
||||
"Pydio Cells needs an external MySQL or MariaDB database. The setup wizard asks for its address, database name and user on the first start.": "Pydio Cells a besoin d'une base de données externe MySQL ou MariaDB. L'assistant de configuration demande son adresse, son nom de base de données et son utilisateur au premier démarrage.",
|
||||
"Pydio Cells redirects to the address given in EXTERNALURL. If the container changes address, edit lxc.environment.runtime: EXTERNALURL and SERVER_IP in /etc/pve/lxc/<CTID>.conf with the container stopped, and delete /config/keys/cert.crt to regenerate the certificate.": "Pydio Cells redirige vers l'adresse indiquée dans EXTERNALURL. Si le conteneur change d'adresse, éditer lxc.environment.runtime: EXTERNALURL et SERVER IP dans /etc/pve/lxc/<CTID>.conf avec le conteneur arrêté, et supprimer /config/keys/cert.crt pour régénérer le certificat.",
|
||||
"Pydio Cells redirects to the address given in EXTERNALURL. If the container changes address, edit lxc.environment.runtime: EXTERNALURL and SERVER_IP in /etc/pve/lxc/<CTID>.conf with the container stopped, and delete /config/keys/cert.crt to regenerate the certificate.": "Pydio Cells redirige vers l'adresse indiquée dans EXTERNALURL. Si le conteneur change d'adresse, éditer lxc.environment.runtime: EXTERNALURL et SERVER_IP dans /etc/pve/lxc/<CTID>.conf avec le conteneur arrêté, et supprimer /config/keys/cert.crt pour régénérer le certificat.",
|
||||
"Pydio-cells is the nextgen file sharing platform for organizations. It is a full rewrite of the Pydio project using the Go language following a micro-service architecture.": "Pydio-cells est la plateforme de partage de fichiers nextgen pour les organisations. C'est une réécriture complète du projet Pydio en utilisant le langage Go suivant une architecture de micro-service.",
|
||||
"QDirStat Qt-based directory statistics: KDirStat without any KDE -- from the author of the original KDirStat.": "QDirStat Statistiques de répertoire basées sur Qt: KDirStat sans KDE -- de l'auteur de l'original KDirStat.",
|
||||
"Quick health check (PASSED / FAILED)": "Bilan de santé rapide (RÉUSSI / ÉCHEC)",
|
||||
@@ -5719,7 +5719,6 @@
|
||||
"Thank you for using ProxMenux. Goodbye!": "Merci d'utiliser ProxMenux. Au revoir!",
|
||||
"That VM is currently stopped, so the GPU can be reassigned now.": "Cette VM est actuellement arrêtée, le GPU peut donc être réaffecté maintenant.",
|
||||
"That doesn't look like an SSH private key. Pick the private key file (no .pub extension, parseable by ssh-keygen).": "Cela ne ressemble pas à une clé privée SSH.Choisissez le fichier de clé privée (pas d'extension .pub, analysable par ssh-keygen).",
|
||||
"The .conf files under /config/fail2ban are rewritten on every start. Keep customizations in the matching .local file, for example jail.local for jail.conf.": "Les fichiers .conf sous /config/fail2ban sont réécrits à chaque démarrage. Gardez les personnalisations dans le fichier .local correspondant, par exemple prison.local pour prison.conf.",
|
||||
"The AppArmor/seccomp relaxation does not include the required consent": "L'AppArmor/seccomp relaxation ne comprend pas le consentement required",
|
||||
"The Bookmark Everything App": "L'application Tout Signet",
|
||||
"The Brave browser is a fast, private and secure web browser for PC, Mac and mobile.": "Le navigateur Brave est un navigateur Web rapide, privé et sécurisé pour PC, Mac et mobile.",
|
||||
@@ -5955,7 +5954,7 @@
|
||||
"The imported Compose requests privileged, but the official jlesage/handbrake documentation does not require it; ProxMenux keeps the LXC unprivileged.": "Le Compose importé demande privilégié, mais la documentation officielle de jlesage/handbrake ne require; ProxMenux maintient le LXC non privilégié.",
|
||||
"The imported OCI groups are not numeric": "Les groupes OCI importés ne sont pas numériques",
|
||||
"The imported OCI user or group is not numeric": "L'utilisateur ou le groupe de OCI importé n'est pas numérique",
|
||||
"The initial user name and password stay written in /etc/pve/lxc/<CTID>.conf as INIT_USERNAME and INIT_PASSWORD. They can be removed after the first login, with the container stopped.": "Le nom d'utilisateur initial et le mot de passe restent écrits dans /etc/pve/lxc/<CTID>.conf comme INIT USERNAME et INIT PASSWORD. Ils peuvent être enlevés après la première connexion, le conteneur étant arrêté.",
|
||||
"The initial user name and password stay written in /etc/pve/lxc/<CTID>.conf as INIT_USERNAME and INIT_PASSWORD. They can be removed after the first login, with the container stopped.": "Le nom d'utilisateur initial et le mot de passe restent écrits dans /etc/pve/lxc/<CTID>.conf comme INIT_USERNAME et INIT_PASSWORD. Ils peuvent être enlevés après la première connexion, le conteneur étant arrêté.",
|
||||
"The installation asks which one to use for these paths.": "L'installation demande lequel utiliser pour ces chemins.",
|
||||
"The installation ended with exit code": "L'installation s'est terminée avec le code de sortie",
|
||||
"The installation requires a server restart to apply changes. Do you want to restart now?": "L'installation nécessite un redémarrage du serveur pour appliquer les modifications. Voulez-vous redémarrer maintenant ?",
|
||||
@@ -6074,7 +6073,7 @@
|
||||
"The rootfs is not managed by Proxmox": "Les roofs ne sont pas gérés par Proxmox",
|
||||
"The rootfs is not mounted": "Les roofs ne sont pas montés",
|
||||
"The same GPU cannot be used by two VMs at the same time.": "Le même GPU ne peut pas être utilisé par deux VM en même temps.",
|
||||
"The same connection can be given as container variables instead of the file: UN_SONARR_0_URL and UN_SONARR_0_API_KEY, or the UN_RADARR_0_ equivalents.": "La même connexion peut être donnée comme variable de conteneur au lieu du fichier : UN SONARR 0 URL et UN SONARR 0 API KEY, ou les UN RADARR 0 equivalents.",
|
||||
"The same connection can be given as container variables instead of the file: UN_SONARR_0_URL and UN_SONARR_0_API_KEY, or the UN_RADARR_0_ equivalents.": "La même connexion peut être donnée comme variable de conteneur au lieu du fichier : UN_SONARR_0_URL et UN_SONARR_0_API_KEY, ou les UN RADARR 0 equivalents.",
|
||||
"The saved MOTD state is invalid; no changes were made": "l'état MOTD enregistré n'est pas valide ;aucun changement n'a été apporté",
|
||||
"The saved OCI record is incomplete or has an unexpected format.": "L'enregistrement OCI enregistré est incomplet ou a un format inattendu.",
|
||||
"The saved projection does not match the native evidence": "La projection enregistrée ne correspond pas à la preuve native",
|
||||
@@ -6822,7 +6821,7 @@
|
||||
"Web interface to manage devices running Tasmota firmware.": "Interface Web pour gérer les appareils utilisant le firmware Tasmota.",
|
||||
"WebCord can be summarized as a pack of security and privacy hardenings, Discord features reimplementations, Electron / Chromium / Discord bugs workarounds, stylesheets, internal pages and wrapped https://discord.com page, designed to conform with ToS as much as it is possible (or hide the changes that might violate it from Discord's eyes).": "WebCord peut être résumé comme un paquet de durcissements de sécurité et de confidentialité, les fonctionnalités Discord réimplémentations, Electron / Chromium / Discord bugs workarounds, les feuilles de style, les pages internes et la page https://discord.com enveloppée, conçue pour se conformer à ToS autant qu'il est possible (ou cacher les changements qui pourraient la violer des yeux de Discord).",
|
||||
"Webgrabplus is a multi-site incremental xmltv epg grabber. It collects tv-program guide data from selected tvguide sites for your favourite channels.": "Webgrabplus est un accrocheur différentiel multisite xmltv egg. Il recueille les données du guide TV-programme à partir de sites sélectionnés pour vos chaînes préférées.",
|
||||
"Webservers & Proxies": "Serveurs Web & Proxies",
|
||||
"Webservers & Proxies": "Serveurs web et proxys",
|
||||
"Website": "Site web",
|
||||
"Webstation is a web native emulation focused LXQt desktop based on Ubuntu.": "Webstation est un ordinateur de bureau LXQt basé sur Ubuntu.",
|
||||
"Webtop - Alpine, Ubuntu, Fedora, and Arch based containers containing full desktop environments in officially supported flavors accessible via any modern web browser.": "Webtop - conteneurs basés sur Alpine, Ubuntu, Fedora et Arch contenant des environnements de bureau complets dans des saveurs officiellement pris en charge accessibles via n'importe quel navigateur Web moderne.",
|
||||
@@ -6855,7 +6854,7 @@
|
||||
"WireGuard® is an extremely simple yet fast and modern VPN that utilizes state-of-the-art cryptography. It aims to be faster, simpler, leaner, and more useful than IPsec, while avoiding the massive headache. It intends to be considerably more performant than OpenVPN. WireGuard is designed as a general purpose VPN for running on embedded interfaces and super computers alike, fit for many different circumstances. Initially released for the Linux kernel, it is now cross-platform (Windows, macOS, BSD, iOS, Android) and widely deployable. It is currently under heavy development, but already it might be regarded as the most secure, easiest to use, and simplest VPN solution in the industry.": "WireGuard® est un VPN extrêmement simple mais moderne qui utilise une cryptographie ultramoderne. Il vise à être plus rapide, plus simple, plus maigre et plus utile que IPsec, tout en évitant les maux de tête massifs. Il a l'intention d'être beaucoup plus performant que OpenVPN. WireGuard est conçu comme un VPN à usage général pour fonctionner sur des interfaces intégrées et des super ordinateurs, adaptés à de nombreuses circonstances différentes. Initialement sorti pour le noyau Linux, il est désormais multiplateforme (Windows, macOS, BSD, iOS, Android) et largement déployable. Il est actuellement en développement, mais il pourrait déjà être considéré comme la solution VPN la plus sûre, la plus facile à utiliser et la plus simple de l'industrie.",
|
||||
"Wired NICs in backup missing on target:": "Cartes réseau filaires dans la sauvegarde manquantes sur la cible :",
|
||||
"Wireshark is the world’s foremost and widely-used network protocol analyzer. It lets you see what’s happening on your network at a microscopic level and is the de facto (and often de jure) standard across many commercial and non-profit enterprises, government agencies, and educational institutions. Wireshark development thrives thanks to the volunteer contributions of networking experts around the globe and is the continuation of a project started by Gerald Combs in 1998.": "Wireshark est l'analyseur de protocole réseau le plus utilisé au monde. Il vous permet de voir ce qui se passe sur votre réseau au niveau microscopique et est la norme de facto (et souvent de jure) dans de nombreuses entreprises commerciales et sans but lucratif, agences gouvernementales et établissements d'enseignement. Le développement de Wireshark prospère grâce aux contributions volontaires d'experts en réseautage dans le monde entier et est la suite d'un projet lancé par Gerald Combs en 1998.",
|
||||
"With dns validation, the DNSPLUGIN variable names the provider plugin. The advanced installation asks for it; otherwise add the line lxc.environment.runtime: DNSPLUGIN=<plugin> to /etc/pve/lxc/<CTID>.conf with the container stopped.": "Avec la validation dns, la variable DNSPLUGIN nomme le plugin fournisseur. L'installation avancée le demande; sinon ajouter la ligne lxc.environment. durée d'exécution: DNSPLUGIN=<plugin> à /etc/pve/lxc/<CTID>.conf avec le conteneur arrêté.",
|
||||
"With dns validation, the DNSPLUGIN variable names the provider plugin. The advanced installation asks for it; otherwise add the line lxc.environment.runtime: DNSPLUGIN=<plugin> to /etc/pve/lxc/<CTID>.conf with the container stopped.": "Avec la validation dns, la variable DNSPLUGIN nomme le plugin fournisseur. L'installation avancée le demande; sinon, ajoutez la ligne lxc.environment.runtime: DNSPLUGIN=<plugin> à /etc/pve/lxc/<CTID>.conf avec le conteneur arrêté.",
|
||||
"With dns validation, write the provider credentials in /config/dns-conf/<plugin>.ini inside the container and restart it.": "Avec la validation dns, écrivez le fournisseur credentials dans /config/dns-conf/<plugin>.ini à l'intérieur du conteneur et redémarrez-le.",
|
||||
"With http validation, port 80 of the router must be forwarded to port 80 of this container.": "Avec la validation http, le port 80 du routeur doit être envoyé au port 80 de ce conteneur.",
|
||||
"With warnings": "Avec des avertissements",
|
||||
|
||||
+28
-28
@@ -120,11 +120,11 @@
|
||||
"ACL Status:": "Stato ACL:",
|
||||
"ACL permissions applied for local access for user:": "ACL permissions applied for local access for user:",
|
||||
"ADVANCED SETTINGS COMPLETE": "IMPOSTAZIONI AVANZATE COMPLETATE",
|
||||
"AI / Coding & Dev-Tools": "AI/codifica e strumenti di sviluppo",
|
||||
"AI / Coding & Dev-Tools": "IA, programmazione e sviluppo",
|
||||
"ALL DATA ON": "TUTTI I DATI SU",
|
||||
"ALL DATA ON THIS DISK WILL BE PERMANENTLY LOST!": "TUTTI I DATI SU QUESTO DISCO SARANNO PERDUTI PERMANENTEMENTE!",
|
||||
"ALL Utilities": "TUTTE le utenze",
|
||||
"ALLOWED_HOSTS cannot contain line breaks": "ALLOWED HOSTS non può contenere interruzioni di linea",
|
||||
"ALLOWED_HOSTS cannot contain line breaks": "ALLOWED_HOSTS non può contenere interruzioni di linea",
|
||||
"AList initial login": "login iniziale AList",
|
||||
"AMD CPU detected": "Rilevata CPU AMD",
|
||||
"AMD CPU fixes applied successfully": "Le correzioni della CPU AMD sono state applicate correttamente",
|
||||
@@ -185,7 +185,7 @@
|
||||
"Actual device path on the host": "Percorso effettivo del dispositivo sull'host",
|
||||
"Adaptation file too large": "File di adattamento troppo grande",
|
||||
"Adaptation file with unexpected permissions or owner": "File di adattamento con autorizzazioni inaspettate o proprietario",
|
||||
"Adblock & DNS": "Adblock & DNS",
|
||||
"Adblock & DNS": "Adblock e DNS",
|
||||
"Add Audio Passthrough": "Aggiungi pass-through audio",
|
||||
"Add CIFS storage:": "Aggiungi spazio di archiviazione CIFS:",
|
||||
"Add Controller or NVMe (PCI passthrough)": "Aggiungi controller o NVMe (passthrough PCI)",
|
||||
@@ -463,7 +463,7 @@
|
||||
"Automatic private network allocation requires a /24 subnet": "Distribuzione automatica della rete privata requires a /24 subnet",
|
||||
"Automatic video library manager for TV Shows": "Gestore automatico della libreria video per spettacoli televisivi",
|
||||
"Automatic/Unattended": "Automatico/non presidiato",
|
||||
"Automation & Scheduling": "Automazione & Scheduling",
|
||||
"Automation & Scheduling": "Automazione e pianificazione",
|
||||
"Available": "Disponibile",
|
||||
"Available Borg archives (newest first):": "Archivi Borg disponibili (prima il più recente):",
|
||||
"Available Borg targets:": "Obiettivi Borg disponibili:",
|
||||
@@ -500,7 +500,7 @@
|
||||
"Backend:": "Backend:",
|
||||
"Background archive extraction for Arr download queues. No web interface.": "Estrazione archivio di sfondo per Arr file di download. Nessuna interfaccia web.",
|
||||
"Backup — VM and CT backups": "Backup: backup di VM e CT",
|
||||
"Backup & Recovery": "Backup & Recupero",
|
||||
"Backup & Recovery": "Backup e ripristino",
|
||||
"Backup Created": "Backup creato",
|
||||
"Backup ID (group name in PBS):": "ID backup (nome del gruppo in PBS):",
|
||||
"Backup ID for this job:": "ID di backup per questo lavoro:",
|
||||
@@ -603,11 +603,11 @@
|
||||
"Broken gasket-dkms package state recovered.": "Lo stato danneggiato del pacchetto gasket-dkms è stato ripristinato.",
|
||||
"Browse Your Life in Images": "Sfoglia la tua vita in immagini",
|
||||
"Browse manually (advanced)...": "Sfoglia manualmente (avanzato)...",
|
||||
"Browsers & Web Desktops": "Browser & Web Desktops",
|
||||
"Browsers & Web Desktops": "Browser e desktop web",
|
||||
"Build and install the gasket and apex kernel modules (DKMS)": "Compila e installa i moduli kernel gasket e apex (DKMS)",
|
||||
"Build dependencies installed.": "Costruisci dipendenze installate.",
|
||||
"Build your personal knowledge base with TriliumNext Notes": "Costruire la vostra base di conoscenza personale con TriliumNext Notes",
|
||||
"Business & ERP": "Affari & ERP",
|
||||
"Business & ERP": "Business e ERP",
|
||||
"CHANGES APPLIED SUCCESSFULLY": "MODIFICHE APPLICATE CON SUCCESSO",
|
||||
"CIFS Client Tools: AVAILABLE": "Strumenti client CIFS: DISPONIBILE",
|
||||
"CIFS Client Tools: NOT AVAILABLE - installing...": "Strumenti client CIFS: NON DISPONIBILE - installazione in corso...",
|
||||
@@ -869,7 +869,7 @@
|
||||
"Commenting legacy ceph.list (if present)...": "Commento legacy ceph.list (se presente)...",
|
||||
"Common Issues Check": "Controllo dei problemi comuni",
|
||||
"Common root for the published views": "Radice comune per le opinioni pubblicate",
|
||||
"Communication & Community": "Comunicazione e Comunità",
|
||||
"Communication & Community": "Comunicazione e comunità",
|
||||
"Community Scripts": "Script di comunità",
|
||||
"Community single-container Home Assistant OS image": "Immagine del sistema operativo Home Assistant",
|
||||
"Compatibility check": "Controllo di compatibilità",
|
||||
@@ -1084,7 +1084,7 @@
|
||||
"Container will pick up the mount on next start": "Il contenitore raccoglierà la montatura al prossimo avvio",
|
||||
"Container with ID": "Contenitore con ID",
|
||||
"Container:": "Contenitore:",
|
||||
"Containers & Docker": "Contenitori & Docker",
|
||||
"Containers & Docker": "Container e Docker",
|
||||
"Containers returned to their previous state": "Contenitori tornati al loro stato precedente",
|
||||
"Containers that are removed:": "Contenitori che vengono rimossi:",
|
||||
"Containers that will be created (one LXC per service, on a private network):": "Contenitori che verranno creati (un LXC per servizio, su una rete privata):",
|
||||
@@ -1157,7 +1157,7 @@
|
||||
"Coral M.2 Apex configuration added - device ready": "Aggiunta configurazione Coral M.2 Apex: dispositivo pronto",
|
||||
"Coral M.2 Apex configuration added - device will be available after reboot": "Aggiunta configurazione Coral M.2 Apex: il dispositivo sarà disponibile dopo il riavvio",
|
||||
"Coral M.2 Apex detected, configuring...": "Rilevato Coral M.2 Apex, configurazione in corso...",
|
||||
"Coral PCIe/M.2 node (e.g. /dev/apex_0)": "Coral PCIe/M.2 nodo (ad esempio /dev/apex 0)",
|
||||
"Coral PCIe/M.2 node (e.g. /dev/apex_0)": "Coral PCIe/M.2 nodo (ad esempio /dev/apex_0)",
|
||||
"Coral TPU Installation": "Installazione TPU Coral",
|
||||
"Coral TPU Uninstall": "Disinstallazione di Coral TPU",
|
||||
"Coral TPU device nodes detected with correct group (apex).": "Nodi del dispositivo Coral TPU rilevati con il gruppo corretto (apice).",
|
||||
@@ -1345,7 +1345,7 @@
|
||||
"Creating the container...": "Creare il contenitore...",
|
||||
"Creating the initial administrator...": "Creazione dell'amministratore iniziale...",
|
||||
"Creating the temporary data container": "Creazione del contenitore dati temporaneo",
|
||||
"Creative & Design": "Creativo e design",
|
||||
"Creative & Design": "Creatività e design",
|
||||
"Credentials are correct": "Le credenziali sono corrette",
|
||||
"Credentials cleared. jwt_secret and API tokens preserved.": "Credenziali cancellate. jwt_secret e token API conservati.",
|
||||
"Credentials file created securely.": "File delle credenziali creato in modo sicuro.",
|
||||
@@ -1455,7 +1455,7 @@
|
||||
"Data wiped from": "Dati cancellati da",
|
||||
"Database management in a single PHP file": "Gestione database in un unico file PHP",
|
||||
"Database server proposed on the login page (empty = typed at each login)": "Server di database proposto nella pagina di login (vuoto = digitato ad ogni login)",
|
||||
"Databases": "Databases",
|
||||
"Databases": "Database",
|
||||
"Datastore name:": "Nome dell'archivio dati:",
|
||||
"Davos is an FTP automation tool that periodically scans given host locations for new files. It can be configured for various purposes, including listening for specific files to appear in the host location, ready for it to download and then move, if required. It also supports completion notifications as well as downstream API calls, to further the workflow.": "Davos è uno strumento di automazione FTP che scansiona periodicamente le posizioni degli host date per i nuovi file. Può essere configurato per vari scopi, tra cui l'ascolto per i file specifici da visualizzare nella posizione dell'host, pronto per il download e quindi spostare, se required. Supporta anche le notifiche di completamento e le chiamate API a valle, per continuare il flusso di lavoro.",
|
||||
"Ddclient is a Perl client used to update dynamic DNS entries for accounts on Dynamic DNS Network Service Provider. It was originally written by Paul Burry and is now mostly by wimpunk. It has the capability to update more than just dyndns and it can fetch your WAN-ipaddress in a few different ways.": "Ddclient è un client Perl utilizzato per aggiornare le voci DNS dinamiche per gli account su Dynamic DNS Network Service Provider. Originariamente è stato scritto da Paul Burry ed è ora per lo più di wimpunk. Ha la capacità di aggiornare più di soli dyndns e può prendere il vostro WAN-ipaddress in pochi modi diversi.",
|
||||
@@ -1731,7 +1731,7 @@
|
||||
"Dry run completed; the container and the mounts were not changed.": "Corsa a secco completata; il contenitore e i supporti non sono stati modificati.",
|
||||
"DuckDNS subdomain without .duckdns.org (comma separated for several)": "Sottodominio DuckDNS senza .duckdns.org (comma separato per diversi)",
|
||||
"DuckDNS token from your account at duckdns.org": "Token DuckDNS dal tuo account su duckdns.org",
|
||||
"DuckDNS updates the subdomain every 5 minutes. Without UPDATE_IP, DuckDNS itself detects the public IPv4 address of the request.": "DuckDNS aggiorna il sottodominio ogni 5 minuti. Senza UPDATE IP, DuckDNS stesso rileva l'indirizzo IPv4 pubblico della richiesta.",
|
||||
"DuckDNS updates the subdomain every 5 minutes. Without UPDATE_IP, DuckDNS itself detects the public IPv4 address of the request.": "DuckDNS aggiorna il sottodominio ogni 5 minuti. Senza UPDATE_IP, DuckDNS stesso rileva l'indirizzo IPv4 pubblico della richiesta.",
|
||||
"DuckStation is a PS1 Emulator aiming for the best accuracy and game support.": "DuckStation è un Emulatore PS1 che mira al miglior supporto accuracy e game.",
|
||||
"Duckdns is a free service which will point a DNS (sub domains of duckdns.org) to an IP of your choice. The service is completely free, and doesn't require reactivation or forum posts to maintain its existence.": "Duckdns è un servizio gratuito che indicherà un DNS (sotto domini di duckdns.org) a un IP di vostra scelta. Il servizio è completamente gratuito, e non require riattivazione o post del forum per mantenere la sua esistenza.",
|
||||
"Dumping AMD GPU ROM BIOS via sysfs...": "Dumping del BIOS ROM della GPU AMD tramite sysfs...",
|
||||
@@ -2239,7 +2239,7 @@
|
||||
"Final cleanup of the stack operation completed": "Pulizia finale della pila operation completata",
|
||||
"Final confirmation": "Conferma finale",
|
||||
"Final storage health/status check": "Controllo finale dell'integrità/stato dell'archiviazione",
|
||||
"Finance & Budgeting": "Finanza e Budgeting",
|
||||
"Finance & Budgeting": "Finanze e budget",
|
||||
"Find your device using https://finds.synology.com": "Trova il tuo dispositivo utilizzando https://finds.synology.com",
|
||||
"Fingerprint:": "Impronta digitale:",
|
||||
"Firefly, the easiest using of WireGuard VPN server, plus version of wg-easy.": "Firefly, il più semplice utilizzo del server VPN WireGuard, oltre alla versione di wg-easy.",
|
||||
@@ -2387,7 +2387,7 @@
|
||||
"GRUB_CMDLINE_LINUX_DEFAULT not found in GRUB config": "GRUB_CMDLINE_LINUX_DEFAULT non trovato nella configurazione di GRUB",
|
||||
"GUI mode (if available)": "Modalità GUI (se disponibile)",
|
||||
"GZDoom is a feature centric port for all Doom engine games, based on ZDoom, adding an OpenGL renderer and powerful scripting capabilities.": "GZDoom è una porta centrica caratteristica per tutti i giochi del motore Doom, basata su ZDoom, aggiungendo un renderer OpenGL e potenti capacità di scripting.",
|
||||
"Gaming & Leisure": "Gioco & Leisure",
|
||||
"Gaming & Leisure": "Giochi e tempo libero",
|
||||
"Gateway is not installed.": "Il gateway non è installato.",
|
||||
"Gateway removed.": "Gateway rimosso.",
|
||||
"Gateway restarted.": "Il gateway è stato riavviato.",
|
||||
@@ -2527,7 +2527,7 @@
|
||||
"Host GPU detected": "Rilevata GPU host",
|
||||
"Host GPU is already bound to vfio-pci. Host reconfiguration/reboot should not be required for this VM-to-VM reassignment.": "La GPU host è già associata a vfio-pci. La riconfigurazione/riavvio dell'host non dovrebbe essere necessario per questa riassegnazione da VM a VM.",
|
||||
"Host IP": "IP dell'ospite",
|
||||
"Host Management": "Gestione host",
|
||||
"Host Management": "Gestione dell'host",
|
||||
"Host Mount Path": "Percorso di montaggio dell'host",
|
||||
"Host NFS/Samba as Proxmox Storage (pvesm)": "Ospita NFS/Samba come storage Proxmox (pvesm)",
|
||||
"Host Path": "Percorso dell'ospite",
|
||||
@@ -2795,7 +2795,7 @@
|
||||
"Initiator IQN is authorised on the target": "L'IQN dell'iniziatore è autorizzato sul target",
|
||||
"Initiator IQN:": "IQN dell'iniziatore:",
|
||||
"Inkscape is professional quality vector graphics software which runs on Linux, Mac OS X and Windows desktop computers.": "Inkscape è un software grafico vettoriale di qualità professionale che funziona su computer desktop Linux, Mac OS X e Windows.",
|
||||
"Inside the LXC, create the administrator: console kimai:user:create YOUR_USERNAME YOUR_EMAIL ROLE_SUPER_ADMIN": "All'interno del LXC, creare l'amministratore: console kimai:user:creare Your USERNAME Your EMAIL ROLE SUPER ADMIN",
|
||||
"Inside the LXC, create the administrator: console kimai:user:create YOUR_USERNAME YOUR_EMAIL ROLE_SUPER_ADMIN": "All'interno del LXC, creare l'amministratore: console kimai:user:creare Your USERNAME Your EMAIL ROLE_SUPER_ADMIN",
|
||||
"Inspect disks before any action": "Ispezionare i dischi prima di qualsiasi azione",
|
||||
"Inspect host device nodes": "Ispezionare i nodi del dispositivo host",
|
||||
"Inspect passthrough/kernel events": "Ispezionare gli eventi passthrough/kernel",
|
||||
@@ -3401,7 +3401,7 @@
|
||||
"Memory settings optimized successfully": "Impostazioni di memoria ottimizzate con successo",
|
||||
"Memory:": "Memoria:",
|
||||
"Memos is a lightweight, self-hosted memo hub. Open Source and Free forever.": "Memos è un hub memo leggero e self-hosted. Open Source e Free per sempre.",
|
||||
"Messaging & Notifications": "Messaggi e notifiche",
|
||||
"Messaging & Notifications": "Messaggistica e notifiche",
|
||||
"Messaging & Queues": "Messaging & Queues",
|
||||
"Messenger for the Decentralized Web": "Messaggero per il Web decentrato",
|
||||
"Method:": "Metodo:",
|
||||
@@ -3664,7 +3664,7 @@
|
||||
"Name of this wallabag instance, shown in the interface and in 2FA codes": "Nome di questa istanza wallabag, mostrata nell'interfaccia e nei codici 2FA",
|
||||
"Name or part of the description of the application": "Nome o parte della descrizione dell'applicazione",
|
||||
"Name:": "Nome:",
|
||||
"Named accounts need private mode. Stop the container, set public: false in /config/config.js, start it again and create each user with: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>": "I conti nominati hanno bisogno di modalità privata. Stop al contenitore, set public: false in /config/config.js, avviare di nuovo e creare ogni utente con: pct exec <CTID> -- env THELOUNGE HOME=/config s6-setuidgid abc thelounge add <user>",
|
||||
"Named accounts need private mode. Stop the container, set public: false in /config/config.js, start it again and create each user with: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>": "I conti nominati hanno bisogno di modalità privata. Stop al contenitore, set public: false in /config/config.js, avviare di nuovo e creare ogni utente con: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>",
|
||||
"Neither /etc/kernel/cmdline nor /etc/default/grub found.": "Non sono stati trovati né /etc/kernel/cmdline né /etc/default/grub.",
|
||||
"Nesting feature enabled": "Funzionalità di annidamento abilitata",
|
||||
"NetBIOS Service: RUNNING": "Servizio NetBIOS: IN ESECUZIONE",
|
||||
@@ -3674,7 +3674,7 @@
|
||||
"Netbox is an IP address management (IPAM) and data center infrastructure management (DCIM) tool. Initially conceived by the network engineering team at DigitalOcean, NetBox was developed specifically to address the needs of network and infrastructure engineers. It is intended to function as a domain-specific source of truth for network operations.": "Netbox è uno strumento di gestione degli indirizzi IP (IPAM) e di gestione delle infrastrutture dei data center (DCIM). Inizialmente concepito dal team di ingegneria di rete di DigitalOcean, NetBox è stato sviluppato specificamente per soddisfare le esigenze degli ingegneri della rete e delle infrastrutture. È destinato a funzionare come fonte di verità specifica di dominio per la rete operations.",
|
||||
"Network": "Rete",
|
||||
"Network :": "Rete :",
|
||||
"Network & Firewall": "Rete e Firewall",
|
||||
"Network & Firewall": "Rete e firewall",
|
||||
"Network (interfaces, DNS)": "Rete (interfacce, DNS)",
|
||||
"Network Bridge": "Ponte di rete",
|
||||
"Network Commands": "Comandi di rete",
|
||||
@@ -4045,7 +4045,7 @@
|
||||
"OCI containers require Proxmox VE 9.1 or later.": "I contenitori OCI richiedono Proxmox VE 9.1 o versione successiva.",
|
||||
"OCI management": "Gestione OCI",
|
||||
"OCI management could not be completed. Check the backend status; no additional cleanup has been authorized.": "La gestione OCI non poteva essere completata. Controlla lo stato del backend; non è stata autorizzata alcuna pulizia aggiuntiva.",
|
||||
"OCI manager Apps (beta)": "App di gestione OCI (beta)",
|
||||
"OCI manager Apps (beta)": "OCI manager Apps (beta)",
|
||||
"OCI manager Apps is a beta: if something does not work as expected, please report it on GitHub with the application name.": "OCI manager Apps è una beta: se qualcosa non funziona come previsto, si prega di segnalarlo su GitHub con il nome dell'applicazione.",
|
||||
"OCI metadata integrity mismatch": "OCI metadati integrità mismatch",
|
||||
"OCI metadata too large": "OCI metadati troppo grandi",
|
||||
@@ -4377,7 +4377,7 @@
|
||||
"Postfix configuration": "Configurazione suffissa",
|
||||
"PostgreSQL": "PostgreSQL",
|
||||
"PostgreSQL URL without an associated service:": "URL PostgreSQL senza un servizio associato:",
|
||||
"PostgreSQL creates the database named in POSTGRES_DB on the first start. The installer default is postgresql.": "PostgreSQL crea il database chiamato in POSTGRES DB al primo avvio. L'impostazione predefinita è postgresql.",
|
||||
"PostgreSQL creates the database named in POSTGRES_DB on the first start. The installer default is postgresql.": "PostgreSQL crea il database chiamato in POSTGRES_DB al primo avvio. L'impostazione predefinita è postgresql.",
|
||||
"PostgreSQL is an advanced, enterprise-class, and open-source relational database system. PostgreSQL supports both SQL (relational) and JSON (non-relational) querying.": "PostgreSQL è un sistema di database relazionale avanzato, di classe enterprise e open source. PostgreSQL supporta sia querying SQL (relazionale) che JSON (non relazionale).",
|
||||
"PostgreSQL requires a password": "PostgreSQL requires una password",
|
||||
"PostgreSQL volume size in GB": "Dimensione del volume PostgreSQL in GB",
|
||||
@@ -4541,7 +4541,7 @@
|
||||
"Pwndrop is a self-deployable file hosting service for sending out red teaming payloads or securely sharing your private files over HTTP and WebDAV.": "Pwndrop è un servizio di hosting di file auto-deployable per l'invio di payload di teaming rosso o la condivisione sicura dei file privati su HTTP e WebDAV.",
|
||||
"PyCharm offers out-of-the-box support for Python, databases, Jupyter, Git, Conda, PyTorch, TensorFlow, Hugging Face, Django, Flask, FastAPI, and more.": "PyCharm offre supporto out-of-the-box per Python, banche dati, Jupyter, Git, Conda, PyTorch, TensorFlow, Hugging Face, Django, Flask, FastAPI, e altro ancora.",
|
||||
"Pydio Cells needs an external MySQL or MariaDB database. The setup wizard asks for its address, database name and user on the first start.": "Pydio Cells ha bisogno di un database MySQL esterno o MariaDB. La procedura guidata di configurazione chiede il suo indirizzo, il nome del database e l'utente al primo avvio.",
|
||||
"Pydio Cells redirects to the address given in EXTERNALURL. If the container changes address, edit lxc.environment.runtime: EXTERNALURL and SERVER_IP in /etc/pve/lxc/<CTID>.conf with the container stopped, and delete /config/keys/cert.crt to regenerate the certificate.": "Pydio Cells reindirizza all'indirizzo indicato in EXTERNALURL. Se il contenitore cambia indirizzo, modifica lxc.environment.runtime: EXTERNALURL e SERVER IP in /etc/pve/lxc/∂.conf con il contenitore interrotto, ed eliminare /config/keys/cert.crt per rigenerare il certificato.",
|
||||
"Pydio Cells redirects to the address given in EXTERNALURL. If the container changes address, edit lxc.environment.runtime: EXTERNALURL and SERVER_IP in /etc/pve/lxc/<CTID>.conf with the container stopped, and delete /config/keys/cert.crt to regenerate the certificate.": "Pydio Cells reindirizza all'indirizzo indicato in EXTERNALURL. Se il contenitore cambia indirizzo, modifica lxc.environment.runtime: EXTERNALURL e SERVER_IP in /etc/pve/lxc/∂.conf con il contenitore interrotto, ed eliminare /config/keys/cert.crt per rigenerare il certificato.",
|
||||
"Pydio-cells is the nextgen file sharing platform for organizations. It is a full rewrite of the Pydio project using the Go language following a micro-service architecture.": "Pydio-cells è la piattaforma di condivisione file di prossima generazione per le organizzazioni. Si tratta di una riscrittura completa del progetto Pydio utilizzando la lingua Go seguendo un'architettura micro-servizio.",
|
||||
"QDirStat Qt-based directory statistics: KDirStat without any KDE -- from the author of the original KDirStat.": "QDirStat Statistiche di directory basate su Qt: KDirStat senza KDE -- dall'autore del KDirStat originale.",
|
||||
"Quick health check (PASSED / FAILED)": "Controllo rapido dello stato (SUPERATO/FALLITO)",
|
||||
@@ -5955,7 +5955,7 @@
|
||||
"The imported Compose requests privileged, but the official jlesage/handbrake documentation does not require it; ProxMenux keeps the LXC unprivileged.": "Il Compose importato richiede privilegiato, ma la documentazione ufficiale jlesage/handbrake non lo require; ProxMenux mantiene il LXC non privato.",
|
||||
"The imported OCI groups are not numeric": "I gruppi OCI importati non sono numerici",
|
||||
"The imported OCI user or group is not numeric": "L'utente o il gruppo OCI importati non è numerico",
|
||||
"The initial user name and password stay written in /etc/pve/lxc/<CTID>.conf as INIT_USERNAME and INIT_PASSWORD. They can be removed after the first login, with the container stopped.": "Il nome utente iniziale e la password rimangono scritti in /etc/pve/lxc/δCTID>.conf come INIT USERNAME e INIT PASSWORD. Possono essere rimossi dopo il primo login, con il contenitore fermato.",
|
||||
"The initial user name and password stay written in /etc/pve/lxc/<CTID>.conf as INIT_USERNAME and INIT_PASSWORD. They can be removed after the first login, with the container stopped.": "Il nome utente iniziale e la password rimangono scritti in /etc/pve/lxc/δCTID>.conf come INIT_USERNAME e INIT_PASSWORD. Possono essere rimossi dopo il primo login, con il contenitore fermato.",
|
||||
"The installation asks which one to use for these paths.": "L'installazione chiede quale utilizzare per questi percorsi.",
|
||||
"The installation ended with exit code": "L'installazione è terminata con il codice di uscita",
|
||||
"The installation requires a server restart to apply changes. Do you want to restart now?": "L'installazione richiede il riavvio del server per applicare le modifiche. Vuoi riavviare adesso?",
|
||||
@@ -6074,7 +6074,7 @@
|
||||
"The rootfs is not managed by Proxmox": "I rootf non sono gestiti da Proxmox",
|
||||
"The rootfs is not mounted": "I rootf non sono montati",
|
||||
"The same GPU cannot be used by two VMs at the same time.": "La stessa GPU non può essere utilizzata da due VM contemporaneamente.",
|
||||
"The same connection can be given as container variables instead of the file: UN_SONARR_0_URL and UN_SONARR_0_API_KEY, or the UN_RADARR_0_ equivalents.": "La stessa connessione può essere data come variabili di contenitore al posto del file: UN SONARR 0 URL e UN SONARR 0 API KEY, o UN RADARR 0 equivalents.",
|
||||
"The same connection can be given as container variables instead of the file: UN_SONARR_0_URL and UN_SONARR_0_API_KEY, or the UN_RADARR_0_ equivalents.": "La stessa connessione può essere data come variabili di contenitore al posto del file: UN_SONARR_0_URL e UN_SONARR_0_API_KEY, o UN RADARR 0 equivalents.",
|
||||
"The saved MOTD state is invalid; no changes were made": "lo stato MOTD salvato non è valido;non sono state apportate modifiche",
|
||||
"The saved OCI record is incomplete or has an unexpected format.": "Il record OCI salvato è incompleto o ha un formato inaspettato.",
|
||||
"The saved projection does not match the native evidence": "La proiezione salvata non corrisponde alle prove native",
|
||||
@@ -6822,7 +6822,7 @@
|
||||
"Web interface to manage devices running Tasmota firmware.": "Interfaccia web per gestire i dispositivi che eseguono il firmware Tasmota.",
|
||||
"WebCord can be summarized as a pack of security and privacy hardenings, Discord features reimplementations, Electron / Chromium / Discord bugs workarounds, stylesheets, internal pages and wrapped https://discord.com page, designed to conform with ToS as much as it is possible (or hide the changes that might violate it from Discord's eyes).": "WebCord può essere riassunto come un pacchetto di indurzioni di sicurezza e privacy, Discord caratteristiche reimplement, Electron / Chromium / Discord bugs workarounds, stylesheets, pagine interne e avvolto https://discord.com pagina, progettato per conformarsi con ToS quanto è possibile (o nascondere le modifiche che potrebbero violarlo dagli occhi di Discord).",
|
||||
"Webgrabplus is a multi-site incremental xmltv epg grabber. It collects tv-program guide data from selected tvguide sites for your favourite channels.": "Webgrabplus è un manubrio multi-sito incrementale xmltv epg. Raccoglie i dati della guida tv-programma da siti di guida selezionati per i tuoi canali preferiti.",
|
||||
"Webservers & Proxies": "Webservers & Proxies",
|
||||
"Webservers & Proxies": "Server web e proxy",
|
||||
"Website": "Sito web",
|
||||
"Webstation is a web native emulation focused LXQt desktop based on Ubuntu.": "Webstation è un desktop LXQt basato su Ubuntu.",
|
||||
"Webtop - Alpine, Ubuntu, Fedora, and Arch based containers containing full desktop environments in officially supported flavors accessible via any modern web browser.": "Webtop - contenitori Alpine, Ubuntu, Fedora e Arch, contenenti ambienti desktop completi in gusti ufficialmente supportati accessibili tramite qualsiasi browser web moderno.",
|
||||
@@ -6855,7 +6855,7 @@
|
||||
"WireGuard® is an extremely simple yet fast and modern VPN that utilizes state-of-the-art cryptography. It aims to be faster, simpler, leaner, and more useful than IPsec, while avoiding the massive headache. It intends to be considerably more performant than OpenVPN. WireGuard is designed as a general purpose VPN for running on embedded interfaces and super computers alike, fit for many different circumstances. Initially released for the Linux kernel, it is now cross-platform (Windows, macOS, BSD, iOS, Android) and widely deployable. It is currently under heavy development, but already it might be regarded as the most secure, easiest to use, and simplest VPN solution in the industry.": "WireGuard® è una VPN estremamente semplice ma veloce e moderna che utilizza la crittografia all'avanguardia. Esso mira ad essere più veloce, più semplice, più snella, e più utile di IPsec, evitando il mal di testa massiccio. Si intende essere molto più performante di OpenVPN. WireGuard è progettato come una VPN di scopo generale per l'esecuzione su interfacce embedded e super computer allo stesso modo, adatto per molte circostanze diverse. Inizialmente rilasciato per il kernel Linux, è ora cross-platform (Windows, macOS, BSD, iOS, Android) e ampiamente implementabile. Attualmente è in forte sviluppo, ma già potrebbe essere considerato come la soluzione VPN più sicura, più facile da usare e più semplice del settore.",
|
||||
"Wired NICs in backup missing on target:": "Schede NIC cablate nel backup mancanti sulla destinazione:",
|
||||
"Wireshark is the world’s foremost and widely-used network protocol analyzer. It lets you see what’s happening on your network at a microscopic level and is the de facto (and often de jure) standard across many commercial and non-profit enterprises, government agencies, and educational institutions. Wireshark development thrives thanks to the volunteer contributions of networking experts around the globe and is the continuation of a project started by Gerald Combs in 1998.": "Wireshark è il principale e ampiamente utilizzato analizzatore di protocollo di rete. Ti permette di vedere cosa sta accadendo sulla tua rete a livello microscopico ed è lo standard de facto (e spesso de jure) in molte imprese commerciali e non-profit, agenzie governative e istituzioni educative. Lo sviluppo di Wireshark prospera grazie ai contributi volontari di esperti di networking in tutto il mondo ed è la continuazione di un progetto avviato da Gerald Combs nel 1998.",
|
||||
"With dns validation, the DNSPLUGIN variable names the provider plugin. The advanced installation asks for it; otherwise add the line lxc.environment.runtime: DNSPLUGIN=<plugin> to /etc/pve/lxc/<CTID>.conf with the container stopped.": "Con la convalida di dns, la variabile DNSPLUGIN nomina il plugin del provider. L'installazione avanzata lo richiede; altrimenti aggiungere la linea lxc.environment. runtime: DNSPLUGIN= <plugin> a /etc/pve/lxc/δCTID>.conf con il contenitore interrotto.",
|
||||
"With dns validation, the DNSPLUGIN variable names the provider plugin. The advanced installation asks for it; otherwise add the line lxc.environment.runtime: DNSPLUGIN=<plugin> to /etc/pve/lxc/<CTID>.conf with the container stopped.": "Con la convalida di dns, la variabile DNSPLUGIN nomina il plugin del provider. L'installazione avanzata lo richiede; altrimenti aggiungere la linea lxc.environment.runtime: DNSPLUGIN= <plugin> a /etc/pve/lxc/ <CTID>.conf con il contenitore fermato.",
|
||||
"With dns validation, write the provider credentials in /config/dns-conf/<plugin>.ini inside the container and restart it.": "Con la validazione di dns, scrivere il credentials del fornitore in /config/dns-conf/δplugin>.ini all'interno del contenitore e riavviarlo.",
|
||||
"With http validation, port 80 of the router must be forwarded to port 80 of this container.": "Con la convalida http, la porta 80 del router deve essere inoltrata alla porta 80 di questo contenitore.",
|
||||
"With warnings": "Con avvertimenti",
|
||||
@@ -7374,7 +7374,7 @@
|
||||
"vfio-pci IDs configured": "ID vfio-pci configurati",
|
||||
"vfio-pci IDs in /etc/modprobe.d/vfio.conf": "ID vfio-pci in /etc/modprobe.d/vfio.conf",
|
||||
"vzdump backup speed optimization completed": "Ottimizzazione della velocità di backup di vzdump completata",
|
||||
"wallabag builds its links from the address given during the installation. If it does not match the address of the container, edit lxc.environment.runtime: SYMFONY__ENV__DOMAIN_NAME in /etc/pve/lxc/<CTID>.conf with the container stopped, and start it again.": "wallabag costruisce i suoi collegamenti dall'indirizzo indicato durante l'installazione. Se non corrisponde all'indirizzo del contenitore, modificare lxc.environment. runtime: SYMFONY ENV DOMAIN NAME in /etc/pve/lxc/δCTID>.conf con il contenitore fermato, e ricominciare.",
|
||||
"wallabag builds its links from the address given during the installation. If it does not match the address of the container, edit lxc.environment.runtime: SYMFONY__ENV__DOMAIN_NAME in /etc/pve/lxc/<CTID>.conf with the container stopped, and start it again.": "wallabag costruisce i suoi collegamenti dall'indirizzo indicato durante l'installazione. Se non corrisponde all'indirizzo del contenitore, modificare lxc.environment.runtime: SYMFONY ENV DOMAIN NAME in /etc/pve/lxc/δCTID>.conf con il contenitore fermato, e ricominciare.",
|
||||
"wallabag listens on port 80 of the container and stores its data in SQLite.": "wallabag ascolta la porta 80 del contenitore e memorizza i suoi dati in SQLite.",
|
||||
"wallabag web interface": "Interfaccia web wallabag",
|
||||
"was": "era",
|
||||
|
||||
+36
-36
@@ -20,7 +20,7 @@
|
||||
"(recommended)": "(recomendado)",
|
||||
"(same MAC — restored config adjusted automatically)": "(mesmo MAC - configuração restaurada ajustada automaticamente)",
|
||||
")": ")",
|
||||
"*Arr Suite": "* Arr Suite",
|
||||
"*Arr Suite": "*Arr Suite",
|
||||
"+ Add a path": "+ Adicione um caminho",
|
||||
"+ Add new Borg target": "+ Adicionar novo alvo Borg",
|
||||
"+ Add new PBS manually": "+ Adicione novo PBS manualmente",
|
||||
@@ -120,7 +120,7 @@
|
||||
"ACL Status:": "Status da ACL:",
|
||||
"ACL permissions applied for local access for user:": "Permissões ACL aplicadas para acesso local do usuário:",
|
||||
"ADVANCED SETTINGS COMPLETE": "CONFIGURAÇÕES AVANÇADAS CONCLUÍDAS",
|
||||
"AI / Coding & Dev-Tools": "IA / Codificação & Ferramentas Dev",
|
||||
"AI / Coding & Dev-Tools": "IA, programação e desenvolvimento",
|
||||
"ALL DATA ON": "TODOS OS DADOS EM",
|
||||
"ALL DATA ON THIS DISK WILL BE PERMANENTLY LOST!": "TODOS OS DADOS NESTE DISCO SERÃO PERMANENTEMENTE PERDIDOS!",
|
||||
"ALL Utilities": "TODOS os utilitários",
|
||||
@@ -185,7 +185,7 @@
|
||||
"Actual device path on the host": "Localização real do dispositivo na máquina",
|
||||
"Adaptation file too large": "Arquivo de adaptação muito grande",
|
||||
"Adaptation file with unexpected permissions or owner": "Arquivo de adaptação com permissões inesperadas ou proprietário",
|
||||
"Adblock & DNS": "Adblock & DNS",
|
||||
"Adblock & DNS": "Adblock e DNS",
|
||||
"Add Audio Passthrough": "Adicionar passagem de áudio",
|
||||
"Add CIFS storage:": "Adicione armazenamento CIFS:",
|
||||
"Add Controller or NVMe (PCI passthrough)": "Adicionar controlador ou NVMe (passagem PCI)",
|
||||
@@ -439,7 +439,7 @@
|
||||
"Auth key is required.": "A chave de autenticação é obrigatória.",
|
||||
"Auth:": "Autenticação:",
|
||||
"Authentication": "Autenticação",
|
||||
"Authentication & Security": "Autenticação e Segurança",
|
||||
"Authentication & Security": "Autenticação e segurança",
|
||||
"Authentication Error": "Erro de autenticação",
|
||||
"Authentication failed.": "Falha na autenticação.",
|
||||
"Authentication required:": "Autenticação necessária:",
|
||||
@@ -463,7 +463,7 @@
|
||||
"Automatic private network allocation requires a /24 subnet": "Alocação automática de rede privada requires a /24 subnet",
|
||||
"Automatic video library manager for TV Shows": "Gerenciador automático de bibliotecas de vídeo para programas de TV",
|
||||
"Automatic/Unattended": "Automático/Autônomo",
|
||||
"Automation & Scheduling": "Programação de Automação",
|
||||
"Automation & Scheduling": "Automação e agendamento",
|
||||
"Available": "Disponível",
|
||||
"Available Borg archives (newest first):": "Arquivos Borg disponíveis (os mais recentes primeiro):",
|
||||
"Available Borg targets:": "Alvos Borg disponíveis:",
|
||||
@@ -500,7 +500,7 @@
|
||||
"Backend:": "Back-end:",
|
||||
"Background archive extraction for Arr download queues. No web interface.": "Extração de arquivo de fundo para as filas de download do Arr. Sem interface web.",
|
||||
"Backup — VM and CT backups": "Backup – backups de VM e CT",
|
||||
"Backup & Recovery": "Backup & Recuperação",
|
||||
"Backup & Recovery": "Backups e recuperação",
|
||||
"Backup Created": "Backup criado",
|
||||
"Backup ID (group name in PBS):": "ID de backup (nome do grupo no PBS):",
|
||||
"Backup ID for this job:": "ID de backup para este trabalho:",
|
||||
@@ -603,11 +603,11 @@
|
||||
"Broken gasket-dkms package state recovered.": "O estado danificado do pacote gasket-dkms foi recuperado.",
|
||||
"Browse Your Life in Images": "Navegue por sua vida em imagens",
|
||||
"Browse manually (advanced)...": "Navegar manualmente (avançado)...",
|
||||
"Browsers & Web Desktops": "Navegadores e Ecrãs Web",
|
||||
"Browsers & Web Desktops": "Navegadores e ambientes de trabalho web",
|
||||
"Build and install the gasket and apex kernel modules (DKMS)": "Compilar e instalar os módulos de kernel gasket e apex (DKMS)",
|
||||
"Build dependencies installed.": "Construa dependências instaladas.",
|
||||
"Build your personal knowledge base with TriliumNext Notes": "Crie sua base de conhecimento pessoal com TriliumPróximos Notas",
|
||||
"Business & ERP": "Negócios & ERP",
|
||||
"Business & ERP": "Negócio e ERP",
|
||||
"CHANGES APPLIED SUCCESSFULLY": "ALTERAÇÕES APLICADAS COM SUCESSO",
|
||||
"CIFS Client Tools: AVAILABLE": "Ferramentas de cliente CIFS: DISPONÍVEIS",
|
||||
"CIFS Client Tools: NOT AVAILABLE - installing...": "Ferramentas cliente CIFS: NÃO DISPONÍVEIS - instalando...",
|
||||
@@ -869,7 +869,7 @@
|
||||
"Commenting legacy ceph.list (if present)...": "Comentando legado ceph.list (se presente)...",
|
||||
"Common Issues Check": "Verificação de problemas comuns",
|
||||
"Common root for the published views": "Raiz comum das opiniões publicadas",
|
||||
"Communication & Community": "Comunicação & Comunidade",
|
||||
"Communication & Community": "Comunicação e comunidade",
|
||||
"Community Scripts": "Scripts da comunidade",
|
||||
"Community single-container Home Assistant OS image": "Imagem do sistema operacional Home Assistant para um único recipiente comunitário",
|
||||
"Compatibility check": "Verificação de compatibilidade",
|
||||
@@ -1041,7 +1041,7 @@
|
||||
"Consider security implications for production environments": "Considere as implicações de segurança para ambientes de produção",
|
||||
"Consider visiting the repository and supporting the project.": "Considere visitar o repositório e apoiar o projeto.",
|
||||
"Console log:": "Registo da consola:",
|
||||
"Container": "Recipiente",
|
||||
"Container": "Contêiner",
|
||||
"Container — LXC root directories": "Container - diretórios raiz LXC",
|
||||
"Container ID": "ID do contêiner",
|
||||
"Container ID not defined. Make sure to select a container first.": "ID do contêiner não definido. Certifique-se de selecionar um contêiner primeiro.",
|
||||
@@ -1083,8 +1083,8 @@
|
||||
"Container volume (included in backups)": "Volume do recipiente (incluído em backups)",
|
||||
"Container will pick up the mount on next start": "O contêiner pegará a montagem na próxima partida",
|
||||
"Container with ID": "Contêiner com ID",
|
||||
"Container:": "Recipiente:",
|
||||
"Containers & Docker": "Containers e Docker",
|
||||
"Container:": "Contêiner:",
|
||||
"Containers & Docker": "Contentores e Docker",
|
||||
"Containers returned to their previous state": "Os contentores voltaram ao seu estado anterior",
|
||||
"Containers that are removed:": "Recipientes que são removidos:",
|
||||
"Containers that will be created (one LXC per service, on a private network):": "Containers que serão criados (um LXC por serviço, em uma rede privada):",
|
||||
@@ -1157,7 +1157,7 @@
|
||||
"Coral M.2 Apex configuration added - device ready": "Configuração Coral M.2 Apex adicionada - dispositivo pronto",
|
||||
"Coral M.2 Apex configuration added - device will be available after reboot": "Configuração Coral M.2 Apex adicionada - o dispositivo estará disponível após a reinicialização",
|
||||
"Coral M.2 Apex detected, configuring...": "Coral M.2 Apex detectado, configurando...",
|
||||
"Coral PCIe/M.2 node (e.g. /dev/apex_0)": "Nó Coral PCIe/M.2 (por exemplo, /dev/apex 0)",
|
||||
"Coral PCIe/M.2 node (e.g. /dev/apex_0)": "Nó Coral PCIe/M.2 (por exemplo, /dev/apex_0)",
|
||||
"Coral TPU Installation": "Instalação Coral TPU",
|
||||
"Coral TPU Uninstall": "Desinstalação do Coral TPU",
|
||||
"Coral TPU device nodes detected with correct group (apex).": "Nós do dispositivo Coral TPU detectados com o grupo correto (apex).",
|
||||
@@ -1345,7 +1345,7 @@
|
||||
"Creating the container...": "A criar o contentor...",
|
||||
"Creating the initial administrator...": "Criando o administrador inicial...",
|
||||
"Creating the temporary data container": "Criando o recipiente de dados temporário",
|
||||
"Creative & Design": "Desenho Criativo",
|
||||
"Creative & Design": "Criatividade e design",
|
||||
"Credentials are correct": "As credenciais estão corretas",
|
||||
"Credentials cleared. jwt_secret and API tokens preserved.": "Credenciais apagadas. jwt_secret e tokens de API preservados.",
|
||||
"Credentials file created securely.": "Arquivo de credenciais criado com segurança.",
|
||||
@@ -1694,7 +1694,7 @@
|
||||
"Docker Mods are only offered for compatible LinuxServer images": "Docker Mods são oferecidos apenas para imagens LinuxServer compatíveis",
|
||||
"Docker Volume Backup": "Docker Volume Backup",
|
||||
"Docker/CLI not available yet or no valid answer": "Docker/CLI ainda não disponível ou nenhuma resposta válida",
|
||||
"Documents & Notes": "Documentos e Notas",
|
||||
"Documents & Notes": "Documentos e notas",
|
||||
"Documents volume size in GB": "Tamanho do volume de documentos em GB",
|
||||
"Dokuwiki is a simple to use and highly versatile Open Source wiki software that doesn't require a database. It is loved by users for its clean and readable syntax. The ease of maintenance, backup and integration makes it an administrator's favorite. Built in access controls and authentication connectors make DokuWiki especially useful in the enterprise context and the large number of plugins contributed by its vibrant community allow for a broad range of use cases beyond a traditional wiki.": "Dokuwiki é um software wiki de código aberto muito simples de usar e altamente versátil que não require um banco de dados. É amado pelos usuários por sua sintaxe limpa e legível. A facilidade de manutenção, backup e integração o torna o favorito do administrador. Conectados em controles de acesso e conectores de autenticação tornam o DokuWiki especialmente útil no contexto empresarial e o grande número de plugins contribuídos por sua comunidade vibrante permitem uma ampla gama de casos de uso além de uma wiki tradicional.",
|
||||
"Dolphin Emulator lets you play GameCube and Wii games with various graphical enhancements and other features are available to improve your game experience.": "O Emulador Dolphin permite que você jogue jogos GameCube e Wii com várias melhorias gráficas e outros recursos estão disponíveis para melhorar sua experiência de jogo.",
|
||||
@@ -1731,7 +1731,7 @@
|
||||
"Dry run completed; the container and the mounts were not changed.": "A corrida a seco foi concluída; o recipiente e as montagens não foram alteradas.",
|
||||
"DuckDNS subdomain without .duckdns.org (comma separated for several)": "Subdomínio DuckDNS sem .duckdns.org (comma separado para vários)",
|
||||
"DuckDNS token from your account at duckdns.org": "DuckDNS token da sua conta em duckdns.org",
|
||||
"DuckDNS updates the subdomain every 5 minutes. Without UPDATE_IP, DuckDNS itself detects the public IPv4 address of the request.": "DuckDNS atualiza o subdomínio a cada 5 minutos. Sem UPDATE IP, o próprio DuckDNS detecta o endereço IPv4 público da solicitação.",
|
||||
"DuckDNS updates the subdomain every 5 minutes. Without UPDATE_IP, DuckDNS itself detects the public IPv4 address of the request.": "DuckDNS atualiza o subdomínio a cada 5 minutos. Sem UPDATE_IP, o próprio DuckDNS detecta o endereço IPv4 público da solicitação.",
|
||||
"DuckStation is a PS1 Emulator aiming for the best accuracy and game support.": "DuckStation é um emulador PS1 que visa o melhor accuracy e suporte a jogos.",
|
||||
"Duckdns is a free service which will point a DNS (sub domains of duckdns.org) to an IP of your choice. The service is completely free, and doesn't require reactivation or forum posts to maintain its existence.": "Duckdns é um serviço gratuito que irá apontar um DNS (subdomínios do duckdns.org) para um IP de sua escolha. O serviço é completamente gratuito, e não require reativação ou posts de fórum para manter sua existência.",
|
||||
"Dumping AMD GPU ROM BIOS via sysfs...": "Despejando BIOS da ROM da GPU AMD via sysfs...",
|
||||
@@ -2230,7 +2230,7 @@
|
||||
"FileBrowser Quantum": "FileBrowser Quantum",
|
||||
"FileBrowser Quantum (new installation)": "FileBrowser Quantum (nova instalação)",
|
||||
"FileDrop is a free, open source file sharing service": "FileDrop é um serviço de compartilhamento de arquivos livre e aberto",
|
||||
"Files & Downloads": "Ficheiros e Transferências",
|
||||
"Files & Downloads": "Ficheiros e transferências",
|
||||
"Files volume size in GB": "Tamanho do volume dos arquivos em GB",
|
||||
"Filesystem": "Sistema de arquivos",
|
||||
"Filesystem Tools Required": "Ferramentas de sistema de arquivos necessárias",
|
||||
@@ -2239,7 +2239,7 @@
|
||||
"Final cleanup of the stack operation completed": "Limpeza final da pilha operation concluída",
|
||||
"Final confirmation": "Confirmação final",
|
||||
"Final storage health/status check": "Verificação final de integridade/status do armazenamento",
|
||||
"Finance & Budgeting": "Finanças & Budgeting",
|
||||
"Finance & Budgeting": "Finanças e orçamento",
|
||||
"Find your device using https://finds.synology.com": "Encontre o seu dispositivo usando https://finds.synology.com",
|
||||
"Fingerprint:": "Impressão digital:",
|
||||
"Firefly, the easiest using of WireGuard VPN server, plus version of wg-easy.": "Firefly, o mais fácil de usar o servidor VPN WireGuard, além da versão do wg-fácil.",
|
||||
@@ -2387,7 +2387,7 @@
|
||||
"GRUB_CMDLINE_LINUX_DEFAULT not found in GRUB config": "GRUB_CMDLINE_LINUX_DEFAULT não encontrado na configuração do GRUB",
|
||||
"GUI mode (if available)": "Modo GUI (se disponível)",
|
||||
"GZDoom is a feature centric port for all Doom engine games, based on ZDoom, adding an OpenGL renderer and powerful scripting capabilities.": "GZDoom é uma porta centrada em recursos para todos os jogos do Doom Engine, baseado no ZDoom, adicionando um renderizador OpenGL e recursos de script poderosos.",
|
||||
"Gaming & Leisure": "Jogos & Leisure",
|
||||
"Gaming & Leisure": "Jogos e lazer",
|
||||
"Gateway is not installed.": "O gateway não está instalado.",
|
||||
"Gateway removed.": "Gateway removido.",
|
||||
"Gateway restarted.": "Gateway reiniciado.",
|
||||
@@ -2527,7 +2527,7 @@
|
||||
"Host GPU detected": "GPU host detectada",
|
||||
"Host GPU is already bound to vfio-pci. Host reconfiguration/reboot should not be required for this VM-to-VM reassignment.": "A GPU host já está vinculada ao vfio-pci. A reconfiguração/reinicialização do host não deve ser necessária para esta reatribuição de VM para VM.",
|
||||
"Host IP": "IP do host",
|
||||
"Host Management": "Gestão da Máquina",
|
||||
"Host Management": "Gestão do anfitrião",
|
||||
"Host Mount Path": "Caminho de montagem do host",
|
||||
"Host NFS/Samba as Proxmox Storage (pvesm)": "Hospedar NFS/Samba como armazenamento Proxmox (pvesm)",
|
||||
"Host Path": "Caminho do host",
|
||||
@@ -2541,7 +2541,7 @@
|
||||
"Host already in VFIO mode — skipping host reconfiguration for VM reassignment": "Host já no modo VFIO — ignorando a reconfiguração do host para reatribuição de VM",
|
||||
"Host audio devices": "Dispositivos de áudio da máquina",
|
||||
"Host backup attached to PVE job": "Backup do host anexado ao trabalho PVE",
|
||||
"Host data is not restored by the backup; confirm it with --acknowledge-external-data": "Os dados da máquina não são restaurados pelo backup; confirme- o com -- acknowledge- external- data",
|
||||
"Host data is not restored by the backup; confirm it with --acknowledge-external-data": "Os dados da máquina não são restaurados pelo backup; confirme-o com --acknowledge-external-data",
|
||||
"Host device for /dev/kvm": "Dispositivo de máquina para /dev/kvm",
|
||||
"Host device for /dev/net/tun": "Dispositivo de máquina para /dev/net/tun",
|
||||
"Host device for /dev/ttyUSB0": "Dispositivo da máquina para /dev/ttyUSB0",
|
||||
@@ -2795,7 +2795,7 @@
|
||||
"Initiator IQN is authorised on the target": "O iniciador IQN está autorizado no alvo",
|
||||
"Initiator IQN:": "IQN do iniciador:",
|
||||
"Inkscape is professional quality vector graphics software which runs on Linux, Mac OS X and Windows desktop computers.": "Inkscape é um software gráfico vetorial de qualidade profissional que funciona em computadores desktop Linux, Mac OS X e Windows.",
|
||||
"Inside the LXC, create the administrator: console kimai:user:create YOUR_USERNAME YOUR_EMAIL ROLE_SUPER_ADMIN": "Dentro do LXC, crie o administrador: console kimai:user:create Your USERNAME Your EMAIL ROLE SUPER ADMIN",
|
||||
"Inside the LXC, create the administrator: console kimai:user:create YOUR_USERNAME YOUR_EMAIL ROLE_SUPER_ADMIN": "Dentro do LXC, crie o administrador: console kimai:user:create Your USERNAME Your EMAIL ROLE_SUPER_ADMIN",
|
||||
"Inspect disks before any action": "Inspecione os discos antes de qualquer ação",
|
||||
"Inspect host device nodes": "Inspecione os nós do dispositivo host",
|
||||
"Inspect passthrough/kernel events": "Inspecionar eventos de passagem/kernel",
|
||||
@@ -3386,7 +3386,7 @@
|
||||
"Max user watches configured": "Máximo de visualizações do usuário configuradas",
|
||||
"Maximum auto-repair attempts reached (3). Please review the log and run any remaining commands manually.": "Máximo de tentativas de reparo automático atingido (3). Revise o log e execute quaisquer comandos restantes manualmente.",
|
||||
"May need to restart terminal": "Pode ser necessário reiniciar o terminal",
|
||||
"Media & Streaming": "& Streaming de Mídia",
|
||||
"Media & Streaming": "Multimédia e streaming",
|
||||
"Media discovery and request management for Jellyfin, Plex and Emby.": "Gerenciamento de descoberta e solicitação de mídia para Jellyfin, Plex e Emby.",
|
||||
"Media library transcoding and health checking, with an internal worker node.": "Transcodificação da biblioteca de mídia e verificação de saúde, com um nó de trabalhador interno.",
|
||||
"Media server": "Servidor de mídia",
|
||||
@@ -3401,7 +3401,7 @@
|
||||
"Memory settings optimized successfully": "Configurações de memória otimizadas com sucesso",
|
||||
"Memory:": "Memória:",
|
||||
"Memos is a lightweight, self-hosted memo hub. Open Source and Free forever.": "Memos é um hub de memorando leve e auto-hospedado. Código Aberto e Livre para sempre.",
|
||||
"Messaging & Notifications": "Mensagens e Notificações",
|
||||
"Messaging & Notifications": "Mensagens e notificações",
|
||||
"Messaging & Queues": "Mensagens & Filas",
|
||||
"Messenger for the Decentralized Web": "Mensageiro para a Web Descentralizada",
|
||||
"Method:": "Método:",
|
||||
@@ -3442,7 +3442,7 @@
|
||||
"Monitor progress:": "Monitore o progresso:",
|
||||
"Monitor, analyze, and alert on network performance.": "Monitorar, analisar e alertar sobre o desempenho da rede.",
|
||||
"Monitoring": "Monitoramento",
|
||||
"Monitoring & Analytics": "Monitoramento e Análise",
|
||||
"Monitoring & Analytics": "Monitorização e análise",
|
||||
"Most common cause: the archive is corrupted (interrupted write, partial copy, or storage issue).": "Causa mais comum: o arquivo está corrompido (gravação interrompida, cópia parcial ou problema de armazenamento).",
|
||||
"Mount Added Successfully:": "Montagem adicionada com sucesso:",
|
||||
"Mount CIFS share:": "Monte o compartilhamento CIFS:",
|
||||
@@ -3652,7 +3652,7 @@
|
||||
"NVMe health status: WARNING (critical_warning =": "Status de integridade do NVMe: AVISO (critical_warning =",
|
||||
"NVMe skipped (to add as PCIe use 'Add Controller or NVMe PCIe to VM'):": "NVMe ignorado (para adicionar como PCIe, use 'Adicionar controlador ou NVMe PCIe à VM'):",
|
||||
"NVMe-specific SMART log": "Registro SMART específico do NVMe",
|
||||
"NVR & Cameras": "Câmeras NVR",
|
||||
"NVR & Cameras": "NVR e câmaras",
|
||||
"NVR with optional VA-API video acceleration and hardware object detectors": "NVR com aceleração de vídeo VA-API opcional e detectores de objetos de hardware",
|
||||
"NZBGet web interface": "Interface Web NZBGet",
|
||||
"Name": "Nome",
|
||||
@@ -3664,7 +3664,7 @@
|
||||
"Name of this wallabag instance, shown in the interface and in 2FA codes": "Nome desta instância wallabag, mostrado na interface e em códigos 2FA",
|
||||
"Name or part of the description of the application": "Nome ou parte da descrição do pedido",
|
||||
"Name:": "Nome:",
|
||||
"Named accounts need private mode. Stop the container, set public: false in /config/config.js, start it again and create each user with: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>": "Contas nomeadas precisam de modo privado. Pare o contêiner, defina público: false in /config/config.js, inicie-o novamente e crie cada usuário com: pct exec <CTID> -- env THELOUNGE HOME=/config s6-setuidgid abc thelounge add <user>",
|
||||
"Named accounts need private mode. Stop the container, set public: false in /config/config.js, start it again and create each user with: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>": "Contas nomeadas precisam de modo privado. Pare o contêiner, defina público: false in /config/config.js, inicie-o novamente e crie cada usuário com: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>",
|
||||
"Neither /etc/kernel/cmdline nor /etc/default/grub found.": "Nem /etc/kernel/cmdline nem /etc/default/grub foram encontrados.",
|
||||
"Nesting feature enabled": "Recurso de aninhamento ativado",
|
||||
"NetBIOS Service: RUNNING": "Serviço NetBIOS: EM EXECUÇÃO",
|
||||
@@ -3674,7 +3674,7 @@
|
||||
"Netbox is an IP address management (IPAM) and data center infrastructure management (DCIM) tool. Initially conceived by the network engineering team at DigitalOcean, NetBox was developed specifically to address the needs of network and infrastructure engineers. It is intended to function as a domain-specific source of truth for network operations.": "Netbox é uma ferramenta de gerenciamento de endereços IP (IPAM) e gerenciamento de infraestrutura de data center (DCIM). Inicialmente concebido pela equipe de engenharia de rede da DigitalOcean, o NetBox foi desenvolvido especificamente para atender às necessidades dos engenheiros de rede e infraestrutura. Pretende-se funcionar como uma fonte específica de domínio de verdade para a rede operations.",
|
||||
"Network": "Rede",
|
||||
"Network :": "Rede :",
|
||||
"Network & Firewall": "Rede e Firewall",
|
||||
"Network & Firewall": "Rede e firewall",
|
||||
"Network (interfaces, DNS)": "Rede (interfaces, DNS)",
|
||||
"Network Bridge": "Ponte de rede",
|
||||
"Network Commands": "Comandos de rede",
|
||||
@@ -4045,7 +4045,7 @@
|
||||
"OCI containers require Proxmox VE 9.1 or later.": "Os contêineres OCI requerem Proxmox VE 9.1 ou posterior.",
|
||||
"OCI management": "Gestão de OCI",
|
||||
"OCI management could not be completed. Check the backend status; no additional cleanup has been authorized.": "A gestão do OCI não pôde ser concluída. Verifique o estado da infra- estrutura; nenhuma limpeza adicional foi autorizada.",
|
||||
"OCI manager Apps (beta)": "Apps do gestor de OCI (beta)",
|
||||
"OCI manager Apps (beta)": "OCI manager Apps (beta)",
|
||||
"OCI manager Apps is a beta: if something does not work as expected, please report it on GitHub with the application name.": "Gerenciador de OCI Apps é um beta: se algo não funcionar como esperado, por favor, relate no GitHub com o nome da aplicação.",
|
||||
"OCI metadata integrity mismatch": "Incompatibilidade da integridade dos metadados OCI",
|
||||
"OCI metadata too large": "Metadados OCI demasiado grandes",
|
||||
@@ -4377,7 +4377,7 @@
|
||||
"Postfix configuration": "Configuração Postfix",
|
||||
"PostgreSQL": "PostgreSQL",
|
||||
"PostgreSQL URL without an associated service:": "URL do PostgreSQL sem um serviço associado:",
|
||||
"PostgreSQL creates the database named in POSTGRES_DB on the first start. The installer default is postgresql.": "PostgreSQL cria o banco de dados nomeado em POSTGRES DB no primeiro início. O instalador do programa é chamado geralmente de postgresql.",
|
||||
"PostgreSQL creates the database named in POSTGRES_DB on the first start. The installer default is postgresql.": "PostgreSQL cria o banco de dados nomeado em POSTGRES_DB no primeiro início. O instalador do programa é chamado geralmente de postgresql.",
|
||||
"PostgreSQL is an advanced, enterprise-class, and open-source relational database system. PostgreSQL supports both SQL (relational) and JSON (non-relational) querying.": "PostgreSQL é um sistema de banco de dados relacional avançado, de classe empresarial e de código aberto. O PostgreSQL suporta consultas SQL (relacionais) e JSON (não relacionais).",
|
||||
"PostgreSQL requires a password": "PostgreSQL requires uma senha",
|
||||
"PostgreSQL volume size in GB": "Tamanho do volume PostgreSQL em GB",
|
||||
@@ -4541,7 +4541,7 @@
|
||||
"Pwndrop is a self-deployable file hosting service for sending out red teaming payloads or securely sharing your private files over HTTP and WebDAV.": "Pwndrop é um serviço de hospedagem de arquivos auto-implantável para enviar cargas de trabalho de equipes vermelhas ou compartilhar seus arquivos privados com segurança por HTTP e WebDAV.",
|
||||
"PyCharm offers out-of-the-box support for Python, databases, Jupyter, Git, Conda, PyTorch, TensorFlow, Hugging Face, Django, Flask, FastAPI, and more.": "O PyCharm oferece suporte para Python, bases de dados, Jupyter, Git, Conda, PyTorch, TensorFlow, Hugging Face, Django, Flask, FastAPI e muito mais.",
|
||||
"Pydio Cells needs an external MySQL or MariaDB database. The setup wizard asks for its address, database name and user on the first start.": "Pydio Cells precisa de um banco de dados externo MySQL ou MariaDB. O assistente de configuração pede o seu endereço, nome do banco de dados e usuário no primeiro início.",
|
||||
"Pydio Cells redirects to the address given in EXTERNALURL. If the container changes address, edit lxc.environment.runtime: EXTERNALURL and SERVER_IP in /etc/pve/lxc/<CTID>.conf with the container stopped, and delete /config/keys/cert.crt to regenerate the certificate.": "Pydio Cells redireciona para o endereço indicado em EXTERNALURL. Se o recipiente mudar de endereço, edite lxc.environment.runtime: EXTERNALURL e SERVER IP em /etc/pve/lxc/<CTID>.conf com o recipiente parado, e apague /config/keys/cert.crt para regenerar o certificado.",
|
||||
"Pydio Cells redirects to the address given in EXTERNALURL. If the container changes address, edit lxc.environment.runtime: EXTERNALURL and SERVER_IP in /etc/pve/lxc/<CTID>.conf with the container stopped, and delete /config/keys/cert.crt to regenerate the certificate.": "Pydio Cells redireciona para o endereço indicado em EXTERNALURL. Se o recipiente mudar de endereço, edite lxc.environment.runtime: EXTERNALURL e SERVER_IP em /etc/pve/lxc/<CTID>.conf com o recipiente parado, e apague /config/keys/cert.crt para regenerar o certificado.",
|
||||
"Pydio-cells is the nextgen file sharing platform for organizations. It is a full rewrite of the Pydio project using the Go language following a micro-service architecture.": "Pydio-cells é a plataforma de compartilhamento de arquivos do nextgen para organizações. É uma reescrita completa do projeto Pydio usando a linguagem Go seguindo uma arquitetura de micro-serviço.",
|
||||
"QDirStat Qt-based directory statistics: KDirStat without any KDE -- from the author of the original KDirStat.": "QDirStat Estatísticas de pastas baseadas em Qt: KDirStat sem qualquer KDE -- do autor do KDirStat original.",
|
||||
"Quick health check (PASSED / FAILED)": "Verificação rápida de integridade (APROVADO/FALHA)",
|
||||
@@ -4686,7 +4686,7 @@
|
||||
"Remapped users:": "Usuários remapeados:",
|
||||
"Reminder: You must install the QEMU Guest Agent inside the Windows VM": "Lembrete: você deve instalar o agente convidado QEMU dentro da VM do Windows",
|
||||
"Remmina is a remote desktop client written in GTK, aiming to be useful for system administrators and travellers, who need to work with lots of remote computers in front of either large or tiny screens. Remmina supports multiple network protocols, in an integrated and consistent user interface. Currently RDP, VNC, SPICE, SSH and EXEC are supported.": "Remmina é um cliente de desktop remoto escrito em GTK, visando ser útil para administradores de sistema e viajantes, que precisam trabalhar com muitos computadores remotos na frente de telas grandes ou minúsculas. Remmina suporta vários protocolos de rede, em uma interface de usuário integrada e consistente. Atualmente RDP, VNC, SPICE, SSH e EXEC são suportados.",
|
||||
"Remote Access & VPN": "Acesso remoto & VPN",
|
||||
"Remote Access & VPN": "Acesso remoto e VPN",
|
||||
"Remote dry run completed; no container was created.": "Execução seca remota concluída; nenhum recipiente foi criado.",
|
||||
"Remote repository path:": "Caminho do repositório remoto:",
|
||||
"Remote server via SSH (recommended — off-host, dedup across machines)": "Servidor remoto via SSH (recomendado — fora do host, desduplicação entre máquinas)",
|
||||
@@ -5955,7 +5955,7 @@
|
||||
"The imported Compose requests privileged, but the official jlesage/handbrake documentation does not require it; ProxMenux keeps the LXC unprivileged.": "Os pedidos Compose importados são privilegiados, mas a documentação oficial jlesage/handbrake não require-lo; ProxMenux mantém o LXC sem privilégios.",
|
||||
"The imported OCI groups are not numeric": "Os grupos OCI importados não são numéricos",
|
||||
"The imported OCI user or group is not numeric": "O usuário ou grupo OCI importado não é numérico",
|
||||
"The initial user name and password stay written in /etc/pve/lxc/<CTID>.conf as INIT_USERNAME and INIT_PASSWORD. They can be removed after the first login, with the container stopped.": "O nome de usuário inicial e senha permanecem escritos em /etc/pve/lxc/<CTID>.conf como INIT USERNAME e INIT PASSWORD. Eles podem ser removidos após o primeiro login, com o recipiente parado.",
|
||||
"The initial user name and password stay written in /etc/pve/lxc/<CTID>.conf as INIT_USERNAME and INIT_PASSWORD. They can be removed after the first login, with the container stopped.": "O nome de usuário inicial e senha permanecem escritos em /etc/pve/lxc/<CTID>.conf como INIT_USERNAME e INIT_PASSWORD. Eles podem ser removidos após o primeiro login, com o recipiente parado.",
|
||||
"The installation asks which one to use for these paths.": "A instalação pergunta qual usar para estes caminhos.",
|
||||
"The installation ended with exit code": "A instalação terminou com o código de saída",
|
||||
"The installation requires a server restart to apply changes. Do you want to restart now?": "A instalação requer a reinicialização do servidor para aplicar as alterações. Quer reiniciar agora?",
|
||||
@@ -6074,7 +6074,7 @@
|
||||
"The rootfs is not managed by Proxmox": "O rootfs não é gerido pelo Proxmox",
|
||||
"The rootfs is not mounted": "O rootfs não está montado",
|
||||
"The same GPU cannot be used by two VMs at the same time.": "A mesma GPU não pode ser usada por duas VMs ao mesmo tempo.",
|
||||
"The same connection can be given as container variables instead of the file: UN_SONARR_0_URL and UN_SONARR_0_API_KEY, or the UN_RADARR_0_ equivalents.": "A mesma conexão pode ser dada como variáveis de container em vez do arquivo: UN SONARR 0 URL e UN SONARR 0 API KEY, ou o UN RADARR 0 equivalentes.",
|
||||
"The same connection can be given as container variables instead of the file: UN_SONARR_0_URL and UN_SONARR_0_API_KEY, or the UN_RADARR_0_ equivalents.": "A mesma conexão pode ser dada como variáveis de container em vez do arquivo: UN_SONARR_0_URL e UN_SONARR_0_API_KEY, ou o UN RADARR 0 equivalentes.",
|
||||
"The saved MOTD state is invalid; no changes were made": "O estado MOTD salvo é inválido;nenhuma alteração foi feita",
|
||||
"The saved OCI record is incomplete or has an unexpected format.": "O registro OCI salvo está incompleto ou tem um formato inesperado.",
|
||||
"The saved projection does not match the native evidence": "A projeção salva não corresponde à evidência nativa",
|
||||
@@ -6822,7 +6822,7 @@
|
||||
"Web interface to manage devices running Tasmota firmware.": "Interface Web para gerenciar dispositivos rodando firmware Tasmota.",
|
||||
"WebCord can be summarized as a pack of security and privacy hardenings, Discord features reimplementations, Electron / Chromium / Discord bugs workarounds, stylesheets, internal pages and wrapped https://discord.com page, designed to conform with ToS as much as it is possible (or hide the changes that might violate it from Discord's eyes).": "WebCord pode ser resumido como um pacote de endurecimentos de segurança e privacidade, recursos de discórdia reimplementações, Electron / Chromium / Erros de discórdia workarounds, stylesheets, páginas internas e página envolto https://discord.com, projetado para se conformar com ToS tanto quanto possível (ou ocultar as alterações que podem violá-lo dos olhos da Discord).",
|
||||
"Webgrabplus is a multi-site incremental xmltv epg grabber. It collects tv-program guide data from selected tvguide sites for your favourite channels.": "Webgrabplus é um multi-site incremental xmltv epg grabber. Ele coleta dados de guias de tv-programa de sites selecionados para seus canais favoritos.",
|
||||
"Webservers & Proxies": "Servidores Web & Proxies",
|
||||
"Webservers & Proxies": "Servidores web e proxies",
|
||||
"Website": "Site",
|
||||
"Webstation is a web native emulation focused LXQt desktop based on Ubuntu.": "Webstation é um ambiente de trabalho LXQt baseado no Ubuntu.",
|
||||
"Webtop - Alpine, Ubuntu, Fedora, and Arch based containers containing full desktop environments in officially supported flavors accessible via any modern web browser.": "Webtop - Embalagens baseadas em Alpine, Ubuntu, Fedora e Arch contendo ambientes de desktop completos em sabores oficialmente suportados acessíveis através de qualquer navegador moderno.",
|
||||
@@ -6855,7 +6855,7 @@
|
||||
"WireGuard® is an extremely simple yet fast and modern VPN that utilizes state-of-the-art cryptography. It aims to be faster, simpler, leaner, and more useful than IPsec, while avoiding the massive headache. It intends to be considerably more performant than OpenVPN. WireGuard is designed as a general purpose VPN for running on embedded interfaces and super computers alike, fit for many different circumstances. Initially released for the Linux kernel, it is now cross-platform (Windows, macOS, BSD, iOS, Android) and widely deployable. It is currently under heavy development, but already it might be regarded as the most secure, easiest to use, and simplest VPN solution in the industry.": "WireGuard® é uma VPN extremamente simples, mas rápida e moderna, que utiliza criptografia de última geração. Pretende ser mais rápido, mais simples, mais magro e mais útil do que o IPsec, evitando ao mesmo tempo a enorme dor de cabeça. Pretende ser consideravelmente mais performante do que o OpenVPN. WireGuard é projetado como uma VPN de propósito geral para execução em interfaces incorporadas e super computadores, apto para muitas circunstâncias diferentes. Inicialmente lançado para o kernel Linux, ele agora é multi-plataforma (Windows, macOS, BSD, iOS, Android) e amplamente implantável. Ele está atualmente em desenvolvimento pesado, mas já pode ser considerado como a solução VPN mais segura, mais fácil de usar e mais simples no setor.",
|
||||
"Wired NICs in backup missing on target:": "NICs com fio no backup ausentes no destino:",
|
||||
"Wireshark is the world’s foremost and widely-used network protocol analyzer. It lets you see what’s happening on your network at a microscopic level and is the de facto (and often de jure) standard across many commercial and non-profit enterprises, government agencies, and educational institutions. Wireshark development thrives thanks to the volunteer contributions of networking experts around the globe and is the continuation of a project started by Gerald Combs in 1998.": "Wireshark é o principal e amplamente utilizado analisador de protocolos de rede do mundo. Ele permite que você veja o que está acontecendo em sua rede em um nível microscópico e é o padrão de fato (e muitas vezes de jure) em muitas empresas comerciais e sem fins lucrativos, agências governamentais e instituições educacionais. O desenvolvimento do Wireshark prospera graças às contribuições voluntárias de especialistas em redes em todo o mundo e é a continuação de um projeto iniciado por Gerald Combs em 1998.",
|
||||
"With dns validation, the DNSPLUGIN variable names the provider plugin. The advanced installation asks for it; otherwise add the line lxc.environment.runtime: DNSPLUGIN=<plugin> to /etc/pve/lxc/<CTID>.conf with the container stopped.": "Com validação dns, as variáveis DNSPLUGIN nomeiam o plugin provedor. A instalação avançada pede; caso contrário, adicione a linha lxc.environment. tempo de execução: DNSPLUGIN=<plugin> para /etc/pve/lxc/<CTID>.conf com o recipiente parado.",
|
||||
"With dns validation, the DNSPLUGIN variable names the provider plugin. The advanced installation asks for it; otherwise add the line lxc.environment.runtime: DNSPLUGIN=<plugin> to /etc/pve/lxc/<CTID>.conf with the container stopped.": "Com validação dns, as variáveis DNSPLUGIN nomeiam o plugin provedor. A instalação avançada pede; caso contrário, adicione a linha lxc.environment.runtime: DNSPLUGIN=<plugin> ao /etc/pve/lxc/<CTID>.conf com o recipiente parado.",
|
||||
"With dns validation, write the provider credentials in /config/dns-conf/<plugin>.ini inside the container and restart it.": "Com validação dns, escreva o provedor credentials em /config/dns-conf/<plugin>.ini dentro do recipiente e reinicie-o.",
|
||||
"With http validation, port 80 of the router must be forwarded to port 80 of this container.": "Com a validação http, a porta 80 do roteador deve ser encaminhada para a porta 80 deste recipiente.",
|
||||
"With warnings": "Com avisos",
|
||||
|
||||
+32
-33
@@ -120,7 +120,7 @@
|
||||
"ACL Status:": "Stav ACL:",
|
||||
"ACL permissions applied for local access for user:": "ACL oprávnenia boli nastavené pre lokálny prístup používateľa:",
|
||||
"ADVANCED SETTINGS COMPLETE": "POKROČILÉ NASTAVENIA SÚ HOTOVÉ",
|
||||
"AI / Coding & Dev-Tools": "AI / Coding & Dev-Tools",
|
||||
"AI / Coding & Dev-Tools": "AI, programovanie a vývoj",
|
||||
"ALL DATA ON": "VŠETKY DÁTA NA",
|
||||
"ALL DATA ON THIS DISK WILL BE PERMANENTLY LOST!": "VŠETKY DÁTA NA TOMTO DISKU BUDÚ NATRVALO STRATENÉ!",
|
||||
"ALL Utilities": "VŠETKY nástroje",
|
||||
@@ -185,7 +185,7 @@
|
||||
"Actual device path on the host": "Skutočná dráha zariadenia na hostiteľovi",
|
||||
"Adaptation file too large": "Adaptačný súbor príliš veľký",
|
||||
"Adaptation file with unexpected permissions or owner": "Adaptačný súbor s neočakávanými oprávneniami alebo majiteľom",
|
||||
"Adblock & DNS": "Adblock & DNS",
|
||||
"Adblock & DNS": "Adblock a DNS",
|
||||
"Add Audio Passthrough": "Pridať audio passthrough",
|
||||
"Add CIFS storage:": "Pridať CIFS úložisko:",
|
||||
"Add Controller or NVMe (PCI passthrough)": "Pridať radič alebo NVMe (priame priradenie cez PCI)",
|
||||
@@ -317,7 +317,7 @@
|
||||
"Already Mounted": "Už je pripojené",
|
||||
"Already configured": "Už nastavené",
|
||||
"Already installed — skipping": "Už nainštalované - preskakujem",
|
||||
"Also add the /dev/srX optical device (recommended)": "Tiež pridať /dev / srX optické zariadenie (odporúčané)",
|
||||
"Also add the /dev/srX optical device (recommended)": "Tiež pridať /dev/srX optické zariadenie (odporúčané)",
|
||||
"Also comment any remaining 'bookworm' entries in *.list if present.": "Zakomentujte aj všetky zostávajúce položky 'bookworm' v *.list, ak existujú.",
|
||||
"Also install the VirtIO network driver during setup to enable network access.": "Počas inštalácie nainštalujte aj sieťový ovládač VirtIO, aby fungoval prístup k sieti.",
|
||||
"Although VFIO can bind to this device, full passthrough to a VM is": "Aj keď sa VFIO vie na toto zariadenie naviazať, úplný passthrough do VM je",
|
||||
@@ -439,7 +439,7 @@
|
||||
"Auth key is required.": "Auth key je povinný.",
|
||||
"Auth:": "Prihlásenie:",
|
||||
"Authentication": "Prihlásenie",
|
||||
"Authentication & Security": "Overenie a bezpečnosť",
|
||||
"Authentication & Security": "Overovanie a zabezpečenie",
|
||||
"Authentication Error": "Chyba prihlásenia",
|
||||
"Authentication failed.": "Prihlásenie zlyhalo.",
|
||||
"Authentication required:": "Vyžaduje prihlásenie:",
|
||||
@@ -500,7 +500,7 @@
|
||||
"Backend:": "Backend:",
|
||||
"Background archive extraction for Arr download queues. No web interface.": "Extrakcia archívu pozadia pre Arr download fronty. Žiadne webové rozhranie.",
|
||||
"Backup — VM and CT backups": "Backup — zálohy VM a CT",
|
||||
"Backup & Recovery": "Záloha a obnova",
|
||||
"Backup & Recovery": "Zálohovanie a obnova",
|
||||
"Backup Created": "Záloha bola vytvorená",
|
||||
"Backup ID (group name in PBS):": "ID zálohy (názov skupiny v PBS):",
|
||||
"Backup ID for this job:": "ID zálohy pre túto úlohu:",
|
||||
@@ -607,7 +607,7 @@
|
||||
"Build and install the gasket and apex kernel modules (DKMS)": "Zostaví a nainštaluje kernel moduly gasket a apex (DKMS)",
|
||||
"Build dependencies installed.": "Závislosti na zostavenie boli nainštalované.",
|
||||
"Build your personal knowledge base with TriliumNext Notes": "Budujte si osobné znalosti základne s TriliumNext Poznámky",
|
||||
"Business & ERP": "Obchod a ERP",
|
||||
"Business & ERP": "Biznis a ERP",
|
||||
"CHANGES APPLIED SUCCESSFULLY": "ZMENY BOLI ÚSPEŠNE POUŽITÉ",
|
||||
"CIFS Client Tools: AVAILABLE": "Nástroje CIFS klienta: DOSTUPNÉ",
|
||||
"CIFS Client Tools: NOT AVAILABLE - installing...": "Nástroje CIFS klienta: NEDOSTUPNÉ - inštalujem...",
|
||||
@@ -869,7 +869,7 @@
|
||||
"Commenting legacy ceph.list (if present)...": "Komentujem starý ceph.list (ak existuje)...",
|
||||
"Common Issues Check": "Kontrola bežných problémov",
|
||||
"Common root for the published views": "Spoločný koreň uverejnených názorov",
|
||||
"Communication & Community": "Komunikácia a Spoločenstvo",
|
||||
"Communication & Community": "Komunikácia a komunita",
|
||||
"Community Scripts": "Komunitné skripty",
|
||||
"Community single-container Home Assistant OS image": "Jednoduchý kontajner Spoločenstva Home Assistant OS image",
|
||||
"Compatibility check": "Kontrola kompatibility",
|
||||
@@ -1142,7 +1142,7 @@
|
||||
"Converts to deb822; keeps .list backups as .bak": "Prevedie na deb822; zálohy .list ponechá ako .bak",
|
||||
"Coordinated backups require zstd": "Koordinované zálohy require zstd",
|
||||
"Cops by Sébastien Lucas, now maintained by MikesPub, stands for Calibre OPDS (and HTML) Php Server.": "Cops by Sébastien Lucas, teraz udržiavané MikesPub, znamená Calibre OPDS (a HTML) Php Server.",
|
||||
"Copy a peer configuration to the host with: pct pull <CTID> /config/peer1/peer1.conf peer1.conf": "Kopírovať konfiguráciu peer k hostiteľovi s: pct pull < CTID > /config/peer1/peer1.conf peer1.conf",
|
||||
"Copy a peer configuration to the host with: pct pull <CTID> /config/peer1/peer1.conf peer1.conf": "Kopírovať konfiguráciu peer k hostiteľovi s: pct pull <CTID> /config/peer1/peer1.conf peer1.conf",
|
||||
"Copy failed": "Kopírovanie zlyhalo",
|
||||
"Copy that file offsite yourself, or download it from the Monitor.": "Skopírujte si tento súbor mimo servera sami alebo ho stiahnite z Monitoru.",
|
||||
"Copy the correct keyfile to this host and rerun Restore — or pick an unencrypted backup.": "Skopírujte správny keyfile na tento host a spustite obnovu znova - alebo vyberte nešifrovanú zálohu.",
|
||||
@@ -1157,7 +1157,7 @@
|
||||
"Coral M.2 Apex configuration added - device ready": "Nastavenie Coral M.2 Apex bolo pridané - zariadenie je pripravené",
|
||||
"Coral M.2 Apex configuration added - device will be available after reboot": "Nastavenie Coral M.2 Apex bolo pridané - zariadenie bude dostupné po reštarte",
|
||||
"Coral M.2 Apex detected, configuring...": "Našiel sa Coral M.2 Apex, nastavujem...",
|
||||
"Coral PCIe/M.2 node (e.g. /dev/apex_0)": "Coral PCIe/M.2 uzly (napr. /dev/apex 0)",
|
||||
"Coral PCIe/M.2 node (e.g. /dev/apex_0)": "Coral PCIe/M.2 uzly (napr. /dev/apex_0)",
|
||||
"Coral TPU Installation": "Inštalácia Coral TPU",
|
||||
"Coral TPU Uninstall": "Odinštalovanie Coral TPU",
|
||||
"Coral TPU device nodes detected with correct group (apex).": "Uzly zariadenia Coral TPU sa našli so správnou skupinou (apex).",
|
||||
@@ -1345,7 +1345,7 @@
|
||||
"Creating the container...": "Vytváram kontajner...",
|
||||
"Creating the initial administrator...": "Vytvorenie počiatočného správcu...",
|
||||
"Creating the temporary data container": "Vytvorenie dočasného dátového kontajnera",
|
||||
"Creative & Design": "Creative & Design",
|
||||
"Creative & Design": "Kreativita a dizajn",
|
||||
"Credentials are correct": "Prihlasovacie údaje sú správne",
|
||||
"Credentials cleared. jwt_secret and API tokens preserved.": "Prihlasovacie údaje sú vymazané. jwt_secret a API tokeny zostali zachované.",
|
||||
"Credentials file created securely.": "Súbor s prihlasovacími údajmi bol bezpečne vytvorený.",
|
||||
@@ -1731,7 +1731,7 @@
|
||||
"Dry run completed; the container and the mounts were not changed.": "Suchý chod dokončený; kontajner a držiaky neboli zmenené.",
|
||||
"DuckDNS subdomain without .duckdns.org (comma separated for several)": "DuckDNS subdoména bez .duckdns.org (koma oddelené pre niekoľko)",
|
||||
"DuckDNS token from your account at duckdns.org": "DuckDNS token z vášho účtu na duckdns.org",
|
||||
"DuckDNS updates the subdomain every 5 minutes. Without UPDATE_IP, DuckDNS itself detects the public IPv4 address of the request.": "DuckDNS aktualizuje subdoménu každých 5 minút. Bez UPDATE IP samotná DuckDNS detekuje verejnú IPv4 adresu žiadosti.",
|
||||
"DuckDNS updates the subdomain every 5 minutes. Without UPDATE_IP, DuckDNS itself detects the public IPv4 address of the request.": "DuckDNS aktualizuje subdoménu každých 5 minút. Bez UPDATE_IP samotná DuckDNS detekuje verejnú IPv4 adresu žiadosti.",
|
||||
"DuckStation is a PS1 Emulator aiming for the best accuracy and game support.": "DuckStation je PS1 Emulátor zameraný na najlepšie accuracy a hernú podporu.",
|
||||
"Duckdns is a free service which will point a DNS (sub domains of duckdns.org) to an IP of your choice. The service is completely free, and doesn't require reactivation or forum posts to maintain its existence.": "Duckdns je bezplatná služba, ktorá bude ukazovať DNS (pod domény duckdns.org) na IP podľa vášho výberu. Služba je úplne zadarmo, a nie je require reaktivácia alebo fóra príspevky udržať jeho existenciu.",
|
||||
"Dumping AMD GPU ROM BIOS via sysfs...": "Vytváram dump AMD GPU ROM BIOS cez sysfs...",
|
||||
@@ -2230,7 +2230,7 @@
|
||||
"FileBrowser Quantum": "FileBrowser Quantum",
|
||||
"FileBrowser Quantum (new installation)": "FileBrowser Quantum (nová inštalácia)",
|
||||
"FileDrop is a free, open source file sharing service": "FileDrop je bezplatná služba zdieľania súborov s otvoreným zdrojom",
|
||||
"Files & Downloads": "Súbory a sťahovania",
|
||||
"Files & Downloads": "Súbory a sťahovanie",
|
||||
"Files volume size in GB": "Veľkosť hlasitosti súborov v GB",
|
||||
"Filesystem": "Súborový systém",
|
||||
"Filesystem Tools Required": "Sú potrebné nástroje pre súborový systém",
|
||||
@@ -2239,7 +2239,7 @@
|
||||
"Final cleanup of the stack operation completed": "Konečné vyčistenie stohu operation dokončené",
|
||||
"Final confirmation": "Posledné potvrdenie",
|
||||
"Final storage health/status check": "Záverečná kontrola stavu úložiska",
|
||||
"Finance & Budgeting": "Finance & Budgeting",
|
||||
"Finance & Budgeting": "Financie a rozpočet",
|
||||
"Find your device using https://finds.synology.com": "Zariadenie nájdete cez https://finds.synology.com",
|
||||
"Fingerprint:": "Odtlačok:",
|
||||
"Firefly, the easiest using of WireGuard VPN server, plus version of wg-easy.": "Firefly, najjednoduchšie používanie WireGuard VPN servera, plus verzia wg-ľahké.",
|
||||
@@ -2387,7 +2387,7 @@
|
||||
"GRUB_CMDLINE_LINUX_DEFAULT not found in GRUB config": "GRUB_CMDLINE_LINUX_DEFAULT sa v nastavení GRUB nenašlo",
|
||||
"GUI mode (if available)": "Grafický režim (ak je dostupný)",
|
||||
"GZDoom is a feature centric port for all Doom engine games, based on ZDoom, adding an OpenGL renderer and powerful scripting capabilities.": "GZDoom je funkcia centrický port pre všetky hry Doom motora, založené na ZDoom, pridanie OpenGL kresbu a mocné skriptovanie schopnosti.",
|
||||
"Gaming & Leisure": "Herné a leisure",
|
||||
"Gaming & Leisure": "Hry a voľný čas",
|
||||
"Gateway is not installed.": "Brána nie je nainštalovaná.",
|
||||
"Gateway removed.": "Brána odstránená.",
|
||||
"Gateway restarted.": "Brána reštartovaná.",
|
||||
@@ -2527,7 +2527,7 @@
|
||||
"Host GPU detected": "Na hoste sa našla GPU",
|
||||
"Host GPU is already bound to vfio-pci. Host reconfiguration/reboot should not be required for this VM-to-VM reassignment.": "GPU na hostovi už je naviazaná na vfio-pci. Pri tomto presune VM-to-VM by nemalo byť potrebné meniť hosta ani reštartovať.",
|
||||
"Host IP": "IP hosta",
|
||||
"Host Management": "Správa hostiteľov",
|
||||
"Host Management": "Správa hostiteľa",
|
||||
"Host Mount Path": "Cesta mountu na hostovi",
|
||||
"Host NFS/Samba as Proxmox Storage (pvesm)": "Host NFS/Samba ako úložisko Proxmoxu (pvesm)",
|
||||
"Host Path": "Cesta na hostovi",
|
||||
@@ -2541,7 +2541,7 @@
|
||||
"Host already in VFIO mode — skipping host reconfiguration for VM reassignment": "Host už je vo VFIO režime - zmena hosta sa pri presune medzi VM preskakuje",
|
||||
"Host audio devices": "Hostiteľské audio zariadenia",
|
||||
"Host backup attached to PVE job": "Záloha hosta bola pripojená k PVE úlohe",
|
||||
"Host data is not restored by the backup; confirm it with --acknowledge-external-data": "Údaje o hostiteľovi nie sú obnovené zálohou; potvrďte ich -- acnown-external-data",
|
||||
"Host data is not restored by the backup; confirm it with --acknowledge-external-data": "Hostiteľské dáta nie sú obnovené zálohou; potvrďte to pomocou --acknowledge-external-data",
|
||||
"Host device for /dev/kvm": "Hostiteľské zariadenie pre /dev/kvm",
|
||||
"Host device for /dev/net/tun": "Hostiteľské zariadenie pre /dev/net/tun",
|
||||
"Host device for /dev/ttyUSB0": "Hostiteľské zariadenie pre /dev/ttyUSB0",
|
||||
@@ -2795,7 +2795,7 @@
|
||||
"Initiator IQN is authorised on the target": "IQN iniciátora je na targete povolené",
|
||||
"Initiator IQN:": "IQN iniciátora:",
|
||||
"Inkscape is professional quality vector graphics software which runs on Linux, Mac OS X and Windows desktop computers.": "Inkscape je profesionálne kvalitný vektorový grafický softvér, ktorý beží na počítačoch Linux, Mac OS X a Windows.",
|
||||
"Inside the LXC, create the administrator: console kimai:user:create YOUR_USERNAME YOUR_EMAIL ROLE_SUPER_ADMIN": "Vnútri LXC, vytvoriť administrátor: konzola kimai:používateľ:vytvorte VAŠE VYUŽITE VAŠE EMAIL ROLE SUPER ADMIN",
|
||||
"Inside the LXC, create the administrator: console kimai:user:create YOUR_USERNAME YOUR_EMAIL ROLE_SUPER_ADMIN": "Vnútri LXC, vytvoriť administrátor: konzola kimai:používateľ:vytvorte VAŠE VYUŽITE VAŠE EMAIL ROLE_SUPER_ADMIN",
|
||||
"Inspect disks before any action": "Skontrolovať disky pred akoukoľvek akciou",
|
||||
"Inspect host device nodes": "Skontrolovať device nodes na hostovi",
|
||||
"Inspect passthrough/kernel events": "Skontrolovať passthrough/kernel udalosti",
|
||||
@@ -3242,7 +3242,7 @@
|
||||
"Limiting size and optimizing journald": "Obmedzujem veľkosť a optimalizujem journald",
|
||||
"Limiting size and optimizing journald...": "Obmedzujem veľkosť a optimalizujem journald...",
|
||||
"Limnoria A robust, full-featured, and user/programmer-friendly Python IRC bot, with many existing plugins. Successor of the well-known Supybot.": "Limnoria Robustný, full-featured, a užívateľsky / programátor-friendly Python IRC robot, s mnohými existujúcimi modulmi. Nástupca známeho Supybota.",
|
||||
"Limnoria joins no IRC network until its configuration file exists. Create it with the setup wizard from the Proxmox host: pct exec <CTID> -- bash -c 'cd /config && limnoria-wizard'": "Limnoria sa pripája k žiadnej sieti IRC, kým neexistuje jej konfiguračný súbor. Vytvorte ho pomocou sprievodcu nastavením z Proxmox hostiteľa: pct exec <CTID > -- bash -c 'cd /config && limnoria-wizard'",
|
||||
"Limnoria joins no IRC network until its configuration file exists. Create it with the setup wizard from the Proxmox host: pct exec <CTID> -- bash -c 'cd /config && limnoria-wizard'": "Limnoria sa pripája k žiadnej sieti IRC, kým neexistuje jej konfiguračný súbor. Vytvorte ho pomocou sprievodcu nastavením z Proxmox hostiteľa: pct exec <CTID> -- bash -c 'cd /config && limnoria-wizard'",
|
||||
"Line to paste (single line, including \"command=...\" prefix):": "Riadok na vloženie (jeden riadok vrátane predpony \"command=...\"):",
|
||||
"Linux Installation Options": "Možnosti inštalácie Linuxu",
|
||||
"Linux/Mac path:": "Cesta pre Linux/Mac:",
|
||||
@@ -3386,7 +3386,7 @@
|
||||
"Max user watches configured": "Maximálny počet user watches je nastavený",
|
||||
"Maximum auto-repair attempts reached (3). Please review the log and run any remaining commands manually.": "Bol dosiahnutý maximálny počet automatických opráv (3). Skontrolujte záznam a zostávajúce príkazy spustite ručne.",
|
||||
"May need to restart terminal": "Možno bude potrebné reštartovať terminál",
|
||||
"Media & Streaming": "Media & Streaming",
|
||||
"Media & Streaming": "Médiá a streaming",
|
||||
"Media discovery and request management for Jellyfin, Plex and Emby.": "Mediálny prieskum a správa požiadaviek pre Jellyfin, Plex a Emby.",
|
||||
"Media library transcoding and health checking, with an internal worker node.": "Média knižnica transkódovanie a zdravotná kontrola, s interným uzol pracovníka.",
|
||||
"Media server": "Mediálny server",
|
||||
@@ -3652,7 +3652,7 @@
|
||||
"NVMe health status: WARNING (critical_warning =": "Stav NVMe: UPOZORNENIE (critical_warning =",
|
||||
"NVMe skipped (to add as PCIe use 'Add Controller or NVMe PCIe to VM'):": "NVMe preskočené (ak ho chcete pridať ako PCIe, použite 'Pridať radič alebo NVMe PCIe do VM'):",
|
||||
"NVMe-specific SMART log": "SMART záznam špecifický pre NVMe",
|
||||
"NVR & Cameras": "NVR & kamery",
|
||||
"NVR & Cameras": "NVR a kamery",
|
||||
"NVR with optional VA-API video acceleration and hardware object detectors": "NVR s voliteľným video zrýchlením VA-API a detektormi hardvérových objektov",
|
||||
"NZBGet web interface": "Webové rozhranie NZBGet",
|
||||
"Name": "Názov",
|
||||
@@ -3664,7 +3664,7 @@
|
||||
"Name of this wallabag instance, shown in the interface and in 2FA codes": "Názov tejto inštancie wallabag, zobrazený v rozhraní a v kódoch 2FA",
|
||||
"Name or part of the description of the application": "Názov alebo časť opisu žiadosti",
|
||||
"Name:": "Názov:",
|
||||
"Named accounts need private mode. Stop the container, set public: false in /config/config.js, start it again and create each user with: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>": "Menované účty potrebujú súkromný režim. Zastaviť kontajner, nastaviť verejnosť: false in /config/config.js, začať znova a vytvoriť každého užívateľa s: pct exec < CTID> -- env THELOUNGE HOME=/config s6-setuid abc thelounge pridať <user >",
|
||||
"Named accounts need private mode. Stop the container, set public: false in /config/config.js, start it again and create each user with: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>": "Menované účty potrebujú súkromný režim. Zastaviť kontajner, nastaviť verejnosť: false in /config/config.js, začať znova a vytvoriť každého užívateľa s: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuid abc thelounge pridať <user>",
|
||||
"Neither /etc/kernel/cmdline nor /etc/default/grub found.": "Nenašiel sa /etc/kernel/cmdline ani /etc/default/grub.",
|
||||
"Nesting feature enabled": "Funkcia nesting bola zapnutá",
|
||||
"NetBIOS Service: RUNNING": "Služba NetBIOS: BEŽÍ",
|
||||
@@ -3674,7 +3674,7 @@
|
||||
"Netbox is an IP address management (IPAM) and data center infrastructure management (DCIM) tool. Initially conceived by the network engineering team at DigitalOcean, NetBox was developed specifically to address the needs of network and infrastructure engineers. It is intended to function as a domain-specific source of truth for network operations.": "Netbox je nástroj riadenia IP adresy (IPAM) a riadenia infraštruktúry dátových centier (DCIM). Pôvodne koncipovaný sieťovým tímom v DigitalOcean, bol NetBox vyvinutý špeciálne pre potreby sieťových a infraštruktúrnych inžinierov. Je určený na fungovanie ako doménový špecifický zdroj pravdy pre siete operations.",
|
||||
"Network": "Sieť",
|
||||
"Network :": "Sieť :",
|
||||
"Network & Firewall": "Sieťový & firewall",
|
||||
"Network & Firewall": "Sieť a firewall",
|
||||
"Network (interfaces, DNS)": "Sieť (rozhrania, DNS)",
|
||||
"Network Bridge": "Sieťový bridge",
|
||||
"Network Commands": "Sieťové príkazy",
|
||||
@@ -4045,7 +4045,7 @@
|
||||
"OCI containers require Proxmox VE 9.1 or later.": "OCI kontajnery vyžadujú Proxmox VE 9.1 alebo novší.",
|
||||
"OCI management": "Riadenie OCI",
|
||||
"OCI management could not be completed. Check the backend status; no additional cleanup has been authorized.": "Riadenie OCI nebolo možné dokončiť. Skontrolujte stav backendu; žiadne dodatočné vyčistenie nebolo povolené.",
|
||||
"OCI manager Apps (beta)": "Aplikácie pre správcu OCI (beta)",
|
||||
"OCI manager Apps (beta)": "OCI manager Apps (beta)",
|
||||
"OCI manager Apps is a beta: if something does not work as expected, please report it on GitHub with the application name.": "OCI manažér Apps je beta: ak niečo nefunguje tak, ako sa očakávalo, nahláste to na GitHub s názvom aplikácie.",
|
||||
"OCI metadata integrity mismatch": "Nepomer integrity metaúdajov OCI",
|
||||
"OCI metadata too large": "Metaúdaje OCI príliš veľké",
|
||||
@@ -4377,7 +4377,7 @@
|
||||
"Postfix configuration": "Nastavenie Postfixu",
|
||||
"PostgreSQL": "PostgreSQL",
|
||||
"PostgreSQL URL without an associated service:": "PostgreSQL URL bez súvisiacej služby:",
|
||||
"PostgreSQL creates the database named in POSTGRES_DB on the first start. The installer default is postgresql.": "PostgreSQL vytvára databázu pomenovanú v POSTGRES DB na prvom začiatku. Štandardný inštalátor je postgresql.",
|
||||
"PostgreSQL creates the database named in POSTGRES_DB on the first start. The installer default is postgresql.": "PostgreSQL vytvára databázu pomenovanú v POSTGRES_DB na prvom začiatku. Štandardný inštalátor je postgresql.",
|
||||
"PostgreSQL is an advanced, enterprise-class, and open-source relational database system. PostgreSQL supports both SQL (relational) and JSON (non-relational) querying.": "PostgreSQL je moderný, podnikový a open-source relačný databázový systém. PostgreSQL podporuje ako SQL (relatívne) tak JSON (nerelatívne) dotazovanie.",
|
||||
"PostgreSQL requires a password": "PostgreSQL requires heslo",
|
||||
"PostgreSQL volume size in GB": "PostgreSQL veľkosť objemu v GB",
|
||||
@@ -4460,7 +4460,7 @@
|
||||
"Process may take several minutes depending on container size": "Proces môže trvať niekoľko minút podľa veľkosti kontajnera",
|
||||
"Process may take several minutes for large containers": "Pri veľkých kontajneroch môže proces trvať niekoľko minút",
|
||||
"Processes using NVIDIA:": "Procesy používajúce NVIDIA:",
|
||||
"Productivity & Workflows": "Produktivita a pracovné toky",
|
||||
"Productivity & Workflows": "Produktivita a pracovné postupy",
|
||||
"Profile": "Profil",
|
||||
"Profile:": "Profil:",
|
||||
"Projectsend is a self-hosted application that lets you upload files and assign them to specific clients that you create yourself. Secure, private and easy. No more depending on external services or e-mail to send those files.": "Projectsend je aplikácia self-hosted, ktorá vám umožní nahrávať súbory a priradiť ich konkrétnym klientom, ktoré vytvoríte sami. Bezpečné, súkromné a jednoduché. Už nie je závislá od externých služieb alebo e-mailu, ktorý by tieto súbory posielal.",
|
||||
@@ -4541,7 +4541,7 @@
|
||||
"Pwndrop is a self-deployable file hosting service for sending out red teaming payloads or securely sharing your private files over HTTP and WebDAV.": "Pwndrop je samozamestnávateľná serverová hostingová služba pre odosielanie červeného spojovacieho užitočného zaťaženia alebo bezpečné zdieľanie vašich súkromných súborov cez HTTP a WebDAV.",
|
||||
"PyCharm offers out-of-the-box support for Python, databases, Jupyter, Git, Conda, PyTorch, TensorFlow, Hugging Face, Django, Flask, FastAPI, and more.": "PyCharm ponúka mimo-of-the-box podporu pre Python, databázy, Jupyter, Git, Conda, PyTorch, TensorFlow, Hugging Face, Django, Flask, FastAPI a ďalšie.",
|
||||
"Pydio Cells needs an external MySQL or MariaDB database. The setup wizard asks for its address, database name and user on the first start.": "Pydio Cells potrebuje externú MySQL alebo MariaDB databázu. Sprievodca nastavením žiada o svoju adresu, meno databázy a užívateľa pri prvom štarte.",
|
||||
"Pydio Cells redirects to the address given in EXTERNALURL. If the container changes address, edit lxc.environment.runtime: EXTERNALURL and SERVER_IP in /etc/pve/lxc/<CTID>.conf with the container stopped, and delete /config/keys/cert.crt to regenerate the certificate.": "Pydio Cells presmeruje na adresu uvedenú v EXTERNURL. Ak kontajner zmení adresu, upravte lxc.environment.runtime: EXTERNURL a SERVER IP v /etc/pve/lxc/<CTID>.conf s kontajnerom zastavil, a odstráňte /config/keys/cert.crt pre regeneráciu certifikátu.",
|
||||
"Pydio Cells redirects to the address given in EXTERNALURL. If the container changes address, edit lxc.environment.runtime: EXTERNALURL and SERVER_IP in /etc/pve/lxc/<CTID>.conf with the container stopped, and delete /config/keys/cert.crt to regenerate the certificate.": "Pydio Cells presmeruje na adresu uvedenú v EXTERNURL. Ak kontajner zmení adresu, upravte lxc.environment.runtime: EXTERNURL a SERVER_IP v /etc/pve/lxc/<CTID>.conf s kontajnerom zastavil, a odstráňte /config/keys/cert.crt pre regeneráciu certifikátu.",
|
||||
"Pydio-cells is the nextgen file sharing platform for organizations. It is a full rewrite of the Pydio project using the Go language following a micro-service architecture.": "Pydio-bunky je platforma pre zdieľanie súborov pre organizácie. Je to úplný prepis projektu Pydio pomocou jazyka Go podľa architektúry mikroslužieb.",
|
||||
"QDirStat Qt-based directory statistics: KDirStat without any KDE -- from the author of the original KDirStat.": "QDirStat Štatistika adresára založená na Qt: KDirStat bez KDE -- od autora pôvodného KDirStat.",
|
||||
"Quick health check (PASSED / FAILED)": "Rýchla kontrola stavu (PASSED / FAILED)",
|
||||
@@ -5393,7 +5393,7 @@
|
||||
"Show size of a directory": "Zobraziť veľkosť priečinka",
|
||||
"Show standard exclude patterns": "Zobraziť štandardné vylučovacie vzory",
|
||||
"Show status of all storage pools": "Zobraziť stav všetkých úložísk",
|
||||
"Show the QR code of a peer again with: pct exec <CTID> -- /app/show-peer 1": "Zobraziť QR kód peera znovu s: pct exec < CTID > -- /app/show-peer 1",
|
||||
"Show the QR code of a peer again with: pct exec <CTID> -- /app/show-peer 1": "Zobraziť QR kód peera znovu s: pct exec <CTID> -- /app/show-peer 1",
|
||||
"Show traffic statistics per interface": "Zobraziť štatistiky prenosu podľa rozhrania",
|
||||
"Show vzdump backup configuration": "Zobraziť nastavenie vzdump záloh",
|
||||
"Shows status and type (nfs/cifs/dir/iscsi...).": "Zobrazí stav a typ (nfs/cifs/dir/iscsi...).",
|
||||
@@ -5719,7 +5719,6 @@
|
||||
"Thank you for using ProxMenux. Goodbye!": "Ďakujeme, že používate ProxMenux. Dovidenia!",
|
||||
"That VM is currently stopped, so the GPU can be reassigned now.": "Tá VM je momentálne zastavená, takže GPU sa teraz dá presunúť.",
|
||||
"That doesn't look like an SSH private key. Pick the private key file (no .pub extension, parseable by ssh-keygen).": "Toto nevyzerá ako súkromný SSH kľúč. Vyberte súbor súkromného kľúča (bez prípony .pub, čitateľný cez ssh-keygen).",
|
||||
"The .conf files under /config/fail2ban are rewritten on every start. Keep customizations in the matching .local file, for example jail.local for jail.conf.": "Súbory .conf pod /config/fail2ban sú prepísané na každom začiatku. Udržujte prispôsobenie v zodpovedajúcom .lokálnom súbore, napríklad vo väzení.lokálne pre väzenie.conf.",
|
||||
"The AppArmor/seccomp relaxation does not include the required consent": "AppArmor/seccomp relaxácia nezahŕňa súhlas required",
|
||||
"The Bookmark Everything App": "Záložka Všetko App",
|
||||
"The Brave browser is a fast, private and secure web browser for PC, Mac and mobile.": "Prehliadač Brave je rýchly, súkromný a bezpečný webový prehliadač pre PC, Mac a mobil.",
|
||||
@@ -5955,7 +5954,7 @@
|
||||
"The imported Compose requests privileged, but the official jlesage/handbrake documentation does not require it; ProxMenux keeps the LXC unprivileged.": "Dovážané kompozície žiadosti privilegované, ale oficiálna jlesage/handbrake dokumentácia nie je require to; ProxMenux udržuje LXC neprivilegované.",
|
||||
"The imported OCI groups are not numeric": "Dovezené skupiny OCI nie sú číselné",
|
||||
"The imported OCI user or group is not numeric": "Dovážaný užívateľ alebo skupina OCI nie je numerická",
|
||||
"The initial user name and password stay written in /etc/pve/lxc/<CTID>.conf as INIT_USERNAME and INIT_PASSWORD. They can be removed after the first login, with the container stopped.": "Počiatočné užívateľské meno a heslo zostávajú zapísané v /etc/pve/lxc/<CTID>.conf ako INIT USERNAME a INIT PASSWORD. Môžu byť odstránené po prvom prihlásení, pričom kontajner sa zastaví.",
|
||||
"The initial user name and password stay written in /etc/pve/lxc/<CTID>.conf as INIT_USERNAME and INIT_PASSWORD. They can be removed after the first login, with the container stopped.": "Počiatočné užívateľské meno a heslo zostávajú zapísané v /etc/pve/lxc/<CTID>.conf ako INIT_USERNAME a INIT_PASSWORD. Môžu byť odstránené po prvom prihlásení, pričom kontajner sa zastaví.",
|
||||
"The installation asks which one to use for these paths.": "Inštalácia žiada, ktorý z nich sa má použiť pre tieto cesty.",
|
||||
"The installation ended with exit code": "Inštalácia skončila kódom výstupu",
|
||||
"The installation requires a server restart to apply changes. Do you want to restart now?": "Na použitie zmien je po inštalácii potrebný reštart servera. Chcete reštartovať teraz?",
|
||||
@@ -6074,7 +6073,7 @@
|
||||
"The rootfs is not managed by Proxmox": "Rootfs nie je riadený Proxmox",
|
||||
"The rootfs is not mounted": "Korene nie sú namontované",
|
||||
"The same GPU cannot be used by two VMs at the same time.": "Rovnakú GPU nemôžu používať dve VM naraz.",
|
||||
"The same connection can be given as container variables instead of the file: UN_SONARR_0_URL and UN_SONARR_0_API_KEY, or the UN_RADARR_0_ equivalents.": "Rovnaké spojenie možno uviesť ako kontajnerové premenné namiesto súboru: UN SONARR 0 URL a UN SONARR 0 API KEY, alebo UN RADARR 0 equivalents.",
|
||||
"The same connection can be given as container variables instead of the file: UN_SONARR_0_URL and UN_SONARR_0_API_KEY, or the UN_RADARR_0_ equivalents.": "Rovnaké spojenie možno uviesť ako kontajnerové premenné namiesto súboru: UN_SONARR_0_URL a UN_SONARR_0_API_KEY, alebo UN RADARR 0 equivalents.",
|
||||
"The saved MOTD state is invalid; no changes were made": "Uložený stav MOTD je neplatný;neboli vykonané žiadne zmeny",
|
||||
"The saved OCI record is incomplete or has an unexpected format.": "Uložený záznam OCI je neúplný alebo má neočakávaný formát.",
|
||||
"The saved projection does not match the native evidence": "Uložená projekcia nezodpovedá natívnemu dôkazu",
|
||||
@@ -6822,7 +6821,7 @@
|
||||
"Web interface to manage devices running Tasmota firmware.": "Webové rozhranie pre správu zariadení bežiacich na Tasmota firmware.",
|
||||
"WebCord can be summarized as a pack of security and privacy hardenings, Discord features reimplementations, Electron / Chromium / Discord bugs workarounds, stylesheets, internal pages and wrapped https://discord.com page, designed to conform with ToS as much as it is possible (or hide the changes that might violate it from Discord's eyes).": "WebCord možno zhrnúť ako balík bezpečnostných a súkromia kalenie, Discord funkcie reimplementácie, Electron / Chromium / Discord chyby práce, štýlové listy, vnútorné stránky a zabalené https://discord.com stránky, navrhnutý tak, aby zodpovedali ToS tak, ako je to možné (alebo skryť zmeny, ktoré by mohli porušovať z očí Discord).",
|
||||
"Webgrabplus is a multi-site incremental xmltv epg grabber. It collects tv-program guide data from selected tvguide sites for your favourite channels.": "Webgrabplus je multi-site prírastkové xmltv epg grabber. Zhromažďuje tv-program sprievodcu dátami z vybraných tvguide stránok pre vaše obľúbené kanály.",
|
||||
"Webservers & Proxies": "Webservers a Proxies",
|
||||
"Webservers & Proxies": "Webové servery a proxy",
|
||||
"Website": "Webová stránka",
|
||||
"Webstation is a web native emulation focused LXQt desktop based on Ubuntu.": "Webstation je webová natívne emulácia zameraná LXQt plocha na základe Ubuntu.",
|
||||
"Webtop - Alpine, Ubuntu, Fedora, and Arch based containers containing full desktop environments in officially supported flavors accessible via any modern web browser.": "Webtop - Alpine, Ubuntu, Fedora, a Arch založené kontajnery obsahujúce plné pracovné prostredie v oficiálne podporovaných príchutiach prístupných cez akýkoľvek moderný webový prehliadač.",
|
||||
@@ -6855,7 +6854,7 @@
|
||||
"WireGuard® is an extremely simple yet fast and modern VPN that utilizes state-of-the-art cryptography. It aims to be faster, simpler, leaner, and more useful than IPsec, while avoiding the massive headache. It intends to be considerably more performant than OpenVPN. WireGuard is designed as a general purpose VPN for running on embedded interfaces and super computers alike, fit for many different circumstances. Initially released for the Linux kernel, it is now cross-platform (Windows, macOS, BSD, iOS, Android) and widely deployable. It is currently under heavy development, but already it might be regarded as the most secure, easiest to use, and simplest VPN solution in the industry.": "WireGuard® je extrémne jednoduchá, ale rýchla a moderná VPN, ktorá využíva najmodernejšiu kryptografiu. Jeho cieľom je byť rýchlejší, jednoduchší, štíhlejší a užitočnejší ako IPsec, pričom sa vyhýba masívnej bolesti hlavy. Má v úmysle byť výrazne výkonnejší ako OpenVPN. WireGuard je navrhnutý ako všeobecný účel VPN pre prevádzku na vstavaných rozhraniach a super počítačoch podobne, vhodný pre mnoho rôznych okolností. Spočiatku sa vydáva pre jadro Linuxu, je teraz cross-platform (Windows, macOS, BSD, iOS, Android) a široko rozmiestnený. To je v súčasnosti v ťažkom vývoji, ale už to môže byť považované za najbezpečnejšie, najjednoduchšie použitie, a najjednoduchšie riešenie VPN v priemysle.",
|
||||
"Wired NICs in backup missing on target:": "Káblové sieťové karty zo zálohy chýbajú na cieli:",
|
||||
"Wireshark is the world’s foremost and widely-used network protocol analyzer. It lets you see what’s happening on your network at a microscopic level and is the de facto (and often de jure) standard across many commercial and non-profit enterprises, government agencies, and educational institutions. Wireshark development thrives thanks to the volunteer contributions of networking experts around the globe and is the continuation of a project started by Gerald Combs in 1998.": "Wireshark je prvoradý a široko používaný sieťový protokol analyzátor. Umožňuje vidieť, čo sa deje na vašej sieti na mikroskopickej úrovni a je de facto (a často de jure) štandard v mnohých komerčných a neziskových podnikoch, vládnych agentúr a vzdelávacích inštitúcií. Rozvoj Wireshark sa darí vďaka dobrovoľným príspevkom odborníkov na vytváranie sietí po celom svete a je pokračovaním projektu, ktorý začal Gerald Combs v roku 1998.",
|
||||
"With dns validation, the DNSPLUGIN variable names the provider plugin. The advanced installation asks for it; otherwise add the line lxc.environment.runtime: DNSPLUGIN=<plugin> to /etc/pve/lxc/<CTID>.conf with the container stopped.": "Pri validácii dns, DNSPLUGIN premenná názvy poskytovateľa plugin. Pokročilá inštalácia si to vyžaduje; inak pridajte linku lxc.environment. čas: DNSPLUGIN=<plugin> to /etc/pve/lxc/<CTID>.conf with the container stopd.",
|
||||
"With dns validation, the DNSPLUGIN variable names the provider plugin. The advanced installation asks for it; otherwise add the line lxc.environment.runtime: DNSPLUGIN=<plugin> to /etc/pve/lxc/<CTID>.conf with the container stopped.": "Pri validácii dns, DNSPLUGIN premenná názvy poskytovateľa plugin. Pokročilá inštalácia si to vyžaduje; inak pridajte riadok lxc.environment.runtime: DNSPLUGIN=<plugin> k /etc/pve/lxc/<CTID>.conf s kontajnerom zastavil.",
|
||||
"With dns validation, write the provider credentials in /config/dns-conf/<plugin>.ini inside the container and restart it.": "S validáciou dns, napíšte poskytovateľa credentials v /config/dns-conf/<plugin>.ini vnútri kontajnera a reštartujte ho.",
|
||||
"With http validation, port 80 of the router must be forwarded to port 80 of this container.": "Pri validácii http sa port 80 routeru musí zaslať do prístavu 80 tohto kontajnera.",
|
||||
"With warnings": "S upozorneniami",
|
||||
@@ -7374,7 +7373,7 @@
|
||||
"vfio-pci IDs configured": "vfio-pci ID nastavené",
|
||||
"vfio-pci IDs in /etc/modprobe.d/vfio.conf": "vfio-pci ID v /etc/modprobe.d/vfio.conf",
|
||||
"vzdump backup speed optimization completed": "Optimalizácia rýchlosti záloh vzdump je dokončená",
|
||||
"wallabag builds its links from the address given during the installation. If it does not match the address of the container, edit lxc.environment.runtime: SYMFONY__ENV__DOMAIN_NAME in /etc/pve/lxc/<CTID>.conf with the container stopped, and start it again.": "wallabag buduje svoje odkazy z adresy uvedenej počas inštalácie. Ak nezodpovedá adrese kontajnera, upravte prostredie lxc. čas: SYMFONY ENV DOMAIN NAME in /etc/pve/lxc/ <CTID >.conf s kontajnerom zastavil, a začať znova.",
|
||||
"wallabag builds its links from the address given during the installation. If it does not match the address of the container, edit lxc.environment.runtime: SYMFONY__ENV__DOMAIN_NAME in /etc/pve/lxc/<CTID>.conf with the container stopped, and start it again.": "wallabag buduje svoje odkazy z adresy uvedenej počas inštalácie. Ak nezodpovedá adrese kontajnera, upravte prostredie lxc. čas: SYMFONY ENV DOMAIN NAME in /etc/pve/lxc/ <CTID>.conf s kontajnerom zastavil, a začať znova.",
|
||||
"wallabag listens on port 80 of the container and stores its data in SQLite.": "wallabag počúva port 80 kontajnera a ukladá svoje údaje v SQLite.",
|
||||
"wallabag web interface": "Webové rozhranie wallabag",
|
||||
"was": "bolo",
|
||||
|
||||
+29
-29
@@ -20,7 +20,7 @@
|
||||
"(recommended)": "(rekommenderad)",
|
||||
"(same MAC — restored config adjusted automatically)": "(samma MAC — återställd konfiguration justeras automatiskt)",
|
||||
")": ")",
|
||||
"*Arr Suite": "Arr Suite",
|
||||
"*Arr Suite": "*Arr Suite",
|
||||
"+ Add a path": "+ Lägg till en sökväg",
|
||||
"+ Add new Borg target": "+ Lägg till nytt Borgmål",
|
||||
"+ Add new PBS manually": "+ Lägg till ny PBS manuellt",
|
||||
@@ -120,11 +120,11 @@
|
||||
"ACL Status:": "ACL-status:",
|
||||
"ACL permissions applied for local access for user:": "ACL-behörigheter tillämpas för lokal åtkomst för användare:",
|
||||
"ADVANCED SETTINGS COMPLETE": "AVANCERADE INSTÄLLNINGAR KLARA",
|
||||
"AI / Coding & Dev-Tools": "AI / Coding & Dev-Tools",
|
||||
"AI / Coding & Dev-Tools": "AI, programmering och utveckling",
|
||||
"ALL DATA ON": "ALLA DATA PÅ",
|
||||
"ALL DATA ON THIS DISK WILL BE PERMANENTLY LOST!": "ALLA DATA PÅ DEN HÄR DISKEN KOMMER ATT FÖRLORAS PERMANENT!",
|
||||
"ALL Utilities": "ALLA Utilities",
|
||||
"ALLOWED_HOSTS cannot contain line breaks": "ALLOWED HOSTS kan inte innehålla radbrytningar",
|
||||
"ALLOWED_HOSTS cannot contain line breaks": "ALLOWED_HOSTS kan inte innehålla radbrytningar",
|
||||
"AList initial login": "AList initial inloggning",
|
||||
"AMD CPU detected": "AMD CPU upptäckt",
|
||||
"AMD CPU fixes applied successfully": "AMD CPU-fixar har använts",
|
||||
@@ -500,7 +500,7 @@
|
||||
"Backend:": "Backend:",
|
||||
"Background archive extraction for Arr download queues. No web interface.": "Bakgrund arkiv extraktion för Arr nedladdning köer. Inget webbgränssnitt.",
|
||||
"Backup — VM and CT backups": "Säkerhetskopiering — VM- och CT-säkerhetskopior",
|
||||
"Backup & Recovery": "Backup & Recovery",
|
||||
"Backup & Recovery": "Säkerhetskopiering och återställning",
|
||||
"Backup Created": "Säkerhetskopiering skapad",
|
||||
"Backup ID (group name in PBS):": "Säkerhetskopierings-ID (gruppnamn i PBS):",
|
||||
"Backup ID for this job:": "Säkerhetskopierings-ID för detta jobb:",
|
||||
@@ -603,11 +603,11 @@
|
||||
"Broken gasket-dkms package state recovered.": "Det trasiga pakettillståndet för gasket-dkms återställdes.",
|
||||
"Browse Your Life in Images": "Bläddra i ditt liv i bilder",
|
||||
"Browse manually (advanced)...": "Bläddra manuellt (avancerat)...",
|
||||
"Browsers & Web Desktops": "Webbläsare & Web Desktops",
|
||||
"Browsers & Web Desktops": "Webbläsare och webbskrivbord",
|
||||
"Build and install the gasket and apex kernel modules (DKMS)": "Bygg och installera kärnmodulerna gasket och apex (DKMS)",
|
||||
"Build dependencies installed.": "Byggberoenden installerade.",
|
||||
"Build your personal knowledge base with TriliumNext Notes": "Bygg din personliga kunskapsbas med TriliumNext Notes",
|
||||
"Business & ERP": "Business & ERP",
|
||||
"Business & ERP": "Företag och ERP",
|
||||
"CHANGES APPLIED SUCCESSFULLY": "ÄNDRINGAR HAR TILLÄMPATS",
|
||||
"CIFS Client Tools: AVAILABLE": "CIFS-klientverktyg: TILLGÄNGLIGT",
|
||||
"CIFS Client Tools: NOT AVAILABLE - installing...": "CIFS-klientverktyg: EJ TILLGÄNGLIGT - installerar...",
|
||||
@@ -1084,7 +1084,7 @@
|
||||
"Container will pick up the mount on next start": "Containern hämtar monteringen vid nästa start",
|
||||
"Container with ID": "Container med ID",
|
||||
"Container:": "Behållare:",
|
||||
"Containers & Docker": "Containers och Docker",
|
||||
"Containers & Docker": "Containrar och Docker",
|
||||
"Containers returned to their previous state": "Containers återvände till sin tidigare stat",
|
||||
"Containers that are removed:": "Behållare som tas bort:",
|
||||
"Containers that will be created (one LXC per service, on a private network):": "Behållare som kommer att skapas (en LXC per tjänst, på ett privat nätverk):",
|
||||
@@ -1157,7 +1157,7 @@
|
||||
"Coral M.2 Apex configuration added - device ready": "Coral M.2 Apex-konfiguration har lagts till - enheten är klar",
|
||||
"Coral M.2 Apex configuration added - device will be available after reboot": "Coral M.2 Apex-konfiguration tillagd - enheten kommer att vara tillgänglig efter omstart",
|
||||
"Coral M.2 Apex detected, configuring...": "Coral M.2 Apex upptäcktes, konfigurerar...",
|
||||
"Coral PCIe/M.2 node (e.g. /dev/apex_0)": "Coral PCIe/M.2 nod (t.ex. /dev/apex 0)",
|
||||
"Coral PCIe/M.2 node (e.g. /dev/apex_0)": "Coral PCIe/M.2 nod (t.ex. /dev/apex_0)",
|
||||
"Coral TPU Installation": "Coral TPU installation",
|
||||
"Coral TPU Uninstall": "Avinstallera Coral TPU",
|
||||
"Coral TPU device nodes detected with correct group (apex).": "Coral TPU-enhetsnoder upptäckts med korrekt grupp (apex).",
|
||||
@@ -1345,7 +1345,7 @@
|
||||
"Creating the container...": "Skapa behållaren...",
|
||||
"Creating the initial administrator...": "Skapa den första administratören...",
|
||||
"Creating the temporary data container": "Skapa den tillfälliga databehållaren",
|
||||
"Creative & Design": "Kreativ och design",
|
||||
"Creative & Design": "Kreativitet och design",
|
||||
"Credentials are correct": "Inloggningsuppgifterna är korrekta",
|
||||
"Credentials cleared. jwt_secret and API tokens preserved.": "Autentiseringsuppgifter rensade. jwt_secret och API-tokens bevarade.",
|
||||
"Credentials file created securely.": "Autentiseringsfil skapad på ett säkert sätt.",
|
||||
@@ -1731,7 +1731,7 @@
|
||||
"Dry run completed; the container and the mounts were not changed.": "Torr kör slutfördes; behållaren och fästen ändrades inte.",
|
||||
"DuckDNS subdomain without .duckdns.org (comma separated for several)": "DuckDNS underdomän utan .duckdns.org (komma separerad för flera)",
|
||||
"DuckDNS token from your account at duckdns.org": "DuckDNS token från ditt konto på duckdns.org",
|
||||
"DuckDNS updates the subdomain every 5 minutes. Without UPDATE_IP, DuckDNS itself detects the public IPv4 address of the request.": "DuckDNS uppdaterar underdomänen var femte minut. Utan UPDATE IP upptäcker DuckDNS själv den offentliga IPv4-adressen för begäran.",
|
||||
"DuckDNS updates the subdomain every 5 minutes. Without UPDATE_IP, DuckDNS itself detects the public IPv4 address of the request.": "DuckDNS uppdaterar underdomänen var femte minut. Utan UPDATE_IP upptäcker DuckDNS själv den offentliga IPv4-adressen för begäran.",
|
||||
"DuckStation is a PS1 Emulator aiming for the best accuracy and game support.": "DuckStation är en PS1 Emulator som syftar till bästa accuracy och spelstöd.",
|
||||
"Duckdns is a free service which will point a DNS (sub domains of duckdns.org) to an IP of your choice. The service is completely free, and doesn't require reactivation or forum posts to maintain its existence.": "Duckdns är en gratis tjänst som kommer att peka en DNS (sub domäner av duckdns.org) till en IP av ditt val. Tjänsten är helt gratis, och require reaktivering eller forumposter för att behålla sin existens.",
|
||||
"Dumping AMD GPU ROM BIOS via sysfs...": "Dumpar AMD GPU ROM BIOS via sysfs...",
|
||||
@@ -2239,7 +2239,7 @@
|
||||
"Final cleanup of the stack operation completed": "Slutlig rensning av stapeln operation färdigställd",
|
||||
"Final confirmation": "Slutlig bekräftelse",
|
||||
"Final storage health/status check": "Slutlig lagringsstatus/statuskontroll",
|
||||
"Finance & Budgeting": "Finans & Budgeting",
|
||||
"Finance & Budgeting": "Ekonomi och budget",
|
||||
"Find your device using https://finds.synology.com": "Hitta din enhet med https://finds.synology.com",
|
||||
"Fingerprint:": "Fingeravtryck:",
|
||||
"Firefly, the easiest using of WireGuard VPN server, plus version of wg-easy.": "Firefly, den enklaste användningen av WireGuard VPN-server, plus version av wg-easy.",
|
||||
@@ -2387,7 +2387,7 @@
|
||||
"GRUB_CMDLINE_LINUX_DEFAULT not found in GRUB config": "GRUB_CMDLINE_LINUX_DEFAULT hittades inte i GRUB-konfigurationen",
|
||||
"GUI mode (if available)": "GUI-läge (om tillgängligt)",
|
||||
"GZDoom is a feature centric port for all Doom engine games, based on ZDoom, adding an OpenGL renderer and powerful scripting capabilities.": "GZDoom är en funktion centric port för alla Doom motorspel, baserat på ZDoom, lägga till en OpenGL renderer och kraftfulla skriptfunktioner.",
|
||||
"Gaming & Leisure": "Spel och Leisure",
|
||||
"Gaming & Leisure": "Spel och fritid",
|
||||
"Gateway is not installed.": "Gateway är inte installerad.",
|
||||
"Gateway removed.": "Gateway har tagits bort.",
|
||||
"Gateway restarted.": "Gateway startade om.",
|
||||
@@ -2527,7 +2527,7 @@
|
||||
"Host GPU detected": "Värd GPU upptäckt",
|
||||
"Host GPU is already bound to vfio-pci. Host reconfiguration/reboot should not be required for this VM-to-VM reassignment.": "Värd-GPU är redan bunden till vfio-pci. Värd omkonfiguration/omstart bör inte krävas för denna VM-till-VM-omtilldelning.",
|
||||
"Host IP": "Värd IP",
|
||||
"Host Management": "Host Management",
|
||||
"Host Management": "Värdhantering",
|
||||
"Host Mount Path": "Värdmonteringssökväg",
|
||||
"Host NFS/Samba as Proxmox Storage (pvesm)": "NFS/Samba på värden som Proxmox-lagring (pvesm)",
|
||||
"Host Path": "Värdsökväg",
|
||||
@@ -2541,7 +2541,7 @@
|
||||
"Host already in VFIO mode — skipping host reconfiguration for VM reassignment": "Värd redan i VFIO-läge — hoppar över värdomkonfiguration för VM-omtilldelning",
|
||||
"Host audio devices": "Värd ljudenheter",
|
||||
"Host backup attached to PVE job": "Värdsäkerhetskopia kopplad till PVE-jobb",
|
||||
"Host data is not restored by the backup; confirm it with --acknowledge-external-data": "Värddata återställs inte av säkerhetskopieringen; bekräftar den med -acknowledge-extern data",
|
||||
"Host data is not restored by the backup; confirm it with --acknowledge-external-data": "Värddata återställs inte av säkerhetskopieringen; bekräfta den med --acknowledge-external-data",
|
||||
"Host device for /dev/kvm": "Värd enhet för /dev/kvm",
|
||||
"Host device for /dev/net/tun": "Värd enhet för /dev/nett/tun",
|
||||
"Host device for /dev/ttyUSB0": "Värd enhet för /dev/ttyUSB0",
|
||||
@@ -2795,7 +2795,7 @@
|
||||
"Initiator IQN is authorised on the target": "Initiator IQN är auktoriserad på målet",
|
||||
"Initiator IQN:": "Initiativtagare IQN:",
|
||||
"Inkscape is professional quality vector graphics software which runs on Linux, Mac OS X and Windows desktop computers.": "Inkscape är professionell kvalitet vektor grafik programvara som körs på Linux, Mac OS X och Windows stationära datorer.",
|
||||
"Inside the LXC, create the administrator: console kimai:user:create YOUR_USERNAME YOUR_EMAIL ROLE_SUPER_ADMIN": "Inuti LXC, skapa administratören: konsol kimai:user: skapa ditt USERNAME YOUR EMAIL ROLE SUPER ADMIN",
|
||||
"Inside the LXC, create the administrator: console kimai:user:create YOUR_USERNAME YOUR_EMAIL ROLE_SUPER_ADMIN": "Inuti LXC, skapa administratören: konsol kimai:user: skapa ditt USERNAME YOUR_EMAIL ROLE_SUPER_ADMIN",
|
||||
"Inspect disks before any action": "Inspektera diskar innan någon åtgärd",
|
||||
"Inspect host device nodes": "Inspektera värdenhetsnoder",
|
||||
"Inspect passthrough/kernel events": "Inspektera passthrough/kärnhändelser",
|
||||
@@ -2967,7 +2967,7 @@
|
||||
"Interrupted operation:": "Avbruten operation:",
|
||||
"Interrupted stack operation found": "Avbruten stack operation hittades",
|
||||
"Invalid 'proxmox-ve' candidate (not 9.x or none). Please verify your repository configuration and network, then retry.": "Ogiltig 'proxmox-ve'-kandidat (inte 9.x eller ingen). Verifiera din arkivkonfiguration och ditt nätverk och försök sedan igen.",
|
||||
"Invalid ALLOWED_HOSTS value": "Invalid ALLOWED HOSTS värde",
|
||||
"Invalid ALLOWED_HOSTS value": "Invalid ALLOWED_HOSTS värde",
|
||||
"Invalid Home Assistant OS check timeout": "Ogiltig Home Assistant OS check timeout",
|
||||
"Invalid ID": "Ogiltigt ID",
|
||||
"Invalid Intel render path": "Invalid Intel render bana",
|
||||
@@ -3386,7 +3386,7 @@
|
||||
"Max user watches configured": "Max användarklockor har konfigurerats",
|
||||
"Maximum auto-repair attempts reached (3). Please review the log and run any remaining commands manually.": "Maximalt antal autoreparationsförsök har uppnåtts (3). Granska loggen och kör eventuella återstående kommandon manuellt.",
|
||||
"May need to restart terminal": "Kan behöva starta om terminalen",
|
||||
"Media & Streaming": "Media & Streaming",
|
||||
"Media & Streaming": "Media och streaming",
|
||||
"Media discovery and request management for Jellyfin, Plex and Emby.": "Media discovery och request management för Jellyfin, Plex och Emby.",
|
||||
"Media library transcoding and health checking, with an internal worker node.": "Mediebiblioteksöverkodning och hälsokontroll, med en intern arbetstagarnod.",
|
||||
"Media server": "Media server",
|
||||
@@ -3413,7 +3413,7 @@
|
||||
"MineOS web interface": "MineOS webbgränssnitt",
|
||||
"Minisatip is a multi-threaded satip server version 1.2 that runs under Linux and it was tested with DVB-S, DVB-S2, DVB-T, DVB-T2, DVB-C, DVB-C2, ATSC and ISDB-T cards.": "Minisatip är en multi-threaded satip server version 1.2 som körs under Linux och det testades med DVB-S, DVB-S2, DVB-T, DVB-T2, DVB-C, DVB-C2, ATSC och ISDB-T-kort.",
|
||||
"Mirror URL not available for this script.": "Mirror URL inte tillgänglig för det här skriptet.",
|
||||
"Miscellaneous": "Miscellan",
|
||||
"Miscellaneous": "Övrigt",
|
||||
"Missing": "Saknad",
|
||||
"Missing OCI metadata:": "OCI-metadata saknas:",
|
||||
"Missing commands after installation:": "Saknade kommandon efter installation:",
|
||||
@@ -3652,7 +3652,7 @@
|
||||
"NVMe health status: WARNING (critical_warning =": "NVMe hälsostatus: VARNING (critical_warning =",
|
||||
"NVMe skipped (to add as PCIe use 'Add Controller or NVMe PCIe to VM'):": "NVMe hoppade över (för att lägga till som PCIe använd 'Lägg till styrenhet eller NVMe PCIe till VM'):",
|
||||
"NVMe-specific SMART log": "NVMe-specifik SMART-logg",
|
||||
"NVR & Cameras": "NVR & Kameror",
|
||||
"NVR & Cameras": "NVR och kameror",
|
||||
"NVR with optional VA-API video acceleration and hardware object detectors": "NVR med valfri VA-API videoacceleration och hårdvaruobjektdetektorer",
|
||||
"NZBGet web interface": "NZBGet webbgränssnitt",
|
||||
"Name": "Namnnamn",
|
||||
@@ -3664,7 +3664,7 @@
|
||||
"Name of this wallabag instance, shown in the interface and in 2FA codes": "Namn på denna wallabag instans, visas i gränssnittet och i 2FA-koder",
|
||||
"Name or part of the description of the application": "Namn eller del av beskrivningen av ansökan",
|
||||
"Name:": "Namn:",
|
||||
"Named accounts need private mode. Stop the container, set public: false in /config/config.js, start it again and create each user with: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>": "Namngivna konton behöver privat läge. Stoppa behållaren, ställ in offentligt: falskt i /config/config.js, starta den igen och skapa varje användare med: pct exec <CTID> - env THELOUNGE HOME=/config s6-setuidgid abc thelounge addera <user>",
|
||||
"Named accounts need private mode. Stop the container, set public: false in /config/config.js, start it again and create each user with: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>": "Namngivna konton behöver privat läge. Stoppa behållaren, ställ in offentligt: falskt i /config/config.js, starta den igen och skapa varje användare med: pct exec <CTID> - env THELOUNGE_HOME=/config s6-setuidgid abc thelounge addera <user>",
|
||||
"Neither /etc/kernel/cmdline nor /etc/default/grub found.": "Varken /etc/kernel/cmdline eller /etc/default/grub hittades.",
|
||||
"Nesting feature enabled": "Kapningsfunktionen aktiverad",
|
||||
"NetBIOS Service: RUNNING": "NetBIOS-tjänst: KÖR",
|
||||
@@ -3674,7 +3674,7 @@
|
||||
"Netbox is an IP address management (IPAM) and data center infrastructure management (DCIM) tool. Initially conceived by the network engineering team at DigitalOcean, NetBox was developed specifically to address the needs of network and infrastructure engineers. It is intended to function as a domain-specific source of truth for network operations.": "Netbox är ett IP-adresshantering (IPAM) och datacenter infrastrukturhantering (DCIM) verktyg. Initialt utformad av nätverksteknikteamet på DigitalOcean, utvecklades NetBox specifikt för att tillgodose behoven hos nätverks- och infrastrukturingenjörer. Den är avsedd att fungera som en domänspecifik källa till sanning för operations.",
|
||||
"Network": "Nätverk",
|
||||
"Network :": "Nätverk:",
|
||||
"Network & Firewall": "Network & Firewall",
|
||||
"Network & Firewall": "Nätverk och brandvägg",
|
||||
"Network (interfaces, DNS)": "Nätverk (gränssnitt, DNS)",
|
||||
"Network Bridge": "Nätverksbrygga",
|
||||
"Network Commands": "Nätverkskommandon",
|
||||
@@ -4045,7 +4045,7 @@
|
||||
"OCI containers require Proxmox VE 9.1 or later.": "OCI-behållare kräver Proxmox VE 9.1 eller senare.",
|
||||
"OCI management": "OCI management",
|
||||
"OCI management could not be completed. Check the backend status; no additional cleanup has been authorized.": "OCI-hanteringen kunde inte slutföras. Kontrollera backend status; ingen ytterligare rengöring har godkänts.",
|
||||
"OCI manager Apps (beta)": "OCI Manager Apps (beta)",
|
||||
"OCI manager Apps (beta)": "OCI manager Apps (beta)",
|
||||
"OCI manager Apps is a beta: if something does not work as expected, please report it on GitHub with the application name.": "OCI Manager Apps är en beta: om något inte fungerar som förväntat, vänligen rapportera det på GitHub med applikationsnamnet.",
|
||||
"OCI metadata integrity mismatch": "OCI metadata integritet mismatch",
|
||||
"OCI metadata too large": "OCI metadata för stor",
|
||||
@@ -4377,7 +4377,7 @@
|
||||
"Postfix configuration": "Postfix-konfiguration",
|
||||
"PostgreSQL": "PostgreSQL",
|
||||
"PostgreSQL URL without an associated service:": "PostgreSQL URL utan tillhörande tjänst:",
|
||||
"PostgreSQL creates the database named in POSTGRES_DB on the first start. The installer default is postgresql.": "PostgreSQL skapar databasen som heter POSTGRES DB i början. Installationsstandarden är postgresql.",
|
||||
"PostgreSQL creates the database named in POSTGRES_DB on the first start. The installer default is postgresql.": "PostgreSQL skapar databasen som heter POSTGRES_DB i början. Installationsstandarden är postgresql.",
|
||||
"PostgreSQL is an advanced, enterprise-class, and open-source relational database system. PostgreSQL supports both SQL (relational) and JSON (non-relational) querying.": "PostgreSQL är ett avancerat, företagsklass och open-source relational databassystem. PostgreSQL stöder både SQL (relational) och JSON (icke-relationell) fråga.",
|
||||
"PostgreSQL requires a password": "PostgreSQL requires ett lösenord",
|
||||
"PostgreSQL volume size in GB": "PostgreSQL volymstorlek i GB",
|
||||
@@ -4541,7 +4541,7 @@
|
||||
"Pwndrop is a self-deployable file hosting service for sending out red teaming payloads or securely sharing your private files over HTTP and WebDAV.": "Pwndrop är en självutnyttjande fil värdtjänst för att skicka ut röda lager nyttolast eller säkert dela dina privata filer över HTTP och WebDAV.",
|
||||
"PyCharm offers out-of-the-box support for Python, databases, Jupyter, Git, Conda, PyTorch, TensorFlow, Hugging Face, Django, Flask, FastAPI, and more.": "PyCharm erbjuder out-of-the-box stöd för Python, databaser, Jupyter, Git, Conda, PyTorch, TensorFlow, Hugging Face, Django, Flask, FastAPI och mer.",
|
||||
"Pydio Cells needs an external MySQL or MariaDB database. The setup wizard asks for its address, database name and user on the first start.": "Pydio Cells behöver en extern MySQL- eller MariaDB-databas. Inställningsguiden ber om sin adress, databasnamn och användare i första början.",
|
||||
"Pydio Cells redirects to the address given in EXTERNALURL. If the container changes address, edit lxc.environment.runtime: EXTERNALURL and SERVER_IP in /etc/pve/lxc/<CTID>.conf with the container stopped, and delete /config/keys/cert.crt to regenerate the certificate.": "Pydio Cells omdirigerar till den adress som ges i EXTERNALURL. Om behållaren ändrar adress, redigera lxc.environment.runtime: EXTERNALURL och SERVER IP i /etc/pve/lxc/<CTID>.conf med behållaren stannade, och ta bort /config/keys/cert.crt för att regenerera certifikatet.",
|
||||
"Pydio Cells redirects to the address given in EXTERNALURL. If the container changes address, edit lxc.environment.runtime: EXTERNALURL and SERVER_IP in /etc/pve/lxc/<CTID>.conf with the container stopped, and delete /config/keys/cert.crt to regenerate the certificate.": "Pydio Cells omdirigerar till den adress som ges i EXTERNALURL. Om behållaren ändrar adress, redigera lxc.environment.runtime: EXTERNALURL och SERVER_IP i /etc/pve/lxc/<CTID>.conf med behållaren stannade, och ta bort /config/keys/cert.crt för att regenerera certifikatet.",
|
||||
"Pydio-cells is the nextgen file sharing platform for organizations. It is a full rewrite of the Pydio project using the Go language following a micro-service architecture.": "Pydio-celler är nästagen fildelningsplattform för organisationer. Det är en fullständig omskrivning av Pydio-projektet med Go-språket efter en mikroservicearkitektur.",
|
||||
"QDirStat Qt-based directory statistics: KDirStat without any KDE -- from the author of the original KDirStat.": "QDirStat Qt-baserad katalogstatistik: KDirStat utan KDE – från författaren till den ursprungliga KDirStat.",
|
||||
"Quick health check (PASSED / FAILED)": "Snabb hälsokontroll (GODKÄND / MISLYCKAD)",
|
||||
@@ -5955,7 +5955,7 @@
|
||||
"The imported Compose requests privileged, but the official jlesage/handbrake documentation does not require it; ProxMenux keeps the LXC unprivileged.": "Den importerade Komponera förfrågningar privilegierade, men den officiella jlesage / handbrake dokumentation inte require det; ProxMenux håller LXC oprivilegierad.",
|
||||
"The imported OCI groups are not numeric": "De importerade OCI-grupperna är inte numeriska",
|
||||
"The imported OCI user or group is not numeric": "Den importerade OCI-användaren eller gruppen är inte numerisk",
|
||||
"The initial user name and password stay written in /etc/pve/lxc/<CTID>.conf as INIT_USERNAME and INIT_PASSWORD. They can be removed after the first login, with the container stopped.": "Det första användarnamnet och lösenordet förblir skrivet i /etc/pve/lxc/<CTID>.conf som INIT USERNAME och INIT PASSWORD. De kan tas bort efter den första inloggningen, med behållaren stannade.",
|
||||
"The initial user name and password stay written in /etc/pve/lxc/<CTID>.conf as INIT_USERNAME and INIT_PASSWORD. They can be removed after the first login, with the container stopped.": "Det första användarnamnet och lösenordet förblir skrivet i /etc/pve/lxc/<CTID>.conf som INIT_USERNAME och INIT_PASSWORD. De kan tas bort efter den första inloggningen, med behållaren stannade.",
|
||||
"The installation asks which one to use for these paths.": "Installationen frågar vilken som ska användas för dessa vägar.",
|
||||
"The installation ended with exit code": "Installationen slutade med exitkod",
|
||||
"The installation requires a server restart to apply changes. Do you want to restart now?": "Installationen kräver en omstart av servern för att tillämpa ändringar. Vill du starta om nu?",
|
||||
@@ -6074,7 +6074,7 @@
|
||||
"The rootfs is not managed by Proxmox": "Rötterna hanteras inte av Proxmox",
|
||||
"The rootfs is not mounted": "Rötterna är inte monterade",
|
||||
"The same GPU cannot be used by two VMs at the same time.": "Samma GPU kan inte användas av två virtuella datorer samtidigt.",
|
||||
"The same connection can be given as container variables instead of the file: UN_SONARR_0_URL and UN_SONARR_0_API_KEY, or the UN_RADARR_0_ equivalents.": "Samma anslutning kan ges som containervariabler i stället för filen: UN SONARR 0 URL och UN SONARR 0 API KEY, eller UN RADARR 0 equivalents.",
|
||||
"The same connection can be given as container variables instead of the file: UN_SONARR_0_URL and UN_SONARR_0_API_KEY, or the UN_RADARR_0_ equivalents.": "Samma anslutning kan ges som containervariabler i stället för filen: UN_SONARR_0_URL och UN_SONARR_0_API_KEY, eller UN RADARR 0 equivalents.",
|
||||
"The saved MOTD state is invalid; no changes were made": "Det sparade MOTD-tillståndet är ogiltigt;inga ändringar gjordes",
|
||||
"The saved OCI record is incomplete or has an unexpected format.": "Den sparade OCI-posten är ofullständig eller har ett oväntat format.",
|
||||
"The saved projection does not match the native evidence": "Den sparade projektionen matchar inte de infödda bevisen",
|
||||
@@ -6822,7 +6822,7 @@
|
||||
"Web interface to manage devices running Tasmota firmware.": "Webbgränssnitt för att hantera enheter som kör Tasmota firmware.",
|
||||
"WebCord can be summarized as a pack of security and privacy hardenings, Discord features reimplementations, Electron / Chromium / Discord bugs workarounds, stylesheets, internal pages and wrapped https://discord.com page, designed to conform with ToS as much as it is possible (or hide the changes that might violate it from Discord's eyes).": "WebCord kan sammanfattas som ett paket av säkerhets- och sekretesshärdningar, Discord-funktioner reimplementations, Electron / Chromium / Discord bugs workarounds, stylesheets, interna sidor och wrapped https://discord.com sida, utformad för att överensstämma med ToS så mycket som möjligt (eller dölja de förändringar som kan bryta mot det från Discords ögon).",
|
||||
"Webgrabplus is a multi-site incremental xmltv epg grabber. It collects tv-program guide data from selected tvguide sites for your favourite channels.": "Webgrabplus är en multi-site inkrementell xmltv epg grabber. Det samlar in tv-programguide data från utvalda tvguide webbplatser för dina favoritkanaler.",
|
||||
"Webservers & Proxies": "Webservers & Proxies",
|
||||
"Webservers & Proxies": "Webbservrar och proxyservrar",
|
||||
"Website": "Webbplats",
|
||||
"Webstation is a web native emulation focused LXQt desktop based on Ubuntu.": "Webstation är en web inhemsk emulering fokuserad LXQt skrivbord baserat på Ubuntu.",
|
||||
"Webtop - Alpine, Ubuntu, Fedora, and Arch based containers containing full desktop environments in officially supported flavors accessible via any modern web browser.": "Webtop - Alpine, Ubuntu, Fedora och Arch-baserade behållare som innehåller fullständiga skrivbordsmiljöer i officiellt stödda smaker tillgängliga via alla moderna webbläsare.",
|
||||
@@ -6855,7 +6855,7 @@
|
||||
"WireGuard® is an extremely simple yet fast and modern VPN that utilizes state-of-the-art cryptography. It aims to be faster, simpler, leaner, and more useful than IPsec, while avoiding the massive headache. It intends to be considerably more performant than OpenVPN. WireGuard is designed as a general purpose VPN for running on embedded interfaces and super computers alike, fit for many different circumstances. Initially released for the Linux kernel, it is now cross-platform (Windows, macOS, BSD, iOS, Android) and widely deployable. It is currently under heavy development, but already it might be regarded as the most secure, easiest to use, and simplest VPN solution in the industry.": "WireGuard® är en extremt enkel men ändå snabb och modern VPN som använder toppmodern kryptografi. Det syftar till att vara snabbare, enklare, smalare och mer användbar än IPsec, samtidigt som man undviker den massiva huvudvärken. Det avser att vara betydligt mer performant än OpenVPN. WireGuard är utformad som ett allmänt ändamål VPN för att köra på inbyggda gränssnitt och superdatorer lika, passar för många olika omständigheter. Initialt släppt för Linux-kärnan är det nu cross-platform (Windows, macOS, BSD, iOS, Android) och allmänt distribuerbar. Det är för närvarande under tung utveckling, men redan kan det anses vara den säkraste, enklaste att använda och enklaste VPN-lösningen i branschen.",
|
||||
"Wired NICs in backup missing on target:": "Trådbundna nätverkskort i säkerhetskopia saknas på målet:",
|
||||
"Wireshark is the world’s foremost and widely-used network protocol analyzer. It lets you see what’s happening on your network at a microscopic level and is the de facto (and often de jure) standard across many commercial and non-profit enterprises, government agencies, and educational institutions. Wireshark development thrives thanks to the volunteer contributions of networking experts around the globe and is the continuation of a project started by Gerald Combs in 1998.": "Wireshark är världens främsta och allmänt använda nätverksprotokollanalysator. Det låter dig se vad som händer på ditt nätverk på en mikroskopisk nivå och är de facto (och ofta de jure) standard över många kommersiella och ideella företag, myndigheter och utbildningsinstitutioner. Wireshark utveckling frodas tack vare de frivilliga bidragen från nätverksexperter runt om i världen och är fortsättningen av ett projekt som startades av Gerald Combs 1998.",
|
||||
"With dns validation, the DNSPLUGIN variable names the provider plugin. The advanced installation asks for it; otherwise add the line lxc.environment.runtime: DNSPLUGIN=<plugin> to /etc/pve/lxc/<CTID>.conf with the container stopped.": "Med dns validering, DNSPLUGIN variabel namn leverantör plugin. Den avancerade installationen ber om det, annars lägg till linjen lxc.miljö. runtime: DNSPLUGIN <plugin> till /etc/pve/lxc/<CTID>.conf med behållaren stannade.",
|
||||
"With dns validation, the DNSPLUGIN variable names the provider plugin. The advanced installation asks for it; otherwise add the line lxc.environment.runtime: DNSPLUGIN=<plugin> to /etc/pve/lxc/<CTID>.conf with the container stopped.": "Med dns validering, DNSPLUGIN variabel namn leverantör plugin. Den avancerade installationen ber om det, annars lägg till linjen lxc.environment.runtime: DNSPLUGIN <plugin> till /etc/pve/lxc/ <CTID>.conf med behållaren stannade.",
|
||||
"With dns validation, write the provider credentials in /config/dns-conf/<plugin>.ini inside the container and restart it.": "Med dns validering, skriv leverantören credentials i /config/dns-conf/<plugin>.ini inuti behållaren och starta om den.",
|
||||
"With http validation, port 80 of the router must be forwarded to port 80 of this container.": "Med http validering måste port 80 av routern vidarebefordras till port 80 av denna behållare.",
|
||||
"With warnings": "Med varningar",
|
||||
@@ -7374,7 +7374,7 @@
|
||||
"vfio-pci IDs configured": "vfio-pci ID:n konfigurerade",
|
||||
"vfio-pci IDs in /etc/modprobe.d/vfio.conf": "vfio-pci ID i /etc/modprobe.d/vfio.conf",
|
||||
"vzdump backup speed optimization completed": "Optimeringen av vzdump-säkerhetskopieringen har slutförts",
|
||||
"wallabag builds its links from the address given during the installation. If it does not match the address of the container, edit lxc.environment.runtime: SYMFONY__ENV__DOMAIN_NAME in /etc/pve/lxc/<CTID>.conf with the container stopped, and start it again.": "wallabag bygger sina länkar från den adress som ges under installationen. Om den inte matchar behållarens adress, redigera lxc.environment. runtime: SYMFONY ENV DOMAIN NAME in /etc/pve/lxc/<CTID>.conf with the container stopped, and start it again.",
|
||||
"wallabag builds its links from the address given during the installation. If it does not match the address of the container, edit lxc.environment.runtime: SYMFONY__ENV__DOMAIN_NAME in /etc/pve/lxc/<CTID>.conf with the container stopped, and start it again.": "wallabag bygger sina länkar från den adress som ges under installationen. Om den inte matchar behållarens adress, redigera lxc.environment.runtime: SYMFONY ENV DOMAIN NAME in /etc/pve/lxc/<CTID>.conf with the container stopped, and start it again.",
|
||||
"wallabag listens on port 80 of the container and stores its data in SQLite.": "wallabag lyssnar på port 80 av behållaren och lagrar sina data i SQLite.",
|
||||
"wallabag web interface": "wallabag webbgränssnitt",
|
||||
"was": "var",
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"category_label": "Authentication & Security",
|
||||
"author": "Bubka",
|
||||
"developer": "Bubka",
|
||||
"icon": null,
|
||||
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/2fauth.webp",
|
||||
"thumbnail": null,
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"category_label": "Finance & Budgeting",
|
||||
"author": "ActualBudget",
|
||||
"developer": "ActualBudget",
|
||||
"icon": null,
|
||||
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/actual-budget.webp",
|
||||
"thumbnail": null,
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"category_label": "Network & Firewall",
|
||||
"author": "AdguardTeam",
|
||||
"developer": "AdguardTeam",
|
||||
"icon": null,
|
||||
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/adguard-home.webp",
|
||||
"thumbnail": null,
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"category_label": "Adblock & DNS",
|
||||
"author": "LinuxServer.io",
|
||||
"developer": null,
|
||||
"icon": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/adguardhome-sync-icon.png",
|
||||
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/adguardhome-sync.webp",
|
||||
"thumbnail": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/adguardhome-sync-banner.png",
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
"description": {
|
||||
"en_US": "Adminer (formerly phpMinAdmin) is a full-featured database management tool written in PHP. Conversely to phpMyAdmin, it consist of a single file ready to deploy to the target server. Adminer is available for MySQL, PostgreSQL, SQLite, MS SQL, Oracle, Firebird, SimpleDB, Elasticsearch and MongoDB."
|
||||
},
|
||||
"category": "ai",
|
||||
"category_label": "AI / Coding & Dev-Tools",
|
||||
"author": "Jakub Vr\u00e1na",
|
||||
"developer": "Jakub Vr\u00e1na",
|
||||
"icon": null,
|
||||
"category": "databases",
|
||||
"category_label": "Databases",
|
||||
"author": "Jakub Vrána",
|
||||
"developer": "Jakub Vrána",
|
||||
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/adminer.webp",
|
||||
"thumbnail": null,
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
"description": {
|
||||
"en_US": "Airsonic-advanced is a free, web-based media streamer, providing ubiquitious access to your music. Use it to share your music with friends, or to listen to your own music while at work. You can stream to multiple players simultaneously, for instance to one player in your kitchen and another in your living room."
|
||||
},
|
||||
"category": "misc",
|
||||
"category_label": "Miscellaneous",
|
||||
"category": "media",
|
||||
"category_label": "Media & Streaming",
|
||||
"author": "LinuxServer.io",
|
||||
"developer": null,
|
||||
"icon": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/airsonic-advanced-icon.png",
|
||||
"icon": "https://cdn.jsdelivr.net/gh/linuxserver/docker-templates@master/linuxserver.io/img/airsonic-advanced-logo.png",
|
||||
"thumbnail": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/airsonic-advanced-banner.png",
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -5,19 +5,19 @@
|
||||
"status": "laboratory-validated",
|
||||
"catalog_ui": {
|
||||
"title": {
|
||||
"en_US": "Alby Hub \u2728"
|
||||
"en_US": "Alby Hub ✨"
|
||||
},
|
||||
"tagline": {
|
||||
"en_US": "Self-custodial Bitcoin Lightning wallet with integrated node and app connections."
|
||||
},
|
||||
"description": {
|
||||
"en_US": "Alby Hub is an open-source, self-custodial Bitcoin Lightning wallet, with the easiest-to-use Lightning Network node for everyone.\nWhether you're an individual, creator, or developer, Alby Hub is your centre for seamless Bitcoin payments.\nEffortlessly connect to a variety of apps like the Alby Browser Extension or Alby Go mobile app, create sub-wallets for family and friends, and take full control of your funds\u2014all within an intuitive interface and developer-ready APIs.\n\n**USEFUL LINKS**\n- [Source Repository](https://github.com/getAlby/hub)\n- [Support](https://support.getalby.com/)\n- [Marketing Site](https://albyhub.com/)\n- [Community of users and developers](https://discord.getalby.com)\n- [Feedback Board, feature requests, bug reports[(https://feedback.getalby.com)\n"
|
||||
"en_US": "Alby Hub is an open-source, self-custodial Bitcoin Lightning wallet, with the easiest-to-use Lightning Network node for everyone.\nWhether you're an individual, creator, or developer, Alby Hub is your centre for seamless Bitcoin payments.\nEffortlessly connect to a variety of apps like the Alby Browser Extension or Alby Go mobile app, create sub-wallets for family and friends, and take full control of your funds—all within an intuitive interface and developer-ready APIs.\n\n**USEFUL LINKS**\n- [Source Repository](https://github.com/getAlby/hub)\n- [Support](https://support.getalby.com/)\n- [Marketing Site](https://albyhub.com/)\n- [Community of users and developers](https://discord.getalby.com)\n- [Feedback Board, feature requests, bug reports[(https://feedback.getalby.com)\n"
|
||||
},
|
||||
"category": "finance",
|
||||
"category_label": "Finance & Budgeting",
|
||||
"author": "getalby",
|
||||
"developer": null,
|
||||
"icon": null,
|
||||
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/alby-hub.webp",
|
||||
"thumbnail": null,
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"category_label": "Productivity & Workflows",
|
||||
"author": "xjxjin",
|
||||
"developer": "xjxjin",
|
||||
"icon": null,
|
||||
"icon": "https://cdn.jsdelivr.net/gh/IceWhaleTech/CasaOS-AppStore@main/Apps/Alist-Sync/icon.png",
|
||||
"thumbnail": null,
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"category_label": "Productivity & Workflows",
|
||||
"author": "Xhofe",
|
||||
"developer": "Xhofe",
|
||||
"icon": null,
|
||||
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/alist.webp",
|
||||
"thumbnail": null,
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
"description": {
|
||||
"en_US": "Altus is an Electron-based WhatsApp client with themes and multiple account support."
|
||||
},
|
||||
"category": "misc",
|
||||
"category_label": "Miscellaneous",
|
||||
"category": "communication",
|
||||
"category_label": "Communication & Community",
|
||||
"author": "LinuxServer.io",
|
||||
"developer": null,
|
||||
"icon": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/altus-icon.png",
|
||||
"icon": "https://cdn.jsdelivr.net/gh/linuxserver/docker-templates@master/linuxserver.io/img/altus-logo.png",
|
||||
"thumbnail": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/altus-banner.png",
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"category_label": "Files & Downloads",
|
||||
"author": "ngosang",
|
||||
"developer": "ngosang",
|
||||
"icon": null,
|
||||
"icon": "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@main/webp/a-mule.webp",
|
||||
"thumbnail": null,
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"category_label": "AI / Coding & Dev-Tools",
|
||||
"author": "LisonEvf",
|
||||
"developer": "LisonEvf",
|
||||
"icon": null,
|
||||
"icon": "https://cdn.jsdelivr.net/gh/IceWhaleTech/CasaOS-AppStore@main/Apps/Anaconda3/icon.png",
|
||||
"thumbnail": null,
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"category_label": "AI / Coding & Dev-Tools",
|
||||
"author": "Mintplex Labs",
|
||||
"developer": "Mintplex Labs",
|
||||
"icon": null,
|
||||
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/anythingllm.webp",
|
||||
"thumbnail": null,
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"category_label": "Messaging & Notifications",
|
||||
"author": "LinuxServer.io",
|
||||
"developer": null,
|
||||
"icon": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/apprise-api-icon.png",
|
||||
"icon": "https://cdn.jsdelivr.net/gh/linuxserver/docker-templates@master/linuxserver.io/img/apprise-api-logo.png",
|
||||
"thumbnail": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/apprise-api-banner.png",
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"category_label": "Documents & Notes",
|
||||
"author": "ArchiveBox",
|
||||
"developer": "ArchiveBox",
|
||||
"icon": null,
|
||||
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/archivebox.webp",
|
||||
"thumbnail": null,
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
"description": {
|
||||
"en_US": "Ardour is an open source, collaborative effort of a worldwide team including musicians, programmers, and professional recording engineers."
|
||||
},
|
||||
"category": "misc",
|
||||
"category_label": "Miscellaneous",
|
||||
"category": "creative",
|
||||
"category_label": "Creative & Design",
|
||||
"author": "LinuxServer.io",
|
||||
"developer": null,
|
||||
"icon": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/ardour-icon.png",
|
||||
"icon": "https://cdn.jsdelivr.net/gh/linuxserver/docker-templates@master/linuxserver.io/img/ardour-logo.png",
|
||||
"thumbnail": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/ardour-banner.png",
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
"description": {
|
||||
"en_US": "Audacity is an easy-to-use, multi-track audio editor and recorder. Developed by a group of volunteers as open source."
|
||||
},
|
||||
"category": "misc",
|
||||
"category_label": "Miscellaneous",
|
||||
"category": "creative",
|
||||
"category_label": "Creative & Design",
|
||||
"author": "LinuxServer.io",
|
||||
"developer": null,
|
||||
"icon": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/audacity-icon.png",
|
||||
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/audacity.webp",
|
||||
"thumbnail": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/audacity-banner.png",
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"category_label": "Media & Streaming",
|
||||
"author": "advplyr",
|
||||
"developer": "advplyr",
|
||||
"icon": null,
|
||||
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/audiobookshelf.webp",
|
||||
"thumbnail": null,
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"category_label": "*Arr Suite",
|
||||
"author": "Autobrr Team",
|
||||
"developer": "Autobrr Team",
|
||||
"icon": null,
|
||||
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/autobrr.webp",
|
||||
"thumbnail": null,
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
"description": {
|
||||
"en_US": "Azahar is an open-source 3DS emulator based on Citra."
|
||||
},
|
||||
"category": "misc",
|
||||
"category_label": "Miscellaneous",
|
||||
"category": "gaming",
|
||||
"category_label": "Gaming & Leisure",
|
||||
"author": "LinuxServer.io",
|
||||
"developer": null,
|
||||
"icon": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/azahar-icon.png",
|
||||
"icon": "https://cdn.jsdelivr.net/gh/linuxserver/docker-templates@master/linuxserver.io/img/azahar-logo.png",
|
||||
"thumbnail": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/azahar-banner.png",
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"category_label": "Productivity & Workflows",
|
||||
"author": "LinuxServer.io",
|
||||
"developer": null,
|
||||
"icon": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/babybuddy-icon.png",
|
||||
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/baby-buddy.webp",
|
||||
"thumbnail": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/babybuddy-banner.png",
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
"description": {
|
||||
"en_US": "Bambu Studio is an open-source, cutting-edge, feature-rich slicing software. It contains project-based workflows, systematically optimized slicing algorithms, and an easy-to-use graphical interface, bringing users an incredibly smooth printing experience."
|
||||
},
|
||||
"category": "misc",
|
||||
"category_label": "Miscellaneous",
|
||||
"category": "creative",
|
||||
"category_label": "Creative & Design",
|
||||
"author": "LinuxServer.io",
|
||||
"developer": null,
|
||||
"icon": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/bambustudio-icon.png",
|
||||
"icon": "https://cdn.jsdelivr.net/gh/linuxserver/docker-templates@master/linuxserver.io/img/bambustudio-logo.png",
|
||||
"thumbnail": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/bambustudio-banner.png",
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"category_label": "*Arr Suite",
|
||||
"author": "LinuxServer.io",
|
||||
"developer": null,
|
||||
"icon": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/bazarr-icon.png",
|
||||
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/bazarr.webp",
|
||||
"thumbnail": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/bazarr-banner.png",
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"category_label": "Productivity & Workflows",
|
||||
"author": "daya0576",
|
||||
"developer": "daya0576",
|
||||
"icon": null,
|
||||
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/beaver-habit-tracker.webp",
|
||||
"thumbnail": null,
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
"description": {
|
||||
"en_US": "Beets is a music library manager and not, for the most part, a music player. It does include a simple player plugin and an experimental Web-based player, but it generally leaves actual sound-reproduction to specialized tools."
|
||||
},
|
||||
"category": "misc",
|
||||
"category_label": "Miscellaneous",
|
||||
"category": "media",
|
||||
"category_label": "Media & Streaming",
|
||||
"author": "LinuxServer.io",
|
||||
"developer": null,
|
||||
"icon": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/beets-icon.png",
|
||||
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/beets.webp",
|
||||
"thumbnail": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/beets-banner.png",
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -11,13 +11,13 @@
|
||||
"en_US": "Privacy-first, self-hosted PDF toolkit"
|
||||
},
|
||||
"description": {
|
||||
"en_US": "**Your PDFs never leave your device.** BentoPDF is a privacy-first PDF toolkit that runs entirely in your browser. Every merge, split, conversion, and edit happens locally on your machine \u2014 no file is ever uploaded to a server. More than 50 tools are bundled into one clean, fast, ad-free interface.\n\n**One app for every PDF job.** Organize and edit your documents (merge, split, reorder, rotate, crop, watermark, page numbers, redaction, annotations and forms), convert to and from PDF (images, Word, Excel, PowerPoint, EPUB, Markdown and more), run OCR, and secure your files with compression, encryption, digital signatures, and metadata cleanup.\n\n**Made for your private cloud.** Self-hosting BentoPDF on a private cloud device like self-hosted server gives your whole household or team a single, ad-free PDF workshop on hardware you control \u2014 fast over the local network, with your documents staying private by design.\n"
|
||||
"en_US": "**Your PDFs never leave your device.** BentoPDF is a privacy-first PDF toolkit that runs entirely in your browser. Every merge, split, conversion, and edit happens locally on your machine — no file is ever uploaded to a server. More than 50 tools are bundled into one clean, fast, ad-free interface.\n\n**One app for every PDF job.** Organize and edit your documents (merge, split, reorder, rotate, crop, watermark, page numbers, redaction, annotations and forms), convert to and from PDF (images, Word, Excel, PowerPoint, EPUB, Markdown and more), run OCR, and secure your files with compression, encryption, digital signatures, and metadata cleanup.\n\n**Made for your private cloud.** Self-hosting BentoPDF on a private cloud device like self-hosted server gives your whole household or team a single, ad-free PDF workshop on hardware you control — fast over the local network, with your documents staying private by design.\n"
|
||||
},
|
||||
"category": "documents",
|
||||
"category_label": "Documents & Notes",
|
||||
"author": "BentoPDF",
|
||||
"developer": "BentoPDF",
|
||||
"icon": null,
|
||||
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/bentopdf.webp",
|
||||
"thumbnail": null,
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
"description": {
|
||||
"en_US": "Bitcoin Knots can be used as a desktop client for regular payments or as a full node server utility for merchants and other payment services."
|
||||
},
|
||||
"category": "misc",
|
||||
"category_label": "Miscellaneous",
|
||||
"category": "finance",
|
||||
"category_label": "Finance & Budgeting",
|
||||
"author": "LinuxServer.io",
|
||||
"developer": null,
|
||||
"icon": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/bitcoin-knots-icon.png",
|
||||
"icon": "https://cdn.jsdelivr.net/gh/linuxserver/docker-templates@master/linuxserver.io/img/bitcoin-knots-logo.png",
|
||||
"thumbnail": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/bitcoin-knots-banner.png",
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
"description": {
|
||||
"en_US": "Wolfenstein: Blade of Agony is a story-driven WWII shooter inspired by Wolfenstein and Doom."
|
||||
},
|
||||
"category": "misc",
|
||||
"category_label": "Miscellaneous",
|
||||
"category": "gaming",
|
||||
"category_label": "Gaming & Leisure",
|
||||
"author": "LinuxServer.io",
|
||||
"developer": null,
|
||||
"icon": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/blade-of-agony-icon.png",
|
||||
"icon": "https://cdn.jsdelivr.net/gh/linuxserver/docker-templates@master/linuxserver.io/img/boa-logo.png",
|
||||
"thumbnail": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/blade-of-agony-banner.png",
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
"description": {
|
||||
"en_US": "Blender is a free and open-source 3D computer graphics software toolset used for creating animated films, visual effects, art, 3D printed models, motion graphics, interactive 3D applications, virtual reality, and computer games. **This image does not support GPU rendering out of the box only accelerated workspace experience**"
|
||||
},
|
||||
"category": "misc",
|
||||
"category_label": "Miscellaneous",
|
||||
"category": "creative",
|
||||
"category_label": "Creative & Design",
|
||||
"author": "LinuxServer.io",
|
||||
"developer": null,
|
||||
"icon": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/blender-icon.png",
|
||||
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/blender.webp",
|
||||
"thumbnail": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/blender-banner.png",
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"category_label": "Productivity & Workflows",
|
||||
"author": "blinkospace",
|
||||
"developer": "blinkospace",
|
||||
"icon": null,
|
||||
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/blinko.webp",
|
||||
"thumbnail": null,
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"category_label": "Miscellaneous",
|
||||
"author": "LinuxServer.io",
|
||||
"developer": null,
|
||||
"icon": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/boinc-icon.png",
|
||||
"icon": "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@main/webp/boinc.webp",
|
||||
"thumbnail": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/boinc-banner.png",
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"category_label": "Documents & Notes",
|
||||
"author": "LinuxServer.io",
|
||||
"developer": null,
|
||||
"icon": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/bookstack-icon.png",
|
||||
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/bookstack.webp",
|
||||
"thumbnail": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/bookstack-banner.png",
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
"description": {
|
||||
"en_US": "The Brave browser is a fast, private and secure web browser for PC, Mac and mobile."
|
||||
},
|
||||
"category": "misc",
|
||||
"category_label": "Miscellaneous",
|
||||
"category": "desktop",
|
||||
"category_label": "Browsers & Web Desktops",
|
||||
"author": "LinuxServer.io",
|
||||
"developer": null,
|
||||
"icon": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/brave-icon.png",
|
||||
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/brave.webp",
|
||||
"thumbnail": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/brave-banner.png",
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
"description": {
|
||||
"en_US": "budge is an open source 'budgeting with envelopes' personal finance app."
|
||||
},
|
||||
"category": "misc",
|
||||
"category_label": "Miscellaneous",
|
||||
"category": "finance",
|
||||
"category_label": "Finance & Budgeting",
|
||||
"author": "LinuxServer.io",
|
||||
"developer": null,
|
||||
"icon": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/budge-icon.png",
|
||||
"icon": "https://cdn.jsdelivr.net/gh/linuxserver/budge@master/frontend/public/logo512.png",
|
||||
"thumbnail": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/budge-banner.png",
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"category_label": "Media & Streaming",
|
||||
"author": "LinuxServer.io",
|
||||
"developer": null,
|
||||
"icon": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/calibre-web-icon.png",
|
||||
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/calibre-web.webp",
|
||||
"thumbnail": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/calibre-web-banner.png",
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
"description": {
|
||||
"en_US": "Calibre is a powerful and easy to use e-book manager. Users say it's outstanding and a must-have. It'll allow you to do nearly everything and it takes things a step beyond normal e-book software. It's also completely free and open source and great for both casual users and computer experts."
|
||||
},
|
||||
"category": "misc",
|
||||
"category_label": "Miscellaneous",
|
||||
"category": "media",
|
||||
"category_label": "Media & Streaming",
|
||||
"author": "LinuxServer.io",
|
||||
"developer": null,
|
||||
"icon": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/calibre-icon.png",
|
||||
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/calibre.webp",
|
||||
"thumbnail": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/calibre-banner.png",
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
"description": {
|
||||
"en_US": "Calligra is an office and graphic art suite by KDE. It is available for desktop PCs, tablet computers, and smartphones. It contains applications for word processing, spreadsheets, presentation, vector graphics, and editing databases."
|
||||
},
|
||||
"category": "misc",
|
||||
"category_label": "Miscellaneous",
|
||||
"category": "documents",
|
||||
"category_label": "Documents & Notes",
|
||||
"author": "LinuxServer.io",
|
||||
"developer": null,
|
||||
"icon": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/calligra-icon.png",
|
||||
"icon": "https://cdn.jsdelivr.net/gh/linuxserver/docker-templates@master/linuxserver.io/img/calligra-logo.png",
|
||||
"thumbnail": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/calligra-banner.png",
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
"description": {
|
||||
"en_US": "Changedetection.io provides free, open-source web page monitoring, notification and change detection."
|
||||
},
|
||||
"category": "misc",
|
||||
"category_label": "Miscellaneous",
|
||||
"category": "monitoring",
|
||||
"category_label": "Monitoring & Analytics",
|
||||
"author": "LinuxServer.io",
|
||||
"developer": null,
|
||||
"icon": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/changedetection.io-icon.png",
|
||||
"icon": "https://cdn.jsdelivr.net/gh/linuxserver/docker-templates@master/linuxserver.io/img/changedetection-icon.png",
|
||||
"thumbnail": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/changedetection.io-banner.png",
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"category_label": "AI / Coding & Dev-Tools",
|
||||
"author": "Mckay Wrigley",
|
||||
"developer": "Mckay Wrigley",
|
||||
"icon": null,
|
||||
"icon": "https://cdn.jsdelivr.net/gh/IceWhaleTech/CasaOS-AppStore@main/Apps/ChatbotUI/icon.png",
|
||||
"thumbnail": null,
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"category_label": "AI / Coding & Dev-Tools",
|
||||
"author": "Yidadaa",
|
||||
"developer": "Yidadaa",
|
||||
"icon": null,
|
||||
"icon": "https://cdn.jsdelivr.net/gh/IceWhaleTech/CasaOS-AppStore@main/Apps/ChatGPT-Next-Web/icon.png",
|
||||
"thumbnail": null,
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
"description": {
|
||||
"en_US": "Chrome is the official web browser from Google, built to be fast, secure, and customizable."
|
||||
},
|
||||
"category": "misc",
|
||||
"category_label": "Miscellaneous",
|
||||
"category": "desktop",
|
||||
"category_label": "Browsers & Web Desktops",
|
||||
"author": "LinuxServer.io",
|
||||
"developer": null,
|
||||
"icon": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/chrome-icon.png",
|
||||
"icon": "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@main/webp/chrome.webp",
|
||||
"thumbnail": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/chrome-banner.png",
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
"description": {
|
||||
"en_US": "Chromium is an open-source browser project that aims to build a safer, faster, and more stable way for all users to experience the web."
|
||||
},
|
||||
"category": "misc",
|
||||
"category_label": "Miscellaneous",
|
||||
"category": "desktop",
|
||||
"category_label": "Browsers & Web Desktops",
|
||||
"author": "LinuxServer.io",
|
||||
"developer": null,
|
||||
"icon": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/chromium-icon.png",
|
||||
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/chromium.webp",
|
||||
"thumbnail": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/chromium-banner.png",
|
||||
"screenshots": [],
|
||||
"architectures": [
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user