mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-11-01 10:22:08 +00:00
Check translation contracts offline, add Swedish to the installer and enable the website languages
- Offline checks for terminal and website catalogs reject translations that change commands, paths, identifiers or placeholders - Terminal and documentation texts that broke those contracts are corrected in every language - Swedish can be chosen in the stable and beta installers - The website routes, language switcher and exported pages cover the eight languages, with the shared website texts in each of them - Website documentation translations are generated only when requested - From PR #475 by @jcastro
This commit is contained in:
@@ -73,6 +73,24 @@ TECHNICAL_TERMS = (
|
||||
"DKMS",
|
||||
"SSH",
|
||||
"API",
|
||||
"Flask",
|
||||
"SQLite",
|
||||
"Prometheus",
|
||||
"Grafana",
|
||||
"Uptime Kuma",
|
||||
"PWA",
|
||||
"Fail2Ban",
|
||||
"Tailscale",
|
||||
"JavaScript",
|
||||
"TypeScript",
|
||||
"Next.js",
|
||||
"Coral",
|
||||
"rclone",
|
||||
"journald",
|
||||
"gasket",
|
||||
"apex",
|
||||
"Alpine",
|
||||
"OpenVINO",
|
||||
)
|
||||
|
||||
PROTECTED_PATTERNS = (
|
||||
@@ -88,9 +106,13 @@ PROTECTED_PATTERNS = (
|
||||
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_]*"),
|
||||
# Identifiers and encoded delimiters remain literal even outside <code>.
|
||||
re.compile(r"(?<![A-Za-z0-9_])_?[A-Za-z][A-Za-z0-9]*(?:_[A-Za-z0-9]+)+(?![A-Za-z0-9_])"),
|
||||
re.compile(r"\b[A-Za-z0-9]*(?:[a-z][A-Z])[A-Za-z0-9]*\b"),
|
||||
re.compile(r"&(?:[A-Za-z]+|#[0-9]+|#x[0-9A-Fa-f]+);"),
|
||||
)
|
||||
LITERAL_TAG_RE = re.compile(
|
||||
r"<(code|kbd|pre)\b[^>]*>.*?</\1>",
|
||||
r"<(code|codeNw|codeXs|kbd|pre)\b[^>]*>.*?</\1>",
|
||||
re.IGNORECASE | re.DOTALL,
|
||||
)
|
||||
|
||||
@@ -109,16 +131,23 @@ ANY_TAG_RE = re.compile(r"</?[A-Za-z][^<>]*>")
|
||||
BARE_SENTINELS = False
|
||||
PLACEHOLDER_RE = re.compile(r"\{[A-Za-z_][A-Za-z0-9_.-]*\}")
|
||||
NON_TRANSLATABLE_KEYS = {
|
||||
"accent",
|
||||
"categoryslug",
|
||||
"command",
|
||||
"code",
|
||||
"href",
|
||||
"icon",
|
||||
"iconbg",
|
||||
"id",
|
||||
"menucmd",
|
||||
"path",
|
||||
"route",
|
||||
"slug",
|
||||
"src",
|
||||
"url",
|
||||
"color",
|
||||
"tone",
|
||||
"variant",
|
||||
}
|
||||
SOURCE_STATE_VERSION = 1
|
||||
|
||||
@@ -186,12 +215,34 @@ def should_copy(source: str, path: tuple[str | int, ...]) -> bool:
|
||||
if not source.strip() or not re.search(r"[A-Za-z]", source):
|
||||
return True
|
||||
last = str(path[-1]).lower() if path else ""
|
||||
# These fields describe the surrounding snippet; they are prose, even
|
||||
# though their names end in "Code".
|
||||
if last in {"aftercode", "beforecode"}:
|
||||
return False
|
||||
# This UI breadcrumb is prose, rather than a filesystem path.
|
||||
if last == "uipath" and "<strong>" in source:
|
||||
return False
|
||||
if last == "flow" and source in {"loader", "dedicated"}:
|
||||
return True
|
||||
# These exact values drive rendering/navigation; similarly named visible
|
||||
# labels remain translatable.
|
||||
if last == "branch" and source in {"main", "develop", "feature/*"}:
|
||||
return True
|
||||
if last == "kind" and source in {"internal", "external"}:
|
||||
return True
|
||||
if last == "key" and source in {"linux", "nas", "windows"}:
|
||||
return True
|
||||
if last in NON_TRANSLATABLE_KEYS or any(
|
||||
last.endswith(suffix)
|
||||
for suffix in ("url", "href", "path", "command", "code", "icon")
|
||||
):
|
||||
return True
|
||||
if re.fullmatch(r"https?://\S+", source) or re.fullmatch(r"/[A-Za-z0-9_./:@%+=-]+", source):
|
||||
if re.fullmatch(r"https?://\S+", source) or re.fullmatch(r"/\S+", source):
|
||||
return True
|
||||
# Standalone literal blocks contain examples, not prose. Separators between
|
||||
# several blocks do not make their command/configuration contents translatable.
|
||||
without_literals = LITERAL_TAG_RE.sub("", source)
|
||||
if without_literals != source and not re.search(r"[A-Za-z]", ANY_TAG_RE.sub("", without_literals)):
|
||||
return True
|
||||
if re.fullmatch(r"[A-Z0-9_.:/+-]{2,}", source):
|
||||
return True
|
||||
@@ -202,6 +253,15 @@ def leaf_token(path: tuple[str | int, ...]) -> str:
|
||||
return json.dumps(path, ensure_ascii=False, separators=(",", ":"))
|
||||
|
||||
|
||||
def literal_values_match(source: Any, target: Any) -> bool:
|
||||
"""Literal commands and rendering metadata must follow the source too."""
|
||||
return all(
|
||||
not should_copy(leaf.source, leaf.path)
|
||||
or get_at_path(target, leaf.path) == leaf.source
|
||||
for leaf in iter_leaves(source)
|
||||
)
|
||||
|
||||
|
||||
def source_fingerprints(source: Any) -> dict[str, str]:
|
||||
return {
|
||||
leaf_token(leaf.path): hashlib.sha256(leaf.source.encode("utf-8")).hexdigest()[:20]
|
||||
@@ -240,7 +300,7 @@ def protect_rich_tags(text: str) -> tuple[str, dict[str, str]]:
|
||||
|
||||
def replace(match: re.Match[str]) -> str:
|
||||
original = match.group(1)
|
||||
if original.lower() in {"code", "kbd", "pre"}:
|
||||
if original.lower() in {"code", "codenw", "codexs", "kbd", "pre"}:
|
||||
return match.group(0)
|
||||
key = original.lower()
|
||||
internal = names.get(key)
|
||||
@@ -329,11 +389,14 @@ def protect_text(text: str) -> tuple[str, dict[str, str]]:
|
||||
|
||||
|
||||
def restore_text(text: str, mapping: dict[str, str]) -> str:
|
||||
missing = [token for token in mapping if token not in text]
|
||||
# A local model may append a digit to a bare sentinel. A substring match
|
||||
# would silently restore the prefix and leak the extra digit into prose.
|
||||
patterns = {token: re.compile(re.escape(token) + r"(?![0-9])") for token in mapping}
|
||||
missing = [token for token, pattern in patterns.items() if not pattern.search(text)]
|
||||
if missing:
|
||||
raise ValueError(f"translation provider changed protected token {missing[0]}")
|
||||
for token, original in mapping.items():
|
||||
text = text.replace(token, original)
|
||||
text = patterns[token].sub(lambda match: original, text)
|
||||
return text
|
||||
|
||||
|
||||
@@ -347,6 +410,11 @@ def validate_contract(source: str, target: str) -> None:
|
||||
raise ValueError("literal code changed")
|
||||
if sorted(PLACEHOLDER_RE.findall(source)) != sorted(PLACEHOLDER_RE.findall(target)):
|
||||
raise ValueError("placeholder contract changed")
|
||||
# Bare numeric protection markers once leaked a trailing zero just
|
||||
# outside an otherwise intact code span. Literal/ICU checks cannot see it.
|
||||
residue = re.compile(r'(?:</(?:code|codeNw|codeXs|pre|kbd)>|<strong>)(0+)(?=\s|[;:/<().,-]|$)')
|
||||
if len(residue.findall(target)) > len(residue.findall(source)):
|
||||
raise ValueError("unexpected numeric residue next to literal markup")
|
||||
|
||||
|
||||
def provider_function(args: argparse.Namespace) -> Callable[[str, str], str]:
|
||||
@@ -822,7 +890,10 @@ def main() -> int:
|
||||
leaves = pending_leaves(source, target, queued_tokens)
|
||||
total_strings += len(iter_leaves(source))
|
||||
missing_strings += len(leaves)
|
||||
schema_changed = not schema_matches(source, target)
|
||||
schema_changed = (
|
||||
not schema_matches(source, target)
|
||||
or not literal_values_match(source, target)
|
||||
)
|
||||
if leaves or schema_changed:
|
||||
pending.append(
|
||||
(
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Check active terminal translations offline, without generating any text.
|
||||
|
||||
Validates formatting fields and literal commands/identifiers. Missing values
|
||||
can retain English fallback; --require-complete makes them errors. This does
|
||||
not establish the accuracy or fluency of the translated prose.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
import re
|
||||
|
||||
from build_translation_cache import (
|
||||
DEFAULT_LANGUAGES, STRUCTURAL_LITERAL_RE, extract_catalog_texts,
|
||||
extract_python_texts, extract_translate_texts,
|
||||
)
|
||||
from build_web_docs_i18n import read_json, validate_contract
|
||||
|
||||
|
||||
def active_sources(root: Path) -> list[str]:
|
||||
# Match build-translation-cache.yml, including launchers outside scripts/.
|
||||
extras = [root / name for name in ('menu', 'install_proxmenux.sh', 'install_proxmenux_beta.sh')]
|
||||
texts = extract_translate_texts(root / 'scripts', extras)
|
||||
texts += extract_translate_texts(root / 'oci/remote')
|
||||
texts += extract_python_texts([root / 'scripts', root / 'oci/src', root / 'oci/remote'])
|
||||
texts += extract_catalog_texts([root / 'oci/catalog'])
|
||||
return sorted({text for text in texts if '$' not in text and '`' not in text})
|
||||
|
||||
|
||||
def validate_message(source: str, target: str, *, title_separator: bool = False) -> None:
|
||||
validate_contract(source, target)
|
||||
for match in STRUCTURAL_LITERAL_RE.finditer(source):
|
||||
literal = match.group()
|
||||
# A page title may replace its decorative separator with a dash.
|
||||
# In command examples, a pipe remains a shell operator.
|
||||
if title_separator and literal == '|':
|
||||
continue
|
||||
# DNS hostnames are case-insensitive. Paths, field names and command
|
||||
# names are not, so do not case-fold those to hide a broken example.
|
||||
is_hostname = re.fullmatch(r'[A-Za-z0-9.-]+\.(?:com|org|net|io)', literal)
|
||||
if literal not in target and not (is_hostname and literal.casefold() in target.casefold()):
|
||||
raise ValueError(f'literal command or identifier changed: {literal}')
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--root', type=Path, default=Path('.'))
|
||||
parser.add_argument('--languages', default=','.join(DEFAULT_LANGUAGES))
|
||||
parser.add_argument('--require-complete', action='store_true')
|
||||
args = parser.parse_args()
|
||||
root = args.root.resolve()
|
||||
texts = active_sources(root)
|
||||
errors = 0
|
||||
for language in args.languages.split(','):
|
||||
if language not in DEFAULT_LANGUAGES:
|
||||
parser.error(f'Unsupported locale: {language}')
|
||||
catalog = read_json(root / 'lang' / f'{language}.json') or {}
|
||||
missing = 0
|
||||
for source in texts:
|
||||
target = catalog.get(source)
|
||||
if not isinstance(target, str) or not target.strip():
|
||||
missing += 1
|
||||
continue
|
||||
try:
|
||||
validate_message(source, target)
|
||||
except ValueError as error:
|
||||
print(f'[{language}] {source!r}: {error}')
|
||||
errors += 1
|
||||
print(f'[{language}] active={len(texts)} missing={missing}')
|
||||
if args.require_complete and missing:
|
||||
errors += 1
|
||||
return 1 if errors else 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
raise SystemExit(main())
|
||||
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Check documentation translation structure and literal contracts offline.
|
||||
|
||||
Missing locales/leaves are allowed by default because the website falls back
|
||||
to English. Use --require-complete when validating a catalog completion PR.
|
||||
This checks data integrity, not translation fluency or linguistic accuracy.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
|
||||
from build_web_docs_i18n import (
|
||||
DEFAULT_LANGUAGES,
|
||||
get_at_path,
|
||||
iter_leaves,
|
||||
literal_values_match,
|
||||
read_json,
|
||||
schema_matches,
|
||||
source_files,
|
||||
)
|
||||
from check_terminal_catalogs import validate_message
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--messages-dir", type=Path, default=Path("web/messages"))
|
||||
parser.add_argument("--languages", default=",".join(DEFAULT_LANGUAGES))
|
||||
parser.add_argument("--require-complete", action="store_true")
|
||||
args = parser.parse_args()
|
||||
root = args.messages_dir.resolve()
|
||||
files = source_files(root / "en", ".")
|
||||
errors = 0
|
||||
for language in args.languages.split(","):
|
||||
language = language.strip()
|
||||
if language not in DEFAULT_LANGUAGES:
|
||||
parser.error(f"Unsupported locale: {language}")
|
||||
missing = checked = present_files = 0
|
||||
for file in files:
|
||||
relative = file.relative_to(root / "en")
|
||||
source = read_json(file)
|
||||
target = read_json(root / language / relative)
|
||||
if target is not None:
|
||||
present_files += 1
|
||||
if args.require_complete and not schema_matches(source, target):
|
||||
print(f"[{language}] {relative}: source/target schema differs")
|
||||
errors += 1
|
||||
for leaf in iter_leaves(source):
|
||||
localized = get_at_path(target, leaf.path)
|
||||
if not isinstance(localized, str) or (leaf.source.strip() and not localized.strip()):
|
||||
missing += 1
|
||||
continue
|
||||
try:
|
||||
validate_message(
|
||||
leaf.source, localized,
|
||||
title_separator=bool(
|
||||
leaf.path and leaf.path[0] == "meta"
|
||||
and leaf.path[-1] in ("title", "ogTitle", "twitterTitle")
|
||||
),
|
||||
)
|
||||
except ValueError as exc:
|
||||
print(f"[{language}] {relative}:{'.'.join(map(str, leaf.path))}: {exc}")
|
||||
errors += 1
|
||||
checked += 1
|
||||
if args.require_complete and not literal_values_match(source, target):
|
||||
print(f"[{language}] {relative}: literal commands or rendering metadata differ")
|
||||
errors += 1
|
||||
print(f"[{language}] files={present_files}/{len(files)} strings={checked} missing={missing}")
|
||||
if args.require_complete and missing:
|
||||
errors += 1
|
||||
return 1 if errors else 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -60,6 +60,124 @@ class WebDocsI18nTests(unittest.TestCase):
|
||||
target = {"title": "Actualizaciones", "url": "https://example.com"}
|
||||
self.assertEqual(MODULE.pending_leaves(source, target), [])
|
||||
|
||||
def test_rendering_metadata_is_copied_but_visible_labels_are_translated(self):
|
||||
for key, value in (("tone", "amber"), ("variant", "source"),
|
||||
("accent", "border-blue-300 bg-blue-50"),
|
||||
("iconBg", "bg-blue-100 text-blue-700"),
|
||||
("color", "green")):
|
||||
with self.subTest(key=key):
|
||||
self.assertTrue(MODULE.should_copy(value, ("steps", 0, key)))
|
||||
self.assertFalse(MODULE.should_copy(value, ("label",)))
|
||||
self.assertEqual(MODULE.merge_tree({key: value}, {key: "translated"}, {}), {key: value})
|
||||
self.assertFalse(MODULE.should_copy("Translation", ("type",)))
|
||||
self.assertFalse(MODULE.should_copy("English", ("lang",)))
|
||||
for value in ("loader", "dedicated"):
|
||||
self.assertTrue(MODULE.should_copy(value, ("cards", 0, "flow")))
|
||||
self.assertFalse(MODULE.should_copy(value, ("label",)))
|
||||
|
||||
def test_literal_only_examples_and_api_routes_are_not_translation_gaps(self):
|
||||
for source in ("<code>apt update</code>",
|
||||
"<code>net0</code> / <code>net1</code>.",
|
||||
"/api/task-log/<upid>", "/api/vms/<vmid>/config"):
|
||||
with self.subTest(source=source):
|
||||
self.assertTrue(MODULE.should_copy(source, ("cell",)))
|
||||
self.assertFalse(MODULE.should_copy("Run <code>apt update</code> first.", ("body",)))
|
||||
self.assertFalse(MODULE.should_copy("After running the command, check its output.", ("afterCode",)))
|
||||
self.assertFalse(MODULE.should_copy("Before running the command, read this.", ("beforeCode",)))
|
||||
self.assertTrue(MODULE.should_copy("curl http://localhost:8008/api/health", ("curlCode",)))
|
||||
|
||||
def test_inline_identifiers_and_encoded_delimiters_round_trip(self):
|
||||
source = "Set RS_SKIP_PATHS, call _rs_apply_hot and keep localStorage at <host>."
|
||||
protected, mapping = MODULE.protect_text(source)
|
||||
for literal in ("RS_SKIP_PATHS", "_rs_apply_hot", "localStorage", "<", ">"):
|
||||
self.assertIn(literal, mapping.values())
|
||||
self.assertNotIn(literal, protected)
|
||||
self.assertEqual(MODULE.restore_text(protected, mapping), source)
|
||||
|
||||
def test_custom_code_spans_keep_commands_literal(self):
|
||||
for tag in ("codeNw", "codeXs"):
|
||||
source = f"Run <{tag}>pct config 100</{tag}>."
|
||||
with self.subTest(tag=tag):
|
||||
protected, mapping = MODULE.protect_rich_tags(source)
|
||||
self.assertEqual(protected, source)
|
||||
self.assertEqual(mapping, {})
|
||||
with self.assertRaisesRegex(ValueError, "literal code changed"):
|
||||
MODULE.validate_contract(source, source.replace("config", "configuration"))
|
||||
with self.assertRaisesRegex(ValueError, "numeric residue"):
|
||||
MODULE.validate_contract(source, source.replace(f"</{tag}>", f"</{tag}>0"))
|
||||
self.assertTrue(MODULE.should_copy(f"<{tag}>pct config 100</{tag}>", ("example",)))
|
||||
|
||||
def test_navigation_identifiers_are_distinct_from_visible_labels(self):
|
||||
values = {
|
||||
"categorySlug": ["system", "network"],
|
||||
"menuCmd": ["menu"],
|
||||
"branch": ["main", "develop", "feature/*"],
|
||||
"kind": ["internal", "external"],
|
||||
"key": ["nas", "linux", "windows"],
|
||||
}
|
||||
for key, items in values.items():
|
||||
for value in items:
|
||||
with self.subTest(key=key, value=value):
|
||||
self.assertTrue(MODULE.should_copy(value, ("cards", 0, key)))
|
||||
self.assertFalse(MODULE.should_copy(value, ("label",)))
|
||||
self.assertFalse(MODULE.should_copy("Translation", ("kind",)))
|
||||
self.assertFalse(MODULE.should_copy("Storage", ("branch",)))
|
||||
|
||||
def test_ui_breadcrumb_is_prose_while_paths_remain_literal(self):
|
||||
source = "In the UI: <strong>Datacenter → Backup → Retention</strong>:"
|
||||
self.assertFalse(MODULE.should_copy(source, ("retention", "uiPath")))
|
||||
self.assertTrue(MODULE.should_copy("/etc/pve/storage.cfg", ("uiPath",)))
|
||||
self.assertTrue(MODULE.should_copy("/etc/pve/storage.cfg", ("configPath",)))
|
||||
|
||||
def test_bare_sentinel_with_added_digit_is_rejected(self):
|
||||
with mock.patch.object(MODULE, "BARE_SENTINELS", True):
|
||||
protected, mapping = MODULE.protect_text("ProxMenux collects metrics.")
|
||||
token = next(iter(mapping))
|
||||
with self.assertRaisesRegex(ValueError, "changed protected token"):
|
||||
MODULE.restore_text(protected.replace(token, token + "0"), mapping)
|
||||
self.assertEqual(MODULE.restore_text(protected, mapping), "ProxMenux collects metrics.")
|
||||
|
||||
def test_numeric_residue_outside_intact_literal_is_rejected(self):
|
||||
examples = [
|
||||
('Run <code>pct config</code> first.', 'Spustite <code>pct config</code>0 najprv.'),
|
||||
('<strong><code>Restart=on-failure</code></strong> restarts the service.',
|
||||
'<strong>0<code>Restart=on-failure</code></strong> reštartuje službu.'),
|
||||
]
|
||||
for source, target in examples:
|
||||
with self.subTest(source=source):
|
||||
with self.assertRaisesRegex(ValueError, 'numeric residue'):
|
||||
MODULE.validate_contract(source, target)
|
||||
MODULE.validate_contract('The result is <code>echo</code>0.',
|
||||
'Výsledok je <code>echo</code>0.')
|
||||
|
||||
def test_product_and_kernel_module_names_are_protected(self):
|
||||
source = "Flask uses SQLite and journald; rclone works with Coral, gasket, apex and Alpine."
|
||||
protected, mapping = MODULE.protect_text(source)
|
||||
for name in ("Flask", "SQLite", "journald", "rclone", "Coral", "gasket", "apex", "Alpine"):
|
||||
self.assertIn(name, mapping.values())
|
||||
self.assertNotIn(name, protected)
|
||||
self.assertEqual(MODULE.restore_text(protected, mapping), source)
|
||||
|
||||
def test_literal_only_changes_sync_without_retranslating_human_prose(self):
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
root = Path(temporary)
|
||||
source = root / "messages/en/common.json"
|
||||
target = root / "messages/de/common.json"
|
||||
source.parent.mkdir(parents=True)
|
||||
target.parent.mkdir(parents=True)
|
||||
source.write_text(json.dumps({"title": "Updates", "code": "tool --version=2", "tone": "blue"}))
|
||||
target.write_text(json.dumps({"title": "Aktualisierungen", "code": "tool --version=1", "tone": "blau"}))
|
||||
provider = mock.Mock(side_effect=AssertionError("Existing prose must not be retranslated"))
|
||||
self.assertEqual(self.run_generator(root, provider), 0)
|
||||
self.assertEqual(json.loads(target.read_text()), {
|
||||
"title": "Aktualisierungen", "code": "tool --version=2", "tone": "blue",
|
||||
})
|
||||
provider.assert_not_called()
|
||||
before = target.stat().st_mtime_ns
|
||||
self.assertEqual(self.run_generator(root, provider), 0)
|
||||
self.assertEqual(target.stat().st_mtime_ns, before)
|
||||
provider.assert_not_called()
|
||||
|
||||
def test_changed_source_text_is_pending_even_with_existing_translation(self):
|
||||
source = {"title": "Updated installation guidance"}
|
||||
target = {"title": "Vorherige Installationsanleitung"}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
"""Keep machine generation explicit without losing automatic validation."""
|
||||
from pathlib import Path
|
||||
import unittest
|
||||
|
||||
import yaml
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[3]
|
||||
|
||||
|
||||
class DocumentationReviewWorkflowTests(unittest.TestCase):
|
||||
def workflow(self, name):
|
||||
return yaml.load(
|
||||
(ROOT / '.github/workflows' / name).read_text(encoding='utf-8'),
|
||||
Loader=yaml.BaseLoader,
|
||||
)
|
||||
|
||||
def test_generation_requires_explicit_dispatch(self):
|
||||
triggers = self.workflow('build-web-docs-i18n.yml')['on']
|
||||
self.assertEqual(set(triggers), {'workflow_dispatch'})
|
||||
|
||||
def test_website_changes_keep_automatic_offline_validation(self):
|
||||
triggers = self.workflow('test-i18n.yml')['on']
|
||||
for event in ('pull_request', 'push'):
|
||||
with self.subTest(event=event):
|
||||
self.assertIn('web/**', triggers[event]['paths'])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,30 @@
|
||||
"""Every shipped terminal language must be selectable during installation."""
|
||||
from pathlib import Path
|
||||
import re
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
SCRIPTS = Path(__file__).resolve().parents[1]
|
||||
ROOT = SCRIPTS.parents[1]
|
||||
sys.path.insert(0, str(SCRIPTS))
|
||||
from build_translation_cache import DEFAULT_LANGUAGES
|
||||
|
||||
|
||||
class InstallerLanguageTests(unittest.TestCase):
|
||||
def test_both_installers_offer_every_shipped_language(self):
|
||||
expected = {'en', *DEFAULT_LANGUAGES}
|
||||
for name in ('install_proxmenux.sh', 'install_proxmenux_beta.sh'):
|
||||
with self.subTest(installer=name):
|
||||
source = (ROOT / name).read_text(encoding='utf-8')
|
||||
function = re.search(r'^select_language\(\) \{(.*?)^\}', source, re.M | re.S)
|
||||
self.assertIsNotNone(function, 'Missing installer language selector')
|
||||
offered = re.findall(r'^\s*"([a-z]{2})"\s+"[^"]+"', function.group(1), re.M)
|
||||
self.assertEqual(set(offered), expected)
|
||||
self.assertEqual(len(offered), len(expected), 'Duplicate language option')
|
||||
# English is the source text in the scripts, not a JSON catalog.
|
||||
for language in set(offered) - {'en'}:
|
||||
self.assertTrue((ROOT / 'lang' / f'{language}.json').is_file(), language)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,82 @@
|
||||
"""Offline regressions for copyable commands and runtime format fields."""
|
||||
import importlib.util
|
||||
import json
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
SCRIPTS = Path(__file__).resolve().parents[1]
|
||||
ROOT = SCRIPTS.parents[1]
|
||||
sys.path.insert(0, str(SCRIPTS))
|
||||
SPEC = importlib.util.spec_from_file_location('check_terminal_catalogs', SCRIPTS / 'check_terminal_catalogs.py')
|
||||
MODULE = importlib.util.module_from_spec(SPEC)
|
||||
assert SPEC and SPEC.loader
|
||||
SPEC.loader.exec_module(MODULE)
|
||||
|
||||
|
||||
class TerminalCatalogsTests(unittest.TestCase):
|
||||
def test_extractor_includes_launchers_remote_scripts_and_catalog_text(self):
|
||||
fixtures = {
|
||||
'menu': 'translate "Main launcher"',
|
||||
'install_proxmenux.sh': 'translate "Stable installer"',
|
||||
'install_proxmenux_beta.sh': 'translate "Beta installer"',
|
||||
'scripts/check.sh': 'translate "Host shell script"',
|
||||
'scripts/check.py': 'translate("Host Python script")',
|
||||
'oci/src/check.py': 'N_("OCI Python script")',
|
||||
'oci/remote/check.py': 'translate("Remote Python script")',
|
||||
'oci/remote/check.sh': 'translate "Remote shell script"',
|
||||
'oci/catalog/app.json': json.dumps({'catalog_ui': {'tagline': {'en_US': 'Application tagline'}}}),
|
||||
}
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
root = Path(temporary)
|
||||
for name, content in fixtures.items():
|
||||
file = root / name
|
||||
file.parent.mkdir(parents=True, exist_ok=True)
|
||||
file.write_text(content, encoding='utf-8')
|
||||
self.assertEqual(set(MODULE.active_sources(root)), {
|
||||
'Main launcher', 'Stable installer', 'Beta installer',
|
||||
'Host shell script', 'Host Python script', 'OCI Python script',
|
||||
'Remote Python script', 'Remote shell script', 'Application tagline',
|
||||
})
|
||||
|
||||
def test_runtime_format_field_cannot_be_translated(self):
|
||||
source = 'Kimai has no default account. Enter the container with: pct enter {main_vmid}'
|
||||
with self.assertRaisesRegex(ValueError, 'placeholder'):
|
||||
MODULE.validate_message(source, 'Kimai nemá účet: pct enter {main vmid}')
|
||||
MODULE.validate_message(source, 'Kimai nemá účet: pct enter {main_vmid}')
|
||||
|
||||
def test_copyable_command_and_environment_variable_are_literal(self):
|
||||
examples = [
|
||||
('Example: pct config 110 | grep unprivileged', 'Ejemplo: configuración pct 110 | grep sin privilegios'),
|
||||
("Use 'pct restore' to recover the disks.", "Verwenden Sie 'pct restart', um die Datenträger wiederherzustellen."),
|
||||
('Invalid ALLOWED_HOSTS value', 'Valeur HÔTES INDÉSIRABLES'),
|
||||
]
|
||||
for source, target in examples:
|
||||
with self.subTest(source=source):
|
||||
with self.assertRaisesRegex(ValueError, 'literal command or identifier'):
|
||||
MODULE.validate_message(source, target)
|
||||
MODULE.validate_message('Example: pct config 110 | grep unprivileged',
|
||||
'Ejemplo: pct config 110 | grep unprivileged')
|
||||
|
||||
def test_dns_capitalization_does_not_relax_file_path_case(self):
|
||||
MODULE.validate_message('Cannot reach download.proxmox.com.',
|
||||
'Download.proxmox.com ist nicht erreichbar.')
|
||||
with self.assertRaisesRegex(ValueError, 'literal command or identifier'):
|
||||
MODULE.validate_message('Check /etc/pve/storage.cfg', 'Prüfen Sie /etc/PVE/storage.cfg')
|
||||
|
||||
def test_shipped_active_catalogs_keep_literal_contracts(self):
|
||||
result = subprocess.run(
|
||||
[sys.executable, '-B', str(SCRIPTS / 'check_terminal_catalogs.py'),
|
||||
'--root', str(ROOT), '--require-complete'],
|
||||
capture_output=True, text=True, timeout=60,
|
||||
)
|
||||
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
|
||||
for locale in MODULE.DEFAULT_LANGUAGES:
|
||||
self.assertIn(f'[{locale}] active=', result.stdout)
|
||||
self.assertNotIn('missing=1', result.stdout)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,94 @@
|
||||
"""Validate complete catalogs without rejecting intentional English fallback."""
|
||||
import json
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
|
||||
SCRIPT = Path(__file__).resolve().parents[1] / "check_web_docs_catalogs.py"
|
||||
|
||||
|
||||
class WebDocsCatalogTests(unittest.TestCase):
|
||||
def run_check(self, root, *options):
|
||||
return subprocess.run(
|
||||
[sys.executable, "-B", str(SCRIPT), "--messages-dir", str(root),
|
||||
"--languages", "de", *options],
|
||||
capture_output=True, text=True,
|
||||
)
|
||||
|
||||
def write_catalog(self, root, locale, content):
|
||||
file = root / locale / "common.json"
|
||||
file.parent.mkdir(parents=True, exist_ok=True)
|
||||
file.write_text(json.dumps(content), encoding="utf-8")
|
||||
|
||||
def test_partial_catalog_keeps_fallback_but_complete_mode_reports_gap(self):
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
root = Path(temporary)
|
||||
self.write_catalog(root, "en", {"title": "Updates", "body": "Check the host."})
|
||||
self.write_catalog(root, "de", {"title": "Aktualisierungen"})
|
||||
partial = self.run_check(root)
|
||||
self.assertEqual(partial.returncode, 0, partial.stdout + partial.stderr)
|
||||
self.assertIn("missing=1", partial.stdout)
|
||||
complete = self.run_check(root, "--require-complete")
|
||||
self.assertEqual(complete.returncode, 1, complete.stdout + complete.stderr)
|
||||
self.assertIn("schema differs", complete.stdout)
|
||||
|
||||
def test_translated_code_is_rejected_in_both_modes(self):
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
root = Path(temporary)
|
||||
self.write_catalog(root, "en", {"body": "Run <code>apt update</code>."})
|
||||
self.write_catalog(root, "de", {"body": "Führe <code>apt aktualisieren</code> aus."})
|
||||
for options in ((), ("--require-complete",)):
|
||||
with self.subTest(options=options):
|
||||
result = self.run_check(root, *options)
|
||||
self.assertEqual(result.returncode, 1, result.stdout + result.stderr)
|
||||
|
||||
def test_bare_commands_and_operators_are_not_prose(self):
|
||||
examples = [
|
||||
("Restore with pct restore.", "Mit pct restart wiederherstellen."),
|
||||
("pveversion | grep pve-manager", "pveversion grep pve-manager"),
|
||||
("cd /opt/my-app && ./update.sh", "cd /opt/meine-app && ./update.sh"),
|
||||
]
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
root = Path(temporary)
|
||||
for source, target in examples:
|
||||
with self.subTest(source=source):
|
||||
self.write_catalog(root, "en", {"body": source})
|
||||
self.write_catalog(root, "de", {"body": target})
|
||||
result = self.run_check(root)
|
||||
self.assertEqual(result.returncode, 1, result.stdout + result.stderr)
|
||||
self.assertIn("literal command or identifier", result.stdout)
|
||||
|
||||
def test_title_separator_can_change_without_relaxing_body_pipes(self):
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
root = Path(temporary)
|
||||
self.write_catalog(root, "en", {"meta": {"title": "Storage | ProxMenux"}})
|
||||
self.write_catalog(root, "de", {"meta": {"title": "Speicher — ProxMenux"}})
|
||||
result = self.run_check(root, "--require-complete")
|
||||
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
|
||||
self.write_catalog(root, "en", {"meta": {"description": "pveversion | grep pve-manager"}})
|
||||
self.write_catalog(root, "de", {"meta": {"description": "pveversion grep pve-manager"}})
|
||||
result = self.run_check(root)
|
||||
self.assertEqual(result.returncode, 1, result.stdout + result.stderr)
|
||||
|
||||
def test_shipped_web_catalogs_keep_literal_contracts(self):
|
||||
messages = SCRIPT.parents[2] / "web" / "messages"
|
||||
result = subprocess.run(
|
||||
[sys.executable, "-B", str(SCRIPT), "--messages-dir", str(messages)],
|
||||
capture_output=True, text=True, timeout=60,
|
||||
)
|
||||
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
|
||||
|
||||
def test_literal_metadata_is_required_but_labels_can_be_localized(self):
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
root = Path(temporary)
|
||||
self.write_catalog(root, "en", {"label": "Updates", "tone": "blue"})
|
||||
self.write_catalog(root, "de", {"label": "Aktualisierungen", "tone": "blau"})
|
||||
invalid = self.run_check(root, "--require-complete")
|
||||
self.assertEqual(invalid.returncode, 1, invalid.stdout + invalid.stderr)
|
||||
self.assertIn("rendering metadata differ", invalid.stdout)
|
||||
self.write_catalog(root, "de", {"label": "Aktualisierungen", "tone": "blue"})
|
||||
valid = self.run_check(root, "--require-complete")
|
||||
self.assertEqual(valid.returncode, 0, valid.stdout + valid.stderr)
|
||||
@@ -0,0 +1,41 @@
|
||||
"""Exercise the static-export language repair on real HTML files."""
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
from test_command_descriptions import require_node
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[3]
|
||||
SCRIPT = ROOT / "web/scripts/localize-export.mjs"
|
||||
|
||||
|
||||
class WebExportLanguageTests(unittest.TestCase):
|
||||
def test_locales_nested_pages_preserved_content_and_idempotence(self):
|
||||
node = require_node()
|
||||
html = '<!doctype html><html lang="en" class="dark"><body><h1>Text</h1><script>const example=\'<html lang="en">\';</script></body></html>'
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
root = Path(temporary)
|
||||
locales = ["en", "es", "de", "fr", "it", "pt", "sk", "sv"]
|
||||
for locale in locales:
|
||||
file = root / "out" / locale / "docs/monitor/index.html"
|
||||
file.parent.mkdir(parents=True)
|
||||
file.write_text(html)
|
||||
for relative in ["out/index.html", "out/assets/index.html"]:
|
||||
file = root / relative
|
||||
file.parent.mkdir(parents=True, exist_ok=True)
|
||||
file.write_text(html)
|
||||
result = subprocess.run([node, str(SCRIPT)], cwd=root, capture_output=True, text=True)
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
self.assertIn("8 localized pages", result.stdout)
|
||||
for locale in locales:
|
||||
actual = (root / "out" / locale / "docs/monitor/index.html").read_text()
|
||||
self.assertEqual(actual, html.replace('<html lang="en"', f'<html lang="{locale}"', 1))
|
||||
for relative in ["out/index.html", "out/assets/index.html"]:
|
||||
self.assertEqual((root / relative).read_text(), html)
|
||||
tracked = root / "out/de/docs/monitor/index.html"
|
||||
before = tracked.stat().st_mtime_ns
|
||||
second = subprocess.run([node, str(SCRIPT)], cwd=root, capture_output=True, text=True)
|
||||
self.assertEqual(second.returncode, 0, second.stderr)
|
||||
self.assertEqual(tracked.stat().st_mtime_ns, before)
|
||||
@@ -1,14 +1,9 @@
|
||||
name: Build web documentation translations
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [develop]
|
||||
paths:
|
||||
- 'web/messages/en/*.json'
|
||||
- 'web/messages/en/**/*.json'
|
||||
- '.github/scripts/build_web_docs_i18n.py'
|
||||
- '.github/scripts/build_translation_cache.py'
|
||||
- '.github/workflows/build-web-docs-i18n.yml'
|
||||
# Source and locale corrections are reviewed together. An automatic run
|
||||
# would treat the changed English fingerprints as stale translations and
|
||||
# overwrite those reviewed locale strings with provider output.
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
languages:
|
||||
|
||||
@@ -9,15 +9,20 @@ on:
|
||||
- 'AppImage/messages/**'
|
||||
- 'AppImage/lib/i18n/**'
|
||||
- 'AppImage/components/terminal-panel.tsx'
|
||||
- 'web/**'
|
||||
- 'CONTRIBUTING.md'
|
||||
# Scheduler consumers and the offline extractor's .sh/.func inputs.
|
||||
- 'scripts/**/*.sh'
|
||||
- 'scripts/**/*.func'
|
||||
- 'scripts/**/*.py'
|
||||
- 'lang/*.json'
|
||||
- 'menu'
|
||||
- 'install_proxmenux.sh'
|
||||
- 'install_proxmenux_beta.sh'
|
||||
- 'oci/src/**/*.py'
|
||||
- 'oci/catalog/**/*.json'
|
||||
- 'oci/remote/**/*.sh'
|
||||
- 'oci/remote/**/*.py'
|
||||
push:
|
||||
branches: [main, develop]
|
||||
paths:
|
||||
@@ -27,15 +32,20 @@ on:
|
||||
- 'AppImage/messages/**'
|
||||
- 'AppImage/lib/i18n/**'
|
||||
- 'AppImage/components/terminal-panel.tsx'
|
||||
- 'web/**'
|
||||
- 'CONTRIBUTING.md'
|
||||
# Scheduler consumers and the offline extractor's .sh/.func inputs.
|
||||
- 'scripts/**/*.sh'
|
||||
- 'scripts/**/*.func'
|
||||
- 'scripts/**/*.py'
|
||||
- 'lang/*.json'
|
||||
- 'menu'
|
||||
- 'install_proxmenux.sh'
|
||||
- 'install_proxmenux_beta.sh'
|
||||
- 'oci/src/**/*.py'
|
||||
- 'oci/catalog/**/*.json'
|
||||
- 'oci/remote/**/*.sh'
|
||||
- 'oci/remote/**/*.py'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
# • whiptail (interactive terminal menus)
|
||||
# • curl (downloads and connectivity checks)
|
||||
# • jq (JSON parsing)
|
||||
# • Python 3 + venv (for translation support)
|
||||
# - Installs pre-generated JSON language catalogs (no translation runtime).
|
||||
# - Creates the ProxMenux base directories and configuration files:
|
||||
# • $BASE_DIR/config.json
|
||||
# • $BASE_DIR/cache.json
|
||||
@@ -396,7 +396,8 @@ select_language() {
|
||||
"de" "German" \
|
||||
"it" "Italian" \
|
||||
"pt" "Portuguese" \
|
||||
"sk" "Slovenčina" 3>&1 1>&2 2>&3)
|
||||
"sk" "Slovenčina" \
|
||||
"sv" "Svenska" 3>&1 1>&2 2>&3)
|
||||
|
||||
if [ -z "$LANGUAGE" ]; then
|
||||
msg_error "No language selected. Exiting."
|
||||
|
||||
@@ -594,7 +594,8 @@ select_language() {
|
||||
"de" "German" \
|
||||
"it" "Italian" \
|
||||
"pt" "Portuguese" \
|
||||
"sk" "Slovenčina" 3>&1 1>&2 2>&3)
|
||||
"sk" "Slovenčina" \
|
||||
"sv" "Svenska" 3>&1 1>&2 2>&3)
|
||||
|
||||
if [ -z "$LANGUAGE" ]; then
|
||||
msg_error "No language selected. Exiting."
|
||||
|
||||
+21
-21
@@ -1643,8 +1643,8 @@
|
||||
"Default Proxmox logo applied": "Standardmäßiges Proxmox-Logo angewendet",
|
||||
"Default is none (video-only passthrough). Use SPACE to toggle selections.": "Der Standardwert ist „Keine“ (nur Video-Passthrough). Verwenden Sie die LEERTASTE, um die Auswahl umzuschalten.",
|
||||
"Default journald configuration restored": "Standard-Journald-Konfiguration wiederhergestellt",
|
||||
"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.": "Der Standardspeicherort ist /mnt/<Name>. Die Freigabe wird hier auf dem Host mit offenen Berechtigungen gemountet, sodass ein unprivilegierter LXC sie binden, mounten und darauf schreiben kann. Für den LXC-Zugriff müssen Sie diesen Pfad mit dem LXC Mount Manager binden.",
|
||||
"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.": "Der Standardspeicherort ist /mnt/<Name>. Die Freigabe wird hier auf dem Host gemountet. Verwenden Sie diesen Pfad in /etc/fstab. Für den LXC-Zugriff müssen Sie diesen Pfad mit dem LXC Mount Manager binden.",
|
||||
"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.": "Der Standardspeicherort ist /mnt/<name>. Die Freigabe wird hier auf dem Host mit offenen Berechtigungen eingehängt, sodass ein unprivilegierter LXC sie per Bind-Mount einbinden und darauf schreiben kann. Verwenden Sie dafür den 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.": "Der Standardspeicherort ist /mnt/<name>. Die Freigabe wird hier auf dem Host eingehängt. Verwenden Sie diesen Pfad in /etc/fstab. Für den Zugriff aus einem LXC binden Sie ihn mit dem LXC Mount Manager als Bind-Mount ein.",
|
||||
"Default login": "Standard-Login",
|
||||
"Default options": "Standardoptionen",
|
||||
"Default options read/write": "Standardoptionen Lesen/Schreiben",
|
||||
@@ -2035,7 +2035,7 @@
|
||||
"Enter VM ID:": "Geben Sie die VM-ID ein:",
|
||||
"Enter VM/CT ID:": "Geben Sie die VM/CT-ID ein:",
|
||||
"Enter ZFS pool name for the selected disk:": "Geben Sie den ZFS-Poolnamen für die ausgewählte Festplatte ein:",
|
||||
"Enter a name for the mount point (used as /mnt/<name>):": "Geben Sie einen Namen für den Mount-Punkt ein (verwendet als /mnt/<Name>):",
|
||||
"Enter a name for the mount point (used as /mnt/<name>):": "Geben Sie einen Namen für den Mountpoint ein (wird als /mnt/<name> verwendet):",
|
||||
"Enter a name for the new virtual machine:": "Geben Sie einen Namen für die neue virtuelle Maschine ein:",
|
||||
"Enter a non-empty password or access token on a single line.": "Geben Sie in einer einzelnen Zeile ein nicht leeres Passwort oder Zugriffstoken ein.",
|
||||
"Enter a number, or write or paste a command:": "Geben Sie eine Zahl ein oder schreiben oder fügen Sie einen Befehl ein:",
|
||||
@@ -2183,7 +2183,7 @@
|
||||
"Example: pct stop 110": "Beispiel: pct stop 110",
|
||||
"Example: pct stop 114": "Beispiel: pct stop 114",
|
||||
"Example: pvesm add nfs nfs-nas --server 192.168.1.50 --export /volume1/proxmox --content import,backup": "Beispiel: pvesm add nfs nfs-nas --server 192.168.1.50 --export /volume1/proxmox --content import,backup",
|
||||
"Example: pvesm path local-lvm:vm-114-disk-0": "Beispiel: pvesm-Pfad local-lvm:vm-114-disk-0",
|
||||
"Example: pvesm path local-lvm:vm-114-disk-0": "Beispiel: pvesm path local-lvm:vm-114-disk-0",
|
||||
"Example: sed -i '/^unprivileged: 1/d' /etc/pve/lxc/110.conf": "Beispiel: sed -i '/^unprivileged: 1/d' /etc/pve/lxc/110.conf",
|
||||
"Examples:": "Beispiele:",
|
||||
"Execute destructive rollback?": "Destruktives Rollback ausführen?",
|
||||
@@ -2495,7 +2495,7 @@
|
||||
"For a consistent export, the VM should be stopped.": "Für einen konsistenten Export sollte die VM gestoppt werden.",
|
||||
"For any question, issue or bug report, please use the official repository": "Für Fragen, Probleme oder Fehlerberichte nutzen Sie bitte das offizielle Repository",
|
||||
"For dedicated GPUs, FLR is required by this policy to reduce VM": "Für dedizierte GPUs ist gemäß dieser Richtlinie FLR erforderlich, um VM zu reduzieren",
|
||||
"For example: pct enter 101": "Beispiel: pct Geben Sie 101 ein",
|
||||
"For example: pct enter 101": "Zum Beispiel: pct enter 101",
|
||||
"For guest shares add: --options guest": "Für Gastfreigaben hinzufügen: --options Guest",
|
||||
"For security reasons, the system cannot format it.": "Aus Sicherheitsgründen kann das System es nicht formatieren.",
|
||||
"For unprivileged containers, use instead:": "Verwenden Sie für nichtprivilegierte Container stattdessen:",
|
||||
@@ -2907,8 +2907,8 @@
|
||||
"If notifications are enabled (Telegram/Discord/ntfy/...), you will receive a \"Host restore finished\" message when all background tasks complete.": "Wenn Benachrichtigungen aktiviert sind (Telegram/Discord/ntfy/...), erhalten Sie die Meldung „Host-Wiederherstellung abgeschlossen“, wenn alle Hintergrundaufgaben abgeschlossen sind.",
|
||||
"If passthrough fails on Windows: install RadeonResetBugFix.": "Wenn Passthrough unter Windows fehlschlägt: Installieren Sie RadeonResetBugFix.",
|
||||
"If path not accessible (ZFS/BTRFS):": "Wenn der Pfad nicht zugänglich ist (ZFS/BTRFS):",
|
||||
"If pvesm path returned a DEVICE (LVM):": "Wenn der pvesm-Pfad ein GERÄT (LVM) zurückgegeben hat:",
|
||||
"If pvesm path returned a DIRECTORY (ZFS/BTRFS):": "Wenn der pvesm-Pfad ein VERZEICHNIS (ZFS/BTRFS) zurückgegeben hat:",
|
||||
"If pvesm path returned a DEVICE (LVM):": "Wenn pvesm path ein GERÄT (LVM) zurückgegeben hat:",
|
||||
"If pvesm path returned a DIRECTORY (ZFS/BTRFS):": "Wenn pvesm path ein VERZEICHNIS (ZFS/BTRFS) zurückgegeben hat:",
|
||||
"If repositories error:": "Bei Repository-Fehler:",
|
||||
"If the container had already been changed, its previous native backup is restored. Shared host directories are not reverted. The disks of the failed attempt are removed when the cleanup succeeds.": "Wenn der Container bereits geändert wurde, wird sein vorheriges natives Backup wiederhergestellt. Freigegebene Hostverzeichnisse werden nicht zurückgesetzt. Die Festplatten des fehlgeschlagenen Versuchs werden entfernt, wenn die Bereinigung erfolgreich ist.",
|
||||
"If the host freezes, remove hostpci entries from": "Wenn der Host einfriert, entfernen Sie die Hostpci-Einträge aus",
|
||||
@@ -3225,7 +3225,7 @@
|
||||
"Interrupted operation:": "Unterbrochene operation:",
|
||||
"Interrupted stack operation found": "Unterbrochener Stapel operation gefunden",
|
||||
"Invalid 'proxmox-ve' candidate (not 9.x or none). Please verify your repository configuration and network, then retry.": "Ungültiger „proxmox-ve“-Kandidat (nicht 9.x oder keiner). Bitte überprüfen Sie Ihre Repository-Konfiguration und Ihr Netzwerk und versuchen Sie es dann erneut.",
|
||||
"Invalid ALLOWED_HOSTS value": "Wert für ungültig ALLOWED HOSTs",
|
||||
"Invalid ALLOWED_HOSTS value": "Ungültiger Wert für ALLOWED_HOSTS",
|
||||
"Invalid Home Assistant OS check timeout": "Invalid Home Assistant OS Check Timeout",
|
||||
"Invalid ID": "Ungültige ID",
|
||||
"Invalid IPv4 address": "Ungültige IPv4-Adresse",
|
||||
@@ -3460,7 +3460,7 @@
|
||||
"Keyfile removed.": "Schlüsseldatei entfernt.",
|
||||
"Keyrings method failed; trying apt-key fallback": "Keyrings-Methode fehlgeschlagen; Ich versuche einen Apt-Key-Fallback",
|
||||
"KiCad - A Cross Platform and Open Source Electronics Design Automation Suite.": "KiCad - Eine Cross-Plattform und Open Source Electronics Design Automation Suite.",
|
||||
"Kimai has no default account. Enter the container with: pct enter {main_vmid}": "Kimai hat kein Standardkonto. Geben Sie den Container ein mit: pct enter {main vmid}",
|
||||
"Kimai has no default account. Enter the container with: pct enter {main_vmid}": "Kimai hat kein Standardkonto. Öffnen Sie eine Shell im Container mit: pct enter {main_vmid}",
|
||||
"Kimai is a professional grade time-tracking application, free and open-source.": "Kimai ist eine professionelle Time-Tracking-Anwendung, kostenlos und Open-Source.",
|
||||
"Kometa is a powerful tool designed to give you complete control over your media libraries. With Kometa, you can take your customization to the next level, with granular control over metadata, collections, overlays, and much more.": "Kometa ist ein leistungsstarkes Tool, das Ihnen die vollständige Kontrolle über Ihre Medienbibliotheken gibt. Mit Kometa können Sie Ihre Anpassung auf die nächste Ebene bringen, mit granularer Kontrolle über Metadaten, Sammlungen, Overlays und vielem mehr.",
|
||||
"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 liest seine Konfiguration aus /config/config.yml und der Container liefert nur /config/config.yml.template. Kopieren Sie die Vorlage auf config.yml, füllen Sie die required Plex und TMDb-Verbindungen aus und starten Sie dann den Container neu.",
|
||||
@@ -3531,7 +3531,7 @@
|
||||
"Limiting size and optimizing journald": "Begrenzung der Größe und Optimierung des Journals",
|
||||
"Limiting size and optimizing journald...": "Größe begrenzen und Journal optimieren...",
|
||||
"Limnoria A robust, full-featured, and user/programmer-friendly Python IRC bot, with many existing plugins. Successor of the well-known Supybot.": "Limnoria Ein robuster, voll ausgestatteter und benutzerfreundlicher Python IRC-Bot mit vielen vorhandenen Plugins. Nachfolger des bekannten Supybot.",
|
||||
"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 schließt sich keinem IRC-Netzwerk an, bis seine Konfigurationsdatei existiert. Erstellen Sie es mit dem Setup-Assistenten aus dem Proxmox-Host: 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 verbindet sich erst mit einem IRC-Netzwerk, wenn die Konfigurationsdatei existiert. Erstellen Sie sie mit dem Einrichtungsassistenten auf dem Proxmox-Host: pct exec <CTID> -- bash -c 'cd /config && limnoria-wizard'",
|
||||
"Line to paste (single line, including \"command=...\" prefix):": "Einzufügende Zeile (einzelne Zeile, einschließlich „command=…“-Präfix):",
|
||||
"Linux Installation Options": "Linux-Installationsoptionen",
|
||||
"Linux/Mac path:": "Linux/Mac-Pfad:",
|
||||
@@ -4263,7 +4263,7 @@
|
||||
"No jobs": "Keine Jobs",
|
||||
"No language selected.": "Keine Sprache ausgewählt.",
|
||||
"No local disk storage configured.": "Kein lokaler Festplattenspeicher konfiguriert.",
|
||||
"No main sources.list present (skipped)": "Keine Hauptquellenliste vorhanden (übersprungen)",
|
||||
"No main sources.list present (skipped)": "Keine zentrale sources.list vorhanden (übersprungen)",
|
||||
"No matches for:": "Keine Treffer für:",
|
||||
"No matching PVE vzdump jobs were found for the PBS backend.": "Für das PBS-Backend wurden keine passenden PVE-vzdump-Jobs gefunden.",
|
||||
"No matching PVE vzdump jobs were found for the local archive backend.": "Für das lokale Archiv-Backend wurden keine passenden PVE-vzdump-Jobs gefunden.",
|
||||
@@ -6993,7 +6993,7 @@
|
||||
"Transaction log:": "Transaktionsprotokoll:",
|
||||
"Translation files:": "Übersetzungsdateien:",
|
||||
"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 wurde für eine einfache und leistungsstarke Nutzung entwickelt. Transmission verfügt über die Funktionen, die Sie von einem BitTorrent-Client erwarten: Verschlüsselung, eine Web-Schnittstelle, Peer-Exchange, Magnet-Links, DHT, μTP, UPnP und NAT-PMP Port-Weiterleitung, Webseed-Unterstützung, Watch-Verzeichnisse, Tracker-Bearbeitung, globale und per-Torrent-Geschwindigkeitsbeschränkungen und mehr.",
|
||||
"Tried pvesm path and manual detection methods": "Versuchte den Pvesm-Pfad und manuelle Erkennungsmethoden",
|
||||
"Tried pvesm path and manual detection methods": "pvesm path und manuelle Erkennungsmethoden wurden versucht",
|
||||
"Trust this certificate and save it for scheduled backups?": "Diesem Zertifikat vertrauen und es für geplante Sicherungen speichern?",
|
||||
"Try Again": "Versuchen Sie es erneut",
|
||||
"Try a different search term.": "Versuchen Sie es mit einem anderen Suchbegriff.",
|
||||
@@ -7249,7 +7249,7 @@
|
||||
"Usage:": "Verwendung:",
|
||||
"Use \"Check test progress\" to see results.": "Verwenden Sie „Testfortschritt prüfen“, um die Ergebnisse anzuzeigen.",
|
||||
"Use 'Export to file' to save it and inspect manually.": "Verwenden Sie „In Datei exportieren“, um es zu speichern und manuell zu überprüfen.",
|
||||
"Use 'pct restore' / 'qmrestore' to recover their disks from your VM backups.": "Verwenden Sie „pct restart“ / „qmrestore“, um ihre Festplatten aus Ihren VM-Backups wiederherzustellen.",
|
||||
"Use 'pct restore' / 'qmrestore' to recover their disks from your VM backups.": "Verwenden Sie 'pct restore' / 'qmrestore', um die Datenträger aus den VM-Sicherungen wiederherzustellen.",
|
||||
"Use Custom backup and uncheck the conflicting path from the list": "Verwenden Sie die benutzerdefinierte Sicherung und deaktivieren Sie den in Konflikt stehenden Pfad aus der Liste",
|
||||
"Use Default Settings?": "Standardeinstellungen verwenden?",
|
||||
"Use Download first if you want to save a copy of the current key. Continue?": "Verwenden Sie zuerst „Herunterladen“, wenn Sie eine Kopie des aktuellen Schlüssels speichern möchten. Weitermachen?",
|
||||
@@ -7994,8 +7994,8 @@
|
||||
"partition(s). Partition table preserved.": "Partition(en). Partitionstabelle bleibt erhalten.",
|
||||
"pasted Compose file": "Einfügen der Compose-Datei",
|
||||
"paths for next boot (/etc/pve, guests, drivers, ...)": "Pfade für den nächsten Start (/etc/pve, Gäste, Treiber, ...)",
|
||||
"pct exec authorization failed": "PCT-Exec-Autorisierung fehlgeschlagen",
|
||||
"pct push failed. Check log:": "PCT-Push fehlgeschlagen. Protokoll prüfen:",
|
||||
"pct exec authorization failed": "Autorisierung für pct exec fehlgeschlagen",
|
||||
"pct push failed. Check log:": "pct push fehlgeschlagen. Protokoll prüfen:",
|
||||
"pending (reboot required to enumerate full group)": "ausstehend (Neustart erforderlich, um die vollständige Gruppe aufzulisten)",
|
||||
"phpMyAdmin is installed with arbitrary server connections enabled: the login page has a Server field where the address of the MySQL or MariaDB server is entered, together with its user and password.": "phpMyAdmin wird mit aktivierten beliebigen Serververbindungen installiert: Die Anmeldeseite hat ein Serverfeld, in dem die Adresse des MySQL- oder MariaDB-Servers zusammen mit seinem Benutzer und seinem Passwort eingegeben wird.",
|
||||
"pigz configuration completed": "Pigz-Konfiguration abgeschlossen",
|
||||
@@ -8018,8 +8018,8 @@
|
||||
"pvesm command not found. This should not happen on Proxmox.": "pvesm-Befehl nicht gefunden. Dies sollte auf Proxmox nicht passieren.",
|
||||
"pvesm not available.": "pvesm nicht verfügbar.",
|
||||
"pvesm not found.": "pvesm nicht gefunden.",
|
||||
"pvesm path failed, trying manual detection...": "pvesm-Pfad fehlgeschlagen, manuelle Erkennung versucht ...",
|
||||
"pvesm status failed": "pvesm-Status fehlgeschlagen",
|
||||
"pvesm path failed, trying manual detection...": "pvesm path fehlgeschlagen, manuelle Erkennung wird versucht...",
|
||||
"pvesm status failed": "pvesm status fehlgeschlagen",
|
||||
"pyLoad is a Free and Open Source download manager written in Python and designed to be extremely lightweight, easily extensible and fully manageable via web.": "pyLoad ist ein Free- und Open Source-Download-Manager, der in Python geschrieben ist und extrem leicht, leicht erweiterbar und vollständig über das Web zu verwalten ist.",
|
||||
"pyLoad web interface": "pyLoad Web Interface",
|
||||
"qBittorrent WebUI password (user: admin)": "qBittorrent WebUI Passwort (Benutzer: admin)",
|
||||
@@ -8078,8 +8078,8 @@
|
||||
"skipped (already exist)": "übersprungen (existiert bereits)",
|
||||
"smbclient command is not working properly.": "Der smbclient-Befehl funktioniert nicht ordnungsgemäß.",
|
||||
"smbclient command not found after installation.": "Der Befehl smbclient wurde nach der Installation nicht gefunden.",
|
||||
"sources.list update skipped (no change)": "Aktualisierung der Quellenliste übersprungen (keine Änderung)",
|
||||
"sources.list updated to Trixie": "Quellen. Liste auf Trixie aktualisiert",
|
||||
"sources.list update skipped (no change)": "Aktualisierung von sources.list übersprungen (keine Änderung)",
|
||||
"sources.list updated to Trixie": "sources.list auf Trixie aktualisiert",
|
||||
"ssh-keygen failed. Cannot create a new SSH key.": "ssh-keygen ist fehlgeschlagen. Es kann kein neuer SSH-Schlüssel erstellt werden.",
|
||||
"stale entry/entries for interfaces no longer present": "veralteter Eintrag/Einträge für Schnittstellen, die nicht mehr vorhanden sind",
|
||||
"standard performance": "Standardleistung",
|
||||
@@ -8098,7 +8098,7 @@
|
||||
"switch_gpu_mode.sh was not found.": "switch_gpu_mode.sh wurde nicht gefunden.",
|
||||
"sysfs ROM dump failed — trying ACPI VFCT table...": "sysfs-ROM-Dump fehlgeschlagen – Versuch der ACPI-VFCT-Tabelle ...",
|
||||
"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 ermöglicht es Ihnen, Protokolle aus Ihrer gesamten Infrastruktur flexibel zu sammeln, zu analysieren, zu klassifizieren, neu zu schreiben und zu korrelieren und sie zu Protokollanalyse-Tools zu speichern oder zu leiten.",
|
||||
"systemctl restart networking failed:": "systemctl-Neustart des Netzwerks fehlgeschlagen:",
|
||||
"systemctl restart networking failed:": "systemctl restart networking fehlgeschlagen:",
|
||||
"systemd OnCalendar expression": "systemd OnCalendar-Ausdruck",
|
||||
"the API key was not generated on the first start": "Der API-Schlüssel wurde beim ersten Start nicht generiert",
|
||||
"the NVIDIA hook of the container is not available:": "der NVIDIA-Hook des Containers ist nicht verfügbar:",
|
||||
@@ -8152,7 +8152,7 @@
|
||||
"video + recognition": "Video + Erkennung",
|
||||
"video only": "nur Video",
|
||||
"vzdump backup speed optimization completed": "vzdump-Backup-Geschwindigkeitsoptimierung abgeschlossen",
|
||||
"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 baut seine Links aus der während der Installation angegebenen Adresse auf. Wenn es nicht mit der Adresse des Containers übereinstimmt, bearbeiten Sie lxc.environment. Laufzeit: SYMFONY ENV DOMAIN NAME in /etc/pve/lxc/<CTID>.conf mit angehaltenem Container und erneut starten.",
|
||||
"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 erzeugt seine Links aus der bei der Installation angegebenen Adresse. Passt diese nicht zur Container-Adresse, stoppen Sie den Container, bearbeiten Sie lxc.environment.runtime: SYMFONY__ENV__DOMAIN_NAME in /etc/pve/lxc/<CTID>.conf und starten Sie ihn erneut.",
|
||||
"wallabag listens on port 80 of the container and stores its data in SQLite.": "wallabag hört auf Port 80 des Containers und speichert seine Daten in SQLite.",
|
||||
"wallabag web interface": "wallabag Web-Schnittstelle",
|
||||
"was": "war",
|
||||
|
||||
+14
-14
@@ -320,7 +320,7 @@
|
||||
"After confirming, you will be asked to choose the NVIDIA driver version to install.": "Después de confirmar, se le pedirá que elija la versión del controlador NVIDIA para instalar.",
|
||||
"After detailed analysis, no changes are needed.": "Después de un análisis detallado, no se necesitan cambios.",
|
||||
"After detailed analysis, no cleanup is needed.": "Después de un análisis detallado, no es necesaria ninguna limpieza.",
|
||||
"After logging in, run: ip a to obtain the IP address.\nThen, enter that IP address in your web browser like this:\n http://IP_ADDRESS\n\nThis will open the Umbral OS dashboard.": "Después de iniciar sesión, ejecute: ip a para obtener la dirección IP.\nLuego, ingrese esa dirección IP en su navegador web de esta manera:\n http://DIRECCIÓN_IP\n\nEsto abrirá el panel de Umbral OS.",
|
||||
"After logging in, run: ip a to obtain the IP address.\nThen, enter that IP address in your web browser like this:\n http://IP_ADDRESS\n\nThis will open the Umbral OS dashboard.": "Después de iniciar sesión, ejecuta ip a para obtener la dirección IP.\nIntroduce esa dirección en el navegador de esta forma:\n http://IP_ADDRESS\n\nSe abrirá el panel de Umbral OS.",
|
||||
"After pasting on the server, ensure the file is chmod 600 and owned by": "Después de pegarlo en el servidor, asegúrese de que el archivo sea chmod 600 y sea propiedad de",
|
||||
"After reboot the system will be fully accessible (SSH, web UI, login), but the following components will be reinstalled in BACKGROUND — until they finish, commands like nvidia-smi may not yet be available:": "Después de reiniciar, el sistema será completamente accesible (SSH, interfaz web e inicio de sesión), pero los siguientes componentes se reinstalarán EN SEGUNDO PLANO; hasta que finalicen, es posible que comandos como nvidia-smi aún no estén disponibles:",
|
||||
"After reboot, these components will reinstall in background:": "Después de reiniciar, estos componentes se reinstalarán en segundo plano:",
|
||||
@@ -1641,8 +1641,8 @@
|
||||
"Default Proxmox logo applied": "Logotipo predeterminado de Proxmox aplicado",
|
||||
"Default is none (video-only passthrough). Use SPACE to toggle selections.": "Por defecto, ninguno (passthrough solo de vídeo). Use ESPACIO para marcar o desmarcar.",
|
||||
"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.",
|
||||
"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/<name>. El recurso compartido se montará aquí, en el host, con permisos abiertos para que un LXC sin privilegios pueda montarlo mediante un bind mount y escribir en él. Usa LXC Mount Manager para crear ese montaje en el LXC.",
|
||||
"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/<name>. El recurso compartido se montará aquí, en el host. Usa esta ruta en /etc/fstab. Para acceder desde un LXC, crea un bind mount de esta ruta con LXC Mount Manager.",
|
||||
"Default login": "Acceso predeterminado",
|
||||
"Default options": "Opciones predeterminadas",
|
||||
"Default options read/write": "Opciones predeterminadas lectura/escritura",
|
||||
@@ -2033,7 +2033,7 @@
|
||||
"Enter VM ID:": "Introduzca el ID de la máquina virtual:",
|
||||
"Enter VM/CT ID:": "Introduzca el ID de VM/CT:",
|
||||
"Enter ZFS pool name for the selected disk:": "Ingrese el nombre del grupo ZFS para el disco seleccionado:",
|
||||
"Enter a name for the mount point (used as /mnt/<name>):": "Ingrese un nombre para el punto de montaje (usado como /mnt/<nombre>):",
|
||||
"Enter a name for the mount point (used as /mnt/<name>):": "Introduce un nombre para el punto de montaje (se usará como /mnt/<name>):",
|
||||
"Enter a name for the new virtual machine:": "Ingrese un nombre para la nueva máquina virtual:",
|
||||
"Enter a non-empty password or access token on a single line.": "Escribe una contraseña o un token de acceso, en una sola línea.",
|
||||
"Enter a number, or write or paste a command:": "Ingrese un número, o escriba o pegue un comando:",
|
||||
@@ -2176,11 +2176,11 @@
|
||||
"Example: cp /etc/pve/lxc/114.conf /etc/pve/lxc/114.conf.bak": "Ejemplo: cp /etc/pve/lxc/114.conf /etc/pve/lxc/114.conf.bak",
|
||||
"Example: daily or Mon..Fri 03:00": "Ejemplo: diario o lunes a viernes 03:00",
|
||||
"Example: mkdir -p /tmp/lxc_convert_114": "Ejemplo: mkdir -p /tmp/lxc_convert_114",
|
||||
"Example: pct config 110 | grep unprivileged": "Ejemplo: configuración pct 110 | grep sin privilegios",
|
||||
"Example: pct stop 110": "Ejemplo: parada pct 110",
|
||||
"Example: pct stop 114": "Ejemplo: parada pct 114",
|
||||
"Example: pct config 110 | grep unprivileged": "Ejemplo: pct config 110 | grep unprivileged",
|
||||
"Example: pct stop 110": "Ejemplo: pct stop 110",
|
||||
"Example: pct stop 114": "Ejemplo: pct stop 114",
|
||||
"Example: pvesm add nfs nfs-nas --server 192.168.1.50 --export /volume1/proxmox --content import,backup": "Ejemplo: pvesm add nfs nfs-nas --server 192.168.1.50 --export /volume1/proxmox --content import,backup",
|
||||
"Example: pvesm path local-lvm:vm-114-disk-0": "Ejemplo: ruta pvesm local-lvm:vm-114-disk-0",
|
||||
"Example: pvesm path local-lvm:vm-114-disk-0": "Ejemplo: pvesm path local-lvm:vm-114-disk-0",
|
||||
"Example: sed -i '/^unprivileged: 1/d' /etc/pve/lxc/110.conf": "Ejemplo: sed -i '/^sin privilegios: 1/d' /etc/pve/lxc/110.conf",
|
||||
"Examples:": "Ejemplos:",
|
||||
"Execute destructive rollback?": "¿Ejecutar el rollback destructivo?",
|
||||
@@ -2492,7 +2492,7 @@
|
||||
"For a consistent export, the VM should be stopped.": "Para una exportación consistente, se debe detener la VM.",
|
||||
"For any question, issue or bug report, please use the official repository": "Para cualquier pregunta, problema o informe de error, utilice el repositorio oficial",
|
||||
"For dedicated GPUs, FLR is required by this policy to reduce VM": "Para GPU dedicadas, esta política requiere FLR para reducir la VM",
|
||||
"For example: pct enter 101": "Por ejemplo: pct introduzca 101",
|
||||
"For example: pct enter 101": "Por ejemplo: pct enter 101",
|
||||
"For guest shares add: --options guest": "Para recursos compartidos de invitado añada: --options guest",
|
||||
"For security reasons, the system cannot format it.": "Por razones de seguridad, el sistema no puede formatearlo.",
|
||||
"For unprivileged containers, use instead:": "Para contenedores sin privilegios, utilice en su lugar:",
|
||||
@@ -5234,7 +5234,7 @@
|
||||
"Replace": "Reemplazar",
|
||||
"Replace <container-id> with the actual ID.": "Reemplace <container-id> con el ID real.",
|
||||
"Replace <container-id> with your actual container ID": "Reemplace <container-id> con su ID de contenedor real",
|
||||
"Replace <storage-identifier> with the value from step 4": "Reemplace <identificador-de-almacenamiento> con el valor del paso 4",
|
||||
"Replace <storage-identifier> with the value from step 4": "Sustituye <storage-identifier> por el valor del paso 4",
|
||||
"Replace invalid port(s)": "Reemplazar puerto(s) no válido(s)",
|
||||
"Replace it?": "¿Reemplazarlo?",
|
||||
"Replace paths with your actual values from step 5": "Reemplace las rutas con sus valores reales del paso 5",
|
||||
@@ -7967,7 +7967,7 @@
|
||||
"partition(s). Partition table preserved.": "partición(es). Se conserva la tabla de particiones.",
|
||||
"pasted Compose file": "archivo Compose pegado",
|
||||
"paths for next boot (/etc/pve, guests, drivers, ...)": "rutas para el próximo arranque (/etc/pve, VM y CT, controladores, ...)",
|
||||
"pct exec authorization failed": "error en la autorización ejecutiva de PCT",
|
||||
"pct exec authorization failed": "Ha fallado la autorización de pct exec",
|
||||
"pct push failed. Check log:": "pct push falló. Revise el log:",
|
||||
"pending (reboot required to enumerate full group)": "pendiente (es necesario reiniciar para enumerar el grupo completo)",
|
||||
"phpMyAdmin is installed with arbitrary server connections enabled: the login page has a Server field where the address of the MySQL or MariaDB server is entered, together with its user and password.": "phpMyAdmin se instala con conexiones de servidor arbitrarias habilitadas: la página de inicio de sesión tiene un campo Server donde se introduce la dirección del servidor MySQL o MariaDB, junto con su usuario y contraseña.",
|
||||
@@ -7991,8 +7991,8 @@
|
||||
"pvesm command not found. This should not happen on Proxmox.": "Comando pvesm no encontrado. Esto no debería suceder en Proxmox.",
|
||||
"pvesm not available.": "pvesm no disponible.",
|
||||
"pvesm not found.": "pvesm no encontrado.",
|
||||
"pvesm path failed, trying manual detection...": "La ruta pvesm falló, intentando la detección manual...",
|
||||
"pvesm status failed": "el estado de pvesm falló",
|
||||
"pvesm path failed, trying manual detection...": "Ha fallado pvesm path; intentando la detección manual...",
|
||||
"pvesm status failed": "Ha fallado pvesm status",
|
||||
"pyLoad is a Free and Open Source download manager written in Python and designed to be extremely lightweight, easily extensible and fully manageable via web.": "pyLoad es un gestor de descargas libre y de código abierto escrito en Python, diseñado para ser muy ligero, fácil de ampliar y totalmente gestionable por web.",
|
||||
"pyLoad web interface": "Interfaz web de pyLoad",
|
||||
"qBittorrent WebUI password (user: admin)": "contraseña de qBittorrent WebUI (usuario: admin)",
|
||||
@@ -8052,7 +8052,7 @@
|
||||
"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 sources.list omitida (sin cambios)",
|
||||
"sources.list updated to Trixie": "fuentes.lista actualizada a Trixie",
|
||||
"sources.list updated to Trixie": "sources.list actualizado 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(s) obsoleta(s) de interfaces que ya no existen",
|
||||
"standard performance": "rendimiento estándar",
|
||||
|
||||
+25
-25
@@ -301,7 +301,7 @@
|
||||
"Address of the database server (mysql and pgsql only)": "Adresse du serveur de base de données (mysql et pgsql uniquement)",
|
||||
"Address of the oci-compose file": "Adresse du fichier oci-compose",
|
||||
"Address to reach Pydio Cells (https://domain or https://IP:8080)": "Adresse pour atteindre Pydio Cells (https://domaine ou https://IP:8080)",
|
||||
"Address used to reach wallabag (http://IP or https://wallabag.example.com)": "Adresse utilisée pour atteindre wallabag (http://IP ou https://wallabag.exemple.com)",
|
||||
"Address used to reach wallabag (http://IP or https://wallabag.example.com)": "Adresse d’accès à wallabag (http://IP ou https://wallabag.example.com)",
|
||||
"Addresses to update: ipv4, ipv6 or both (uses an external service)": "Adresses à mettre à jour: ipv4, ipv6 ou les deux (utilise un service externe)",
|
||||
"Adguardhome Sync web interface": "Interface web Adguardhome Sync",
|
||||
"Adguardhome-sync is a tool to synchronize AdGuardHome config to replica instances.": "Adguardhome-sync est un outil pour synchroniser la configuration AdGuardHome pour reproduire des instances.",
|
||||
@@ -322,7 +322,7 @@
|
||||
"After confirming, you will be asked to choose the NVIDIA driver version to install.": "Après confirmation, il vous sera demandé de choisir la version du pilote NVIDIA à installer.",
|
||||
"After detailed analysis, no changes are needed.": "Après une analyse détaillée, aucune modification n’est nécessaire.",
|
||||
"After detailed analysis, no cleanup is needed.": "Après une analyse détaillée, aucun nettoyage n’est nécessaire.",
|
||||
"After logging in, run: ip a to obtain the IP address.\nThen, enter that IP address in your web browser like this:\n http://IP_ADDRESS\n\nThis will open the Umbral OS dashboard.": "Après vous être connecté, exécutez : ip a pour obtenir l'adresse IP.\nEnsuite, saisissez cette adresse IP dans votre navigateur Web comme ceci :\n http://ADRESSE_IP\n\nCela ouvrira le tableau de bord Umbral OS.",
|
||||
"After logging in, run: ip a to obtain the IP address.\nThen, enter that IP address in your web browser like this:\n http://IP_ADDRESS\n\nThis will open the Umbral OS dashboard.": "Après la connexion, exécutez ip a pour obtenir l’adresse IP.\nSaisissez ensuite cette adresse dans votre navigateur sous cette forme :\n http://IP_ADDRESS\n\nLe tableau de bord Umbral OS s’ouvrira.",
|
||||
"After pasting on the server, ensure the file is chmod 600 and owned by": "Après avoir collé sur le serveur, assurez-vous que le fichier est chmod 600 et appartient à",
|
||||
"After reboot the system will be fully accessible (SSH, web UI, login), but the following components will be reinstalled in BACKGROUND — until they finish, commands like nvidia-smi may not yet be available:": "Après le redémarrage, le système sera entièrement accessible (SSH, interface utilisateur Web, connexion), mais les composants suivants seront réinstallés en ARRIÈRE-PLAN — jusqu'à ce qu'ils soient terminés, des commandes comme nvidia-smi peuvent ne pas encore être disponibles :",
|
||||
"After reboot, these components will reinstall in background:": "Après le redémarrage, ces composants seront réinstallés en arrière-plan :",
|
||||
@@ -1643,8 +1643,8 @@
|
||||
"Default Proxmox logo applied": "Logo Proxmox par défaut appliqué",
|
||||
"Default is none (video-only passthrough). Use SPACE to toggle selections.": "La valeur par défaut est aucune (passthrough vidéo uniquement). Utilisez ESPACE pour basculer les sélections.",
|
||||
"Default journald configuration restored": "Configuration journald par défaut restaurée",
|
||||
"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.": "L'emplacement par défaut est /mnt/<nom>. Le partage sera monté ici sur l'hôte avec des autorisations ouvertes afin qu'un LXC non privilégié puisse y effectuer un montage en liaison et y écrire. Pour l'accès LXC, montez en liaison ce chemin avec le gestionnaire de montage LXC.",
|
||||
"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.": "L'emplacement par défaut est /mnt/<nom>. Le partage sera monté ici sur l'hôte. Utilisez ce chemin dans /etc/fstab. Pour l'accès LXC, montez en liaison ce chemin avec le gestionnaire de montage LXC.",
|
||||
"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.": "L’emplacement par défaut est /mnt/<name>. Le partage sera monté ici sur l’hôte avec des permissions ouvertes, afin qu’un LXC non privilégié puisse le monter par liaison et y écrire. Utilisez LXC Mount Manager pour créer ce montage dans le LXC.",
|
||||
"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.": "L’emplacement par défaut est /mnt/<name>. Le partage sera monté ici sur l’hôte. Utilisez ce chemin dans /etc/fstab. Pour y accéder depuis un LXC, créez un montage lié de ce chemin avec LXC Mount Manager.",
|
||||
"Default login": "Connexion par défaut",
|
||||
"Default options": "Options par défaut",
|
||||
"Default options read/write": "Options par défaut lecture/écriture",
|
||||
@@ -1920,7 +1920,7 @@
|
||||
"Dry run completed; the container and the mounts were not changed.": "Le parcours à sec est terminé; le conteneur et les supports n'ont pas été changés.",
|
||||
"DuckDNS subdomain without .duckdns.org (comma separated for several)": "DuckDNS sous-domaine sans .duckdns.org (comma séparé pour plusieurs)",
|
||||
"DuckDNS token from your account at duckdns.org": "Jeton DuckDNS de votre compte sur duckdns.org",
|
||||
"DuckDNS updates the subdomain every 5 minutes. Without UPDATE_IP, DuckDNS itself detects the public IPv4 address of the request.": "DuckDNS met à jour le sous-domaine toutes les 5 minutes. Sans mise à jour, DuckDNS détecte lui-même l'adresse IPv4 publique de la requête.",
|
||||
"DuckDNS updates the subdomain every 5 minutes. Without UPDATE_IP, DuckDNS itself detects the public IPv4 address of the request.": "DuckDNS met à jour le sous-domaine toutes les 5 minutes. Sans UPDATE_IP, DuckDNS détecte lui-même l’adresse IPv4 publique de la requête.",
|
||||
"DuckStation is a PS1 Emulator aiming for the best accuracy and game support.": "DuckStation est un émulateur PS1 visant le meilleur accuracy et le meilleur support de jeu.",
|
||||
"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 est un service gratuit qui dirigera un DNS (sous-domaines de duckdns.org) vers une IP de votre choix. Le service est entièrement gratuit, et ne require réactivation ou forum posts pour maintenir son existence.",
|
||||
"Dumping AMD GPU ROM BIOS via sysfs...": "Vidage du BIOS ROM GPU AMD via sysfs...",
|
||||
@@ -2179,11 +2179,11 @@
|
||||
"Example: cp /etc/pve/lxc/114.conf /etc/pve/lxc/114.conf.bak": "Exemple : cp /etc/pve/lxc/114.conf /etc/pve/lxc/114.conf.bak",
|
||||
"Example: daily or Mon..Fri 03:00": "Exemple : tous les jours ou du lundi au vendredi à 03h00",
|
||||
"Example: mkdir -p /tmp/lxc_convert_114": "Exemple : mkdir -p /tmp/lxc_convert_114",
|
||||
"Example: pct config 110 | grep unprivileged": "Exemple : configuration PCT 110 | grep sans privilège",
|
||||
"Example: pct stop 110": "Exemple : PCT stop 110",
|
||||
"Example: pct stop 114": "Exemple : PCT arrêt 114",
|
||||
"Example: pct config 110 | grep unprivileged": "Exemple : pct config 110 | grep unprivileged",
|
||||
"Example: pct stop 110": "Exemple : pct stop 110",
|
||||
"Example: pct stop 114": "Exemple : pct stop 114",
|
||||
"Example: pvesm add nfs nfs-nas --server 192.168.1.50 --export /volume1/proxmox --content import,backup": "Exemple : pvesm add nfs nfs-nas --server 192.168.1.50 --export /volume1/proxmox --content import,backup",
|
||||
"Example: pvesm path local-lvm:vm-114-disk-0": "Exemple : chemin pvesm local-lvm:vm-114-disk-0",
|
||||
"Example: pvesm path local-lvm:vm-114-disk-0": "Exemple : pvesm path local-lvm:vm-114-disk-0",
|
||||
"Example: sed -i '/^unprivileged: 1/d' /etc/pve/lxc/110.conf": "Exemple : sed -i '/^unprivileged : 1/d' /etc/pve/lxc/110.conf",
|
||||
"Examples:": "Exemples :",
|
||||
"Execute destructive rollback?": "Exécuter une restauration destructrice ?",
|
||||
@@ -2495,7 +2495,7 @@
|
||||
"For a consistent export, the VM should be stopped.": "Pour une exportation cohérente, la VM doit être arrêtée.",
|
||||
"For any question, issue or bug report, please use the official repository": "Pour toute question, problème ou rapport de bug, veuillez utiliser le référentiel officiel",
|
||||
"For dedicated GPUs, FLR is required by this policy to reduce VM": "Pour les GPU dédiés, FLR est requis par cette stratégie pour réduire les VM",
|
||||
"For example: pct enter 101": "Par exemple : PCT, entrez 101",
|
||||
"For example: pct enter 101": "Par exemple : pct enter 101",
|
||||
"For guest shares add: --options guest": "Pour les partages invités, ajoutez : --options invité",
|
||||
"For security reasons, the system cannot format it.": "Pour des raisons de sécurité, le système ne peut pas le formater.",
|
||||
"For unprivileged containers, use instead:": "Pour les conteneurs non privilégiés, utilisez plutôt :",
|
||||
@@ -2907,8 +2907,8 @@
|
||||
"If notifications are enabled (Telegram/Discord/ntfy/...), you will receive a \"Host restore finished\" message when all background tasks complete.": "Si les notifications sont activées (Telegram/Discord/ntfy/...), vous recevrez un message « Restauration de l'hôte terminée » lorsque toutes les tâches en arrière-plan seront terminées.",
|
||||
"If passthrough fails on Windows: install RadeonResetBugFix.": "Si le relais échoue sous Windows : installez RadeonResetBugFix.",
|
||||
"If path not accessible (ZFS/BTRFS):": "Si chemin non accessible (ZFS/BTRFS) :",
|
||||
"If pvesm path returned a DEVICE (LVM):": "Si le chemin pvesm a renvoyé un DEVICE (LVM) :",
|
||||
"If pvesm path returned a DIRECTORY (ZFS/BTRFS):": "Si le chemin pvesm renvoie un RÉPERTOIRE (ZFS/BTRFS) :",
|
||||
"If pvesm path returned a DEVICE (LVM):": "Si pvesm path a renvoyé un PÉRIPHÉRIQUE (LVM) :",
|
||||
"If pvesm path returned a DIRECTORY (ZFS/BTRFS):": "Si pvesm path a renvoyé un RÉPERTOIRE (ZFS/BTRFS) :",
|
||||
"If repositories error:": "Si erreur de référentiels :",
|
||||
"If the container had already been changed, its previous native backup is restored. Shared host directories are not reverted. The disks of the failed attempt are removed when the cleanup succeeds.": "Si le conteneur a déjà été modifié, sa sauvegarde native précédente est restaurée. Les répertoires hôtes partagés ne sont pas rétablis. Les disques de la tentative ayant échoué sont supprimés une fois le nettoyage réussi.",
|
||||
"If the host freezes, remove hostpci entries from": "Si l'hôte se bloque, supprimez les entrées hostpci de",
|
||||
@@ -3048,7 +3048,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": "Dans le LXC, créez l’administrateur : console kimai:user:create YOUR_USERNAME YOUR_EMAIL 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",
|
||||
@@ -3225,7 +3225,7 @@
|
||||
"Interrupted operation:": "Interruption du opera:",
|
||||
"Interrupted stack operation found": "Pile interrompue operation trouvée",
|
||||
"Invalid 'proxmox-ve' candidate (not 9.x or none). Please verify your repository configuration and network, then retry.": "Candidat 'proxmox-ve' invalide (pas 9.x ou aucun). Veuillez vérifier la configuration et le réseau de votre référentiel, puis réessayez.",
|
||||
"Invalid ALLOWED_HOSTS value": "Valeur HÔTES INDÉSIRABLES",
|
||||
"Invalid ALLOWED_HOSTS value": "Valeur ALLOWED_HOSTS invalide",
|
||||
"Invalid Home Assistant OS check timeout": "Non valide Home Assistant OS check timeout",
|
||||
"Invalid ID": "Pièce d'identité invalide",
|
||||
"Invalid IPv4 address": "Adresse IPv4 non valide",
|
||||
@@ -3460,7 +3460,7 @@
|
||||
"Keyfile removed.": "fichier clé supprimé.",
|
||||
"Keyrings method failed; trying apt-key fallback": "La méthode des porte-clés a échoué ; essayer la solution de secours apt-key",
|
||||
"KiCad - A Cross Platform and Open Source Electronics Design Automation Suite.": "KiCad - Une plateforme croisée et une suite d'automatisation de conception électronique ouverte.",
|
||||
"Kimai has no default account. Enter the container with: pct enter {main_vmid}": "Kimai n'a pas de compte par défaut. Saisissez le conteneur avec : pct entre {main vmid}",
|
||||
"Kimai has no default account. Enter the container with: pct enter {main_vmid}": "Kimai n’a pas de compte par défaut. Ouvrez un shell dans le conteneur avec : pct enter {main_vmid}",
|
||||
"Kimai is a professional grade time-tracking application, free and open-source.": "Kimai est une application professionnelle de suivi du temps, libre et open-source.",
|
||||
"Kometa is a powerful tool designed to give you complete control over your media libraries. With Kometa, you can take your customization to the next level, with granular control over metadata, collections, overlays, and much more.": "Kometa est un outil puissant conçu pour vous donner un contrôle complet sur vos bibliothèques multimédias. Avec Kometa, vous pouvez porter votre personnalisation au niveau suivant, avec un contrôle granulaire sur les métadonnées, les collections, les superpositions et bien plus encore.",
|
||||
"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 lit sa configuration à partir de /config/config.yml et le conteneur ne livre que /config/config.yml.template. Copiez le modèle pour config.yml, remplissez les connexions required Plex et TMDb, puis redémarrez le conteneur.",
|
||||
@@ -3512,7 +3512,7 @@
|
||||
"Leave empty to keep every backup (not recommended).": "Laissez vide pour conserver chaque sauvegarde (non recommandé).",
|
||||
"Leave empty to use the retention of the storage.": "Laisser vide pour utiliser la rétention du stockage.",
|
||||
"Legacy PVE 8 .list files commented or not present": "Fichiers .list hérités PVE 8 commentés ou non présents",
|
||||
"Legacy ceph.list commented or not present": "Ceph.list hérité commenté ou non présent",
|
||||
"Legacy ceph.list commented or not present": "Ancien fichier ceph.list commenté ou absent",
|
||||
"Legacy gasket-dkms cleanup could not be verified as complete.": "Impossible de confirmer que le nettoyage de l'ancien paquet gasket-dkms est terminé.",
|
||||
"Legacy gasket-dkms detected": "Ancien paquet gasket-dkms détecté",
|
||||
"Legacy network tools (e.g., ifconfig)": "Outils réseau hérités (par exemple, ifconfig)",
|
||||
@@ -4263,7 +4263,7 @@
|
||||
"No jobs": "Aucun emploi",
|
||||
"No language selected.": "Aucune langue sélectionnée.",
|
||||
"No local disk storage configured.": "Aucun stockage sur disque local configuré.",
|
||||
"No main sources.list present (skipped)": "Aucune liste de sources principale présente (ignorée)",
|
||||
"No main sources.list present (skipped)": "Aucun fichier sources.list principal présent (ignoré)",
|
||||
"No matches for:": "Aucune correspondance pour :",
|
||||
"No matching PVE vzdump jobs were found for the PBS backend.": "Aucune tâche vzdump PVE correspondante n'a été trouvée pour le backend PBS.",
|
||||
"No matching PVE vzdump jobs were found for the local archive backend.": "Aucune tâche vzdump PVE correspondante n'a été trouvée pour le backend d'archive local.",
|
||||
@@ -6992,7 +6992,7 @@
|
||||
"Transaction log:": "Registre des transactions & #160;:",
|
||||
"Translation files:": "Fichiers de traduction :",
|
||||
"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 conçu pour une utilisation facile et puissante. Transmission possède les fonctionnalités que vous souhaitez d'un client BitTorrent : cryptage, interface web, échange entre pairs, liens magnétiques, DHT, μTP, UPnP et le transfert de port NAT-PMP, support de webseed, répertoires de veille, édition de tracker, limites de vitesse globales et per-torrent, et plus encore.",
|
||||
"Tried pvesm path and manual detection methods": "Chemin pvesm essayé et méthodes de détection manuelle",
|
||||
"Tried pvesm path and manual detection methods": "pvesm path et les méthodes de détection manuelle ont été essayés",
|
||||
"Trust this certificate and save it for scheduled backups?": "Faire confiance à ce certificat et l'enregistrer pour les sauvegardes planifiées ?",
|
||||
"Try Again": "Essayer à nouveau",
|
||||
"Try a different search term.": "Essayez un autre terme de recherche.",
|
||||
@@ -7248,7 +7248,7 @@
|
||||
"Usage:": "Utilisation :",
|
||||
"Use \"Check test progress\" to see results.": "Utilisez « Vérifier la progression du test » pour voir les résultats.",
|
||||
"Use 'Export to file' to save it and inspect manually.": "Utilisez « Exporter vers un fichier » pour l'enregistrer et l'inspecter manuellement.",
|
||||
"Use 'pct restore' / 'qmrestore' to recover their disks from your VM backups.": "Utilisez « PCT Restore » / « qmrestore » pour récupérer leurs disques à partir des sauvegardes de votre VM.",
|
||||
"Use 'pct restore' / 'qmrestore' to recover their disks from your VM backups.": "Utilisez 'pct restore' / 'qmrestore' pour récupérer leurs disques depuis les sauvegardes des VM.",
|
||||
"Use Custom backup and uncheck the conflicting path from the list": "Utilisez la sauvegarde personnalisée et décochez le chemin en conflit dans la liste",
|
||||
"Use Default Settings?": "Utiliser les paramètres par défaut ?",
|
||||
"Use Download first if you want to save a copy of the current key. Continue?": "utilisez d'abord Télécharger si vous souhaitez enregistrer une copie de la clé actuelle. Continuer?",
|
||||
@@ -7993,8 +7993,8 @@
|
||||
"partition(s). Partition table preserved.": "partition(s). Table de partition conservée.",
|
||||
"pasted Compose file": "fichier Compose collé",
|
||||
"paths for next boot (/etc/pve, guests, drivers, ...)": "chemins pour le prochain démarrage (/etc/pve, invités, pilotes, ...)",
|
||||
"pct exec authorization failed": "échec de l'autorisation d'exécution PCT",
|
||||
"pct push failed. Check log:": "La poussée PCT a échoué. Journal de vérification :",
|
||||
"pct exec authorization failed": "Échec de l’autorisation pour pct exec",
|
||||
"pct push failed. Check log:": "Échec de pct push. Consultez le journal :",
|
||||
"pending (reboot required to enumerate full group)": "en attente (redémarrage requis pour énumérer le groupe complet)",
|
||||
"phpMyAdmin is installed with arbitrary server connections enabled: the login page has a Server field where the address of the MySQL or MariaDB server is entered, together with its user and password.": "phpMyAdmin est installé avec des connexions de serveur arbitraires activées : la page de connexion a un champ Serveur où l'adresse du serveur MySQL ou MariaDB est saisie, ainsi que son utilisateur et son mot de passe.",
|
||||
"pigz configuration completed": "configuration pigz terminée",
|
||||
@@ -8017,8 +8017,8 @@
|
||||
"pvesm command not found. This should not happen on Proxmox.": "Commande pvesm introuvable. Cela ne devrait pas arriver sur Proxmox.",
|
||||
"pvesm not available.": "pvesm non disponible.",
|
||||
"pvesm not found.": "pvesm introuvable.",
|
||||
"pvesm path failed, trying manual detection...": "Échec du chemin pvesm, tentative de détection manuelle...",
|
||||
"pvesm status failed": "le statut pvesm a échoué",
|
||||
"pvesm path failed, trying manual detection...": "Échec de pvesm path, tentative de détection manuelle...",
|
||||
"pvesm status failed": "Échec de pvesm status",
|
||||
"pyLoad is a Free and Open Source download manager written in Python and designed to be extremely lightweight, easily extensible and fully manageable via web.": "pyLoad est un gestionnaire de téléchargement gratuit et Open Source écrit en Python et conçu pour être extrêmement léger, facilement extensible et entièrement gérable via le web.",
|
||||
"pyLoad web interface": "PyLoad interface web",
|
||||
"qBittorrent WebUI password (user: admin)": "qBittorrent Mot de passe WebUI (utilisateur: admin)",
|
||||
@@ -8097,7 +8097,7 @@
|
||||
"switch_gpu_mode.sh was not found.": "switch_gpu_mode.sh n'a pas été trouvé.",
|
||||
"sysfs ROM dump failed — trying ACPI VFCT table...": "Échec du vidage de la ROM sysfs - tentative de la table 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 vous permet de collecter, d'analyser, de classer, de réécrire et de corréler les logs de toute votre infrastructure et de les stocker ou de les acheminer vers des outils d'analyse de log.",
|
||||
"systemctl restart networking failed:": "échec du redémarrage du réseau systemctl :",
|
||||
"systemctl restart networking failed:": "Échec de systemctl restart networking :",
|
||||
"systemd OnCalendar expression": "expression systemd OnCalendar",
|
||||
"the API key was not generated on the first start": "la clé API n'a pas été générée au premier démarrage",
|
||||
"the NVIDIA hook of the container is not available:": "le hook NVIDIA du conteneur n'est pas disponible :",
|
||||
@@ -8151,7 +8151,7 @@
|
||||
"video + recognition": "vidéo + reconnaissance",
|
||||
"video only": "vidéo uniquement",
|
||||
"vzdump backup speed optimization completed": "Optimisation de la vitesse de sauvegarde de vzdump terminée",
|
||||
"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 construit ses liens à partir de l'adresse donnée pendant l'installation. S'il ne correspond pas à l'adresse du conteneur, modifier lxc.environnement. temps d'exécution: SYMFONY ENV DOMAIN NAME dans /etc/pve/lxc/<CTID>.conf avec le conteneur arrêté, et recommencer.",
|
||||
"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 construit ses liens avec l’adresse indiquée à l’installation. Si elle ne correspond pas à celle du conteneur, arrêtez-le, modifiez lxc.environment.runtime: SYMFONY__ENV__DOMAIN_NAME dans /etc/pve/lxc/<CTID>.conf, puis redémarrez-le.",
|
||||
"wallabag listens on port 80 of the container and stores its data in SQLite.": "wallabag écoute sur le port 80 du conteneur et stocke ses données dans SQLite.",
|
||||
"wallabag web interface": "Interface web wallabag",
|
||||
"was": "était",
|
||||
|
||||
+22
-22
@@ -138,7 +138,7 @@
|
||||
"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",
|
||||
"ALLOWED_HOSTS cannot contain line breaks": "Allowed hosts não pode conter quebras de linha",
|
||||
"ALLOWED_HOSTS cannot contain line breaks": "ALLOWED_HOSTS não pode conter quebras de linha",
|
||||
"AList initial login": "Login inicial do AList",
|
||||
"AMD (ROCm)": "AMD (ROCm)",
|
||||
"AMD (VA-API and ROCm detection)": "AMD (detecção VA-API e ROCm)",
|
||||
@@ -1643,8 +1643,8 @@
|
||||
"Default Proxmox logo applied": "Logotipo padrão do Proxmox aplicado",
|
||||
"Default is none (video-only passthrough). Use SPACE to toggle selections.": "O padrão é nenhum (passagem somente de vídeo). Use ESPAÇO para alternar as seleções.",
|
||||
"Default journald configuration restored": "Configuração padrão do diário 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.": "O local padrão é /mnt/<nome>. O compartilhamento será montado aqui no host com permissões abertas para que um LXC sem privilégios possa montar e gravar nele. Para acesso LXC, monte este caminho com o 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.": "O local padrão é /mnt/<nome>. O compartilhamento será montado aqui no host. Use este caminho em /etc/fstab. Para acesso LXC, monte este caminho com o LXC Mount Manager.",
|
||||
"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.": "A localização predefinida é /mnt/<name>. A partilha será montada aqui no host com permissões abertas, para que um LXC sem privilégios a possa montar por bind mount e nela escrever. Utilize o LXC Mount Manager para criar essa montagem no LXC.",
|
||||
"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.": "A localização predefinida é /mnt/<name>. A partilha será montada aqui no host. Utilize este caminho em /etc/fstab. Para aceder a partir de um LXC, crie um bind mount deste caminho com o LXC Mount Manager.",
|
||||
"Default login": "Utilizador por omissão",
|
||||
"Default options": "Opções padrão",
|
||||
"Default options read/write": "Opções padrão leitura/gravação",
|
||||
@@ -2035,7 +2035,7 @@
|
||||
"Enter VM ID:": "Insira o ID da VM:",
|
||||
"Enter VM/CT ID:": "Insira o ID da VM/CT:",
|
||||
"Enter ZFS pool name for the selected disk:": "Insira o nome do pool ZFS para o disco selecionado:",
|
||||
"Enter a name for the mount point (used as /mnt/<name>):": "Insira um nome para o ponto de montagem (usado como /mnt/<nome>):",
|
||||
"Enter a name for the mount point (used as /mnt/<name>):": "Introduza um nome para o ponto de montagem (será usado como /mnt/<name>):",
|
||||
"Enter a name for the new virtual machine:": "Insira um nome para a nova máquina virtual:",
|
||||
"Enter a non-empty password or access token on a single line.": "Insira uma senha ou token de acesso não vazio em uma única linha.",
|
||||
"Enter a number, or write or paste a command:": "Digite um número ou escreva ou cole um comando:",
|
||||
@@ -2179,11 +2179,11 @@
|
||||
"Example: cp /etc/pve/lxc/114.conf /etc/pve/lxc/114.conf.bak": "Exemplo: cp /etc/pve/lxc/114.conf /etc/pve/lxc/114.conf.bak",
|
||||
"Example: daily or Mon..Fri 03:00": "Exemplo: diariamente ou Seg..Sex 03:00",
|
||||
"Example: mkdir -p /tmp/lxc_convert_114": "Exemplo: mkdir -p /tmp/lxc_convert_114",
|
||||
"Example: pct config 110 | grep unprivileged": "Exemplo: configuração pct 110 | grep sem privilégios",
|
||||
"Example: pct config 110 | grep unprivileged": "Exemplo: pct config 110 | grep unprivileged",
|
||||
"Example: pct stop 110": "Exemplo: pct stop 110",
|
||||
"Example: pct stop 114": "Exemplo: parada pct 114",
|
||||
"Example: pct stop 114": "Exemplo: pct stop 114",
|
||||
"Example: pvesm add nfs nfs-nas --server 192.168.1.50 --export /volume1/proxmox --content import,backup": "Exemplo: pvesm add nfs nfs-nas --server 192.168.1.50 --export /volume1/proxmox --content import,backup",
|
||||
"Example: pvesm path local-lvm:vm-114-disk-0": "Exemplo: caminho pvesm local-lvm:vm-114-disk-0",
|
||||
"Example: pvesm path local-lvm:vm-114-disk-0": "Exemplo: pvesm path local-lvm:vm-114-disk-0",
|
||||
"Example: sed -i '/^unprivileged: 1/d' /etc/pve/lxc/110.conf": "Exemplo: sed -i '/^unprivileged: 1/d' /etc/pve/lxc/110.conf",
|
||||
"Examples:": "Exemplos:",
|
||||
"Execute destructive rollback?": "Executar reversão destrutiva?",
|
||||
@@ -2495,7 +2495,7 @@
|
||||
"For a consistent export, the VM should be stopped.": "Para uma exportação consistente, a VM deve ser interrompida.",
|
||||
"For any question, issue or bug report, please use the official repository": "Para qualquer dúvida, problema ou relatório de bug, use o repositório oficial",
|
||||
"For dedicated GPUs, FLR is required by this policy to reduce VM": "Para GPUs dedicadas, o FLR é exigido por esta política para reduzir VM",
|
||||
"For example: pct enter 101": "Por exemplo: pct digite 101",
|
||||
"For example: pct enter 101": "Por exemplo: pct enter 101",
|
||||
"For guest shares add: --options guest": "Para compartilhamentos de convidados, adicione: --options guest",
|
||||
"For security reasons, the system cannot format it.": "Por motivos de segurança, o sistema não pode formatá-lo.",
|
||||
"For unprivileged containers, use instead:": "Para contêineres sem privilégios, use:",
|
||||
@@ -2907,8 +2907,8 @@
|
||||
"If notifications are enabled (Telegram/Discord/ntfy/...), you will receive a \"Host restore finished\" message when all background tasks complete.": "Se as notificações estiverem habilitadas (Telegram/Discord/ntfy/...), você receberá uma mensagem \"Restauração do host concluída\" quando todas as tarefas em segundo plano forem concluídas.",
|
||||
"If passthrough fails on Windows: install RadeonResetBugFix.": "Se a passagem falhar no Windows: instale RadeonResetBugFix.",
|
||||
"If path not accessible (ZFS/BTRFS):": "Se o caminho não estiver acessível (ZFS/BTRFS):",
|
||||
"If pvesm path returned a DEVICE (LVM):": "Se o caminho pvesm retornou um DEVICE (LVM):",
|
||||
"If pvesm path returned a DIRECTORY (ZFS/BTRFS):": "Se o caminho pvesm retornou um DIRETÓRIO (ZFS/BTRFS):",
|
||||
"If pvesm path returned a DEVICE (LVM):": "Se pvesm path devolveu um DISPOSITIVO (LVM):",
|
||||
"If pvesm path returned a DIRECTORY (ZFS/BTRFS):": "Se pvesm path devolveu um DIRETÓRIO (ZFS/BTRFS):",
|
||||
"If repositories error:": "Se houver erro nos repositórios:",
|
||||
"If the container had already been changed, its previous native backup is restored. Shared host directories are not reverted. The disks of the failed attempt are removed when the cleanup succeeds.": "Se o contêiner já tiver sido alterado, seu backup nativo anterior será restaurado. Os diretórios de host compartilhados não são revertidos. Os discos da tentativa fracassada serão removidos quando a limpeza for bem-sucedida.",
|
||||
"If the host freezes, remove hostpci entries from": "Se o host congelar, remova as entradas hostpci de",
|
||||
@@ -3048,7 +3048,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",
|
||||
@@ -3225,7 +3225,7 @@
|
||||
"Interrupted operation:": "operation interrompida:",
|
||||
"Interrupted stack operation found": "Pilha interrompida operation encontrada",
|
||||
"Invalid 'proxmox-ve' candidate (not 9.x or none). Please verify your repository configuration and network, then retry.": "Candidato 'proxmox-ve' inválido (não 9.x ou nenhum). Verifique a configuração e a rede do seu repositório e tente novamente.",
|
||||
"Invalid ALLOWED_HOSTS value": "Valor Allowed hosts inválido",
|
||||
"Invalid ALLOWED_HOSTS value": "Valor de ALLOWED_HOSTS inválido",
|
||||
"Invalid Home Assistant OS check timeout": "Tempo de verificação do sistema operacional Home Assistant inválido",
|
||||
"Invalid ID": "ID inválido",
|
||||
"Invalid IPv4 address": "Endereço IPv4 inválido",
|
||||
@@ -3460,7 +3460,7 @@
|
||||
"Keyfile removed.": "arquivo-chave removido.",
|
||||
"Keyrings method failed; trying apt-key fallback": "O método dos chaveiros falhou; tentando substituto do apt-key",
|
||||
"KiCad - A Cross Platform and Open Source Electronics Design Automation Suite.": "KiCad - Uma plataforma cruzada e Open Source Electronics Design Automation Suite.",
|
||||
"Kimai has no default account. Enter the container with: pct enter {main_vmid}": "Kimai não tem conta padrão. Digite o recipiente com: pct enter {main vmid}",
|
||||
"Kimai has no default account. Enter the container with: pct enter {main_vmid}": "O Kimai não tem uma conta predefinida. Aceda ao contentor com: pct enter {main_vmid}",
|
||||
"Kimai is a professional grade time-tracking application, free and open-source.": "Kimai é um aplicativo de rastreamento de tempo profissional, gratuito e de código aberto.",
|
||||
"Kometa is a powerful tool designed to give you complete control over your media libraries. With Kometa, you can take your customization to the next level, with granular control over metadata, collections, overlays, and much more.": "Kometa é uma ferramenta poderosa projetada para lhe dar controle completo sobre suas bibliotecas de mídia. Com o Kometa, você pode levar sua personalização para o próximo nível, com controle granular sobre metadados, coleções, sobreposições e muito mais.",
|
||||
"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 lê a sua configuração a partir de /config/config.yml e o recipiente apenas navios /config/config.yml.template. Copie o modelo para config.yml, preencha o requi vermelho Plex e conexões TMDb, em seguida, reinicie o recipiente.",
|
||||
@@ -3512,7 +3512,7 @@
|
||||
"Leave empty to keep every backup (not recommended).": "Deixe em branco para manter todos os backups (não recomendado).",
|
||||
"Leave empty to use the retention of the storage.": "Deixe em branco para usar a retenção do armazenamento.",
|
||||
"Legacy PVE 8 .list files commented or not present": "Arquivos .list PVE 8 legados comentados ou não presentes",
|
||||
"Legacy ceph.list commented or not present": "Ceph.list legado comentado ou não presente",
|
||||
"Legacy ceph.list commented or not present": "ceph.list antigo comentado ou inexistente",
|
||||
"Legacy gasket-dkms cleanup could not be verified as complete.": "Não foi possível confirmar a conclusão da limpeza do pacote gasket-dkms legado.",
|
||||
"Legacy gasket-dkms detected": "gasket-dkms legado detetado",
|
||||
"Legacy network tools (e.g., ifconfig)": "Ferramentas de rede legadas (por exemplo, ifconfig)",
|
||||
@@ -4263,7 +4263,7 @@
|
||||
"No jobs": "Sem empregos",
|
||||
"No language selected.": "Nenhum idioma selecionado.",
|
||||
"No local disk storage configured.": "Nenhum armazenamento em disco local configurado.",
|
||||
"No main sources.list present (skipped)": "Nenhuma fonte principal.list presente (ignorada)",
|
||||
"No main sources.list present (skipped)": "Não existe um sources.list principal (ignorado)",
|
||||
"No matches for:": "Nenhuma correspondência para:",
|
||||
"No matching PVE vzdump jobs were found for the PBS backend.": "Nenhum trabalho PVE vzdump correspondente foi encontrado para o backend do PBS.",
|
||||
"No matching PVE vzdump jobs were found for the local archive backend.": "Nenhum trabalho PVE vzdump correspondente foi encontrado para o back-end do arquivo local.",
|
||||
@@ -6993,7 +6993,7 @@
|
||||
"Transaction log:": "Registo de transacções:",
|
||||
"Translation files:": "Arquivos de tradução:",
|
||||
"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 é projetado para uso fácil e poderoso. Transmission tem os recursos que você deseja de um cliente BitTorrent: criptografia, uma interface web, troca de pares, links magnéticos, DHT, μTP, encaminhamento de portas UPnP e NAT-PMP, suporte a webseed, diretórios de relógio, edição de rastreadores, limites de velocidade globais e per-torrent, e muito mais.",
|
||||
"Tried pvesm path and manual detection methods": "Tentei caminho pvesm e métodos de detecção manual",
|
||||
"Tried pvesm path and manual detection methods": "Foram tentados pvesm path e os métodos de deteção manual",
|
||||
"Trust this certificate and save it for scheduled backups?": "Confiar neste certificado e salvá-lo para backups agendados?",
|
||||
"Try Again": "Tente novamente",
|
||||
"Try a different search term.": "Experimente um termo de pesquisa diferente.",
|
||||
@@ -7213,7 +7213,7 @@
|
||||
"Updates file is empty or unreadable.": "O arquivo de atualizações está vazio ou ilegível.",
|
||||
"Updating": "Actualização",
|
||||
"Updating APT package lists...": "Atualizando listas de pacotes APT...",
|
||||
"Updating Debian Bookworm → Trixie in sources.list...": "Atualizando Debian Bookworm → Trixie em fontes.list...",
|
||||
"Updating Debian Bookworm → Trixie in sources.list...": "A atualizar Debian Bookworm → Trixie em sources.list...",
|
||||
"Updating Figurine binary...": "Atualizando o binário da estatueta...",
|
||||
"Updating Lynis to the latest version...": "Atualizando Lynis para a versão mais recente...",
|
||||
"Updating PVE application manager...": "Atualizando o gerenciador de aplicativos PVE...",
|
||||
@@ -8018,8 +8018,8 @@
|
||||
"pvesm command not found. This should not happen on Proxmox.": "Comando pvesm não encontrado. Isso não deveria acontecer no Proxmox.",
|
||||
"pvesm not available.": "pvesm não disponível.",
|
||||
"pvesm not found.": "pvesm não encontrado.",
|
||||
"pvesm path failed, trying manual detection...": "caminho pvesm falhou, tentando detecção manual...",
|
||||
"pvesm status failed": "status pvesm falhou",
|
||||
"pvesm path failed, trying manual detection...": "O pvesm path falhou; a tentar a deteção manual...",
|
||||
"pvesm status failed": "O pvesm status falhou",
|
||||
"pyLoad is a Free and Open Source download manager written in Python and designed to be extremely lightweight, easily extensible and fully manageable via web.": "pyLoad é um gerenciador de download livre e Open Source escrito em Python e projetado para ser extremamente leve, facilmente extensível e totalmente gerenciável via web.",
|
||||
"pyLoad web interface": "interface web pyLoad",
|
||||
"qBittorrent WebUI password (user: admin)": "Senha do WebUI do qBittorrent (utilizador: administrador)",
|
||||
@@ -8079,7 +8079,7 @@
|
||||
"smbclient command is not working properly.": "O comando smbclient não está funcionando corretamente.",
|
||||
"smbclient command not found after installation.": "Comando smbclient não encontrado após a instalação.",
|
||||
"sources.list update skipped (no change)": "Atualização de sources.list ignorada (sem alteração)",
|
||||
"sources.list updated to Trixie": "fontes.list atualizado para Trixie",
|
||||
"sources.list updated to Trixie": "sources.list atualizado para Trixie",
|
||||
"ssh-keygen failed. Cannot create a new SSH key.": "ssh-keygen falhou. Não é possível criar uma nova chave SSH.",
|
||||
"stale entry/entries for interfaces no longer present": "entradas/entradas obsoletas para interfaces não estão mais presentes",
|
||||
"standard performance": "desempenho padrão",
|
||||
@@ -8098,7 +8098,7 @@
|
||||
"switch_gpu_mode.sh was not found.": "switch_gpu_mode.sh não foi encontrado.",
|
||||
"sysfs ROM dump failed — trying ACPI VFCT table...": "Falha no despejo de ROM do sysfs - tentando tabela 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.": "o syslog-ng permite coletar, analisar, classificar, reescrever e correlacionar logs de toda sua infraestrutura e armazená-los ou roteá-los para ferramentas de análise de log.",
|
||||
"systemctl restart networking failed:": "falha na reinicialização da rede do systemctl:",
|
||||
"systemctl restart networking failed:": "O systemctl restart networking falhou:",
|
||||
"systemd OnCalendar expression": "Expressão Systemd OnCalendar",
|
||||
"the API key was not generated on the first start": "a tecla API não foi gerada no primeiro início",
|
||||
"the NVIDIA hook of the container is not available:": "o hook NVIDIA do contêiner não está disponível:",
|
||||
@@ -8152,7 +8152,7 @@
|
||||
"video + recognition": "vídeo + reconhecimento",
|
||||
"video only": "apenas vídeo",
|
||||
"vzdump backup speed optimization completed": "otimização da velocidade de backup do vzdump concluída",
|
||||
"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 constrói seus links a partir do endereço fornecido durante a instalação. Se não corresponder ao endereço do recipiente, edite lxc.environment. tempo de execução: SYMFONY ENV DOMAIN NAME em /etc/pve/lxc/<CTID>.conf com o recipiente parado, e inicie-o novamente.",
|
||||
"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.": "O wallabag gera as ligações com o endereço indicado na instalação. Se não corresponder ao do contentor, pare-o, edite lxc.environment.runtime: SYMFONY__ENV__DOMAIN_NAME em /etc/pve/lxc/<CTID>.conf e volte a iniciá-lo.",
|
||||
"wallabag listens on port 80 of the container and stores its data in SQLite.": "wallabag escuta na porta 80 do recipiente e armazena seus dados em SQLite.",
|
||||
"wallabag web interface": "Interface Web wallabag",
|
||||
"was": "era",
|
||||
|
||||
+6
-6
@@ -138,7 +138,7 @@
|
||||
"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",
|
||||
"ALLOWED_HOSTS cannot contain line breaks": "UDELENÉ HOSTS nemôžu obsahovať prestávky na čiare",
|
||||
"ALLOWED_HOSTS cannot contain line breaks": "ALLOWED_HOSTS nesmie obsahovať zalomenia riadkov",
|
||||
"AList initial login": "AList začiatočné prihlásenie",
|
||||
"AMD (ROCm)": "AMD (ROCm)",
|
||||
"AMD (VA-API and ROCm detection)": "AMD (detekcia VA-API a ROCm)",
|
||||
@@ -322,7 +322,7 @@
|
||||
"After confirming, you will be asked to choose the NVIDIA driver version to install.": "Po potvrdení si vyberiete verziu ovládača NVIDIA, ktorú chcete nainštalovať.",
|
||||
"After detailed analysis, no changes are needed.": "Po podrobnej analýze nie sú potrebné žiadne zmeny.",
|
||||
"After detailed analysis, no cleanup is needed.": "Po podrobnej analýze nie je potrebné žiadne čistenie.",
|
||||
"After logging in, run: ip a to obtain the IP address.\nThen, enter that IP address in your web browser like this:\n http://IP_ADDRESS\n\nThis will open the Umbral OS dashboard.": "Po prihlásení spustite príkaz: ip a, aby ste zistili IP adresu.\nPotom túto IP adresu zadajte do prehliadača takto:\n http://IP_ADRESA\n\nOtvorí sa tým webové rozhranie Umbral OS.",
|
||||
"After logging in, run: ip a to obtain the IP address.\nThen, enter that IP address in your web browser like this:\n http://IP_ADDRESS\n\nThis will open the Umbral OS dashboard.": "Po prihlásení zistite IP adresu príkazom ip a.\nPotom ju zadajte do prehliadača v tomto tvare:\n http://IP_ADDRESS\n\nOtvorí sa panel Umbral OS.",
|
||||
"After pasting on the server, ensure the file is chmod 600 and owned by": "Po vložení na serveri overte, že súbor má chmod 600 a vlastní ho",
|
||||
"After reboot the system will be fully accessible (SSH, web UI, login), but the following components will be reinstalled in BACKGROUND — until they finish, commands like nvidia-smi may not yet be available:": "Po reštarte bude systém plne dostupný (SSH, webové rozhranie, prihlásenie), ale tieto súčasti sa budú doinštalovávať NA POZADÍ - kým neskončia, príkazy ako nvidia-smi ešte nemusia byť dostupné:",
|
||||
"After reboot, these components will reinstall in background:": "Po reštarte sa tieto súčasti doinštalujú na pozadí:",
|
||||
@@ -3048,7 +3048,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": "V LXC vytvorte správcu príkazom: console kimai:user:create YOUR_USERNAME YOUR_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",
|
||||
@@ -3225,7 +3225,7 @@
|
||||
"Interrupted operation:": "Prerušená operation:",
|
||||
"Interrupted stack operation found": "Prerušený zásobník operation nájdený",
|
||||
"Invalid 'proxmox-ve' candidate (not 9.x or none). Please verify your repository configuration and network, then retry.": "Neplatný kandidát 'proxmox-ve' (nie je 9.x alebo chýba). Skontrolujte nastavenie repozitárov a sieť, potom skúste znova.",
|
||||
"Invalid ALLOWED_HOSTS value": "Neplatná hodnota UDELENÁ HOSTS",
|
||||
"Invalid ALLOWED_HOSTS value": "Neplatná hodnota ALLOWED_HOSTS",
|
||||
"Invalid Home Assistant OS check timeout": "Neplatný čas odhlásenia Home Assistant OS",
|
||||
"Invalid ID": "Neplatné ID",
|
||||
"Invalid IPv4 address": "Neplatná adresa IPv4",
|
||||
@@ -3460,7 +3460,7 @@
|
||||
"Keyfile removed.": "Keyfile odstránený.",
|
||||
"Keyrings method failed; trying apt-key fallback": "Metóda keyrings zlyhala; skúšam náhradný apt-key postup",
|
||||
"KiCad - A Cross Platform and Open Source Electronics Design Automation Suite.": "KiCad - Cross Platform a Open Source Electronics Design Automation Suite.",
|
||||
"Kimai has no default account. Enter the container with: pct enter {main_vmid}": "Kimai nemá predvolený účet. Zadajte kontajner s: pct zadajte {main vmid}",
|
||||
"Kimai has no default account. Enter the container with: pct enter {main_vmid}": "Kimai nemá predvolený účet. Do kontajnera vstúpite príkazom: pct enter {main_vmid}",
|
||||
"Kimai is a professional grade time-tracking application, free and open-source.": "Kimai je profesionálna časová aplikácia, zadarmo a open-source.",
|
||||
"Kometa is a powerful tool designed to give you complete control over your media libraries. With Kometa, you can take your customization to the next level, with granular control over metadata, collections, overlays, and much more.": "Kometa je výkonný nástroj navrhnutý tak, aby vám plnú kontrolu nad vaše mediálne knižnice. S Kometa, môžete vziať svoje prispôsobenie na ďalšiu úroveň, s granulovanou kontrolou nad metaúdaje, zbierky, prekrývanie, a oveľa viac.",
|
||||
"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 číta svoju konfiguráciu z /config/config.yml a kontajner iba lode /config/config.yml.templát. Skopírujte šablónu pre config.yml, vyplňte required Plex a TMDb pripojenia, potom reštartujte kontajner.",
|
||||
@@ -8153,7 +8153,7 @@
|
||||
"video + recognition": "video + rozpoznávanie",
|
||||
"video only": "iba video",
|
||||
"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 vytvára odkazy z adresy zadanej pri inštalácii. Ak sa nezhoduje s adresou kontajnera, zastavte ho, upravte lxc.environment.runtime: SYMFONY__ENV__DOMAIN_NAME v /etc/pve/lxc/<CTID>.conf a znova ho spustite.",
|
||||
"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",
|
||||
|
||||
+18
-18
@@ -322,7 +322,7 @@
|
||||
"After confirming, you will be asked to choose the NVIDIA driver version to install.": "Efter bekräftelse kommer du att bli ombedd att välja NVIDIA-drivrutinsversionen att installera.",
|
||||
"After detailed analysis, no changes are needed.": "Efter detaljerad analys behövs inga ändringar.",
|
||||
"After detailed analysis, no cleanup is needed.": "Efter detaljerad analys behövs ingen rengöring.",
|
||||
"After logging in, run: ip a to obtain the IP address.\nThen, enter that IP address in your web browser like this:\n http://IP_ADDRESS\n\nThis will open the Umbral OS dashboard.": "När du har loggat in, kör: ip a för att få IP-adressen.\nAnge sedan den IP-adressen i din webbläsare så här:\n http://IP_ADRESS\n\nDetta öppnar Umbral OS-instrumentpanelen.",
|
||||
"After logging in, run: ip a to obtain the IP address.\nThen, enter that IP address in your web browser like this:\n http://IP_ADDRESS\n\nThis will open the Umbral OS dashboard.": "Kör ip a efter inloggningen för att ta reda på IP-adressen.\nAnge sedan adressen i webbläsaren så här:\n http://IP_ADDRESS\n\nDå öppnas instrumentpanelen för Umbral OS.",
|
||||
"After pasting on the server, ensure the file is chmod 600 and owned by": "Efter att ha klistrat in på servern, se till att filen är chmod 600 och ägs av",
|
||||
"After reboot the system will be fully accessible (SSH, web UI, login), but the following components will be reinstalled in BACKGROUND — until they finish, commands like nvidia-smi may not yet be available:": "Efter omstart kommer systemet att vara fullt tillgängligt (SSH, webbgränssnitt, inloggning), men följande komponenter kommer att installeras om i BAKGRUND - tills de är klara kanske kommandon som nvidia-smi inte är tillgängliga ännu:",
|
||||
"After reboot, these components will reinstall in background:": "Efter omstart kommer dessa komponenter att installeras om i bakgrunden:",
|
||||
@@ -1643,8 +1643,8 @@
|
||||
"Default Proxmox logo applied": "Standard Proxmox-logotyp tillämpas",
|
||||
"Default is none (video-only passthrough). Use SPACE to toggle selections.": "Standard är ingen (endast videogenomströmning). Använd MELLANSLAG för att växla mellan val.",
|
||||
"Default journald configuration restored": "Standard journalkonfiguration återställd",
|
||||
"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.": "Standardplatsen är /mnt/<namn>. Delingen kommer att monteras här på värden med öppna behörigheter så att en oprivilegierad LXC kan bind-mounta och skriva till den. För LXC-åtkomst, bind-montera den här sökvägen med 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.": "Standardplatsen är /mnt/<namn>. Delen kommer att monteras här på värden. Använd denna sökväg i /etc/fstab. För LXC-åtkomst, bind-montera den här sökvägen med LXC Mount Manager.",
|
||||
"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.": "Standardplatsen är /mnt/<name>. Den delade resursen monteras här på värden med öppna behörigheter, så att en oprivilegierad LXC-container kan bind-montera den och skriva till den. Använd LXC Mount Manager för att skapa monteringen i LXC-containern.",
|
||||
"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.": "Standardplatsen är /mnt/<name>. Den delade resursen monteras här på värden. Använd sökvägen i /etc/fstab. För åtkomst från en LXC-container, skapa en bind-montering av sökvägen med LXC Mount Manager.",
|
||||
"Default login": "Standard inloggning",
|
||||
"Default options": "Standardalternativ",
|
||||
"Default options read/write": "Standardalternativ läs/skriv",
|
||||
@@ -2035,7 +2035,7 @@
|
||||
"Enter VM ID:": "Ange VM ID:",
|
||||
"Enter VM/CT ID:": "Ange VM/CT ID:",
|
||||
"Enter ZFS pool name for the selected disk:": "Ange ZFS-poolnamn för den valda disken:",
|
||||
"Enter a name for the mount point (used as /mnt/<name>):": "Ange ett namn för monteringspunkten (används som /mnt/<namn>):",
|
||||
"Enter a name for the mount point (used as /mnt/<name>):": "Ange ett namn för monteringspunkten (används som /mnt/<name>):",
|
||||
"Enter a name for the new virtual machine:": "Ange ett namn för den nya virtuella maskinen:",
|
||||
"Enter a non-empty password or access token on a single line.": "Ange ett icke-tomt lösenord eller åtkomsttoken på en enda rad.",
|
||||
"Enter a number, or write or paste a command:": "Ange ett nummer, eller skriv eller klistra in ett kommando:",
|
||||
@@ -2183,7 +2183,7 @@
|
||||
"Example: pct stop 110": "Exempel: pct stop 110",
|
||||
"Example: pct stop 114": "Exempel: pct stop 114",
|
||||
"Example: pvesm add nfs nfs-nas --server 192.168.1.50 --export /volume1/proxmox --content import,backup": "Exempel: pvesm add nfs nfs-nas --server 192.168.1.50 --export /volume1/proxmox --content import,säkerhetskopia",
|
||||
"Example: pvesm path local-lvm:vm-114-disk-0": "Exempel: pvesm sökväg local-lvm:vm-114-disk-0",
|
||||
"Example: pvesm path local-lvm:vm-114-disk-0": "Exempel: pvesm path local-lvm:vm-114-disk-0",
|
||||
"Example: sed -i '/^unprivileged: 1/d' /etc/pve/lxc/110.conf": "Exempel: sed -i '/^unprivileged: 1/d' /etc/pve/lxc/110.conf",
|
||||
"Examples:": "Exempel:",
|
||||
"Execute destructive rollback?": "Utföra destruktiv återställning?",
|
||||
@@ -2495,7 +2495,7 @@
|
||||
"For a consistent export, the VM should be stopped.": "För en konsekvent export bör den virtuella datorn stoppas.",
|
||||
"For any question, issue or bug report, please use the official repository": "För alla frågor, problem eller felrapporter, använd det officiella arkivet",
|
||||
"For dedicated GPUs, FLR is required by this policy to reduce VM": "För dedikerade GPU:er krävs FLR enligt denna policy för att minska virtuella datorer",
|
||||
"For example: pct enter 101": "Till exempel: pct ange 101",
|
||||
"For example: pct enter 101": "Till exempel: pct enter 101",
|
||||
"For guest shares add: --options guest": "För gästandelar lägg till: --options gäst",
|
||||
"For security reasons, the system cannot format it.": "Av säkerhetsskäl kan systemet inte formatera det.",
|
||||
"For unprivileged containers, use instead:": "För oprivilegierade behållare, använd istället:",
|
||||
@@ -2773,7 +2773,7 @@
|
||||
"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ä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/net/tun": "Enhet på värden för /dev/net/tun",
|
||||
"Host device for /dev/ttyUSB0": "Värd enhet för /dev/ttyUSB0",
|
||||
"Host device for /dev/video10": "Värd enhet för /dev/video10",
|
||||
"Host device for /dev/video11": "Värd enhet för /dev/video11",
|
||||
@@ -2907,8 +2907,8 @@
|
||||
"If notifications are enabled (Telegram/Discord/ntfy/...), you will receive a \"Host restore finished\" message when all background tasks complete.": "Om aviseringar är aktiverade (Telegram/Discord/ntfy/...), kommer du att få meddelandet \"Värdåterställning avslutad\" när alla bakgrundsuppgifter är klara.",
|
||||
"If passthrough fails on Windows: install RadeonResetBugFix.": "Om passthrough misslyckas på Windows: installera RadeonResetBugFix.",
|
||||
"If path not accessible (ZFS/BTRFS):": "Om sökväg inte är tillgänglig (ZFS/BTRFS):",
|
||||
"If pvesm path returned a DEVICE (LVM):": "Om pvesm-sökvägen returnerade en DEVICE (LVM):",
|
||||
"If pvesm path returned a DIRECTORY (ZFS/BTRFS):": "Om pvesm-sökvägen returnerade en DIRECTORY (ZFS/BTRFS):",
|
||||
"If pvesm path returned a DEVICE (LVM):": "Om pvesm path returnerade en ENHET (LVM):",
|
||||
"If pvesm path returned a DIRECTORY (ZFS/BTRFS):": "Om pvesm path returnerade en KATALOG (ZFS/BTRFS):",
|
||||
"If repositories error:": "Om förrådsfel:",
|
||||
"If the container had already been changed, its previous native backup is restored. Shared host directories are not reverted. The disks of the failed attempt are removed when the cleanup succeeds.": "Om behållaren redan hade ändrats, återställs dess tidigare inbyggda säkerhetskopia. Delade värdkataloger återställs inte. Diskarna för det misslyckade försöket tas bort när rensningen lyckas.",
|
||||
"If the host freezes, remove hostpci entries from": "Om värden fryser, ta bort hostpci-poster från",
|
||||
@@ -3048,7 +3048,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": "Skapa administratören inne i LXC-containern: console kimai:user:create YOUR_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",
|
||||
@@ -3460,7 +3460,7 @@
|
||||
"Keyfile removed.": "Nyckelfilen har tagits bort.",
|
||||
"Keyrings method failed; trying apt-key fallback": "Nyckelringsmetoden misslyckades; försöker apt-key fallback",
|
||||
"KiCad - A Cross Platform and Open Source Electronics Design Automation Suite.": "KiCad - En Cross Platform och Open Source Electronics Design Automation Suite.",
|
||||
"Kimai has no default account. Enter the container with: pct enter {main_vmid}": "Kimai har inget standardkonto. Ange behållaren med: pct enter {main vmid}",
|
||||
"Kimai has no default account. Enter the container with: pct enter {main_vmid}": "Kimai har inget standardkonto. Öppna ett skal i containern med: pct enter {main_vmid}",
|
||||
"Kimai is a professional grade time-tracking application, free and open-source.": "Kimai är en professionell tidsspårningsapplikation, fri och öppen källkod.",
|
||||
"Kometa is a powerful tool designed to give you complete control over your media libraries. With Kometa, you can take your customization to the next level, with granular control over metadata, collections, overlays, and much more.": "Kometa är ett kraftfullt verktyg för att ge dig fullständig kontroll över dina mediebibliotek. Med Kometa kan du ta din anpassning till nästa nivå, med granulär kontroll över metadata, samlingar, överlagringar och mycket mer.",
|
||||
"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 läser sin konfiguration från /config/config.yml och behållaren endast fartyg /config/config.yml.template. Kopiera mallen till config.yml, fyll i required Plex och TMDb-anslutningar och starta sedan om behållaren.",
|
||||
@@ -3531,7 +3531,7 @@
|
||||
"Limiting size and optimizing journald": "Begränsning av storlek och optimering av journal",
|
||||
"Limiting size and optimizing journald...": "Begränsar storlek och optimerar journal...",
|
||||
"Limnoria A robust, full-featured, and user/programmer-friendly Python IRC bot, with many existing plugins. Successor of the well-known Supybot.": "Limnoria En robust, fullfjädrad och användarvänlig Python IRC bot, med många befintliga plugins. Framgång för den välkända Supybot.",
|
||||
"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 går med i inget IRC-nätverk tills dess konfigurationsfil finns. Skapa den med installationsguiden från Proxmox-värden: 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 ansluter inte till något IRC-nätverk förrän konfigurationsfilen finns. Skapa den med installationsguiden från Proxmox-värden: pct exec <CTID> -- bash -c 'cd /config && limnoria-wizard'",
|
||||
"Line to paste (single line, including \"command=...\" prefix):": "Rad att klistra in (en rad, inklusive \"command=...\" prefix):",
|
||||
"Linux Installation Options": "Linux installationsalternativ",
|
||||
"Linux/Mac path:": "Linux/Mac sökväg:",
|
||||
@@ -4600,7 +4600,7 @@
|
||||
"Partition created:": "Partition skapad:",
|
||||
"Partition table wiped": "Skiljebord torkat",
|
||||
"Pass /dev/kvm to the LXC": "Pass /dev/kvm till LXC",
|
||||
"Pass /dev/net/tun to the LXC": "Pass /dev/netto/tun till LXC",
|
||||
"Pass /dev/net/tun to the LXC": "Ge LXC-containern åtkomst till /dev/net/tun",
|
||||
"Pass /dev/ttyUSB0 to the LXC": "Pass /dev/ttyUSB0 till LXC",
|
||||
"Pass /dev/video10 to the LXC": "Pass /dev/video10 till LXC",
|
||||
"Pass /dev/video11 to the LXC": "Pass /dev/video11 till LXC",
|
||||
@@ -5250,7 +5250,7 @@
|
||||
"Replace": "Ersätta",
|
||||
"Replace <container-id> with the actual ID.": "Ersätt <container-id> med det faktiska ID:t.",
|
||||
"Replace <container-id> with your actual container ID": "Ersätt <container-id> med ditt faktiska container-ID",
|
||||
"Replace <storage-identifier> with the value from step 4": "Ersätt <lagringsidentifierare> med värdet från steg 4",
|
||||
"Replace <storage-identifier> with the value from step 4": "Ersätt <storage-identifier> med värdet från steg 4",
|
||||
"Replace invalid port(s)": "Ersätt ogiltiga port(ar)",
|
||||
"Replace it?": "Byt ut den?",
|
||||
"Replace paths with your actual values from step 5": "Ersätt sökvägar med dina faktiska värden från steg 5",
|
||||
@@ -6993,7 +6993,7 @@
|
||||
"Transaction log:": "Transaktionslogg:",
|
||||
"Translation files:": "Översättningsfiler:",
|
||||
"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 är utformad för enkel, kraftfull användning. Transmission har de funktioner du vill ha från en BitTorrent-klient: kryptering, ett webbgränssnitt, peer-utbyte, magnetlänkar, DHT, μTP, UPnP och NAT-PMP-port vidarebefordran, webseed support, watch kataloger, tracker redigering, globala och per-torrent hastighet gränser, och mer.",
|
||||
"Tried pvesm path and manual detection methods": "Testade pvesm-väg och manuella detekteringsmetoder",
|
||||
"Tried pvesm path and manual detection methods": "Har provat pvesm path och metoder för manuell identifiering",
|
||||
"Trust this certificate and save it for scheduled backups?": "Lita på det här certifikatet och spara det för schemalagda säkerhetskopieringar?",
|
||||
"Try Again": "Försök igen",
|
||||
"Try a different search term.": "Prova en annan sökterm.",
|
||||
@@ -8018,8 +8018,8 @@
|
||||
"pvesm command not found. This should not happen on Proxmox.": "pvesm-kommandot hittades inte. Detta bör inte hända på Proxmox.",
|
||||
"pvesm not available.": "pvesm inte tillgänglig.",
|
||||
"pvesm not found.": "pvesm hittades inte.",
|
||||
"pvesm path failed, trying manual detection...": "pvesm sökväg misslyckades, försöker manuell upptäckt...",
|
||||
"pvesm status failed": "pvesm-status misslyckades",
|
||||
"pvesm path failed, trying manual detection...": "pvesm path misslyckades, försöker identifiera manuellt...",
|
||||
"pvesm status failed": "pvesm status misslyckades",
|
||||
"pyLoad is a Free and Open Source download manager written in Python and designed to be extremely lightweight, easily extensible and fully manageable via web.": "pyLoad är en gratis och öppen källkod nedladdningshanterare skriven i Python och utformad för att vara extremt lätt, lättföränderlig och fullt hanterbar via webben.",
|
||||
"pyLoad web interface": "PyLoad webbgränssnitt",
|
||||
"qBittorrent WebUI password (user: admin)": "qBittorrent WebUI lösenord (användare: admin)",
|
||||
@@ -8098,7 +8098,7 @@
|
||||
"switch_gpu_mode.sh was not found.": "switch_gpu_mode.sh hittades inte.",
|
||||
"sysfs ROM dump failed — trying ACPI VFCT table...": "sysfs ROM-dump misslyckades — försöker ACPI VFCT-tabell...",
|
||||
"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 låter dig flexibelt samla in, analysera, klassificera, skriva och korrelera loggar från hela din infrastruktur och lagra eller dirigera dem för att logga analysverktyg.",
|
||||
"systemctl restart networking failed:": "systemctl omstart av nätverk misslyckades:",
|
||||
"systemctl restart networking failed:": "systemctl restart networking misslyckades:",
|
||||
"systemd OnCalendar expression": "systemd OnCalendar-uttryck",
|
||||
"the API key was not generated on the first start": "API-nyckeln genererades inte i första början",
|
||||
"the NVIDIA hook of the container is not available:": "NVIDIA-hooken för behållaren är inte tillgänglig:",
|
||||
|
||||
@@ -5,7 +5,12 @@ serves every published page under locale-prefixed URLs:
|
||||
|
||||
- `/en/<path>` — English, the source of truth
|
||||
- `/es/<path>` — Spanish
|
||||
- `/de/<path>` — German
|
||||
- `/fr/<path>` — French
|
||||
- `/it/<path>` — Italian
|
||||
- `/pt/<path>` — Portuguese
|
||||
- `/sk/<path>` — Slovak, with English fallback where needed
|
||||
- `/sv/<path>` — Swedish
|
||||
|
||||
We use [`next-intl`](https://next-intl.dev) for the i18n plumbing. Anyone
|
||||
can translate the docs without writing TypeScript: most of the work is
|
||||
@@ -148,6 +153,18 @@ Example:
|
||||
|
||||
### 4. Test locally
|
||||
|
||||
From the repository root, check the available catalogs without using a
|
||||
translation provider:
|
||||
|
||||
```bash
|
||||
python3 .github/scripts/check_web_docs_catalogs.py
|
||||
```
|
||||
|
||||
For a full locale-completion change, add `--require-complete` to also require
|
||||
every English file and leaf. This validates schema, placeholders, rich-text
|
||||
tags, literal code and rendering metadata; it does not replace linguistic
|
||||
review. Partial translations can continue to use the English fallback.
|
||||
|
||||
```bash
|
||||
cd web
|
||||
npm run dev
|
||||
@@ -311,7 +328,10 @@ registers a renderer for them.
|
||||
If you want to add a language that isn't in the project yet:
|
||||
|
||||
1. Create `messages/<locale>/common.json` and the page catalogs. The automated
|
||||
builder can provide the initial baseline.
|
||||
builder can provide the initial baseline when explicitly dispatched. It
|
||||
does not run on merge: changing English and its translations together must
|
||||
not trigger machine retranslation of the reviewed text. Offline validation
|
||||
still runs automatically for website changes.
|
||||
2. Review the shared navigation and a representative set of documentation
|
||||
pages with a native speaker.
|
||||
3. Add the locale code to `routing.ts` only when the locale is ready to be
|
||||
|
||||
+5
-4
@@ -8,13 +8,14 @@ const inter = Inter({ subsets: ["latin"] })
|
||||
* Minimal root layout — the localized layout under [locale]/ does the
|
||||
* real work (provider, navbar, etc.) but cannot own <html>/<body> tags
|
||||
* because Next.js requires those at the root level. Lang is set to the
|
||||
* default locale here and refined client-side from inside the locale
|
||||
* layout so the page still renders correctly with JS disabled (defaults
|
||||
* to English) and switches to the active locale once hydrated.
|
||||
* default locale here; scripts/localize-export.mjs sets the exported
|
||||
* document's language before search indexing, and LocaleHtmlSync keeps
|
||||
* it in sync during client navigation. The root-only hydration suppression
|
||||
* allows that intentional lang attribute change in the static export.
|
||||
*/
|
||||
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<html lang="en" className="dark">
|
||||
<html lang="en" className="dark" suppressHydrationWarning>
|
||||
<body className={`${inter.className} bg-background text-foreground antialiased`}>
|
||||
{children}
|
||||
</body>
|
||||
|
||||
@@ -29,7 +29,12 @@ export function LanguageSwitcher() {
|
||||
const labels: Record<string, string> = {
|
||||
en: t("en"),
|
||||
es: t("es"),
|
||||
de: t("de"),
|
||||
fr: t("fr"),
|
||||
it: t("it"),
|
||||
pt: t("pt"),
|
||||
sk: t("sk"),
|
||||
sv: t("sv"),
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ import { defineRouting } from "next-intl/routing"
|
||||
* `CONTRIBUTING-TRANSLATIONS.md`.
|
||||
*/
|
||||
export const routing = defineRouting({
|
||||
locales: ["en", "es", "sk"],
|
||||
locales: ["en", "es", "de", "fr", "it", "pt", "sk", "sv"],
|
||||
defaultLocale: "en",
|
||||
localePrefix: "always",
|
||||
})
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
{
|
||||
"site": {
|
||||
"name": "ProxMenux",
|
||||
"tagline": "Interaktives Menü und Web-Dashboard für Proxmox VE"
|
||||
},
|
||||
"nav": {
|
||||
"home": "Startseite",
|
||||
"docs": "Dokumentation",
|
||||
"documentation": "Dokumentation",
|
||||
"guides": "Anleitungen",
|
||||
"changelog": "Änderungsprotokoll",
|
||||
"github": "GitHub",
|
||||
"rss": "RSS",
|
||||
"rssTitle": "RSS-Feed",
|
||||
"menuOpen": "Menü öffnen"
|
||||
},
|
||||
"footer": {
|
||||
"sponsorHeading": "Projekt unterstützen",
|
||||
"sponsorBody": "Wenn Sie das Projekt unterstützen möchten.",
|
||||
"sponsorAlt": "Auf Ko-fi unterstützen",
|
||||
"connectHeading": "Community",
|
||||
"connectBody": "Beteiligen Sie sich an den Community-Diskussionen auf GitHub, um Hilfe zu erhalten, Ideen auszutauschen und zum Projekt beizutragen. Jede Idee ist willkommen!",
|
||||
"joinDiscussion": "An der Diskussion teilnehmen",
|
||||
"copyrightPrefix": "ProxMenux, ein gemeinschaftliches Open-Source-Projekt von",
|
||||
"copyrightSuffix": "."
|
||||
},
|
||||
"language": {
|
||||
"switcher": "Sprache",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"sk": "Slovenčina",
|
||||
"de": "Deutsch",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"pt": "Português",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"resources": {
|
||||
"documentation": {
|
||||
"title": "Dokumentation",
|
||||
"description": "Systembeschreibung und Benutzeranleitungen"
|
||||
},
|
||||
"changelog": {
|
||||
"title": "Änderungsprotokoll",
|
||||
"description": "Informationen zu den neuesten Aktualisierungen"
|
||||
},
|
||||
"guides": {
|
||||
"title": "Anleitungen",
|
||||
"description": "Schrittweise Anleitungen für häufige Aufgaben"
|
||||
},
|
||||
"github": {
|
||||
"title": "GitHub-Repository",
|
||||
"description": "Sehen Sie sich den Quellcode an."
|
||||
}
|
||||
},
|
||||
"docSidebar": {
|
||||
"documentation": "Dokumentation",
|
||||
"items": {
|
||||
"introduction": "Einführung",
|
||||
"installation": "Installation",
|
||||
"proxmenuxMonitor": "ProxMenux Monitor",
|
||||
"monitorOverview": "Übersicht",
|
||||
"architecture": "Architektur",
|
||||
"accessAuth": "Zugriff und Authentifizierung",
|
||||
"dashboard": "Dashboard",
|
||||
"dashboardSystemOverview": "Registerkarte Systemübersicht",
|
||||
"dashboardApps": "Registerkarte Apps",
|
||||
"dashboardStorage": "Registerkarte Speicher",
|
||||
"dashboardNetwork": "Registerkarte Netzwerk",
|
||||
"dashboardVmsLxcs": "Registerkarte VMs und LXCs",
|
||||
"dashboardVmsLxcsApp": "App",
|
||||
"dashboardVmsLxcsUpdates": "Aktualisierungen",
|
||||
"dashboardHardware": "Registerkarte Hardware",
|
||||
"dashboardSystemLogs": "Registerkarte Systemprotokolle",
|
||||
"dashboardTerminal": "Registerkarte Terminal",
|
||||
"dashboardSecurity": "Registerkarte Sicherheit",
|
||||
"dashboardSettings": "Registerkarte Einstellungen",
|
||||
"healthMonitor": "Zustandsüberwachung",
|
||||
"auditReport": "Prüfung und Berichte",
|
||||
"auditReportOverview": "Übersicht",
|
||||
"auditReportAssessment": "Bewertung und Inventar",
|
||||
"auditReportPolicy": "Richtlinie",
|
||||
"auditReportChanges": "Änderungen",
|
||||
"auditReportReports": "Berichte und Vergleiche",
|
||||
"auditReportScope": "Umfang und Garantien",
|
||||
"notifications": "Benachrichtigungen",
|
||||
"aiAssistant": "KI-Assistent",
|
||||
"apiReference": "API-Referenz",
|
||||
"integrations": "Integrationen",
|
||||
"ociManager": "OCI manager Apps",
|
||||
"ociOverview": "Übersicht",
|
||||
"ociArchitecture": "So wird ein OCI-Image umgesetzt",
|
||||
"ociCustomImage": "Image außerhalb des Katalogs",
|
||||
"ociStorageNetwork": "Daten, Pfade und Netzwerk",
|
||||
"ociHardware": "Geräte und Beschleunigung",
|
||||
"ociStacks": "Anwendungen mit mehreren Containern",
|
||||
"ociLifecycle": "Installieren, aktualisieren und ändern",
|
||||
"ociMonitor": "In ProxMenux Monitor",
|
||||
"proxmenuxScripts": "ProxMenux Scripts",
|
||||
"postInstallScript": "Skript zur Nachinstallation",
|
||||
"postInstallOverview": "Übersicht",
|
||||
"postInstallAutomated": "Automatisch",
|
||||
"postInstallCustomizable": "Anpassbar",
|
||||
"postInstallBasicSettings": "Grundeinstellungen",
|
||||
"postInstallSystem": "System",
|
||||
"postInstallVirtualization": "Virtualisierung",
|
||||
"postInstallNetwork": "Netzwerk",
|
||||
"postInstallStorage": "Speicher",
|
||||
"postInstallSecurity": "Sicherheit",
|
||||
"postInstallCustomization": "Anpassung",
|
||||
"postInstallMonitoring": "Überwachung",
|
||||
"postInstallPerformance": "Leistung",
|
||||
"postInstallOptional": "Optional",
|
||||
"postInstallUpdates": "Verfügbare Aktualisierungen installieren",
|
||||
"postInstallUninstall": "Optimierungen entfernen",
|
||||
"gpusCoralTpu": "GPUs und Coral TPU",
|
||||
"nvidiaHost": "NVIDIA-Treiber auf dem Host installieren",
|
||||
"coralHost": "Coral TPU auf dem Host installieren",
|
||||
"addGpuLxc": "GPU für einen LXC freigeben",
|
||||
"addCoralLxc": "Coral TPU für einen LXC freigeben",
|
||||
"addGpuVm": "GPU einer VM zuweisen (Passthrough)",
|
||||
"switchGpuMode": "GPU-Modus wechseln (VM ↔ LXC)",
|
||||
"createVm": "VM erstellen",
|
||||
"createVmOverview": "Übersicht",
|
||||
"createVmSystemNas": "NAS-Systeme",
|
||||
"createVmSynology": "Synology-VM",
|
||||
"createVmNasOthers": "Weitere NAS-Systeme",
|
||||
"createVmSystemWindows": "Windows-Systeme",
|
||||
"createVmSystemLinux": "Linux-Systeme",
|
||||
"diskManager": "Datenträgerverwaltung",
|
||||
"diskManagerOverview": "Übersicht",
|
||||
"diskImportVm": "Datenträger in eine VM importieren",
|
||||
"diskImportImageVm": "Datenträgerabbild in eine VM importieren",
|
||||
"diskAddController": "Controller oder NVMe-Gerät zu einer VM hinzufügen",
|
||||
"diskImportLxc": "Datenträger in einen LXC importieren",
|
||||
"diskFormat": "Physischen Datenträger formatieren oder löschen",
|
||||
"diskSmart": "SMART-Zustand und Datenträgertests",
|
||||
"storageShareManager": "Speicher und Freigaben verwalten",
|
||||
"storageShareOverview": "Übersicht",
|
||||
"hostStorage": "Speicher in den Host einbinden",
|
||||
"hostNfs": "NFS-Freigabe als Proxmox-Speicher hinzufügen",
|
||||
"hostSamba": "Samba-Freigabe als Proxmox-Speicher hinzufügen",
|
||||
"hostIscsi": "iSCSI-Ziel als Proxmox-Speicher hinzufügen",
|
||||
"hostLocalDisk": "Lokalen Datenträger als Proxmox-Speicher hinzufügen",
|
||||
"hostLocalShared": "Freigegebenes Verzeichnis auf dem Host anlegen",
|
||||
"lxcMountPoints": "LXC-Mountpoints (Host ↔ CT)",
|
||||
"lxcNetworkSharing": "Netzwerkfreigaben in LXC",
|
||||
"lxcNfsClient": "NFS-Client in LXC",
|
||||
"lxcSambaClient": "Samba-Client in LXC",
|
||||
"lxcNfsServer": "NFS-Server in LXC",
|
||||
"lxcSambaServer": "Samba-Server in LXC",
|
||||
"network": "Netzwerk",
|
||||
"networkOverview": "Übersicht",
|
||||
"networkDiagnostics": "Diagnose",
|
||||
"networkMonitoring": "Werkzeuge zur Echtzeitüberwachung",
|
||||
"networkBridge": "Netzwerk-Bridges prüfen und reparieren",
|
||||
"networkConfig": "Konfiguration prüfen und bereinigen",
|
||||
"networkPersistent": "Dauerhafte Schnittstellennamen",
|
||||
"networkBackup": "Schnittstellen sichern und neu starten",
|
||||
"security": "Sicherheit",
|
||||
"securityOverview": "Übersicht",
|
||||
"securityFail2ban": "Fail2Ban",
|
||||
"securityLynis": "Lynis",
|
||||
"utilities": "Dienstprogramme",
|
||||
"utilsOverview": "Übersicht",
|
||||
"utilsUupDump": "ISO-Erstellung mit UUP Dump",
|
||||
"utilsSystemUtils": "Systemwerkzeuge installieren",
|
||||
"utilsSystemUpdate": "Proxmox-System aktualisieren",
|
||||
"utilsUpgradePve": "Von PVE 8 auf PVE 9 aktualisieren",
|
||||
"utilsExportVm": "VM als OVA/OVF exportieren",
|
||||
"utilsImportVm": "VM aus OVA/OVF importieren",
|
||||
"settingsProxmenux": "ProxMenux-Einstellungen",
|
||||
"settingsOverview": "Übersicht",
|
||||
"settingsMonitor": "ProxMenux Monitor",
|
||||
"settingsBeta": "Release-Kanal wechseln",
|
||||
"settingsVersion": "Versionsinformationen anzeigen",
|
||||
"settingsUninstall": "ProxMenux deinstallieren",
|
||||
"commandsReference": "Befehlsreferenz",
|
||||
"commandsOverview": "Übersicht",
|
||||
"commandsSystem": "Nützliche Systembefehle",
|
||||
"commandsVmCt": "VMs und CTs verwalten",
|
||||
"commandsStorage": "Speicher und Datenträger",
|
||||
"commandsNetwork": "Netzwerkbefehle",
|
||||
"commandsUpdates": "Aktualisierungen und Pakete",
|
||||
"commandsGpu": "GPU-Passthrough",
|
||||
"commandsZfs": "ZFS verwalten",
|
||||
"commandsBackup": "Sichern und Wiederherstellen",
|
||||
"commandsTools": "Systemwerkzeuge für die Befehlszeile",
|
||||
"glossary": "Glossar",
|
||||
"about": "Über das Projekt",
|
||||
"aboutOverview": "Übersicht",
|
||||
"aboutFaq": "FAQ",
|
||||
"aboutContributors": "Mitwirkende",
|
||||
"aboutContributing": "Mitwirken",
|
||||
"aboutCodeOfConduct": "Verhaltenskodex",
|
||||
"externalRepositories": "Externe Repositorys",
|
||||
"backupRestore": "Sichern und Wiederherstellen",
|
||||
"backupRestoreOverview": "Übersicht",
|
||||
"backupRestoreHowItWorks": "Funktionsweise",
|
||||
"backupRestoreDestinations": "Ziele",
|
||||
"backupRestoreDestOverview": "Übersicht",
|
||||
"backupRestoreDestLocal": "Lokales Archiv",
|
||||
"backupRestoreDestPbs": "Proxmox Backup Server",
|
||||
"backupRestoreDestBorg": "Borg",
|
||||
"backupRestoreCreating": "Sicherungen erstellen",
|
||||
"backupRestoreJobs": "Geplante Aufträge",
|
||||
"backupRestoreRestoring": "Wiederherstellen",
|
||||
"backupRestoreCrossKernel": "Wiederherstellung mit anderer Kernel-Version",
|
||||
"backupRestoreGlossary": "Glossar"
|
||||
}
|
||||
},
|
||||
"hero": {
|
||||
"title": "ProxMenux",
|
||||
"tagline": "Ein interaktives Menü und Web-Dashboard für Proxmox VE",
|
||||
"description": "ProxMenux verbindet ein interaktives Menü mit einem Web-Dashboard für Proxmox VE. Führen Sie Befehle, Skripte und geführte Assistenten über das Terminalmenü aus oder verfolgen Sie Host-Zustand, Messwerte und Benachrichtigungen im Browser.",
|
||||
"installButton": "Jetzt installieren",
|
||||
"whatIsButton": "Was ist ProxMenux?",
|
||||
"logoAlt": "ProxMenux-Logo"
|
||||
},
|
||||
"docNav": {
|
||||
"previous": "Zurück",
|
||||
"next": "Weiter"
|
||||
},
|
||||
"tocPanel": {
|
||||
"onThisPage": "Auf dieser Seite"
|
||||
},
|
||||
"supportProject": {
|
||||
"heading": "Unterstützen Sie das Projekt!",
|
||||
"body": "Wenn Sie <strong>ProxMenux</strong> hilfreich finden, geben Sie dem Projekt eine ⭐ auf GitHub, damit auch andere darauf aufmerksam werden.",
|
||||
"button": "Stern auf GitHub vergeben"
|
||||
},
|
||||
"rssLink": {
|
||||
"heading": "Bleiben Sie auf dem Laufenden!",
|
||||
"body": "Abonnieren Sie unseren RSS-Feed, um über neue Änderungen informiert zu werden.",
|
||||
"copy": "Kopieren",
|
||||
"copied": "Kopiert!",
|
||||
"copyTitle": "RSS-URL kopieren",
|
||||
"openFeed": "RSS-Feed öffnen",
|
||||
"openTitle": "RSS-Feed öffnen"
|
||||
},
|
||||
"changelog": {
|
||||
"pageTitle": "Änderungsprotokoll",
|
||||
"meta": {
|
||||
"title": "ProxMenux-Änderungsprotokoll",
|
||||
"titleSuffix": "Versionshinweise",
|
||||
"latest": "Aktuell",
|
||||
"mostRecent": "Neueste Version",
|
||||
"description": "Versionshinweise und Aktualisierungsverlauf für ProxMenux, das menügesteuerte Skript zur Verwaltung von Proxmox VE.",
|
||||
"descriptionTail": "Neue Funktionen, Fehlerbehebungen, Sicherheitsupdates, Verbesserungen an ProxMenux Monitor, Kompatibilität mit KI-Anbietern, zusätzliche Absicherung beim GPU-Passthrough und mehr.",
|
||||
"ogDescription": "Versionshinweise für ProxMenux.",
|
||||
"ogTail": "Abonnieren Sie den RSS-Feed oder besuchen Sie diese Seite erneut, um neue Versionen zu finden."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,12 @@
|
||||
"switcher": "Language",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"sk": "Slovenčina"
|
||||
"sk": "Slovenčina",
|
||||
"de": "Deutsch",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"pt": "Português",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"resources": {
|
||||
"documentation": {
|
||||
|
||||
@@ -28,7 +28,12 @@
|
||||
"switcher": "Idioma",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"sk": "Slovenčina"
|
||||
"sk": "Slovenčina",
|
||||
"de": "Deutsch",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"pt": "Português",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"resources": {
|
||||
"documentation": {
|
||||
|
||||
@@ -157,7 +157,7 @@
|
||||
"<strong>Filesystems runtime del kernel y sistema</strong> — <code>/proc</code>, <code>/sys</code>, <code>/dev</code> y <code>/run</code> son pseudo-filesystems que produce el kernel y udev; no se persisten en ningún sitio.",
|
||||
"<strong>Binarios de paquetes bajo <code>/usr/bin</code>, <code>/usr/lib</code>, <code>/lib</code>, <code>/sbin</code></strong> — los reinstala el APT del destino a partir de <code>packages.manual.list</code>.",
|
||||
"<strong><code>/var/log/</code>, <code>/var/tmp/</code>, <code>/var/cache/</code></strong> — estado runtime por host, no se restaura.",
|
||||
"<strong><code>/home/USUARIO</code></strong> — no está en el perfil por defecto. Añadirlo como ruta custom cuando un sistema tenga directorios home de usuario que deban sobrevivir a una restauración."
|
||||
"<strong><code>/home/USER</code></strong> — no está en el perfil por defecto. Añadirlo como ruta custom cuando un sistema tenga directorios home de usuario que deban sobrevivir a una restauración."
|
||||
],
|
||||
"customPathsTitle": "Cómo se tratan las rutas custom",
|
||||
"customPathsBody": "Una ruta custom añadida en línea en modo Custom o persistida en <code>backup-extra-paths.txt</code> pasa por el mismo pipeline de <code>rsync</code> que las rutas del perfil por defecto. Se aplican las exclusiones globales. Si la ruta custom está bajo <code>/root/</code> o <code>/usr/local/share/proxmenux/</code>, siguen aplicando las exclusiones específicas de arriba. Cada ruta archivada — default o custom — queda registrada en <code>metadata/paths_archived.txt</code>. Las rutas que no existen en el origen se registran en <code>metadata/missing_paths.txt</code> sin detener la copia."
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
},
|
||||
"intro": {
|
||||
"title": "Cada salto de kernel se maneja de forma distinta",
|
||||
"body": "Cuando la restauración detecta que la copia y el destino tienen versiones mayores distintas de kernel, el flujo se ramifica en función de la dirección del salto — si la copia es más antigua o más reciente que el destino — porque los dos casos tienen modos de fallo opuestos. Las copias más recientes que el destino se restauran limpiamente tal cual (verificado empíricamente en múltiples pruebas de banco). Las copias más antiguas que el destino necesitan un filtro para evitar romper el arranque del destino con configuración escrita para un kernel que desde entonces ha cambiado."
|
||||
"body": "El kernel de un host Proxmox se identifica mediante una versión como <code>6.17.13-2-pve</code>. Los dos primeros números (<strong>6.17</strong> en este ejemplo) definen la versión principal: cuando cambian, algunos archivos de configuración del kernel anterior podrían no ser válidos para el nuevo. Si la restauración detecta versiones principales distintas en la copia y en el destino, el proceso toma un camino u otro según la dirección del salto: si el kernel de la copia es anterior o posterior al del destino. Los dos casos presentan riesgos opuestos. Las copias con un kernel más reciente que el del destino se restauran tal cual, sin problemas según las pruebas realizadas con varios saltos de kernel. Las copias con un kernel anterior al del destino necesitan un filtro para evitar que una configuración del kernel antiguo impida arrancar el sistema de destino."
|
||||
},
|
||||
"directionCheck": {
|
||||
"heading": "La comprobación de dirección",
|
||||
@@ -78,7 +78,7 @@
|
||||
"intro": "Para desarrolladores que quieran trazar o extender el comportamiento cross-kernel:",
|
||||
"rows": [
|
||||
{ "component": "Detección de dirección", "location": "<code>hb_compat_check</code> en <code>lib_host_backup_common.sh</code>. Fija <code>HB_COMPAT_KERNEL_DIRECTION</code>." },
|
||||
{ "component": "Lista de rutas del subconjunto seguro", "location": "<code>hb_unsafe_paths_cross_version</code> en <code>lib_host_backup_common.sh</code>. Emite líneas <code>path\\tmotivo</code> usadas tanto por el filtro CLI como por el endpoint Web <code>/api/host-backups/restore/prepare</code>." },
|
||||
{ "component": "Lista de rutas del subconjunto seguro", "location": "<code>hb_unsafe_paths_cross_version</code> en <code>lib_host_backup_common.sh</code>. Emite líneas <code>path\\treason</code> usadas tanto por el filtro CLI como por el endpoint Web <code>/api/host-backups/restore/prepare</code>." },
|
||||
{ "component": "Fases de hidratación", "location": "<code>_rs_hyd_grub</code>, <code>_rs_hyd_kernel_cmdline</code>, <code>_rs_hyd_modules</code>, <code>_rs_hyd_files</code> en <code>backup_host.sh</code>. Orquestados por <code>_rs_apply_bk_older_hydration</code>." },
|
||||
{ "component": "Forzado de reflow post-arranque", "location": "<code>apply_pending_restore.sh</code> lee <code>HB_HYDRATION_APPLIED</code> de <code>plan.env</code> y fuerza <code>NEEDS_INITRAMFS=1</code>/<code>NEEDS_GRUB=1</code>." },
|
||||
{ "component": "Preview Web", "location": "<code>/api/host-backups/restore/prepare</code> en <code>flask_server.py</code>. Fuentea la librería helper, ejecuta <code>_rs_apply_bk_older_hydration</code> en modo plan, devuelve las acciones al modal Web." }
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
},
|
||||
"sameArchive": {
|
||||
"heading": "El contenido interno de la copia es el mismo en cualquier destino",
|
||||
"body": "Con independencia de dónde se guarde la copia, dentro siempre están los mismos tres bloques descritos en <em>Cómo funciona</em>: el sistema de ficheros (<code>rootfs/</code>), los metadatos (<code>metadata/</code>) y el manifiesto (<code>manifest.json</code>). Al extraer una copia local <code>.tar.zst</code>, restaurar un archivo <code>.pxar</code> desde PBS o descomprimir un archivo Borg, el árbol de directorios resultante es idéntico en los tres casos. Esto significa que el proceso de restauración lee siempre los mismos ficheros y no le importa desde qué destino provenga la copia."
|
||||
"body": "Los tres destinos contienen la misma estructura <code>rootfs/</code> + <code>metadata/</code> + <code>manifest.json</code> descrita en <em>Cómo funciona</em>. Extraer un <code>.tar.zst</code> de un archivo local, restaurar un <code>.pxar</code> desde PBS o extraer un archivo de Borg con <code>borg extract</code> produce el mismo árbol de directorios. El proceso de restauración (<code>_rs_check_layout</code>, <code>_rs_apply</code>, <code>_rs_prepare_pending_restore</code>) lee los mismos tres componentes sin necesitar saber de qué destino proceden."
|
||||
},
|
||||
"extractStandalone": {
|
||||
"heading": "Extraer una copia fuera de ProxMenux",
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
},
|
||||
"repoSelection": {
|
||||
"heading": "Selección del repositorio",
|
||||
"intro": "ProxMenux descubre repositorios PBS desde dos fuentes en cada copia. El usuario elige uno desde un menú unificado; esa elección determina, para esa ejecución concreta, contra qué servidor y datastore se envía la copia, con qué contraseña se autentica y con qué huella (<em>fingerprint</em>) valida el certificado.",
|
||||
"intro": "ProxMenux descubre los repositorios de PBS a partir de dos fuentes en cada copia de seguridad. El usuario elige uno en un menú unificado; esa elección determina los valores de <code>HB_PBS_REPOSITORY</code>, <code>HB_PBS_SECRET</code> y <code>HB_PBS_FINGERPRINT</code> para esa ejecución.",
|
||||
"sourceRows": [
|
||||
{
|
||||
"source": "storage.cfg de Proxmox (auto-descubierto)",
|
||||
@@ -46,7 +46,7 @@
|
||||
"backupIdTitle": "Nombrado del backup ID",
|
||||
"backupIdBody": "El backup ID por defecto es <code>hostcfg-HOSTNAME</code>. Se pide al usuario que lo confirme o edite antes de la subida; cualquier carácter fuera de <code>[A-Za-z0-9_-]</code> se elimina y los guiones finales se recortan. Reutilizar el mismo ID entre ejecuciones es intencional — PBS trata el ID como un <em>grupo</em>, y cada copia posterior aparece como un nuevo backup dentro de ese grupo, compartiendo dedup con las ejecuciones previas.",
|
||||
"pxarTitle": "Qué se incluye dentro del archivo .pxar",
|
||||
"pxarBody": "Al construir el archivo <code>.pxar</code> se empaqueta el directorio de trabajo completo: el sistema de ficheros del host (<code>rootfs/</code>), los metadatos (<code>metadata/</code>) y el manifiesto (<code>manifest.json</code>). Al restaurar, ProxMenux compara la información del manifiesto con la del host destino para detectar si son equivalentes, si cambia el hardware o si se trata de un equipo distinto, y ajustar el proceso en consecuencia. Las copias antiguas —hechas con versiones anteriores de ProxMenux que empaquetaban solo el sistema de ficheros— siguen restaurándose sin problema: el flujo de restauración detecta ese formato heredado y lo reorganiza automáticamente."
|
||||
"pxarBody": "El origen del <code>.pxar</code> es todo el directorio <code>staging_root</code>, con <code>rootfs/</code>, <code>metadata/</code> y <code>manifest.json</code> juntos. Las versiones anteriores utilizaban <code>$staging_root/rootfs</code> como origen; esto dejaba <code>metadata/</code> fuera del archivo y la comprobación de compatibilidad de la restauración no tenía datos que leer, por lo que mostraba advertencias de restauración entre hosts incluso al restaurar en el mismo host. Las copias antiguas creadas solo a partir de rootfs siguen restaurándose correctamente mediante la rama del caso 3 de <code>_rs_check_layout</code>, que vuelve a colocar el árbol plano <code>etc/var/root/usr</code> dentro de una estructura <code>rootfs/</code>."
|
||||
},
|
||||
"encryption": {
|
||||
"heading": "Cifrado del lado del cliente",
|
||||
@@ -61,9 +61,9 @@
|
||||
"modesSharedTitle": "Clave compartida (importar la misma en cada host)",
|
||||
"modesSharedBody": "Se genera una única clave y se importa en todos los hosts mediante la opción <em>Usar una clave existente</em>. La gestión es más sencilla: hay un solo secreto que proteger, y cualquier host puede leer las copias de cualquier otro (útil para verificación centralizada, ejercicios de restauración cruzada o consolidación). A cambio, si la clave compartida se filtra queda expuesto todo el conjunto de hosts a la vez. Recomendado para laboratorios personales y entornos donde todos los hosts pertenecen al mismo responsable y comparten el mismo nivel de confianza.",
|
||||
"recoveryTitle": "¿Subir la clave a PBS? — el usuario decide",
|
||||
"recoveryBody": "Justo después de elegir la clave, ProxMenux pregunta si se quiere subir una copia de esa clave a PBS como red de seguridad, con dos opciones. <strong>No</strong> (por defecto) mantiene la clave solo en el host; ProxMenux no toca PBS con nada relacionado con la recuperación y el usuario gestiona por su cuenta la copia externa (desde el Monitor, la acción <em>Descargar</em> en la fila del destino PBS la exporta en el acto). <strong>Sí</strong> pide una passphrase de recuperación —dos veces, para comprobar que coincidan—; con esa passphrase, la clave se envuelve localmente con AES-256-CBC y PBKDF2 (600 000 iteraciones, sal aleatoria) en un fichero <code>pbs-key.recovery.enc</code>. A partir de ese momento, cada copia cifrada sube también ese fichero envuelto a PBS. Ni la passphrase ni la clave en claro salen del host. La respuesta se puede cambiar después desde el Monitor en cualquier momento; el interruptor está inline en la fila del destino PBS y el botón que aparece se adapta al estado (empezar a subir, dejar de subir, o cambiar la passphrase).",
|
||||
"recoveryBody": "Justo después de elegir la clave, ProxMenux hace una única pregunta explícita — <em>¿Subir clave a PBS?</em> — con dos respuestas. <strong>No se sube nada a PBS hasta que el usuario responde Sí.</strong> La opción por defecto es <em>No, mantener solo local</em>: la clave se queda solo en su ruta local, ProxMenux no toca PBS con nada relacionado con la recuperación y el usuario gestiona por su cuenta la copia externa (desde el Monitor, el botón <em>Descargar archivo clave</em> de la fila del destino PBS la exporta en el acto). Al elegir <em>Sí, subir</em> se pide una passphrase de recuperación —dos veces, para comprobar que coincidan— y ProxMenux envuelve la clave con esa passphrase usando AES-256-CBC y PBKDF2 (600 000 iteraciones, sal aleatoria) en un fichero <code>pbs-key.recovery.enc</code>. A partir de ese momento, cada backup cifrado sube también ese fichero envuelto a PBS como un grupo de backup asociado. Ni la passphrase ni la clave en claro salen del host. La respuesta se puede cambiar después desde el Monitor en cualquier momento: el interruptor de la fila del destino PBS cambia entre Sí y No y se aplica al momento (empezar a subir, dejar de subir o cambiar la passphrase, según el estado).",
|
||||
"blobUploadTitle": "Grupo emparejado en PBS",
|
||||
"blobUploadBody1": "Cuando el usuario ha respondido Sí, ProxMenux sube el sobre de recuperación a PBS después de cada copia cifrada como un segundo grupo emparejado, con el mismo nombre que el del host pero terminado en <code>-keyrecovery</code>. Los dos grupos aparecen juntos en el listado del datastore: uno con las copias del host, otro con los sobres. <strong>El sobre nunca sale del host en claro</strong>: se cifra en el host con AES-256-CBC y PBKDF2 antes de enviar un solo byte (<code>openssl enc -aes-256-cbc -pbkdf2 -iter 600000 -salt</code>). PBS solo recibe el sobre ya cifrado.",
|
||||
"blobUploadBody1": "Cuando la custodia está configurada como <em>Sí, subir</em>, ProxMenux sube el archivo de recuperación protegido a PBS después de cada copia cifrada. Lo guarda en un segundo grupo de copia asociado, con el mismo nombre que el grupo del host y el sufijo <code>-keyrecovery</code>. Los dos grupos aparecen juntos en la lista del almacén de datos: uno para las copias del host y otro para los archivos de recuperación. <strong>El archivo de recuperación nunca sale del host en texto plano</strong>: se cifra en el propio host con AES-256-CBC y PBKDF2 antes de enviar ningún dato (<code>openssl enc -aes-256-cbc -pbkdf2 -iter 600000 -salt</code>). PBS solo recibe el archivo ya cifrado.",
|
||||
"envelopeSecurityTitle": "¿No es un riesgo subir el archivo keyrecovery a PBS?",
|
||||
"envelopeSecurityBody": "El sobre viaja y se guarda cifrado en todo momento. La passphrase de recuperación no sale nunca del host: el cifrado ocurre en local antes de la subida y PBS solo recibe el resultado ya cifrado. Un administrador de PBS —o cualquiera con acceso al datastore— puede descargar el sobre, pero sin la passphrase no puede leer la clave que contiene: son solo bytes cifrados. Para reconstruir la clave hacen falta las dos cosas a la vez, el sobre y la passphrase, y solo el usuario tiene ambas.",
|
||||
"blobUploadConstraintTitle": "Por qué dos grupos y no uno solo cifrado",
|
||||
@@ -73,7 +73,7 @@
|
||||
"recoverTitle": "Recuperación en un equipo recién instalado",
|
||||
"recoverBody": "Cuando la clave no está en su sitio —tras reinstalar el host desde cero o después de eliminarla a propósito— el flujo de restauración prueba tres fuentes en orden y se queda con la primera que produce una clave usable. Primero, si el repositorio PBS elegido tiene una clave gestionada por PVE en <code>/etc/pve/priv/storage/<NAME>.enc</code>, se copia sola a la ruta canónica. Segundo, si en PBS hay un grupo <code>-keyrecovery</code>, se descarga la copia más reciente y se pide la passphrase de recuperación para abrirla. Tercero, si ninguna de las dos anteriores funciona o el usuario las descarta, el diálogo pide la ruta absoluta donde ha dejado la clave en este host, y se copia a la ruta canónica. El Monitor expone el mismo flujo dentro del modal de la copia. Si al Restaurar, Descargar o Ver contenido falta la clave, aparece un panel ámbar arriba del modal con las mismas tres vías de importación. Si la clave está instalada pero no es la correcta para esa copia, PBS devuelve un error de tipo <code>wrong key — manifest's key XX does not match provided key YY</code> y el modal muestra un panel estructurado con el fingerprint que PBS espera (el que quedó grabado en el manifest de la copia), para que el usuario sepa qué clave concreta necesita importar.",
|
||||
"monitorManagementTitle": "Gestionar la clave desde el Monitor",
|
||||
"monitorManagementBody": "En la página de configuración de copias, la fila de cada destino PBS incluye los controles de la clave. Tres acciones directas: <em>Descargar</em> exporta la clave actual al navegador. <em>Subir</em> reemplaza la clave instalada por otra que aporta el usuario (la anterior solo se sobrescribe cuando la nueva ha llegado correctamente a su sitio). <em>Eliminar</em> retira la clave del host. Justo al lado está el interruptor del sobre de recuperación: un Sí/No para subir o no la clave a PBS, un campo de passphrase que aparece al elegir Sí, y un botón que se adapta al estado actual (empezar a subir, dejar de subir, o cambiar la passphrase). Los controles del Monitor y el diálogo del shell hacen lo mismo por dentro, así que el resultado en disco y en PBS es idéntico se use la que se use."
|
||||
"monitorManagementBody": "El Monitor muestra los controles del archivo de clave en cada fila de destino PBS de la página de configuración de copias. Hay tres acciones: <em>Descargar</em> envía el archivo de clave actual al navegador del usuario; <em>Subir</em> sustituye el archivo de clave instalado por uno proporcionado por el usuario (el anterior solo se sobrescribe cuando el nuevo se ha guardado correctamente en la ruta canónica); y <em>Eliminar</em> borra el archivo de clave del host. Junto a estas acciones hay un único control de custodia para la recuperación: las opciones Sí y No de <em>¿Subir la clave a PBS?</em>, un campo para la frase de contraseña al elegir Sí y un botón contextual para aplicar el cambio, con el texto <em>Iniciar subida</em>, <em>Detener subida</em> o <em>Actualizar frase de contraseña</em> según el estado actual. Todas las acciones utilizan los mismos endpoints de Flask que el menú de terminal, por lo que el resultado en disco y el estado en PBS son idénticos desde ambas interfaces."
|
||||
},
|
||||
"restoreAccess": {
|
||||
"heading": "Recuperación del lado de la restauración",
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
{
|
||||
"id": "repositorio-pbs",
|
||||
"term": "Repositorio PBS",
|
||||
"def": "Combinación de servidor Proxmox Backup Server + <a href=\"#datastore\">datastore</a> + usuario al que se suben las copias. Se identifica con el formato <code>usuario@realm@host:datastore</code>. Un mismo servidor PBS puede alojar varios repositorios."
|
||||
"def": "Combinación de servidor Proxmox Backup Server + <a href=\"#datastore\">datastore</a> + usuario al que se suben las copias. Se identifica con el formato <code>user@realm@host:datastore</code>. Un mismo servidor PBS puede alojar varios repositorios."
|
||||
},
|
||||
{
|
||||
"id": "datastore",
|
||||
|
||||
@@ -121,7 +121,7 @@
|
||||
}
|
||||
],
|
||||
"schemaTitle": "Validación por esquema",
|
||||
"schemaBody": "ProxMenux incluye una plantilla que describe qué campos debe contener el manifiesto y qué forma tiene cada uno. Cuando se genera una copia se puede comprobar automáticamente que el manifiesto respeta esa plantilla, de modo que si un colector produjera un JSON malformado o con un campo mal escrito se detectaría en el momento. Es una comprobación destinada al desarrollo del propio ProxMenux: si el sistema no la tiene instalada, la copia sigue funcionando con normalidad y el manifiesto se genera igual."
|
||||
"schemaBody": "El manifiesto se valida con <code>scripts/backup_restore/schema/manifest.schema.json</code>. Ejecutar <code>build_manifest.sh --validate</code> activa una validación JSON Schema en Python (requiere <code>python3</code> y <code>jsonschema</code>). Si el módulo no está instalado, se omite la comprobación sin mostrar ningún aviso: esta validación es principalmente una ayuda para el desarrollo, no una dependencia necesaria durante la ejecución."
|
||||
},
|
||||
"applications": {
|
||||
"heading": "El inventario de aplicaciones",
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
},
|
||||
{
|
||||
"action": "Descargar",
|
||||
"detail": "Exporta el archivo como un fichero portable <code>.tar.zst</code> (tar comprimido con zstd). Se puede extraer en cualquier sistema Linux con <code>tar --zstd -xf FICHERO.tar.zst</code>, o desde macOS/Windows con herramientas que soporten zstd (7-Zip, PeaZip, Keka…). El árbol extraído contiene <code>manifest.json</code>, <code>metadata/</code> y <code>rootfs/</code>, exactamente el mismo layout que consume la restauración. Es útil para inspección offline o para restaurar en un host que no tiene acceso al destino original (PBS, Borg)."
|
||||
"detail": "Exporta el archivo como un fichero portable <code>.tar.zst</code> (tar comprimido con zstd). Se puede extraer en cualquier sistema Linux con <code>tar --zstd -xf FILE.tar.zst</code>, o desde macOS/Windows con herramientas que soporten zstd (7-Zip, PeaZip, Keka…). El árbol extraído contiene <code>manifest.json</code>, <code>metadata/</code> y <code>rootfs/</code>, exactamente el mismo layout que consume la restauración. Es útil para inspección offline o para restaurar en un host que no tiene acceso al destino original (PBS, Borg)."
|
||||
},
|
||||
{
|
||||
"action": "Restaurar",
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
},
|
||||
"apply": {
|
||||
"title": "Aplicar cambios del host + workloads",
|
||||
"body": "Una vez confirmas, el script escribe los cambios del lado del host — <code>vfio.conf</code>, blacklist, módulos y (para NVIDIA) la regla udev por BDF en <code>/etc/udev/rules.d/10-proxmenux-vfio-bind.rules</code> más el estado BDF en <code>/etc/proxmenux/vfio-bind.bdfs</code>. También aplica la política de conflicto elegida a cada VM/LXC afectada. Si la config del host realmente cambió, ejecuta <code>update-initramfs -u -k all</code> — si no, salta ese paso."
|
||||
"body": "Tras confirmar, el script escribe los cambios en el host: <code>vfio.conf</code>, la lista de módulos bloqueados, los módulos y, para NVIDIA, la regla udev por BDF en <code>/etc/udev/rules.d/10-proxmenux-vfio-bind.rules</code> y el estado BDF en <code>/etc/proxmenux/vfio-bind.bdfs</code>. También aplica la política de conflictos elegida a cada VM/LXC afectado. Si la configuración del host ha cambiado, ejecuta <code>update-initramfs -u -k all</code> y después <code>proxmox-boot-tool refresh</code>; si no ha cambiado, omite ambos comandos."
|
||||
},
|
||||
"reboot": {
|
||||
"title": "Reiniciar",
|
||||
|
||||
@@ -257,7 +257,7 @@
|
||||
"<strong>Hecho.</strong> El 2FA está ahora activo. La próxima vez que te logues, el panel pide primero la contraseña; una vez aceptada pide el código actual de 6 dígitos."
|
||||
],
|
||||
"setupStep4Sub": [
|
||||
"<em>Camino fácil:</em> en la app, pulsa <em>Añadir cuenta</em> → <em>Escanear código QR</em>, apunta la cámara al QR en la pantalla. La app nombra la entrada automáticamente (algo como <code>ProxMenux Monitor (tu-usuario)</code>) y empieza a mostrar un código de 6 dígitos que se refresca cada 30 segundos.",
|
||||
"<em>Camino fácil:</em> en la app, pulsa <em>Añadir cuenta</em> → <em>Escanear código QR</em>, apunta la cámara al QR en la pantalla. La app nombra la entrada automáticamente (algo como <code>ProxMenux Monitor (your-username)</code>) y empieza a mostrar un código de 6 dígitos que se refresca cada 30 segundos.",
|
||||
"<em>Plan B manual</em> (cuando escanear no es posible — p. ej. configurando en el mismo móvil con el que abriste el panel): pulsa <em>Añadir cuenta</em> → <em>Introducir clave de setup</em>. Escribe cualquier nombre (p. ej. <em>Proxmox Monitor</em>), pega la cadena Base32 del diálogo, deja <em>Tipo</em> como <em>Basado en tiempo</em>, guarda."
|
||||
],
|
||||
"testTitle": "Prueba antes de hacer logout",
|
||||
@@ -319,7 +319,7 @@
|
||||
"heading": "Secure Gateway (Tailscale)",
|
||||
"intro": "Los reverse proxies son la respuesta clásica a \"llegar al panel desde fuera\" pero requieren un dominio público, certificado y un puerto abierto en el borde. <strong>Secure Gateway</strong> es la alternativa cero-puertos que viene dentro del propio Monitor — una app desplegable preconstruida que levanta un LXC Alpine ejecutando <a>Tailscale</a> como subnet router. Una vez unido a tu tailnet, cada dispositivo en él puede llegar al Monitor en la propia IP LAN del host — desde un portátil de vacaciones, un móvil con 5G u otro nodo — sin exponer TCP 8008 a internet.",
|
||||
"calloutTitle": "Por qué esto es cómodo",
|
||||
"calloutBody": "La URL se mantiene igual que en la LAN — <code>http://<ip-lan-proxmox>:8008</code> funciona donde Tailscale funcione. Sin certificados, sin DNS, sin port forwarding. El propio Monitor ve la petición viniendo de una IP de tailnet (típicamente <code>100.x.y.z</code>), así que el log de auth y el hook de Fail2Ban siguen funcionando como en la LAN.",
|
||||
"calloutBody": "La URL se mantiene igual que en la LAN — <code>http://<proxmox-lan-ip>:8008</code> funciona donde Tailscale funcione. Sin certificados, sin DNS, sin port forwarding. El propio Monitor ve la petición viniendo de una IP de tailnet (típicamente <code>100.x.y.z</code>), así que el log de auth y el hook de Fail2Ban siguen funcionando como en la LAN.",
|
||||
"deployBody": "El flujo de despliegue es una sola pantalla — elige el storage LXC del host, pega un auth-key de Tailscale (generado en <a>login.tailscale.com/admin/settings/keys</a>), elige qué subnets anunciar, pulsa Deploy. El LXC tarda ~30 segundos en arrancar y se registra en el tailnet automáticamente.",
|
||||
"outro": "El despliegue paso a paso, la configuración de subnet-routes, las ACLs de Tailscale y el modo Exit Node se documentan por separado en <link>Dashboard → Security → Secure Gateway</link> — ahí vive el wizard de despliegue en la UI del panel. Esta página solo cubre el patrón de acceso."
|
||||
},
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
"heading": "Convenciones",
|
||||
"items": [
|
||||
"Todas las peticiones y respuestas son JSON salvo que se indique explícitamente (la descarga de logs es texto plano, <code>/api/prometheus</code> es text/plain en formato OpenMetrics, el log de tareas es texto plano).",
|
||||
"Los endpoints que modifican estado con éxito devuelven <code>'{'\"success\": true, ...'}'</code>. Las respuestas de error usan un estado HTTP no-2xx con <code>'{'\"success\": false, \"error\": \"'<'motivo'>'\"'}'</code>.",
|
||||
"Los endpoints que modifican estado con éxito devuelven <code>'{'\"success\": true, ...'}'</code>. Las respuestas de error usan un estado HTTP no-2xx con <code>'{'\"success\": false, \"error\": \"'<'reason'>'\"'}'</code>.",
|
||||
"Los endpoints de listado aceptan <code>limit</code>, <code>offset</code>, <code>since</code> opcionales y filtros específicos por categoría vía query string.",
|
||||
"Los campos de tiempo se devuelven como segundos epoch Unix o ISO-8601 con zona horaria explícita, nunca como cadenas de locale."
|
||||
]
|
||||
@@ -174,7 +174,7 @@
|
||||
"syncVsAsyncBody": "Las acciones a nivel de sistema (power del host, PVE update, self-update de ProxMenux) pueden tardar minutos — corren en su propia unit systemd transitoria y exponen un endpoint <code>.../status</code> más un <code>DELETE</code> para cancelar. Las acciones VM / LXC (start, stop, shutdown, reboot, backup) son rápidas y usan el estilo fire-and-return que la UI del Monitor ya expone: el POST devuelve el resultado directo. Ambos estilos comparten el mismo modelo de autenticación (JWT o token de API de larga duración).",
|
||||
"curlTitle": "Ejemplo con curl",
|
||||
"curlBody": "Disparar una actualización de PVE y hacer polling hasta que termine — exactamente la misma secuencia que ejecutaría una automatización de Home Assistant o un playbook de Ansible:",
|
||||
"curlCode": "TOKEN=<tu token full_admin>\n\ncurl -sSf -X POST \\\n -H \"Authorization: Bearer $TOKEN\" \\\n https://<host>:8008/api/system/pve-update/run\n\nwhile true; do\n state=$(curl -sSf -H \"Authorization: Bearer $TOKEN\" \\\n https://<host>:8008/api/system/pve-update/status | jq -r .state)\n [ \"$state\" != \"running\" ] && break\n sleep 30\ndone\necho \"estado final: $state\"",
|
||||
"curlCode": "TOKEN=<your full_admin token>\n\ncurl -sSf -X POST \\\n -H \"Authorization: Bearer $TOKEN\" \\\n https://<host>:8008/api/system/pve-update/run\n\nwhile true; do\n state=$(curl -sSf -H \"Authorization: Bearer $TOKEN\" \\\n https://<host>:8008/api/system/pve-update/status | jq -r .state)\n [ \"$state\" != \"running\" ] && break\n sleep 30\ndone\necho \"final state: $state\"",
|
||||
"haTitle": "Snippet de integración con Home Assistant",
|
||||
"haBody": "Un sensor <code>rest</code> hace polling del estado y un <code>rest_command</code> dispara la actualización. Conecta ambos a un botón del dashboard y a las automatizaciones que quieras:",
|
||||
"haCode": "# configuration.yaml\nsensor:\n - platform: rest\n resource: https://pve.local:8008/api/system/pve-update/status\n name: pve_update_state\n value_template: \"{{ value_json.state }}\"\n scan_interval: 60\n headers:\n Authorization: \"Bearer !secret proxmenux_token\"\n\nrest_command:\n pve_update:\n url: https://pve.local:8008/api/system/pve-update/run\n method: POST\n headers:\n Authorization: \"Bearer !secret proxmenux_token\"\n\n # Encender VM 100 (funciona igual para LXC — mismo endpoint)\n vm_100_start:\n url: https://pve.local:8008/api/vms/100/control\n method: POST\n content_type: 'application/json'\n payload: '{\"action\": \"start\"}'\n headers:\n Authorization: \"Bearer !secret proxmenux_token\"\n\n # Backup de la VM 100 al storage 'pbs-main'\n vm_100_backup:\n url: https://pve.local:8008/api/vms/100/backup\n method: POST\n content_type: 'application/json'\n payload: '{\"storage\": \"pbs-main\", \"mode\": \"snapshot\", \"compress\": \"zstd\"}'\n headers:\n Authorization: \"Bearer !secret proxmenux_token\""
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
],
|
||||
"sourcesHeading": "Fuentes para la versión disponible",
|
||||
"sources": [
|
||||
"<strong>Repositorio de GitHub</strong>: último lanzamiento o etiqueta de un repositorio público <code>propietario/nombre</code>.",
|
||||
"<strong>Repositorio de GitHub</strong>: último lanzamiento o etiqueta de un repositorio público <code>owner/name</code>.",
|
||||
"<strong>HTTP JSON</strong>: un punto final público y una ruta como <code>data.version</code> o <code>releases[0].tag_name</code>.",
|
||||
"<strong>Docker Hub</strong>: etiquetas versionadas filtradas con una expresión regular. La vista previa muestra etiquetas reales coincidentes antes de guardar.",
|
||||
"Las etiquetas móviles como <code>latest</code>, <code>stable</code> o <code>lts</code> no contienen una versión. Esas imágenes se siguen por digest desde las actualizaciones de imágenes Docker."
|
||||
|
||||
@@ -110,8 +110,8 @@
|
||||
"No incluyas <code>pct exec</code>; ProxMenux ya entra en el contenedor y ejecuta el comando como root."
|
||||
],
|
||||
"exampleLead": "Ejemplo de procedimiento completo dentro del contenedor:",
|
||||
"example": "cd /opt/mi-app && ./update.sh",
|
||||
"callout": "Un comando de versión como <code>miapp --version</code> solo lee una versión; no instala nada. Los comandos se ejecutan con privilegios administrativos y deben revisarse con el mismo cuidado que un comando de shell como root."
|
||||
"example": "cd /opt/my-app && ./update.sh",
|
||||
"callout": "Un comando de versión como <code>myapp --version</code> solo lee una versión; no instala nada. Los comandos se ejecutan con privilegios administrativos y deben revisarse con el mismo cuidado que un comando de shell como root."
|
||||
},
|
||||
"bulk": {
|
||||
"heading": "Actualización en bloque",
|
||||
@@ -142,7 +142,7 @@
|
||||
"La espera tras una versión solo se aplica a las apps seleccionadas con seguimiento. Las apps sin seguimiento ejecutan su actualizador cuando vence la programación.",
|
||||
"El estado de la última ejecución diferencia entre éxito, finalización parcial, error, retención de seguridad y ausencia de elementos pendientes. Después de la primera ejecución programada, <strong>Actualizaciones → Actualizaciones programadas → Ver log</strong> abre la salida completa capturada del actualizador y de los scripts secundarios que haya ejecutado.",
|
||||
"Después de cada ejecución, ProxMenux comprueba el marcador estándar de Debian que indica si es necesario reiniciar. Cuando hace falta, la pestaña Actualizaciones y la notificación de finalización lo indican; el aviso se elimina cuando ese LXC se inicia o reinicia.",
|
||||
"En el host Proxmox, los logs de las ejecuciones programadas se guardan en <code>/usr/local/share/proxmenux/logs/lxc-updates/</code> con el nombre <code><VMID>-scheduled-<id-de-ejecución>.log</code>. Se conservan los diez últimos logs de cada LXC y los archivos más antiguos se eliminan automáticamente.",
|
||||
"En el host Proxmox, los logs de las ejecuciones programadas se guardan en <code>/usr/local/share/proxmenux/logs/lxc-updates/</code> con el nombre <code><VMID>-scheduled-<run-id>.log</code>. Se conservan los diez últimos logs de cada LXC y los archivos más antiguos se eliminan automáticamente.",
|
||||
"Este historial corresponde a las actualizaciones programadas. Una actualización manual muestra su salida en tiempo real en la ventana de ejecución del Monitor y no crea un log de ejecución programada en ese directorio.",
|
||||
"Las programaciones externas detectadas de Proxmox VE Helper-Scripts se muestran aparte para hacer visible cualquier automatización coincidente."
|
||||
],
|
||||
@@ -186,7 +186,7 @@
|
||||
},
|
||||
{
|
||||
"problem": "Una actualización programada indica que es necesario reiniciar",
|
||||
"resolution": "Abre <strong>Ver log</strong> para revisar la ejecución completada y reinicia ese LXC. ProxMenux elimina el aviso mediante el evento de ciclo de vida existente cuando el contenedor vuelve a arrancar."
|
||||
"resolution": "Abre Ver registro para revisar la ejecución completada y después reinicia ese LXC. ProxMenux borra el aviso cuando el evento de ciclo de vida detecta el nuevo arranque."
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
"headingHref": "https://gethomepage.dev",
|
||||
"intro": "Homepage es un panel de aplicaciones totalmente estático y personalizable. ProxMenux Monitor se enchufa vía el widget <code>customapi</code> integrado — pega una entrada de servicio en <code>services.yaml</code>, reinicia Homepage y la tarjeta aparece con números en vivo.",
|
||||
"iconCalloutTitle": "El logo oficial de ProxMenux está en dashboardicons.com",
|
||||
"iconCalloutBody": "Las guías de abajo usan <code>icon: proxmenux.png</code>. Homepage resuelve automáticamente los nombres de archivo simples contra <a1>dashboardicons.com</a1> — una librería de iconos curada para paneles autoalojados. La entrada de ProxMenux vive en <a2>dashboardicons.com/icons/external/proxmenux</a2> y Homepage la descarga en el primer render. La misma búsqueda funciona para miles de otras herramientas (Telegram, Discord, Grafana, Tailscale, etc.) — basta con escribir <code>icon: <nombre>.png</code> en cualquier entrada de servicio.",
|
||||
"iconCalloutBody": "Las guías de abajo usan <code>icon: proxmenux.png</code>. Homepage resuelve automáticamente los nombres de archivo simples contra <a1>dashboardicons.com</a1> — una librería de iconos curada para paneles autoalojados. La entrada de ProxMenux vive en <a2>dashboardicons.com/icons/external/proxmenux</a2> y Homepage la descarga en el primer render. La misma búsqueda funciona para miles de otras herramientas (Telegram, Discord, Grafana, Tailscale, etc.) — basta con escribir <code>icon: <name>.png</code> en cualquier entrada de servicio.",
|
||||
"imageAlt": "Panel Homepage mostrando tres tarjetas de ProxMenux Monitor (EDGE, VOID, DREAM) con uptime, CPU, RAM y temperatura para cada host Proxmox",
|
||||
"imageCaption": "Tres instancias de ProxMenux Monitor renderizadas como tarjetas Homepage — uptime, CPU, RAM y temperatura de CPU leídas en vivo desde <code>/api/system</code> en cada host cada 10 s.",
|
||||
"basicTitle": "Widget básico — sin autenticación",
|
||||
@@ -94,7 +94,7 @@
|
||||
"twoColTipBody": "Reemplaza cualquier par de tarjetas (p. ej. <em>Sistema</em> + <em>VMs</em>, o <em>Almacenamiento</em> + <em>Red</em>) con un único <code>horizontal-stack</code> envolviendo ambas, para que siempre se rendericen lado a lado independientemente del ancho de pantalla:",
|
||||
"twoColTipOutro": "En móvil la fila se mantiene comprimida; el auto layout de HA (sin horizontal-stack) refluye mejor a anchos estrechos.",
|
||||
"step6Title": "6 · Automatizaciones",
|
||||
"step6Body": "Tres automatizaciones que cubren los escenarios reactivos más comunes — reemplaza <code>notify.mobile_app_<tu_movil></code> por el servicio notify que uses:",
|
||||
"step6Body": "Tres automatizaciones que cubren los escenarios reactivos más comunes — reemplaza <code>notify.mobile_app_<your_phone></code> por el servicio notify que uses:",
|
||||
"logoTitle": "Sobre el logo de ProxMenux",
|
||||
"logoBody": "La tarjeta picture-entity en la parte superior del YAML Lovelace descarga el logo oficial de ProxMenux desde <a1>dashboardicons.com</a1> — una librería de iconos gratuita curada para paneles autoalojados. La entrada de ProxMenux vive en <a2>dashboardicons.com/icons/external/proxmenux</a2>. Home Assistant descarga el SVG sobre HTTPS en el primer render y lo cachea.",
|
||||
"logoBrokenTitle": "Si la tarjeta del logo muestra una imagen rota",
|
||||
@@ -120,7 +120,7 @@
|
||||
"tokenTipTitle": "Token vía archivo o env, no inline",
|
||||
"tokenTipBody": "Para despliegues en producción evita poner el token inline. Prometheus soporta <code>credentials_file: /etc/prometheus/secrets/proxmenux.token</code> como alternativa — guarda el token en un archivo 0600 y deja que Prometheus lo lea.",
|
||||
"step2Title": "2 · Verifica el scrape con un par de queries",
|
||||
"step2Body": "Antes de configurar Grafana, confirma que Prometheus realmente tiene los datos. Abre la propia UI de Prometheus en <code>http://<host-prometheus>:9090</code>, pulsa <em>Query</em> y ejecuta cualquiera de estas — deberías obtener números en vivo de tu host Proxmox:",
|
||||
"step2Body": "Antes de configurar Grafana, confirma que Prometheus realmente tiene los datos. Abre la propia UI de Prometheus en <code>http://<prometheus-host>:9090</code>, pulsa <em>Query</em> y ejecuta cualquiera de estas — deberías obtener números en vivo de tu host Proxmox:",
|
||||
"headerQuery": "Query",
|
||||
"headerConfirms": "Qué confirma",
|
||||
"verifyRows": [
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
"Arranca el hilo de fondo de despacho. El hilo hace polling de la cola de eventos y camina cada evento por la pipeline diagramada arriba."
|
||||
],
|
||||
"activeAlt": "Tarjeta de notificaciones activada con pestañas de canales, nombre visible y opciones avanzadas de IA",
|
||||
"activeCaption": "Estado activo: pestañas Telegram, Gotify, Discord, Email, Pushover y Apprise, nombre visible, categorías por canal y opciones avanzadas de IA."
|
||||
"activeCaption": "Estado activo: pestañas de canales en la parte superior (Telegram / Gotify / Discord / correo electrónico / Pushover / Apprise), campo Nombre para mostrar, lista de categorías de cada canal y sección desplegable <em>Avanzado: mejora con IA</em>."
|
||||
},
|
||||
"sources": {
|
||||
"heading": "Fuentes de eventos",
|
||||
@@ -119,7 +119,7 @@
|
||||
"groupItems": [
|
||||
"Añade el bot al grupo como miembro (y hazlo admin si el grupo lo requiere para publicar).",
|
||||
"Envía cualquier mensaje en el grupo.",
|
||||
"Abre <code>https://api.telegram.org/bot<TU_TOKEN>/getUpdates</code> en un navegador. Busca <code>chat.id</code> en la respuesta JSON — para grupos es un número negativo, para supergrupos empieza con <code>-100</code>.",
|
||||
"Abre <code>https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates</code> en un navegador. Busca <code>chat.id</code> en la respuesta JSON — para grupos es un número negativo, para supergrupos empieza con <code>-100</code>.",
|
||||
"Para supergrupos con <em>Topics</em> activado, anota también el <code>message_thread_id</code> del tema al que quieres apuntar — eso va en el campo opcional <em>Topic ID</em>."
|
||||
],
|
||||
"groupAlt": "Formulario de canal Telegram con Bot Token (enmascarado), Chat ID negativo prefijado con -100 indicando un supergrupo, y Topic ID 3 configurado para entregar a un tema específico",
|
||||
@@ -203,7 +203,7 @@
|
||||
"stepsTitle": "Pasos",
|
||||
"steps": [
|
||||
"Elige el servicio destino en la <a>wiki de Apprise</a> y copia la plantilla de URL para él. Cada página de servicio muestra el esquema exacto a usar (<code>ntfy://</code>, <code>matrix://</code>, <code>pover://</code>, <code>slack://</code>…) más cualquier token, canal u hostname requerido.",
|
||||
"Rellena los placeholders con tus propias credenciales. Por ejemplo, un topic de ntfy.sh tiene aspecto de <code>ntfy://ntfy.sh/mi-topic</code>; una URL de Pushover tiene aspecto de <code>pover://user@token</code>; una URL de Matrix tiene aspecto de <code>matrix://user:pass@host:port/#room</code>.",
|
||||
"Sustituye los marcadores por tus credenciales. Ejemplos: ntfy.sh <code>ntfy://ntfy.sh/my-topic</code>; Pushover <code>pover://user@token</code>; Matrix <code>matrix://user:pass@host:port/#room</code>.",
|
||||
"Pega la URL final en el campo <em>Apprise URL</em> en la pestaña Apprise del panel Notifications y guarda.",
|
||||
"Pulsa <em>Send Test</em> para verificar que la URL es alcanzable y las credenciales se aceptan."
|
||||
],
|
||||
@@ -295,7 +295,7 @@
|
||||
"rows": [
|
||||
{
|
||||
"stage": "1. Deduplicación por huella",
|
||||
"what": "Cada evento genera una huella (<code>event_type + campos clave de data</code>). Las huellas idénticas dentro de una ventana corta se consideran duplicados del primero.",
|
||||
"what": "Cada evento genera una huella (<code>event_type + key fields from data</code>). Las huellas idénticas dentro de una ventana corta se consideran duplicados del primero.",
|
||||
"tunable": "No — lógica interna del dispatcher."
|
||||
},
|
||||
{
|
||||
@@ -339,7 +339,7 @@
|
||||
"<strong>Llamadores remotos.</strong> Cinco capas se apilan encima del rate-limiting: un shared secret en la cabecera <code>X-Webhook-Secret</code>, un timestamp de frescura en <code>X-ProxMenux-Timestamp</code> (rechazado si se desvía más allá de la ventana configurada), una búsqueda de caché de replay y una allowlist de IP opcional. El shared secret vive en la tabla de ajustes SQLite del Monitor — no en <code>/etc/pve/priv/notifications.cfg</code> — y se genera en el primer setup. Este camino existe para integraciones personalizadas que hacen POST desde fuera del host; el destino configurado por PVE nunca lo ejercita."
|
||||
],
|
||||
"practiceTitle": "En la práctica",
|
||||
"practiceBody": "El setup de PVE escribe el destino como <code>http://127.0.0.1:8008</code>, así que las notificaciones emitidas por PVE siempre pasan por el camino loopback con seguridad solo rate-limit. El camino de llamador remoto con shared secret es opt-in para integraciones personalizadas — apunta un servicio externo a <code>https://<host-monitor>:<port>/api/notifications/webhook</code> y suministra la cabecera <code>X-Webhook-Secret</code> para usarlo.",
|
||||
"practiceBody": "El setup de PVE escribe el destino como <code>http://127.0.0.1:8008</code>, así que las notificaciones emitidas por PVE siempre pasan por el camino loopback con seguridad solo rate-limit. El camino de llamador remoto con shared secret es opt-in para integraciones personalizadas — apunta un servicio externo a <code>https://<monitor-host>:<port>/api/notifications/webhook</code> y suministra la cabecera <code>X-Webhook-Secret</code> para usarlo.",
|
||||
"actionsIntro": "El Monitor gestiona este destino a través de tres acciones en la pestaña Settings:",
|
||||
"actionsItems": [
|
||||
"<strong>Setup</strong> — corre automáticamente cuando activas Notifications. Crea la entrada en <code>/etc/pve/notifications.cfg</code>. El archivo solo se escribe cuando su contenido tiene que cambiar, y se guarda un backup del anterior en <code>/usr/local/share/proxmenux/backups/pve-notifications/</code> (los tres más recientes). No se escribe nada mientras <code>/etc/pve</code> no está montado: un Monitor que arranca durante un reinicio de <code>pve-cluster</code> registra la entrada cuando vuelve.",
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
"table": {
|
||||
"headers": ["Tipo", "Identificación", "Validación"],
|
||||
"rows": [
|
||||
["Intel/AMD DRM", "<code>/dev/dri/renderD*</code> y <code>/sys/class/drm/NODO/device/vendor</code>", "Un dispositivo de caracteres con fabricante <code>0x8086</code> (Intel) o <code>0x1002</code> (AMD)"],
|
||||
["Intel/AMD DRM", "<code>/dev/dri/renderD*</code> y <code>/sys/class/drm/NODE/device/vendor</code>", "Un dispositivo de caracteres con fabricante <code>0x8086</code> (Intel) o <code>0x1002</code> (AMD)"],
|
||||
["OpenCL AMD", "El render node, más <code>/dev/kfd</code> cuando el perfil lo necesita", "Existencia, tipo, fabricante, permisos y compatibilidad declarada"],
|
||||
["AMD ROCm", "El nodo de render, <code>/dev/kfd</code> y la generación que declara el driver de cómputo en <code>/sys/class/kfd/kfd/topology/nodes/*/properties</code>", "Una generación para la que la imagen ROCm de la aplicación trae kernels, las GPU RDNA2 que incluye y las posteriores, se ofrece tal cual. Las demás GPU de esas familias, como las Radeon 680M y 780M, se ofrecen como experimentales y nunca son la opción propuesta: ROCm no las soporta oficialmente, la aplicación las presenta como la generación de su familia (<code>HSA_OVERRIDE_GFX_VERSION</code>) y el instalador pide confirmación antes de descargar la imagen, que es más grande. Una GPU anterior, como los gráficos integrados de un Ryzen 5000U, no se ofrece e Immich deja el reconocimiento en la CPU"],
|
||||
["NVIDIA", "<code>nvidia-smi</code> y <code>nvidia-container-cli</code>", "GPU, UUID, bus PCI, versión del driver, Toolkit, nodos <code>/dev/nvidia*</code>, binarios y librerías"],
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
"items": [
|
||||
{ "title": "Contenedor y remoto", "body": "El VMID del contenedor Rclone, el nombre exacto del remoto y, opcionalmente, una ruta dentro de él." },
|
||||
{ "title": "Nombre y caché", "body": "El nombre del montaje y el modo de caché VFS: <code>off</code>, <code>minimal</code>, <code>writes</code> o <code>full</code> (por defecto)." },
|
||||
{ "title": "Vistas publicadas", "body": "Una raíz común, <code>/mnt/oci-shared</code> por defecto, contiene una vista de lectura y escritura en <code>/mnt/oci-shared/remotes/NOMBRE</code> y una de solo lectura en <code>/mnt/oci-shared/remotes-ro/NOMBRE</code>." },
|
||||
{ "title": "Vistas publicadas", "body": "Una raíz común, <code>/mnt/oci-shared</code> de forma predeterminada, contiene una vista de lectura y escritura en <code>/mnt/oci-shared/remotes/NAME</code> y otra de solo lectura en <code>/mnt/oci-shared/remotes-ro/NAME</code>." },
|
||||
{ "title": "Activación", "body": "Tras una confirmación, el CT se detiene, se configuran su orden de arranque y un hookscript de Proxmox VE, y se vuelve a iniciar. La operación espera hasta que las dos vistas están montadas en el host." }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
"<code>SystemMaxUse=64M</code> / <code>RuntimeMaxUse=60M</code> — caps duros sobre el uso de disco/memoria del journal.",
|
||||
"<code>Compress=yes</code>, <code>Seal=no</code> — comprimir logs, saltar el forward-secure sealing (ahorra CPU).",
|
||||
"<code>MaxLevelStore=info</code> — almacenar info y superiores (requerido para el visor de logs del ProxMenux Monitor y para que Fail2Ban detecte fallos de autenticación SSH/Proxmox desde el journal).",
|
||||
"Rate-limits: <code>1000 eventos / 30 s</code> para prevenir flooding de logs.",
|
||||
"Límite de frecuencia: <code>1000 events / 30 s</code> para evitar una avalancha de registros.",
|
||||
"<code>ForwardToSyslog=no</code>, <code>ForwardToWall=no</code> — no duplicar mensajes a syslog ni broadcastear a consolas."
|
||||
],
|
||||
"tipTitle": "Por qué importa MaxLevelStore=info",
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
"<strong>Entrada del portal</strong> — escribe la IP o hostname del servidor del target iSCSI. Se asume el puerto <code>3260</code> a menos que escribas <code>host:port</code>.",
|
||||
"<strong>Descubrimiento de targets</strong> — ProxMenux llama a <code>iscsiadm --mode discovery --type sendtargets --portal <ip:port></code>. El servidor responde con cada IQN que permite ver a este initiator. Si el descubrimiento falla, el script muestra el error exacto de <code>iscsiadm</code> y lista las causas comunes (IP incorrecta, firewall, IQN del initiator no autorizado).",
|
||||
"<strong>Selección del target</strong> — si hay un solo target se selecciona automáticamente; con varios targets se muestra un menú.",
|
||||
"<strong>Storage ID</strong> — por defecto es <code>iscsi-<último segmento del IQN, máx. 20 caracteres></code>. Solo letras, dígitos, <code>-</code> y <code>_</code>.",
|
||||
"<strong>Storage ID</strong> — por defecto es <code>iscsi-<last IQN segment, 20 chars max></code>. Solo letras, dígitos, <code>-</code> y <code>_</code>.",
|
||||
"<strong>Content type</strong> — a diferencia de NFS / Samba, el contenido iSCSI está <strong>fijado a <code>images</code></strong>. iSCSI expone dispositivos de bloque raw, no un sistema de archivos, así que Proxmox solo te deja alojar discos de VM ahí."
|
||||
],
|
||||
"authTitle": "Autorizar el initiator de Proxmox en el target",
|
||||
|
||||
@@ -129,7 +129,7 @@
|
||||
},
|
||||
"troubleshoot": {
|
||||
"heading": "Solución de problemas",
|
||||
"noMountTitle": "El montaje aparece en la config del pct pero no dentro del contenedor",
|
||||
"noMountTitle": "El montaje aparece en pct config, pero no dentro del contenedor",
|
||||
"noMountBody": "Los bind mounts solo se adjuntan cuando el contenedor arranca. Si añadiste el montaje mientras el CT estaba corriendo, reinícialo (<code>pct reboot <ctid></code>). Si ya está reiniciado y sigue faltando, comprueba <code>pct config <ctid></code> para confirmar que la entrada existe y que la ruta del host realmente contiene un directorio.",
|
||||
"noWriteTitle": "El contenedor puede ver el directorio pero no puede escribir",
|
||||
"noWriteBody": "Casi siempre un problema de permisos. Para contenedores unprivileged, ejecuta de nuevo el fix de permisos del script — las ACLs del directorio del host pueden haber sido reseteadas por otra herramienta (rsync, restore desde backup, <code>chmod</code> manual). Para CIFS, revisa las opciones de montaje en el host: <code>findmnt /mnt/pve/cifs-…</code>, busca valores <code>uid=</code> / <code>gid=</code> / <code>file_mode=</code>.",
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
{
|
||||
"site": {
|
||||
"name": "ProxMenux",
|
||||
"tagline": "Menu interactif et tableau de bord web pour Proxmox VE"
|
||||
},
|
||||
"nav": {
|
||||
"home": "Accueil",
|
||||
"docs": "Documentation",
|
||||
"documentation": "Documentation",
|
||||
"guides": "Guides",
|
||||
"changelog": "Journal des modifications",
|
||||
"github": "GitHub",
|
||||
"rss": "RSS",
|
||||
"rssTitle": "Flux RSS",
|
||||
"menuOpen": "Ouvrir le menu"
|
||||
},
|
||||
"footer": {
|
||||
"sponsorHeading": "Soutenir le projet",
|
||||
"sponsorBody": "Si vous souhaitez soutenir le projet.",
|
||||
"sponsorAlt": "Soutenez-moi sur Ko-fi",
|
||||
"connectHeading": "Communauté",
|
||||
"connectBody": "Rejoignez les discussions de la communauté sur GitHub pour obtenir de l’aide, partager vos idées et contribuer au projet. Toutes les idées sont les bienvenues !",
|
||||
"joinDiscussion": "Participer à la discussion",
|
||||
"copyrightPrefix": "ProxMenux, un projet collaboratif et open source créé par",
|
||||
"copyrightSuffix": "."
|
||||
},
|
||||
"language": {
|
||||
"switcher": "Langue",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"sk": "Slovenčina",
|
||||
"de": "Deutsch",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"pt": "Português",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"resources": {
|
||||
"documentation": {
|
||||
"title": "Documentation",
|
||||
"description": "Présentation du système et guides d’utilisation"
|
||||
},
|
||||
"changelog": {
|
||||
"title": "Journal des modifications",
|
||||
"description": "Informations sur les dernières mises à jour"
|
||||
},
|
||||
"guides": {
|
||||
"title": "Guides",
|
||||
"description": "Tutoriels et guides pas à pas pour les tâches courantes"
|
||||
},
|
||||
"github": {
|
||||
"title": "Dépôt GitHub",
|
||||
"description": "Consultez le code source."
|
||||
}
|
||||
},
|
||||
"docSidebar": {
|
||||
"documentation": "Documentation",
|
||||
"items": {
|
||||
"introduction": "Introduction",
|
||||
"installation": "Installation",
|
||||
"proxmenuxMonitor": "ProxMenux Monitor",
|
||||
"monitorOverview": "Vue d’ensemble",
|
||||
"architecture": "Architecture",
|
||||
"accessAuth": "Accès et authentification",
|
||||
"dashboard": "Tableau de bord",
|
||||
"dashboardSystemOverview": "Onglet Vue d’ensemble du système",
|
||||
"dashboardApps": "Onglet Applications",
|
||||
"dashboardStorage": "Onglet Stockage",
|
||||
"dashboardNetwork": "Onglet Réseau",
|
||||
"dashboardVmsLxcs": "Onglet VM et LXC",
|
||||
"dashboardVmsLxcsApp": "Application",
|
||||
"dashboardVmsLxcsUpdates": "Mises à jour",
|
||||
"dashboardHardware": "Onglet Matériel",
|
||||
"dashboardSystemLogs": "Onglet Journaux système",
|
||||
"dashboardTerminal": "Onglet Terminal",
|
||||
"dashboardSecurity": "Onglet Sécurité",
|
||||
"dashboardSettings": "Onglet Paramètres",
|
||||
"healthMonitor": "Surveillance de l’état du système",
|
||||
"auditReport": "Audit et rapports",
|
||||
"auditReportOverview": "Vue d’ensemble",
|
||||
"auditReportAssessment": "Évaluation et inventaire",
|
||||
"auditReportPolicy": "Politique",
|
||||
"auditReportChanges": "Modifications",
|
||||
"auditReportReports": "Rapports et comparaisons",
|
||||
"auditReportScope": "Périmètre et garanties",
|
||||
"notifications": "Notifications",
|
||||
"aiAssistant": "Assistant IA",
|
||||
"apiReference": "Référence de l’API",
|
||||
"integrations": "Intégrations",
|
||||
"ociManager": "OCI manager Apps",
|
||||
"ociOverview": "Vue d’ensemble",
|
||||
"ociArchitecture": "Comment une image OCI est adaptée",
|
||||
"ociCustomImage": "Image absente du catalogue",
|
||||
"ociStorageNetwork": "Données, chemins et réseau",
|
||||
"ociHardware": "Périphériques et accélération",
|
||||
"ociStacks": "Applications à plusieurs conteneurs",
|
||||
"ociLifecycle": "Installer, mettre à jour et modifier",
|
||||
"ociMonitor": "Dans ProxMenux Monitor",
|
||||
"proxmenuxScripts": "ProxMenux Scripts",
|
||||
"postInstallScript": "Script de post-installation",
|
||||
"postInstallOverview": "Vue d’ensemble",
|
||||
"postInstallAutomated": "Automatique",
|
||||
"postInstallCustomizable": "Personnalisable",
|
||||
"postInstallBasicSettings": "Paramètres de base",
|
||||
"postInstallSystem": "Système",
|
||||
"postInstallVirtualization": "Virtualisation",
|
||||
"postInstallNetwork": "Réseau",
|
||||
"postInstallStorage": "Stockage",
|
||||
"postInstallSecurity": "Sécurité",
|
||||
"postInstallCustomization": "Personnalisation",
|
||||
"postInstallMonitoring": "Surveillance",
|
||||
"postInstallPerformance": "Performances",
|
||||
"postInstallOptional": "Facultatif",
|
||||
"postInstallUpdates": "Appliquer les mises à jour disponibles",
|
||||
"postInstallUninstall": "Supprimer les optimisations",
|
||||
"gpusCoralTpu": "GPU et Coral TPU",
|
||||
"nvidiaHost": "Installer les pilotes NVIDIA sur l’hôte",
|
||||
"coralHost": "Installer Coral TPU sur l’hôte",
|
||||
"addGpuLxc": "Donner accès à un GPU dans un LXC",
|
||||
"addCoralLxc": "Donner accès à Coral TPU dans un LXC",
|
||||
"addGpuVm": "Attribuer un GPU à une VM (passthrough)",
|
||||
"switchGpuMode": "Changer le mode du GPU (VM ↔ LXC)",
|
||||
"createVm": "Créer une VM",
|
||||
"createVmOverview": "Vue d’ensemble",
|
||||
"createVmSystemNas": "Systèmes NAS",
|
||||
"createVmSynology": "VM Synology",
|
||||
"createVmNasOthers": "Autres systèmes NAS",
|
||||
"createVmSystemWindows": "Systèmes Windows",
|
||||
"createVmSystemLinux": "Systèmes Linux",
|
||||
"diskManager": "Gestionnaire de disques",
|
||||
"diskManagerOverview": "Vue d’ensemble",
|
||||
"diskImportVm": "Importer un disque dans une VM",
|
||||
"diskImportImageVm": "Importer une image disque dans une VM",
|
||||
"diskAddController": "Ajouter un contrôleur ou un périphérique NVMe à une VM",
|
||||
"diskImportLxc": "Importer un disque dans un LXC",
|
||||
"diskFormat": "Formater ou effacer un disque physique",
|
||||
"diskSmart": "État SMART et tests du disque",
|
||||
"storageShareManager": "Gestion du stockage et des partages",
|
||||
"storageShareOverview": "Vue d’ensemble",
|
||||
"hostStorage": "Intégration du stockage à l’hôte",
|
||||
"hostNfs": "Ajouter un partage NFS comme stockage Proxmox",
|
||||
"hostSamba": "Ajouter un partage Samba comme stockage Proxmox",
|
||||
"hostIscsi": "Ajouter une cible iSCSI comme stockage Proxmox",
|
||||
"hostLocalDisk": "Ajouter un disque local comme stockage Proxmox",
|
||||
"hostLocalShared": "Créer un répertoire partagé sur l’hôte",
|
||||
"lxcMountPoints": "Points de montage LXC (hôte ↔ CT)",
|
||||
"lxcNetworkSharing": "Partages réseau dans LXC",
|
||||
"lxcNfsClient": "Client NFS dans LXC",
|
||||
"lxcSambaClient": "Client Samba dans LXC",
|
||||
"lxcNfsServer": "Serveur NFS dans LXC",
|
||||
"lxcSambaServer": "Serveur Samba dans LXC",
|
||||
"network": "Réseau",
|
||||
"networkOverview": "Vue d’ensemble",
|
||||
"networkDiagnostics": "Diagnostic",
|
||||
"networkMonitoring": "Outils de surveillance en temps réel",
|
||||
"networkBridge": "Analyse et réparation des ponts réseau",
|
||||
"networkConfig": "Analyse et nettoyage de la configuration",
|
||||
"networkPersistent": "Noms persistants des interfaces",
|
||||
"networkBackup": "Sauvegarde et redémarrage des interfaces",
|
||||
"security": "Sécurité",
|
||||
"securityOverview": "Vue d’ensemble",
|
||||
"securityFail2ban": "Fail2Ban",
|
||||
"securityLynis": "Lynis",
|
||||
"utilities": "Utilitaires",
|
||||
"utilsOverview": "Vue d’ensemble",
|
||||
"utilsUupDump": "Création d’ISO avec UUP Dump",
|
||||
"utilsSystemUtils": "Installation d’utilitaires système",
|
||||
"utilsSystemUpdate": "Mise à jour du système Proxmox",
|
||||
"utilsUpgradePve": "Passer de PVE 8 à PVE 9",
|
||||
"utilsExportVm": "Exporter une VM au format OVA/OVF",
|
||||
"utilsImportVm": "Importer une VM depuis OVA/OVF",
|
||||
"settingsProxmenux": "Paramètres de ProxMenux",
|
||||
"settingsOverview": "Vue d’ensemble",
|
||||
"settingsMonitor": "ProxMenux Monitor",
|
||||
"settingsBeta": "Changer de canal de publication",
|
||||
"settingsVersion": "Afficher les informations de version",
|
||||
"settingsUninstall": "Désinstaller ProxMenux",
|
||||
"commandsReference": "Référence des commandes",
|
||||
"commandsOverview": "Vue d’ensemble",
|
||||
"commandsSystem": "Commandes système utiles",
|
||||
"commandsVmCt": "Gestion des VM et CT",
|
||||
"commandsStorage": "Stockage et disques",
|
||||
"commandsNetwork": "Commandes réseau",
|
||||
"commandsUpdates": "Mises à jour et paquets",
|
||||
"commandsGpu": "Passthrough GPU",
|
||||
"commandsZfs": "Gestion de ZFS",
|
||||
"commandsBackup": "Sauvegarde et restauration",
|
||||
"commandsTools": "Outils système en ligne de commande",
|
||||
"glossary": "Glossaire",
|
||||
"about": "À propos",
|
||||
"aboutOverview": "Vue d’ensemble",
|
||||
"aboutFaq": "FAQ",
|
||||
"aboutContributors": "Contributeurs",
|
||||
"aboutContributing": "Contribuer",
|
||||
"aboutCodeOfConduct": "Code de conduite",
|
||||
"externalRepositories": "Dépôts externes",
|
||||
"backupRestore": "Sauvegarde et restauration",
|
||||
"backupRestoreOverview": "Vue d’ensemble",
|
||||
"backupRestoreHowItWorks": "Fonctionnement",
|
||||
"backupRestoreDestinations": "Destinations",
|
||||
"backupRestoreDestOverview": "Vue d’ensemble",
|
||||
"backupRestoreDestLocal": "Archive locale",
|
||||
"backupRestoreDestPbs": "Proxmox Backup Server",
|
||||
"backupRestoreDestBorg": "Borg",
|
||||
"backupRestoreCreating": "Créer des sauvegardes",
|
||||
"backupRestoreJobs": "Tâches planifiées",
|
||||
"backupRestoreRestoring": "Restaurer",
|
||||
"backupRestoreCrossKernel": "Restauration entre versions du noyau",
|
||||
"backupRestoreGlossary": "Glossaire"
|
||||
}
|
||||
},
|
||||
"hero": {
|
||||
"title": "ProxMenux",
|
||||
"tagline": "Un menu interactif et un tableau de bord web pour Proxmox VE",
|
||||
"description": "ProxMenux réunit un menu interactif et un tableau de bord web pour Proxmox VE. Exécutez des commandes, des scripts et des assistants depuis le terminal, ou consultez l’état de l’hôte, ses métriques et ses notifications dans un navigateur.",
|
||||
"installButton": "Installer maintenant",
|
||||
"whatIsButton": "Qu’est-ce que ProxMenux ?",
|
||||
"logoAlt": "Logo ProxMenux"
|
||||
},
|
||||
"docNav": {
|
||||
"previous": "Précédent",
|
||||
"next": "Suivant"
|
||||
},
|
||||
"tocPanel": {
|
||||
"onThisPage": "Sur cette page"
|
||||
},
|
||||
"supportProject": {
|
||||
"heading": "Soutenez le projet !",
|
||||
"body": "Si <strong>ProxMenux</strong> vous est utile, donnez-lui une ⭐ sur GitHub pour aider d’autres personnes à le découvrir.",
|
||||
"button": "Ajouter une étoile sur GitHub"
|
||||
},
|
||||
"rssLink": {
|
||||
"heading": "Suivez les nouveautés !",
|
||||
"body": "Abonnez-vous à notre flux RSS pour être informé des nouveautés.",
|
||||
"copy": "Copier",
|
||||
"copied": "Copié !",
|
||||
"copyTitle": "Copier l’URL du flux RSS",
|
||||
"openFeed": "Ouvrir le flux RSS",
|
||||
"openTitle": "Ouvrir le flux RSS"
|
||||
},
|
||||
"changelog": {
|
||||
"pageTitle": "Journal des modifications",
|
||||
"meta": {
|
||||
"title": "Journal des modifications de ProxMenux",
|
||||
"titleSuffix": "Notes de version",
|
||||
"latest": "Dernière version",
|
||||
"mostRecent": "Version la plus récente",
|
||||
"description": "Notes de version et historique des mises à jour de ProxMenux, le script à menus pour administrer Proxmox VE.",
|
||||
"descriptionTail": "Nouvelles fonctionnalités, corrections de bugs, mises à jour de sécurité, améliorations de ProxMenux Monitor, compatibilité avec les fournisseurs d’IA, sécurisation du passthrough GPU et bien plus.",
|
||||
"ogDescription": "Notes de version de ProxMenux.",
|
||||
"ogTail": "Abonnez-vous au flux RSS ou revenez consulter les nouvelles versions."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
{
|
||||
"site": {
|
||||
"name": "ProxMenux",
|
||||
"tagline": "Menu interattivo e dashboard web per Proxmox VE"
|
||||
},
|
||||
"nav": {
|
||||
"home": "Home",
|
||||
"docs": "Documentazione",
|
||||
"documentation": "Documentazione",
|
||||
"guides": "Guide",
|
||||
"changelog": "Registro delle modifiche",
|
||||
"github": "GitHub",
|
||||
"rss": "RSS",
|
||||
"rssTitle": "Feed RSS",
|
||||
"menuOpen": "Apri menu"
|
||||
},
|
||||
"footer": {
|
||||
"sponsorHeading": "Sostieni il progetto",
|
||||
"sponsorBody": "Se desideri sostenere il progetto.",
|
||||
"sponsorAlt": "Sostienimi su Ko-fi",
|
||||
"connectHeading": "Community",
|
||||
"connectBody": "Partecipa alle discussioni della community su GitHub per ricevere aiuto, condividere idee e contribuire al progetto. Ogni idea è benvenuta!",
|
||||
"joinDiscussion": "Partecipa alla discussione",
|
||||
"copyrightPrefix": "ProxMenux, un progetto collaborativo e open source di",
|
||||
"copyrightSuffix": "."
|
||||
},
|
||||
"language": {
|
||||
"switcher": "Lingua",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"sk": "Slovenčina",
|
||||
"de": "Deutsch",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"pt": "Português",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"resources": {
|
||||
"documentation": {
|
||||
"title": "Documentazione",
|
||||
"description": "Descrizione del sistema e guide per l’utente"
|
||||
},
|
||||
"changelog": {
|
||||
"title": "Registro delle modifiche",
|
||||
"description": "Informazioni sugli ultimi aggiornamenti"
|
||||
},
|
||||
"guides": {
|
||||
"title": "Guide",
|
||||
"description": "Tutorial e guide passo passo per le attività più comuni"
|
||||
},
|
||||
"github": {
|
||||
"title": "Repository GitHub",
|
||||
"description": "Esplora il codice sorgente."
|
||||
}
|
||||
},
|
||||
"docSidebar": {
|
||||
"documentation": "Documentazione",
|
||||
"items": {
|
||||
"introduction": "Introduzione",
|
||||
"installation": "Installazione",
|
||||
"proxmenuxMonitor": "ProxMenux Monitor",
|
||||
"monitorOverview": "Panoramica",
|
||||
"architecture": "Architettura",
|
||||
"accessAuth": "Accesso e autenticazione",
|
||||
"dashboard": "Dashboard",
|
||||
"dashboardSystemOverview": "Scheda Panoramica del sistema",
|
||||
"dashboardApps": "Scheda App",
|
||||
"dashboardStorage": "Scheda Archiviazione",
|
||||
"dashboardNetwork": "Scheda Rete",
|
||||
"dashboardVmsLxcs": "Scheda VM e LXC",
|
||||
"dashboardVmsLxcsApp": "App",
|
||||
"dashboardVmsLxcsUpdates": "Aggiornamenti",
|
||||
"dashboardHardware": "Scheda Hardware",
|
||||
"dashboardSystemLogs": "Scheda Log di sistema",
|
||||
"dashboardTerminal": "Scheda Terminale",
|
||||
"dashboardSecurity": "Scheda Sicurezza",
|
||||
"dashboardSettings": "Scheda Impostazioni",
|
||||
"healthMonitor": "Monitoraggio dello stato",
|
||||
"auditReport": "Verifica e report",
|
||||
"auditReportOverview": "Panoramica",
|
||||
"auditReportAssessment": "Valutazione e inventario",
|
||||
"auditReportPolicy": "Criteri",
|
||||
"auditReportChanges": "Modifiche",
|
||||
"auditReportReports": "Report e confronti",
|
||||
"auditReportScope": "Ambito e garanzie",
|
||||
"notifications": "Notifiche",
|
||||
"aiAssistant": "Assistente IA",
|
||||
"apiReference": "Riferimento API",
|
||||
"integrations": "Integrazioni",
|
||||
"ociManager": "OCI manager Apps",
|
||||
"ociOverview": "Panoramica",
|
||||
"ociArchitecture": "Come viene adattata un’immagine OCI",
|
||||
"ociCustomImage": "Immagine non presente nel catalogo",
|
||||
"ociStorageNetwork": "Dati, percorsi e rete",
|
||||
"ociHardware": "Dispositivi e accelerazione",
|
||||
"ociStacks": "Applicazioni con più container",
|
||||
"ociLifecycle": "Installazione, aggiornamento e modifica",
|
||||
"ociMonitor": "In ProxMenux Monitor",
|
||||
"proxmenuxScripts": "ProxMenux Scripts",
|
||||
"postInstallScript": "Script di post-installazione",
|
||||
"postInstallOverview": "Panoramica",
|
||||
"postInstallAutomated": "Automatico",
|
||||
"postInstallCustomizable": "Personalizzabile",
|
||||
"postInstallBasicSettings": "Impostazioni di base",
|
||||
"postInstallSystem": "Sistema",
|
||||
"postInstallVirtualization": "Virtualizzazione",
|
||||
"postInstallNetwork": "Rete",
|
||||
"postInstallStorage": "Archiviazione",
|
||||
"postInstallSecurity": "Sicurezza",
|
||||
"postInstallCustomization": "Personalizzazione",
|
||||
"postInstallMonitoring": "Monitoraggio",
|
||||
"postInstallPerformance": "Prestazioni",
|
||||
"postInstallOptional": "Facoltativo",
|
||||
"postInstallUpdates": "Applica gli aggiornamenti disponibili",
|
||||
"postInstallUninstall": "Rimuovi le ottimizzazioni",
|
||||
"gpusCoralTpu": "GPU e Coral TPU",
|
||||
"nvidiaHost": "Installa i driver NVIDIA sull’host",
|
||||
"coralHost": "Installa Coral TPU sull’host",
|
||||
"addGpuLxc": "Abilita una GPU in un LXC",
|
||||
"addCoralLxc": "Abilita Coral TPU in un LXC",
|
||||
"addGpuVm": "Assegna una GPU a una VM (passthrough)",
|
||||
"switchGpuMode": "Cambia modalità GPU (VM ↔ LXC)",
|
||||
"createVm": "Crea una VM",
|
||||
"createVmOverview": "Panoramica",
|
||||
"createVmSystemNas": "Sistemi NAS",
|
||||
"createVmSynology": "VM Synology",
|
||||
"createVmNasOthers": "Altri sistemi NAS",
|
||||
"createVmSystemWindows": "Sistemi Windows",
|
||||
"createVmSystemLinux": "Sistemi Linux",
|
||||
"diskManager": "Gestione dischi",
|
||||
"diskManagerOverview": "Panoramica",
|
||||
"diskImportVm": "Importa un disco in una VM",
|
||||
"diskImportImageVm": "Importa un’immagine disco in una VM",
|
||||
"diskAddController": "Aggiungi un controller o un dispositivo NVMe a una VM",
|
||||
"diskImportLxc": "Importa un disco in un LXC",
|
||||
"diskFormat": "Formatta o cancella un disco fisico",
|
||||
"diskSmart": "Stato SMART e test del disco",
|
||||
"storageShareManager": "Gestione archiviazione e condivisioni",
|
||||
"storageShareOverview": "Panoramica",
|
||||
"hostStorage": "Integrazione dell’archiviazione nell’host",
|
||||
"hostNfs": "Aggiungi una condivisione NFS come storage Proxmox",
|
||||
"hostSamba": "Aggiungi una condivisione Samba come storage Proxmox",
|
||||
"hostIscsi": "Aggiungi una destinazione iSCSI come storage Proxmox",
|
||||
"hostLocalDisk": "Aggiungi un disco locale come storage Proxmox",
|
||||
"hostLocalShared": "Crea una directory condivisa sull’host",
|
||||
"lxcMountPoints": "Punti di montaggio LXC (host ↔ CT)",
|
||||
"lxcNetworkSharing": "Condivisioni di rete in LXC",
|
||||
"lxcNfsClient": "Client NFS in LXC",
|
||||
"lxcSambaClient": "Client Samba in LXC",
|
||||
"lxcNfsServer": "Server NFS in LXC",
|
||||
"lxcSambaServer": "Server Samba in LXC",
|
||||
"network": "Rete",
|
||||
"networkOverview": "Panoramica",
|
||||
"networkDiagnostics": "Diagnostica",
|
||||
"networkMonitoring": "Strumenti di monitoraggio in tempo reale",
|
||||
"networkBridge": "Analisi e riparazione dei bridge di rete",
|
||||
"networkConfig": "Analisi e pulizia della configurazione",
|
||||
"networkPersistent": "Nomi persistenti delle interfacce",
|
||||
"networkBackup": "Backup e riavvio delle interfacce",
|
||||
"security": "Sicurezza",
|
||||
"securityOverview": "Panoramica",
|
||||
"securityFail2ban": "Fail2Ban",
|
||||
"securityLynis": "Lynis",
|
||||
"utilities": "Utilità",
|
||||
"utilsOverview": "Panoramica",
|
||||
"utilsUupDump": "Creazione di ISO con UUP Dump",
|
||||
"utilsSystemUtils": "Installazione di utilità di sistema",
|
||||
"utilsSystemUpdate": "Aggiornamento del sistema Proxmox",
|
||||
"utilsUpgradePve": "Passaggio da PVE 8 a PVE 9",
|
||||
"utilsExportVm": "Esporta una VM in OVA/OVF",
|
||||
"utilsImportVm": "Importa una VM da OVA/OVF",
|
||||
"settingsProxmenux": "Impostazioni di ProxMenux",
|
||||
"settingsOverview": "Panoramica",
|
||||
"settingsMonitor": "ProxMenux Monitor",
|
||||
"settingsBeta": "Cambia canale di rilascio",
|
||||
"settingsVersion": "Mostra informazioni sulla versione",
|
||||
"settingsUninstall": "Disinstalla ProxMenux",
|
||||
"commandsReference": "Riferimento dei comandi",
|
||||
"commandsOverview": "Panoramica",
|
||||
"commandsSystem": "Comandi di sistema utili",
|
||||
"commandsVmCt": "Gestione di VM e CT",
|
||||
"commandsStorage": "Archiviazione e dischi",
|
||||
"commandsNetwork": "Comandi di rete",
|
||||
"commandsUpdates": "Aggiornamenti e pacchetti",
|
||||
"commandsGpu": "Passthrough GPU",
|
||||
"commandsZfs": "Gestione di ZFS",
|
||||
"commandsBackup": "Backup e ripristino",
|
||||
"commandsTools": "Strumenti di sistema da riga di comando",
|
||||
"glossary": "Glossario",
|
||||
"about": "Informazioni sul progetto",
|
||||
"aboutOverview": "Panoramica",
|
||||
"aboutFaq": "FAQ",
|
||||
"aboutContributors": "Collaboratori",
|
||||
"aboutContributing": "Come contribuire",
|
||||
"aboutCodeOfConduct": "Codice di condotta",
|
||||
"externalRepositories": "Repository esterni",
|
||||
"backupRestore": "Backup e ripristino",
|
||||
"backupRestoreOverview": "Panoramica",
|
||||
"backupRestoreHowItWorks": "Come funziona",
|
||||
"backupRestoreDestinations": "Destinazioni",
|
||||
"backupRestoreDestOverview": "Panoramica",
|
||||
"backupRestoreDestLocal": "Archivio locale",
|
||||
"backupRestoreDestPbs": "Proxmox Backup Server",
|
||||
"backupRestoreDestBorg": "Borg",
|
||||
"backupRestoreCreating": "Creare backup",
|
||||
"backupRestoreJobs": "Attività pianificate",
|
||||
"backupRestoreRestoring": "Ripristino",
|
||||
"backupRestoreCrossKernel": "Ripristino tra versioni del kernel",
|
||||
"backupRestoreGlossary": "Glossario"
|
||||
}
|
||||
},
|
||||
"hero": {
|
||||
"title": "ProxMenux",
|
||||
"tagline": "Un menu interattivo e una dashboard web per Proxmox VE",
|
||||
"description": "ProxMenux unisce un menu interattivo e una dashboard web per Proxmox VE. Esegui comandi, script e procedure guidate dal terminale oppure controlla lo stato dell’host, le metriche e le notifiche dal browser.",
|
||||
"installButton": "Installa ora",
|
||||
"whatIsButton": "Che cos’è ProxMenux?",
|
||||
"logoAlt": "Logo di ProxMenux"
|
||||
},
|
||||
"docNav": {
|
||||
"previous": "Precedente",
|
||||
"next": "Successivo"
|
||||
},
|
||||
"tocPanel": {
|
||||
"onThisPage": "In questa pagina"
|
||||
},
|
||||
"supportProject": {
|
||||
"heading": "Sostieni il progetto!",
|
||||
"body": "Se <strong>ProxMenux</strong> ti è utile, lascia una ⭐ su GitHub per aiutare altre persone a scoprirlo.",
|
||||
"button": "Lascia una stella su GitHub"
|
||||
},
|
||||
"rssLink": {
|
||||
"heading": "Resta aggiornato!",
|
||||
"body": "Iscriviti al feed RSS per ricevere le novità.",
|
||||
"copy": "Copia",
|
||||
"copied": "Copiato!",
|
||||
"copyTitle": "Copia l’URL del feed RSS",
|
||||
"openFeed": "Apri il feed RSS",
|
||||
"openTitle": "Apri il feed RSS"
|
||||
},
|
||||
"changelog": {
|
||||
"pageTitle": "Registro delle modifiche",
|
||||
"meta": {
|
||||
"title": "Registro delle modifiche di ProxMenux",
|
||||
"titleSuffix": "Note di rilascio",
|
||||
"latest": "Ultima versione",
|
||||
"mostRecent": "Versione più recente",
|
||||
"description": "Note di rilascio e cronologia degli aggiornamenti di ProxMenux, lo script a menu per gestire Proxmox VE.",
|
||||
"descriptionTail": "Nuove funzionalità, correzioni di bug, aggiornamenti di sicurezza, miglioramenti di ProxMenux Monitor, compatibilità con i fornitori IA, maggiore sicurezza del passthrough GPU e altro.",
|
||||
"ogDescription": "Note di rilascio di ProxMenux.",
|
||||
"ogTail": "Iscriviti al feed RSS o torna su questa pagina per le nuove versioni."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
{
|
||||
"site": {
|
||||
"name": "ProxMenux",
|
||||
"tagline": "Menu interativo e painel web para o Proxmox VE"
|
||||
},
|
||||
"nav": {
|
||||
"home": "Início",
|
||||
"docs": "Documentação",
|
||||
"documentation": "Documentação",
|
||||
"guides": "Guias",
|
||||
"changelog": "Histórico de alterações",
|
||||
"github": "GitHub",
|
||||
"rss": "RSS",
|
||||
"rssTitle": "Feed RSS",
|
||||
"menuOpen": "Abrir menu"
|
||||
},
|
||||
"footer": {
|
||||
"sponsorHeading": "Apoiar o projeto",
|
||||
"sponsorBody": "Se quiser apoiar o projeto.",
|
||||
"sponsorAlt": "Apoie-me no Ko-fi",
|
||||
"connectHeading": "Comunidade",
|
||||
"connectBody": "Participe nas discussões da comunidade no GitHub para obter ajuda, partilhar ideias e contribuir para o projeto. Todas as ideias são bem-vindas!",
|
||||
"joinDiscussion": "Participar na discussão",
|
||||
"copyrightPrefix": "ProxMenux, um projeto colaborativo e de código aberto criado por",
|
||||
"copyrightSuffix": "."
|
||||
},
|
||||
"language": {
|
||||
"switcher": "Idioma",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"sk": "Slovenčina",
|
||||
"de": "Deutsch",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"pt": "Português",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"resources": {
|
||||
"documentation": {
|
||||
"title": "Documentação",
|
||||
"description": "Descrição do sistema e guias de utilização"
|
||||
},
|
||||
"changelog": {
|
||||
"title": "Histórico de alterações",
|
||||
"description": "Informações sobre as últimas atualizações"
|
||||
},
|
||||
"guides": {
|
||||
"title": "Guias",
|
||||
"description": "Tutoriais e guias passo a passo para tarefas comuns"
|
||||
},
|
||||
"github": {
|
||||
"title": "Repositório do GitHub",
|
||||
"description": "Explore o código-fonte."
|
||||
}
|
||||
},
|
||||
"docSidebar": {
|
||||
"documentation": "Documentação",
|
||||
"items": {
|
||||
"introduction": "Introdução",
|
||||
"installation": "Instalação",
|
||||
"proxmenuxMonitor": "ProxMenux Monitor",
|
||||
"monitorOverview": "Visão geral",
|
||||
"architecture": "Arquitetura",
|
||||
"accessAuth": "Acesso e autenticação",
|
||||
"dashboard": "Painel",
|
||||
"dashboardSystemOverview": "Separador Visão geral do sistema",
|
||||
"dashboardApps": "Separador Aplicações",
|
||||
"dashboardStorage": "Separador Armazenamento",
|
||||
"dashboardNetwork": "Separador Rede",
|
||||
"dashboardVmsLxcs": "Separador VM e LXC",
|
||||
"dashboardVmsLxcsApp": "Aplicação",
|
||||
"dashboardVmsLxcsUpdates": "Atualizações",
|
||||
"dashboardHardware": "Separador Hardware",
|
||||
"dashboardSystemLogs": "Separador Registos do sistema",
|
||||
"dashboardTerminal": "Separador Terminal",
|
||||
"dashboardSecurity": "Separador Segurança",
|
||||
"dashboardSettings": "Separador Definições",
|
||||
"healthMonitor": "Monitor de estado",
|
||||
"auditReport": "Auditoria e relatórios",
|
||||
"auditReportOverview": "Visão geral",
|
||||
"auditReportAssessment": "Avaliação e inventário",
|
||||
"auditReportPolicy": "Política",
|
||||
"auditReportChanges": "Alterações",
|
||||
"auditReportReports": "Relatórios e comparações",
|
||||
"auditReportScope": "Âmbito e garantias",
|
||||
"notifications": "Notificações",
|
||||
"aiAssistant": "Assistente de IA",
|
||||
"apiReference": "Referência da API",
|
||||
"integrations": "Integrações",
|
||||
"ociManager": "OCI manager Apps",
|
||||
"ociOverview": "Visão geral",
|
||||
"ociArchitecture": "Como é adaptada uma imagem OCI",
|
||||
"ociCustomImage": "Imagem fora do catálogo",
|
||||
"ociStorageNetwork": "Dados, caminhos e rede",
|
||||
"ociHardware": "Dispositivos e aceleração",
|
||||
"ociStacks": "Aplicações com vários contentores",
|
||||
"ociLifecycle": "Instalar, atualizar e modificar",
|
||||
"ociMonitor": "No ProxMenux Monitor",
|
||||
"proxmenuxScripts": "ProxMenux Scripts",
|
||||
"postInstallScript": "Script de pós-instalação",
|
||||
"postInstallOverview": "Visão geral",
|
||||
"postInstallAutomated": "Automático",
|
||||
"postInstallCustomizable": "Personalizável",
|
||||
"postInstallBasicSettings": "Definições básicas",
|
||||
"postInstallSystem": "Sistema",
|
||||
"postInstallVirtualization": "Virtualização",
|
||||
"postInstallNetwork": "Rede",
|
||||
"postInstallStorage": "Armazenamento",
|
||||
"postInstallSecurity": "Segurança",
|
||||
"postInstallCustomization": "Personalização",
|
||||
"postInstallMonitoring": "Monitorização",
|
||||
"postInstallPerformance": "Desempenho",
|
||||
"postInstallOptional": "Opcional",
|
||||
"postInstallUpdates": "Aplicar as atualizações disponíveis",
|
||||
"postInstallUninstall": "Remover otimizações",
|
||||
"gpusCoralTpu": "GPU e Coral TPU",
|
||||
"nvidiaHost": "Instalar controladores NVIDIA no host",
|
||||
"coralHost": "Instalar Coral TPU no host",
|
||||
"addGpuLxc": "Disponibilizar uma GPU num LXC",
|
||||
"addCoralLxc": "Disponibilizar Coral TPU num LXC",
|
||||
"addGpuVm": "Atribuir uma GPU a uma VM (passthrough)",
|
||||
"switchGpuMode": "Alterar o modo da GPU (VM ↔ LXC)",
|
||||
"createVm": "Criar uma VM",
|
||||
"createVmOverview": "Visão geral",
|
||||
"createVmSystemNas": "Sistemas NAS",
|
||||
"createVmSynology": "VM Synology",
|
||||
"createVmNasOthers": "Outros sistemas NAS",
|
||||
"createVmSystemWindows": "Sistemas Windows",
|
||||
"createVmSystemLinux": "Sistemas Linux",
|
||||
"diskManager": "Gestor de discos",
|
||||
"diskManagerOverview": "Visão geral",
|
||||
"diskImportVm": "Importar um disco para uma VM",
|
||||
"diskImportImageVm": "Importar uma imagem de disco para uma VM",
|
||||
"diskAddController": "Adicionar um controlador ou dispositivo NVMe a uma VM",
|
||||
"diskImportLxc": "Importar um disco para um LXC",
|
||||
"diskFormat": "Formatar ou apagar um disco físico",
|
||||
"diskSmart": "Estado SMART e testes do disco",
|
||||
"storageShareManager": "Gestor de armazenamento e partilhas",
|
||||
"storageShareOverview": "Visão geral",
|
||||
"hostStorage": "Integração de armazenamento no host",
|
||||
"hostNfs": "Adicionar uma partilha NFS como armazenamento do Proxmox",
|
||||
"hostSamba": "Adicionar uma partilha Samba como armazenamento do Proxmox",
|
||||
"hostIscsi": "Adicionar um destino iSCSI como armazenamento do Proxmox",
|
||||
"hostLocalDisk": "Adicionar um disco local como armazenamento do Proxmox",
|
||||
"hostLocalShared": "Criar um diretório partilhado no host",
|
||||
"lxcMountPoints": "Pontos de montagem LXC (host ↔ CT)",
|
||||
"lxcNetworkSharing": "Partilhas de rede em LXC",
|
||||
"lxcNfsClient": "Cliente NFS em LXC",
|
||||
"lxcSambaClient": "Cliente Samba em LXC",
|
||||
"lxcNfsServer": "Servidor NFS em LXC",
|
||||
"lxcSambaServer": "Servidor Samba em LXC",
|
||||
"network": "Rede",
|
||||
"networkOverview": "Visão geral",
|
||||
"networkDiagnostics": "Diagnóstico",
|
||||
"networkMonitoring": "Ferramentas de monitorização em tempo real",
|
||||
"networkBridge": "Análise e reparação de bridges de rede",
|
||||
"networkConfig": "Análise e limpeza da configuração",
|
||||
"networkPersistent": "Nomes persistentes das interfaces",
|
||||
"networkBackup": "Cópia de segurança e reinício das interfaces",
|
||||
"security": "Segurança",
|
||||
"securityOverview": "Visão geral",
|
||||
"securityFail2ban": "Fail2Ban",
|
||||
"securityLynis": "Lynis",
|
||||
"utilities": "Utilitários",
|
||||
"utilsOverview": "Visão geral",
|
||||
"utilsUupDump": "Criação de ISO com UUP Dump",
|
||||
"utilsSystemUtils": "Instalação de utilitários do sistema",
|
||||
"utilsSystemUpdate": "Atualização do sistema Proxmox",
|
||||
"utilsUpgradePve": "Atualizar do PVE 8 para o PVE 9",
|
||||
"utilsExportVm": "Exportar uma VM para OVA/OVF",
|
||||
"utilsImportVm": "Importar uma VM a partir de OVA/OVF",
|
||||
"settingsProxmenux": "Definições do ProxMenux",
|
||||
"settingsOverview": "Visão geral",
|
||||
"settingsMonitor": "ProxMenux Monitor",
|
||||
"settingsBeta": "Alterar o canal de versões",
|
||||
"settingsVersion": "Mostrar informações da versão",
|
||||
"settingsUninstall": "Desinstalar o ProxMenux",
|
||||
"commandsReference": "Referência de comandos",
|
||||
"commandsOverview": "Visão geral",
|
||||
"commandsSystem": "Comandos úteis do sistema",
|
||||
"commandsVmCt": "Gestão de VM e CT",
|
||||
"commandsStorage": "Armazenamento e discos",
|
||||
"commandsNetwork": "Comandos de rede",
|
||||
"commandsUpdates": "Atualizações e pacotes",
|
||||
"commandsGpu": "Passthrough de GPU",
|
||||
"commandsZfs": "Gestão do ZFS",
|
||||
"commandsBackup": "Cópia de segurança e restauro",
|
||||
"commandsTools": "Ferramentas de sistema para a linha de comandos",
|
||||
"glossary": "Glossário",
|
||||
"about": "Sobre o projeto",
|
||||
"aboutOverview": "Visão geral",
|
||||
"aboutFaq": "FAQ",
|
||||
"aboutContributors": "Colaboradores",
|
||||
"aboutContributing": "Como contribuir",
|
||||
"aboutCodeOfConduct": "Código de conduta",
|
||||
"externalRepositories": "Repositórios externos",
|
||||
"backupRestore": "Cópia de segurança e restauro",
|
||||
"backupRestoreOverview": "Visão geral",
|
||||
"backupRestoreHowItWorks": "Como funciona",
|
||||
"backupRestoreDestinations": "Destinos",
|
||||
"backupRestoreDestOverview": "Visão geral",
|
||||
"backupRestoreDestLocal": "Arquivo local",
|
||||
"backupRestoreDestPbs": "Proxmox Backup Server",
|
||||
"backupRestoreDestBorg": "Borg",
|
||||
"backupRestoreCreating": "Criar cópias de segurança",
|
||||
"backupRestoreJobs": "Tarefas agendadas",
|
||||
"backupRestoreRestoring": "Restaurar",
|
||||
"backupRestoreCrossKernel": "Restauro entre versões do kernel",
|
||||
"backupRestoreGlossary": "Glossário"
|
||||
}
|
||||
},
|
||||
"hero": {
|
||||
"title": "ProxMenux",
|
||||
"tagline": "Um menu interativo e um painel web para o Proxmox VE",
|
||||
"description": "O ProxMenux reúne um menu interativo e um painel web para o Proxmox VE. Execute comandos, scripts e assistentes a partir do terminal ou consulte o estado do host, as métricas e as notificações no navegador.",
|
||||
"installButton": "Instalar agora",
|
||||
"whatIsButton": "O que é o ProxMenux?",
|
||||
"logoAlt": "Logótipo do ProxMenux"
|
||||
},
|
||||
"docNav": {
|
||||
"previous": "Anterior",
|
||||
"next": "Seguinte"
|
||||
},
|
||||
"tocPanel": {
|
||||
"onThisPage": "Nesta página"
|
||||
},
|
||||
"supportProject": {
|
||||
"heading": "Apoie o projeto!",
|
||||
"body": "Se o <strong>ProxMenux</strong> lhe é útil, dê-lhe uma ⭐ no GitHub para ajudar outras pessoas a descobri-lo.",
|
||||
"button": "Dar uma estrela no GitHub"
|
||||
},
|
||||
"rssLink": {
|
||||
"heading": "Acompanhe as novidades!",
|
||||
"body": "Subscreva o feed RSS para receber as novidades.",
|
||||
"copy": "Copiar",
|
||||
"copied": "Copiado!",
|
||||
"copyTitle": "Copiar o URL do feed RSS",
|
||||
"openFeed": "Abrir o feed RSS",
|
||||
"openTitle": "Abrir o feed RSS"
|
||||
},
|
||||
"changelog": {
|
||||
"pageTitle": "Histórico de alterações",
|
||||
"meta": {
|
||||
"title": "Histórico de alterações do ProxMenux",
|
||||
"titleSuffix": "Notas da versão",
|
||||
"latest": "Última versão",
|
||||
"mostRecent": "Versão mais recente",
|
||||
"description": "Notas de versão e histórico de atualizações do ProxMenux, o script com menus para gerir o Proxmox VE.",
|
||||
"descriptionTail": "Novas funcionalidades, correções de erros, atualizações de segurança, melhorias do ProxMenux Monitor, compatibilidade com fornecedores de IA, reforço de segurança do passthrough de GPU e muito mais.",
|
||||
"ogDescription": "Notas de versão do ProxMenux.",
|
||||
"ogTail": "Subscreva o feed RSS ou volte a esta página para consultar novas versões."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,12 @@
|
||||
"switcher": "Jazyk",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"sk": "Slovenčina"
|
||||
"sk": "Slovenčina",
|
||||
"de": "Deutsch",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"pt": "Português",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"resources": {
|
||||
"documentation": {
|
||||
@@ -193,7 +198,15 @@
|
||||
"backupRestoreJobs": "Plánované úlohy",
|
||||
"backupRestoreRestoring": "Obnova",
|
||||
"backupRestoreCrossKernel": "Obnova medzi kernelmi",
|
||||
"backupRestoreGlossary": "Slovník pojmov"
|
||||
"backupRestoreGlossary": "Slovník pojmov",
|
||||
"dashboardApps": "Karta Aplikácie",
|
||||
"auditReport": "Audit a správy",
|
||||
"auditReportOverview": "Prehľad",
|
||||
"auditReportAssessment": "Hodnotenie a inventár",
|
||||
"auditReportPolicy": "Pravidlá",
|
||||
"auditReportChanges": "Zmeny",
|
||||
"auditReportReports": "Správy a porovnania",
|
||||
"auditReportScope": "Rozsah a záruky"
|
||||
}
|
||||
},
|
||||
"hero": {
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
],
|
||||
"sourcesHeading": "Zdroje dostupnej verzie",
|
||||
"sources": [
|
||||
"<strong>GitHub repozitár</strong>: najnovšie vydanie alebo značka verejného repozitára <code>vlastník/názov</code>.",
|
||||
"<strong>GitHub repozitár</strong>: najnovšie vydanie alebo značka verejného repozitára <code>owner/name</code>.",
|
||||
"<strong>HTTP JSON</strong>: verejný koncový bod a cesta ako <code>data.version</code> alebo <code>releases[0].tag_name</code>.",
|
||||
"<strong>Docker Hub</strong>: verzované značky filtrované regulárnym výrazom. Živý náhľad pred uložením ukáže skutočné zodpovedajúce značky.",
|
||||
"Pohyblivé značky ako <code>latest</code>, <code>stable</code> alebo <code>lts</code> neobsahujú verziu. Tieto obrazy sledujte podľa digestu v aktualizáciách Docker obrazov."
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
"Nepridávajte <code>pct exec</code>; ProxMenux už vstupuje do kontajnera a príkaz spúšťa ako root."
|
||||
],
|
||||
"exampleLead": "Príklad úplného postupu v kontajneri:",
|
||||
"example": "cd /opt/moja-aplikacia && ./update.sh",
|
||||
"example": "cd /opt/my-app && ./update.sh",
|
||||
"callout": "Príkaz ako <code>myapp --version</code> iba číta verziu a nič neaktualizuje. Príkazy sa spúšťajú s oprávneniami správcu a musia sa kontrolovať ako príkazy shellu root."
|
||||
},
|
||||
"bulk": {
|
||||
@@ -140,7 +140,7 @@
|
||||
"items": [
|
||||
"Vyberte predvoľbu alebo cron výraz a potom presné ciele: balíky OS, jednotlivé aplikácie, Docker Engine, samostatné jednotky Dockeru alebo skupiny služieb Compose.",
|
||||
"Oneskorenie po vydaní platí iba pre vybrané aplikácie so sledovaním verzie. Aplikácie bez sledovania spustia aktualizátor pri každom termíne.",
|
||||
"Stav posledného behu rozlišuje úspech, čiastočné dokončenie, zlyhanie, bezpečnostné pozdržanie a stav bez čakajúcich aktualizácií.",
|
||||
"Stav posledného behu rozlišuje úspech, čiastočné dokončenie, zlyhanie, bezpečnostné pozastavenie a žiadne čakajúce aktualizácie. Po prvom plánovanom behu otvorí <strong>Aktualizácie → Plánované aktualizácie → Zobraziť záznam</strong> celý výstup aktualizátora a podradených skriptov.",
|
||||
"Zistené externé plány Proxmox VE Helper-Scripts sa zobrazia samostatne, aby bola viditeľná prekrývajúca sa automatizácia."
|
||||
],
|
||||
"callout": "Pred zapnutím plánu otestujte každú vybranú metódu manuálne. Plánovaný príkaz nemôže odpovedať na interaktívne otázky."
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
{
|
||||
"site": {
|
||||
"name": "ProxMenux",
|
||||
"tagline": "Interaktiv meny och webbaserad instrumentpanel för Proxmox VE"
|
||||
},
|
||||
"nav": {
|
||||
"home": "Start",
|
||||
"docs": "Dokumentation",
|
||||
"documentation": "Dokumentation",
|
||||
"guides": "Guider",
|
||||
"changelog": "Ändringslogg",
|
||||
"github": "GitHub",
|
||||
"rss": "RSS",
|
||||
"rssTitle": "RSS-flöde",
|
||||
"menuOpen": "Öppna meny"
|
||||
},
|
||||
"footer": {
|
||||
"sponsorHeading": "Stöd projektet",
|
||||
"sponsorBody": "Om du vill stödja projektet.",
|
||||
"sponsorAlt": "Stöd mig på Ko-fi",
|
||||
"connectHeading": "Gemenskap",
|
||||
"connectBody": "Delta i diskussionerna på GitHub för att få hjälp, dela idéer och bidra till projektet. Alla idéer är välkomna!",
|
||||
"joinDiscussion": "Delta i diskussionen",
|
||||
"copyrightPrefix": "ProxMenux, ett samarbetsprojekt med öppen källkod av",
|
||||
"copyrightSuffix": "."
|
||||
},
|
||||
"language": {
|
||||
"switcher": "Språk",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"sk": "Slovenčina",
|
||||
"de": "Deutsch",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"pt": "Português",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"resources": {
|
||||
"documentation": {
|
||||
"title": "Dokumentation",
|
||||
"description": "Systembeskrivning och användarguider"
|
||||
},
|
||||
"changelog": {
|
||||
"title": "Ändringslogg",
|
||||
"description": "Information om de senaste uppdateringarna"
|
||||
},
|
||||
"guides": {
|
||||
"title": "Guider",
|
||||
"description": "Stegvisa instruktioner och guider för vanliga uppgifter"
|
||||
},
|
||||
"github": {
|
||||
"title": "GitHub-arkiv",
|
||||
"description": "Utforska källkoden."
|
||||
}
|
||||
},
|
||||
"docSidebar": {
|
||||
"documentation": "Dokumentation",
|
||||
"items": {
|
||||
"introduction": "Introduktion",
|
||||
"installation": "Installation",
|
||||
"proxmenuxMonitor": "ProxMenux Monitor",
|
||||
"monitorOverview": "Översikt",
|
||||
"architecture": "Arkitektur",
|
||||
"accessAuth": "Åtkomst och autentisering",
|
||||
"dashboard": "Instrumentpanel",
|
||||
"dashboardSystemOverview": "Fliken Systemöversikt",
|
||||
"dashboardApps": "Fliken Program",
|
||||
"dashboardStorage": "Fliken Lagring",
|
||||
"dashboardNetwork": "Fliken Nätverk",
|
||||
"dashboardVmsLxcs": "Fliken VM och LXC",
|
||||
"dashboardVmsLxcsApp": "Program",
|
||||
"dashboardVmsLxcsUpdates": "Uppdateringar",
|
||||
"dashboardHardware": "Fliken Maskinvara",
|
||||
"dashboardSystemLogs": "Fliken Systemloggar",
|
||||
"dashboardTerminal": "Fliken Terminal",
|
||||
"dashboardSecurity": "Fliken Säkerhet",
|
||||
"dashboardSettings": "Fliken Inställningar",
|
||||
"healthMonitor": "Systemövervakning",
|
||||
"auditReport": "Granskning och rapporter",
|
||||
"auditReportOverview": "Översikt",
|
||||
"auditReportAssessment": "Bedömning och inventering",
|
||||
"auditReportPolicy": "Policy",
|
||||
"auditReportChanges": "Ändringar",
|
||||
"auditReportReports": "Rapporter och jämförelser",
|
||||
"auditReportScope": "Omfattning och garantier",
|
||||
"notifications": "Aviseringar",
|
||||
"aiAssistant": "AI-assistent",
|
||||
"apiReference": "API-referens",
|
||||
"integrations": "Integrationer",
|
||||
"ociManager": "OCI manager Apps",
|
||||
"ociOverview": "Översikt",
|
||||
"ociArchitecture": "Så anpassas en OCI-avbildning",
|
||||
"ociCustomImage": "Avbildning utanför katalogen",
|
||||
"ociStorageNetwork": "Data, sökvägar och nätverk",
|
||||
"ociHardware": "Enheter och acceleration",
|
||||
"ociStacks": "Program med flera containrar",
|
||||
"ociLifecycle": "Installera, uppdatera och ändra",
|
||||
"ociMonitor": "I ProxMenux Monitor",
|
||||
"proxmenuxScripts": "ProxMenux Scripts",
|
||||
"postInstallScript": "Skript efter installationen",
|
||||
"postInstallOverview": "Översikt",
|
||||
"postInstallAutomated": "Automatiskt",
|
||||
"postInstallCustomizable": "Anpassningsbart",
|
||||
"postInstallBasicSettings": "Grundinställningar",
|
||||
"postInstallSystem": "System",
|
||||
"postInstallVirtualization": "Virtualisering",
|
||||
"postInstallNetwork": "Nätverk",
|
||||
"postInstallStorage": "Lagring",
|
||||
"postInstallSecurity": "Säkerhet",
|
||||
"postInstallCustomization": "Anpassning",
|
||||
"postInstallMonitoring": "Övervakning",
|
||||
"postInstallPerformance": "Prestanda",
|
||||
"postInstallOptional": "Valfritt",
|
||||
"postInstallUpdates": "Installera tillgängliga uppdateringar",
|
||||
"postInstallUninstall": "Ta bort optimeringar",
|
||||
"gpusCoralTpu": "GPU och Coral TPU",
|
||||
"nvidiaHost": "Installera NVIDIA-drivrutiner på värden",
|
||||
"coralHost": "Installera Coral TPU på värden",
|
||||
"addGpuLxc": "Gör en GPU tillgänglig i en LXC",
|
||||
"addCoralLxc": "Gör Coral TPU tillgänglig i en LXC",
|
||||
"addGpuVm": "Tilldela en GPU till en VM (passthrough)",
|
||||
"switchGpuMode": "Byt GPU-läge (VM ↔ LXC)",
|
||||
"createVm": "Skapa en VM",
|
||||
"createVmOverview": "Översikt",
|
||||
"createVmSystemNas": "NAS-system",
|
||||
"createVmSynology": "Synology-VM",
|
||||
"createVmNasOthers": "Andra NAS-system",
|
||||
"createVmSystemWindows": "Windows-system",
|
||||
"createVmSystemLinux": "Linux-system",
|
||||
"diskManager": "Diskhantering",
|
||||
"diskManagerOverview": "Översikt",
|
||||
"diskImportVm": "Importera en disk till en VM",
|
||||
"diskImportImageVm": "Importera en diskavbildning till en VM",
|
||||
"diskAddController": "Lägg till en styrenhet eller NVMe-enhet i en VM",
|
||||
"diskImportLxc": "Importera en disk till en LXC",
|
||||
"diskFormat": "Formatera eller radera en fysisk disk",
|
||||
"diskSmart": "SMART-status och disktester",
|
||||
"storageShareManager": "Hantering av lagring och delningar",
|
||||
"storageShareOverview": "Översikt",
|
||||
"hostStorage": "Anslut lagring till värden",
|
||||
"hostNfs": "Lägg till en NFS-delning som Proxmox-lagring",
|
||||
"hostSamba": "Lägg till en Samba-delning som Proxmox-lagring",
|
||||
"hostIscsi": "Lägg till ett iSCSI-mål som Proxmox-lagring",
|
||||
"hostLocalDisk": "Lägg till en lokal disk som Proxmox-lagring",
|
||||
"hostLocalShared": "Skapa en delad katalog på värden",
|
||||
"lxcMountPoints": "LXC-monteringspunkter (värd ↔ CT)",
|
||||
"lxcNetworkSharing": "Nätverksdelning i LXC",
|
||||
"lxcNfsClient": "NFS-klient i LXC",
|
||||
"lxcSambaClient": "Samba-klient i LXC",
|
||||
"lxcNfsServer": "NFS-server i LXC",
|
||||
"lxcSambaServer": "Samba-server i LXC",
|
||||
"network": "Nätverk",
|
||||
"networkOverview": "Översikt",
|
||||
"networkDiagnostics": "Diagnostik",
|
||||
"networkMonitoring": "Verktyg för övervakning i realtid",
|
||||
"networkBridge": "Analysera och reparera nätverksbryggor",
|
||||
"networkConfig": "Analysera och rensa konfigurationen",
|
||||
"networkPersistent": "Beständiga gränssnittsnamn",
|
||||
"networkBackup": "Säkerhetskopiera och starta om gränssnitt",
|
||||
"security": "Säkerhet",
|
||||
"securityOverview": "Översikt",
|
||||
"securityFail2ban": "Fail2Ban",
|
||||
"securityLynis": "Lynis",
|
||||
"utilities": "Verktyg",
|
||||
"utilsOverview": "Översikt",
|
||||
"utilsUupDump": "Skapa ISO med UUP Dump",
|
||||
"utilsSystemUtils": "Installera systemverktyg",
|
||||
"utilsSystemUpdate": "Uppdatera Proxmox-systemet",
|
||||
"utilsUpgradePve": "Uppgradera från PVE 8 till PVE 9",
|
||||
"utilsExportVm": "Exportera en VM till OVA/OVF",
|
||||
"utilsImportVm": "Importera en VM från OVA/OVF",
|
||||
"settingsProxmenux": "ProxMenux-inställningar",
|
||||
"settingsOverview": "Översikt",
|
||||
"settingsMonitor": "ProxMenux Monitor",
|
||||
"settingsBeta": "Byt versionskanal",
|
||||
"settingsVersion": "Visa versionsinformation",
|
||||
"settingsUninstall": "Avinstallera ProxMenux",
|
||||
"commandsReference": "Kommandoreferens",
|
||||
"commandsOverview": "Översikt",
|
||||
"commandsSystem": "Användbara systemkommandon",
|
||||
"commandsVmCt": "Hantera VM och CT",
|
||||
"commandsStorage": "Lagring och diskar",
|
||||
"commandsNetwork": "Nätverkskommandon",
|
||||
"commandsUpdates": "Uppdateringar och paket",
|
||||
"commandsGpu": "GPU-passthrough",
|
||||
"commandsZfs": "Hantera ZFS",
|
||||
"commandsBackup": "Säkerhetskopiering och återställning",
|
||||
"commandsTools": "Systemverktyg för kommandoraden",
|
||||
"glossary": "Ordlista",
|
||||
"about": "Om projektet",
|
||||
"aboutOverview": "Översikt",
|
||||
"aboutFaq": "FAQ",
|
||||
"aboutContributors": "Medverkande",
|
||||
"aboutContributing": "Bidra",
|
||||
"aboutCodeOfConduct": "Uppförandekod",
|
||||
"externalRepositories": "Externa arkiv",
|
||||
"backupRestore": "Säkerhetskopiering och återställning",
|
||||
"backupRestoreOverview": "Översikt",
|
||||
"backupRestoreHowItWorks": "Så fungerar det",
|
||||
"backupRestoreDestinations": "Mål",
|
||||
"backupRestoreDestOverview": "Översikt",
|
||||
"backupRestoreDestLocal": "Lokalt arkiv",
|
||||
"backupRestoreDestPbs": "Proxmox Backup Server",
|
||||
"backupRestoreDestBorg": "Borg",
|
||||
"backupRestoreCreating": "Skapa säkerhetskopior",
|
||||
"backupRestoreJobs": "Schemalagda jobb",
|
||||
"backupRestoreRestoring": "Återställning",
|
||||
"backupRestoreCrossKernel": "Återställning mellan kärnversioner",
|
||||
"backupRestoreGlossary": "Ordlista"
|
||||
}
|
||||
},
|
||||
"hero": {
|
||||
"title": "ProxMenux",
|
||||
"tagline": "En interaktiv meny och webbaserad instrumentpanel för Proxmox VE",
|
||||
"description": "ProxMenux kombinerar en interaktiv meny med en webbaserad instrumentpanel för Proxmox VE. Kör kommandon, skript och guidade steg från terminalmenyn, eller följ värdens status, mätvärden och aviseringar i webbläsaren.",
|
||||
"installButton": "Installera nu",
|
||||
"whatIsButton": "Vad är ProxMenux?",
|
||||
"logoAlt": "ProxMenux-logotyp"
|
||||
},
|
||||
"docNav": {
|
||||
"previous": "Föregående",
|
||||
"next": "Nästa"
|
||||
},
|
||||
"tocPanel": {
|
||||
"onThisPage": "På den här sidan"
|
||||
},
|
||||
"supportProject": {
|
||||
"heading": "Stöd projektet!",
|
||||
"body": "Om du har nytta av <strong>ProxMenux</strong> kan du ge projektet en ⭐ på GitHub så att fler upptäcker det.",
|
||||
"button": "Ge en stjärna på GitHub"
|
||||
},
|
||||
"rssLink": {
|
||||
"heading": "Följ uppdateringarna!",
|
||||
"body": "Prenumerera på vårt RSS-flöde för att få information om nyheter.",
|
||||
"copy": "Kopiera",
|
||||
"copied": "Kopierat!",
|
||||
"copyTitle": "Kopiera RSS-adressen",
|
||||
"openFeed": "Öppna RSS-flödet",
|
||||
"openTitle": "Öppna RSS-flödet"
|
||||
},
|
||||
"changelog": {
|
||||
"pageTitle": "Ändringslogg",
|
||||
"meta": {
|
||||
"title": "Ändringslogg för ProxMenux",
|
||||
"titleSuffix": "Versionsinformation",
|
||||
"latest": "Senaste",
|
||||
"mostRecent": "Senaste versionen",
|
||||
"description": "Versionsinformation och uppdateringshistorik för ProxMenux, det menystyrda skriptet för administration av Proxmox VE.",
|
||||
"descriptionTail": "Nya funktioner, felrättningar, säkerhetsuppdateringar, förbättringar i ProxMenux Monitor, stöd för AI-leverantörer, säkrare GPU-passthrough och mer.",
|
||||
"ogDescription": "Versionsinformation för ProxMenux.",
|
||||
"ogTail": "Prenumerera via RSS eller besök sidan igen för att se nya versioner."
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -4,10 +4,10 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build && pagefind --site out --output-path public/pagefind && cp -r public/pagefind out/pagefind",
|
||||
"build": "next build && node scripts/localize-export.mjs && pagefind --site out --output-path public/pagefind && cp -r public/pagefind out/pagefind",
|
||||
"start": "next start",
|
||||
"lint": "next lint",
|
||||
"index": "pagefind --site out --output-path public/pagefind && cp -r public/pagefind out/pagefind"
|
||||
"index": "node scripts/localize-export.mjs && pagefind --site out --output-path public/pagefind && cp -r public/pagefind out/pagefind"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hookform/resolvers": "^3.9.1",
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
// Next's shared root layout cannot read its nested [locale] parameter.
|
||||
// Set the static document language before Pagefind indexes the export, so
|
||||
// search and no-JavaScript readers see the same locale as the hydrated app.
|
||||
import { readdir, readFile, writeFile } from 'node:fs/promises'
|
||||
import { join } from 'node:path'
|
||||
|
||||
async function htmlFiles(directory) {
|
||||
const entries = await readdir(directory, { withFileTypes: true })
|
||||
const files = await Promise.all(entries.map(entry => {
|
||||
const path = join(directory, entry.name)
|
||||
return entry.isDirectory() ? htmlFiles(path) : entry.isFile() && entry.name.endsWith('.html') ? [path] : []
|
||||
}))
|
||||
return files.flat()
|
||||
}
|
||||
|
||||
let count = 0
|
||||
for (const entry of await readdir('out', { withFileTypes: true })) {
|
||||
if (!entry.isDirectory() || !/^[a-z]{2}(?:-[a-z0-9]+)?$/.test(entry.name)) continue
|
||||
const locale = entry.name
|
||||
for (const file of await htmlFiles(join('out', locale))) {
|
||||
const original = await readFile(file, 'utf8')
|
||||
const updated = original.replace(/<html\b([^>]*)>/i, (tag, attributes) => {
|
||||
const next = /\blang\s*=\s*["'][^"']*["']/i.test(attributes)
|
||||
? attributes.replace(/\blang\s*=\s*["'][^"']*["']/i, `lang="${locale}"`)
|
||||
: `${attributes} lang="${locale}"`
|
||||
return `<html${next}>`
|
||||
})
|
||||
if (updated !== original) await writeFile(file, updated, 'utf8')
|
||||
count += 1
|
||||
}
|
||||
}
|
||||
console.log(`Static document language verified for ${count} localized pages.`)
|
||||
Reference in New Issue
Block a user