feat(oci): run official container images as native LXC containers

Adds the OCI manager: an engine that turns a Docker Compose file into an
LXC definition, a catalog of 365 applications drawn from LinuxServer.io
and other container image sources, and a per-instance registry recording
what each container was built from. Reachable from the main menu.

Catalog text is translated like every other string in the project: the
taglines go through translate() and land in lang/*.json, so the entries
read in all eight languages instead of only English.

Translation cache builder:
- a failed translation leaves the key absent rather than writing English,
  which previously made the string count as translated forever
- a result identical to a 3+ word source is rejected, catching a provider
  that silently returns the text it was given
- strings that are nothing but glossary terms keep their source spelling
  instead of being discarded as failures
- no backoff between attempts when the provider is deterministic
- application names are protected so "HAOS One" survives translation
- argos joins the provider list, and the workflow reads the OCI sources

Audit & Report:
- findings that moved in the wrong direction between runs are reported
  alongside the ones that improved
- an accepted risk can carry a review date and is flagged when it falls due
- backup checks explain in plain language what they looked at and what to
  do next

Monitor:
- disks can be excluded from periodic reads, and an idle disk says so
  instead of showing a stale temperature
- per-disk identity survives a controller or enclosure change
- scheduled Borg backups resolve their SSH key from the repository entry
- PVE upgrades log the package list and the resulting dpkg changes

The web build no longer copies scripts/ into public/: the documentation
links to GitHub, so nothing read that folder.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
MacRimi
2026-09-22 18:24:59 +02:00
co-authored by Claude Opus 5
parent b36498f215
commit bcabcb618c
670 changed files with 221410 additions and 215 deletions
+29 -17
View File
@@ -208,7 +208,7 @@
"notApplicable": "n / A",
"error": "Fehler",
"system": "System",
"standby": "Stehen zu",
"standby": "Standby",
"standbyTitle": "Das Laufwerk befindet sich im Standby-Modus – Smartctl wurde übersprungen, um es im Ruhezustand zu halten",
"filesystemCorruption": "Dateisystembeschädigung erkannt",
"ioErrorOne": "{count} E/A-Fehler in 5 Min",
@@ -2206,7 +2206,7 @@
"password": "Passwort",
"usernamePlaceholder": "Geben Sie Ihren Benutzernamen ein",
"passwordPlaceholder": "Geben Sie Ihr Passwort ein",
"rememberMe": "Erinnere dich an mich",
"rememberMe": "Anmeldedaten merken",
"missingCredentials": "Bitte geben Sie Benutzernamen und Passwort ein",
"missingTotp": "Bitte geben Sie Ihren 2FA-Code ein",
"invalidCredentials": "Falscher Benutzername oder Passwort",
@@ -3396,7 +3396,7 @@
},
"roles": {
"active": "aktiv",
"standby": "stehen zu",
"standby": "Standby",
"down": "runter"
},
"empty": {
@@ -5208,6 +5208,9 @@
"noFindings": "No findings match the current filter.",
"affectedCount": "{count} affected",
"acceptedNotice": "{count} accepted risk(s) recorded on this host.",
"reviewOn": "Überprüfen am: {when}",
"reviewDue": "Zur Überprüfung fällig — die Entscheidung gilt weiter",
"reviewDueNotice": "{count} akzeptierte Entscheidung(en) stehen zur Überprüfung an.",
"states": {
"fail": "Failed",
"warn": "Warning",
@@ -5228,6 +5231,8 @@
},
"detail": {
"why": "Context",
"whatItMeans": "Was das bedeutet",
"whatToDo": "Was zu tun ist",
"evidence": "Evidence",
"affected": "Affected",
"acceptedRisk": "Accepted risk",
@@ -5674,20 +5679,23 @@
},
"summaryFallback": "The check could not be evaluated",
"acceptRisk": {
"action": "Accept risk",
"revoke": "Return to active",
"title": "Accept this risk",
"reasonLabel": "Reason",
"reasonHelp": "Required. It is recorded together with the author and the date.",
"reasonPlaceholder": "e.g. Lab containers, not covered on purpose",
"expiryLabel": "Review after",
"expiryHelp": "When the period ends the finding becomes active again.",
"expiryNever": "Does not expire",
"expiry90": "90 days",
"expiry180": "180 days",
"expiry365": "1 year",
"cancel": "Cancel",
"confirm": "Accept risk"
"action": "Risiko akzeptieren",
"revoke": "Wieder aktivieren",
"title": "Dieses Risiko akzeptieren",
"reasonLabel": "Begründung",
"reasonHelp": "Erforderlich. Sie wird zusammen mit Urheber und Datum festgehalten.",
"reasonPlaceholder": "z. B. Labor-Container, absichtlich nicht abgedeckt",
"expiryLabel": "Gilt nicht mehr nach",
"expiryHelp": "Nach Ablauf des Zeitraums wird der Befund wieder aktiv.",
"expiryNever": "Läuft nicht ab",
"reviewLabel": "An Überprüfung erinnern",
"reviewHelp": "Die Entscheidung gilt weiter; sie wird nur wieder in Erinnerung gerufen.",
"reviewNever": "Keine Erinnerung",
"expiry90": "90 Tage",
"expiry180": "180 Tage",
"expiry365": "1 Jahr",
"cancel": "Abbrechen",
"confirm": "Risiko akzeptieren"
},
"incomplete": "Unvollständige Nachweise",
"progress": "{completed} von {total} geprüft",
@@ -6085,6 +6093,10 @@
"unchanged": "{count} Prüfungen ergaben dasselbe wie zuvor.",
"new": "Neu",
"newNote": "jetzt gemeldet, vorher nicht",
"worse": "Verschlechtert",
"worseNote": "weiterhin gemeldet, und schwerwiegender oder weiter reichend als zuvor",
"better": "Verbessert",
"betterNote": "weiterhin gemeldet, aber weniger schwerwiegend oder weniger weit reichend als zuvor",
"resolved": "Behoben",
"resolvedNote": "nicht mehr gemeldet, und niemand hat sie akzeptiert",
"accepted": "Akzeptiert",
+69 -2
View File
@@ -807,7 +807,11 @@
"friday": "Friday",
"saturday": "Saturday"
}
}
},
"idle": "Idle",
"idleTitle": "Not read while nothing is using it, so it can spin down. Its temperature is shown again as soon as the disk is in use.",
"diskExcluded": "Excluded",
"diskExcludedTitle": "Excluded from periodic reads in Settings."
},
"details": {
"temperature": {
@@ -1404,6 +1408,8 @@
"imageUpToDate": "Up to date",
"imageInstalledTag": "installed tag",
"imageDigestUnknown": "Digest unavailable",
"imagePinned": "Pinned to a digest",
"imagePinnedTitle": "This container runs the exact image its digest names. A newer tag does not change it; editing the reference in its configuration does.",
"dockerPendingSummary": "{count} Docker image update(s) detected. Update with the owning Docker or Compose workflow.",
"postApplyChecking": "Verifying update result…",
"postApplyAllOk": "{count} package(s) applied successfully — nothing pending.",
@@ -2197,6 +2203,18 @@
"reset": "Restore default",
"hint": "Drag to reorder · On touch, long-press first",
"customActive": "Using custom navigation order."
},
"diskExclusions": {
"title": "Disk exclusions",
"description": "Disks that are never read on a schedule, so they can spin down on their own timer.",
"empty": "No physical disks found.",
"disk": "Disk",
"periodicReads": "Periodic reads",
"excluded": "Excluded",
"notConnected": "Not connected",
"saveFailed": "Could not save the disk exclusions.",
"help": "An excluded disk gets no scheduled temperature or SMART reads — not even a power-mode query — so it is left entirely alone. Opening its SMART details still reads it.",
"idleHelp": "Mechanical disks with no activity are already left alone automatically until something uses them again."
}
},
"login": {
@@ -5208,6 +5226,11 @@
"noFindings": "No findings match the current filter.",
"affectedCount": "{count} affected",
"acceptedNotice": "{count} accepted risk(s) recorded on this host.",
"noActionNeeded": "Nothing to do. This check found what it expects to find.",
"couldNotEvaluate": "This check could not be evaluated, so it reports nothing either way. The evidence records what it was unable to read.",
"reviewOn": "Review on: {when}",
"reviewDue": "Due for review — the decision still stands",
"reviewDueNotice": "{count} accepted decision(s) are due for review.",
"states": {
"fail": "Failed",
"warn": "Warning",
@@ -5228,6 +5251,8 @@
},
"detail": {
"why": "Context",
"whatItMeans": "What this means",
"whatToDo": "What to do",
"evidence": "Evidence",
"affected": "Affected",
"acceptedRisk": "Accepted risk",
@@ -5240,6 +5265,13 @@
"backup": {
"guest_coverage": {
"title": "Backup coverage",
"explanation": "A backup protects only what a job actually selects. This check pairs the guests on this node with the jobs that run here, so a guest nobody backs up appears as such instead of being assumed to be covered by something else.",
"nextStep": {
"noJobs": "Create a backup job on this node and select the guests holding data you would not want to rebuild by hand. A job that exists but is disabled selects nothing.",
"uncovered": "Decide, for each of these guests, whether it holds anything worth keeping. Add the ones that do to a job; for the ones that do not, declare that in the policy so they stop being counted here.",
"excludedData": "Open each job's exclusion list and confirm that what it leaves out is data you can afford to lose. An exclusion added to make a job faster protects nothing it skips.",
"uncoveredExpected": "The policy declares these guests as requiring a backup and no enabled job selects them. Either add them to a job or change what the policy declares, so the two agree."
},
"rationale": "Enabled backup jobs on this node, the guests each one selects, and guest data excluded from them. Configured coverage does not prove that a usable backup exists. Whether an unselected guest was meant to be protected comes from the declared policy.",
"summary": {
"noJobs": "No backup job is defined on this node for the {total} guests it holds",
@@ -5252,6 +5284,12 @@
},
"last_backup_age": {
"title": "Age of stored backups",
"explanation": "A job that exists is not the same as a copy that exists. This check reads the newest stored copy of each guest and how long ago it was written, which is how far back you would have to go if you had to restore today.",
"nextStep": {
"stale": "Find out why the job stopped producing copies for these guests: it may have been disabled, its schedule may never fire, or its runs may be failing. The run results check reports how each job last ended.",
"noBackups": "No stored copy matches any guest on this node. If the jobs write to a destination this node cannot read, that is expected; otherwise they are producing nothing.",
"attention": "Review the guests listed. Each one either has no recent copy or has one older than the age in use."
},
"rationale": "Age: time elapsed since the latest stored backup. Limit used: the reference age against which that backup is compared.",
"summary": {
"recent": "All {total} guest/destination checks meet the stated age policy",
@@ -5263,6 +5301,12 @@
},
"retention_defined": {
"title": "Backup retention",
"explanation": "Retention decides how many copies are kept and for how long. Without it a destination fills until it stops accepting new copies, and a backup that cannot be written is the one you find out about on the day you need it.",
"nextStep": {
"missing": "Set a retention on these jobs, or on the storage they write to. Proxmox takes the job's setting first, then the storage's, then the node default.",
"notDeclared": "These jobs keep every copy they make. That is a deliberate choice for some destinations, but confirm the destination has room to keep growing.",
"onServer": "These jobs write to a backup server, which prunes them under its own rules. What it keeps cannot be read from this node, so check the retention there."
},
"rationale": "Retention as Proxmox resolves it: the job's setting, then the storage's, then the node default. Retention applied by a backup server is not readable from this node.",
"summary": {
"allDefined": "All {total} jobs resolve a retention setting",
@@ -5274,6 +5318,11 @@
},
"verification_state": {
"title": "Backup verification",
"explanation": "Verification reads a stored copy back and confirms it is intact. It is the difference between a copy that exists and a copy that can be read — a distinction that only matters on the day you need it.",
"nextStep": {
"failed": "A copy that fails verification cannot be relied on. Check whether an earlier copy of the same guest verified, and look at the storage the failed copies live on.",
"notVerified": "Nothing has confirmed that these copies can be read back. A backup server can verify on a schedule of its own, separately from the job that wrote them."
},
"rationale": "The verification result Proxmox Backup Server records for each guest's newest copy, and whether an earlier copy of the same guest verified. Verification reads a stored copy back; it is not a restore.",
"summary": {
"allVerified": "The newest copy of all {total} guests has been verified intact",
@@ -5284,6 +5333,11 @@
},
"job_results": {
"title": "Backup run results",
"explanation": "How each job's most recent run ended, as this node recorded it. A job can be configured perfectly and still fail every night, and this is where that shows.",
"nextStep": {
"someFailed": "Read the error in the task log for these runs. A run that ends with an error produced no usable copy for the guests it covers.",
"recovered": "These guests failed an earlier run and have succeeded since. The earlier error is still worth reading: a failure that resolved itself often returns."
},
"rationale": "How each guest's most recent recorded run ended, from the node's task log. Only the latest run is graded. The log is retained for a limited period.",
"summary": {
"allSucceeded": "All {total} recorded backup runs ended without error",
@@ -5294,6 +5348,12 @@
},
"host_recovery": {
"title": "Host recovery",
"explanation": "Backing up the guests does not restore the node. This check looks at whether the node's own configuration — its storage definitions, its network, its users — is stored anywhere, which is what rebuilding the host itself depends on.",
"nextStep": {
"noHostBackup": "Nothing stores this node's own configuration. Rebuilding it would mean reconstructing the storage, network and user definitions by hand, from whatever notes exist.",
"attention": "Review the host configuration records listed. Each has something worth looking at: a run that failed, a destination that is gone, or a copy older than the age in use.",
"scheduledOnly": "A timer will produce host configuration backups, but none is stored yet. Until the first one runs, the node's own configuration is not protected."
},
"rationale": "Host backups as ProxMenux records them: each job it ran, when, whether it succeeded, the destination it wrote to and whether that copy is still there. A job writing to a backup server names no local path. Encryption keys are reported by count and recorded escrow mode only.",
"summary": {
"noHostBackup": "No host configuration backup is stored and no timer produces one",
@@ -5680,9 +5740,12 @@
"reasonLabel": "Reason",
"reasonHelp": "Required. It is recorded together with the author and the date.",
"reasonPlaceholder": "e.g. Lab containers, not covered on purpose",
"expiryLabel": "Review after",
"expiryLabel": "Stops applying after",
"expiryHelp": "When the period ends the finding becomes active again.",
"expiryNever": "Does not expire",
"reviewLabel": "Remind me to review",
"reviewHelp": "The decision stays in force; it is only brought back to your attention.",
"reviewNever": "No reminder",
"expiry90": "90 days",
"expiry180": "180 days",
"expiry365": "1 year",
@@ -6085,6 +6148,10 @@
"unchanged": "{count} checks reported the same result as before.",
"new": "New",
"newNote": "reported now and not before",
"worse": "Worse",
"worseNote": "still reported, and graver or reaching further than before",
"better": "Better",
"betterNote": "still reported, but less grave or reaching less far than before",
"resolved": "Resolved",
"resolvedNote": "no longer reported, and nobody accepted them",
"accepted": "Accepted",
+71 -4
View File
@@ -208,7 +208,7 @@
"notApplicable": "n / A",
"error": "Error",
"system": "Sistema",
"standby": "Apoyar",
"standby": "En reposo",
"standbyTitle": "La unidad está en espera: se omitió smartctl para mantenerla apagada",
"filesystemCorruption": "Se detectó corrupción en el sistema de archivos",
"ioErrorOne": "{count} Error de E/S en 5 minutos",
@@ -808,6 +808,10 @@
"saturday": "Sábado"
}
},
"idle": "En reposo",
"idleTitle": "No se lee mientras nada lo usa, para que pueda apagarse. Su temperatura vuelve a mostrarse en cuanto el disco se usa.",
"diskExcluded": "Excluido",
"diskExcludedTitle": "Excluido de las lecturas periódicas en Ajustes.",
"savedSmartData": "datos SMART guardados"
},
"details": {
@@ -1383,6 +1387,8 @@
"imageUpToDate": "Actualizada",
"imageInstalledTag": "etiqueta instalada",
"imageDigestUnknown": "Digest no disponible",
"imagePinned": "Anclada a un digest",
"imagePinnedTitle": "Este contenedor ejecuta exactamente la imagen que indica su digest. Un tag más reciente no la cambia; para cambiarla hay que editar la referencia en su configuración.",
"dockerPendingSummary": "Se detectaron {count} actualización(es) de imágenes Docker. Actualízalas con su flujo de Docker o Compose.",
"postApplyChecking": "Comprobando resultado de la actualización…",
"postApplyAllOk": "{count} paquete(s) aplicados correctamente — nada pendiente.",
@@ -2198,6 +2204,18 @@
"reset": "Restaurar por defecto",
"hint": "Arrastra para reordenar · En táctil, mantén pulsado primero",
"customActive": "Usando orden de navegación personalizado."
},
"diskExclusions": {
"title": "Exclusiones de discos",
"description": "Discos que nunca se leen de forma periódica, para que puedan apagarse con su propio temporizador.",
"empty": "No se han encontrado discos físicos.",
"disk": "Disco",
"periodicReads": "Lecturas periódicas",
"excluded": "Excluido",
"notConnected": "No conectado",
"saveFailed": "No se pudieron guardar las exclusiones de discos.",
"help": "Un disco excluido no recibe lecturas periódicas de temperatura ni de SMART —ni siquiera la consulta de su estado de energía—, así que el Monitor no lo consulta en absoluto. Abrir sus detalles SMART sí lo lee.",
"idleHelp": "Los discos mecánicos sin actividad ya no se consultan automáticamente, para no sacarlos del reposo, hasta que algo vuelve a usarlos."
}
},
"login": {
@@ -2206,7 +2224,7 @@
"password": "Contraseña",
"usernamePlaceholder": "Ingrese su nombre de usuario",
"passwordPlaceholder": "Introduce tu contraseña",
"rememberMe": "Acuérdate de mí",
"rememberMe": "Recordar",
"missingCredentials": "Por favor ingrese nombre de usuario y contraseña",
"missingTotp": "Por favor ingresa tu código 2FA",
"invalidCredentials": "Nombre de usuario o contraseña incorrectos",
@@ -3396,7 +3414,7 @@
},
"roles": {
"active": "activo",
"standby": "apoyar",
"standby": "en espera",
"down": "abajo"
},
"empty": {
@@ -5208,6 +5226,11 @@
"noFindings": "Ningún hallazgo coincide con el filtro actual.",
"affectedCount": "{count} afectados",
"acceptedNotice": "{count} riesgo(s) aceptado(s) registrados en este host.",
"noActionNeeded": "No hay nada que hacer. Esta comprobación ha encontrado lo que espera encontrar.",
"couldNotEvaluate": "Esta comprobación no se ha podido evaluar, así que no afirma nada en ningún sentido. La evidencia recoge qué no pudo leer.",
"reviewOn": "Revisar el: {when}",
"reviewDue": "Toca revisarla — la decisión sigue en vigor",
"reviewDueNotice": "{count} decisión(es) aceptada(s) esperan revisión.",
"states": {
"fail": "Fallo",
"warn": "Aviso",
@@ -5228,6 +5251,8 @@
},
"detail": {
"why": "Contexto",
"whatItMeans": "Qué significa",
"whatToDo": "Qué hacer",
"evidence": "Evidencia",
"affected": "Afectados",
"acceptedRisk": "Riesgo aceptado",
@@ -5240,6 +5265,13 @@
"backup": {
"guest_coverage": {
"title": "Cobertura de backups",
"explanation": "Un backup solo protege lo que un trabajo selecciona de verdad. Esta comprobación cruza los invitados de este nodo con los trabajos que se ejecutan aquí, de modo que un invitado al que nadie respalda aparece como tal en lugar de darse por cubierto por algo.",
"nextStep": {
"noJobs": "Crea un trabajo de backup en este nodo y selecciona los invitados que guarden datos que no querrías rehacer a mano. Un trabajo que existe pero está deshabilitado no selecciona nada.",
"uncovered": "Decide, para cada uno de estos invitados, si guarda algo que merezca conservarse. Añade a un trabajo los que sí; para los que no, decláralo en la política y dejarán de contarse aquí.",
"excludedData": "Abre la lista de exclusiones de cada trabajo y confirma que lo que deja fuera son datos que puedes permitirte perder. Una exclusión añadida para acelerar un trabajo no protege nada de lo que omite.",
"uncoveredExpected": "La política declara que estos invitados requieren backup y ningún trabajo activo los selecciona. Añádelos a un trabajo o cambia lo que declara la política, para que ambas cosas coincidan."
},
"rationale": "Trabajos de backup habilitados en este nodo, los invitados que selecciona cada uno y los datos del invitado excluidos de ellos. La cobertura configurada no demuestra que exista una copia utilizable. Si un invitado no seleccionado debía protegerse lo indica la política declarada.",
"summary": {
"noJobs": "No hay ningún trabajo de backup definido en este nodo para los {total} invitados que alberga",
@@ -5252,6 +5284,12 @@
},
"last_backup_age": {
"title": "Antigüedad de las copias almacenadas",
"explanation": "Que exista un trabajo no es lo mismo que exista una copia. Esta comprobación lee la copia más reciente de cada invitado y cuánto hace que se escribió, que es hasta dónde tendrías que retroceder si hoy hubiera que restaurar.",
"nextStep": {
"stale": "Averigua por qué el trabajo dejó de producir copias de estos invitados: puede estar deshabilitado, su programación puede no dispararse nunca, o sus ejecuciones pueden estar fallando. La comprobación de resultados indica cómo terminó cada trabajo.",
"noBackups": "Ninguna copia almacenada corresponde a un invitado de este nodo. Si los trabajos escriben en un destino que este nodo no puede leer, es lo esperable; si no, no están produciendo nada.",
"attention": "Revisa los invitados de la lista. Cada uno no tiene copia reciente o la que tiene supera la antigüedad en uso."
},
"rationale": "Antigüedad: tiempo transcurrido desde la última copia almacenada. Límite utilizado: antigüedad de referencia con la que se compara esa copia.",
"summary": {
"recent": "Las {total} comprobaciones de máquina/destino cumplen el criterio de antigüedad indicado",
@@ -5263,6 +5301,12 @@
},
"retention_defined": {
"title": "Retención de backups",
"explanation": "La retención decide cuántas copias se conservan y durante cuánto tiempo. Sin ella un destino se llena hasta dejar de admitir copias nuevas, y un backup que no se puede escribir es justo del que te enteras el día que lo necesitas.",
"nextStep": {
"missing": "Define una retención en estos trabajos, o en el almacenamiento donde escriben. Proxmox toma primero el ajuste del trabajo, después el del almacenamiento y por último el del nodo.",
"notDeclared": "Estos trabajos conservan todas las copias que hacen. En algunos destinos es una decisión deliberada, pero confirma que el destino tiene sitio para seguir creciendo.",
"onServer": "Estos trabajos escriben en un servidor de backup, que las poda con sus propias reglas. Lo que conserva no se puede leer desde este nodo, así que comprueba la retención allí."
},
"rationale": "La retención tal como la resuelve Proxmox: el ajuste del trabajo, después el del almacenamiento y después el valor por defecto del nodo. La retención que aplica un servidor de backup no se puede leer desde este nodo.",
"summary": {
"allDefined": "Los {total} trabajos resuelven un ajuste de retención",
@@ -5274,6 +5318,11 @@
},
"verification_state": {
"title": "Verificación de las copias",
"explanation": "La verificación vuelve a leer una copia almacenada y confirma que está íntegra. Es la diferencia entre una copia que existe y una copia que se puede leer, una distinción que solo importa el día que la necesitas.",
"nextStep": {
"failed": "No se puede confiar en una copia que no supera la verificación. Comprueba si una copia anterior del mismo invitado sí la superó, y revisa el almacenamiento donde residen las que han fallado.",
"notVerified": "Nada ha confirmado que estas copias se puedan volver a leer. Un servidor de backup puede verificarlas con una programación propia, independiente del trabajo que las escribió."
},
"rationale": "El resultado de verificación que Proxmox Backup Server registra para la copia más reciente de cada invitado, y si una copia anterior del mismo invitado se verificó. La verificación lee una copia almacenada; no es una restauración.",
"summary": {
"allVerified": "La copia más reciente de los {total} invitados se ha verificado íntegra",
@@ -5284,6 +5333,11 @@
},
"job_results": {
"title": "Resultado de las ejecuciones de backup",
"explanation": "Cómo terminó la última ejecución de cada trabajo, según lo registró este nodo. Un trabajo puede estar perfectamente configurado y aun así fallar todas las noches, y es aquí donde eso se ve.",
"nextStep": {
"someFailed": "Lee el error en el registro de tareas de estas ejecuciones. Una ejecución que termina con error no ha producido ninguna copia utilizable de los invitados que cubre.",
"recovered": "Estos invitados fallaron en una ejecución anterior y desde entonces han terminado bien. El error anterior merece leerse igualmente: un fallo que se arregló solo suele volver."
},
"rationale": "Cómo terminó la ejecución más reciente de cada invitado, según el registro de tareas del nodo. Solo se gradúa la última. El registro se conserva un tiempo limitado.",
"summary": {
"allSucceeded": "Las {total} ejecuciones de backup registradas terminaron sin error",
@@ -5294,6 +5348,12 @@
},
"host_recovery": {
"title": "Recuperación del host",
"explanation": "Respaldar los invitados no restaura el nodo. Esta comprobación mira si la configuración del propio nodo —sus definiciones de almacenamiento, su red, sus usuarios— está guardada en algún sitio, que es de lo que depende poder reconstruir el host.",
"nextStep": {
"noHostBackup": "Nada guarda la configuración de este nodo. Reconstruirlo supondría rehacer a mano las definiciones de almacenamiento, red y usuarios, a partir de las notas que haya.",
"attention": "Revisa los registros de configuración del host de la lista. Cada uno tiene algo que mirar: una ejecución que falló, un destino que ya no está, o una copia más antigua que el límite en uso.",
"scheduledOnly": "Un temporizador producirá backups de la configuración del host, pero todavía no hay ninguno guardado. Hasta que se ejecute el primero, la configuración del nodo no está protegida."
},
"rationale": "Backups del host tal como los registra ProxMenux: cada trabajo que ejecutó, cuándo, si terminó bien, el destino donde escribió y si esa copia sigue ahí. Un trabajo que escribe en un servidor de backup no nombra ninguna ruta local. Las claves de cifrado se exponen solo por recuento y modo de custodia registrado.",
"summary": {
"noHostBackup": "No hay ningún backup de la configuración del host almacenado ni temporizador que lo genere",
@@ -5680,9 +5740,12 @@
"reasonLabel": "Motivo",
"reasonHelp": "Obligatorio. Queda registrado junto al autor y la fecha.",
"reasonPlaceholder": "p. ej. Contenedores de laboratorio, sin cobertura a propósito",
"expiryLabel": "Revisar dentro de",
"expiryLabel": "Deja de aplicarse tras",
"expiryHelp": "Al cumplirse el plazo el hallazgo vuelve a estado activo.",
"expiryNever": "No caduca",
"reviewLabel": "Recordarme revisarla",
"reviewHelp": "La decisión sigue en vigor; solo vuelve a tu atención.",
"reviewNever": "Sin recordatorio",
"expiry90": "90 días",
"expiry180": "180 días",
"expiry365": "1 año",
@@ -6085,6 +6148,10 @@
"unchanged": "{count} comprobaciones dieron el mismo resultado que antes.",
"new": "Nuevos",
"newNote": "se informan ahora y antes no",
"worse": "Empeoraron",
"worseNote": "se siguen informando, y son más graves o alcanzan a más que antes",
"better": "Mejoraron",
"betterNote": "se siguen informando, pero son menos graves o alcanzan a menos que antes",
"resolved": "Resueltos",
"resolvedNote": "ya no se informan, y nadie los aceptó",
"accepted": "Aceptados",
+29 -17
View File
@@ -208,7 +208,7 @@
"notApplicable": "n / A",
"error": "Erreur",
"system": "Système",
"standby": "Attendre",
"standby": "Veille",
"standbyTitle": "Le lecteur est en veille - smartctl a été ignoré pour le maintenir en veille",
"filesystemCorruption": "Corruption du système de fichiers détectée",
"ioErrorOne": "{count} Erreur d'E/S dans 5 min",
@@ -2206,7 +2206,7 @@
"password": "Mot de passe",
"usernamePlaceholder": "Entrez votre nom d'utilisateur",
"passwordPlaceholder": "Entrez votre mot de passe",
"rememberMe": "Souviens-toi de moi",
"rememberMe": "Mémoriser",
"missingCredentials": "Veuillez entrer votre nom d'utilisateur et votre mot de passe",
"missingTotp": "Veuillez entrer votre code 2FA",
"invalidCredentials": "Nom d'utilisateur ou mot de passe incorrect",
@@ -3396,7 +3396,7 @@
},
"roles": {
"active": "actif",
"standby": "attendre",
"standby": "secours",
"down": "vers le bas"
},
"empty": {
@@ -5208,6 +5208,9 @@
"noFindings": "No findings match the current filter.",
"affectedCount": "{count} affected",
"acceptedNotice": "{count} accepted risk(s) recorded on this host.",
"reviewOn": "À revoir le : {when}",
"reviewDue": "À revoir — la décision reste en vigueur",
"reviewDueNotice": "{count} décision(s) acceptée(s) sont à revoir.",
"states": {
"fail": "Failed",
"warn": "Warning",
@@ -5228,6 +5231,8 @@
},
"detail": {
"why": "Context",
"whatItMeans": "Ce que cela signifie",
"whatToDo": "Que faire",
"evidence": "Evidence",
"affected": "Affected",
"acceptedRisk": "Accepted risk",
@@ -5674,20 +5679,23 @@
},
"summaryFallback": "The check could not be evaluated",
"acceptRisk": {
"action": "Accept risk",
"revoke": "Return to active",
"title": "Accept this risk",
"reasonLabel": "Reason",
"reasonHelp": "Required. It is recorded together with the author and the date.",
"reasonPlaceholder": "e.g. Lab containers, not covered on purpose",
"expiryLabel": "Review after",
"expiryHelp": "When the period ends the finding becomes active again.",
"expiryNever": "Does not expire",
"expiry90": "90 days",
"expiry180": "180 days",
"expiry365": "1 year",
"cancel": "Cancel",
"confirm": "Accept risk"
"action": "Accepter le risque",
"revoke": "Remettre en actif",
"title": "Accepter ce risque",
"reasonLabel": "Motif",
"reasonHelp": "Obligatoire. Il est enregistré avec son auteur et la date.",
"reasonPlaceholder": "ex. Conteneurs de laboratoire, non couverts volontairement",
"expiryLabel": "Cesse de s'appliquer après",
"expiryHelp": "À la fin de la période, le constat redevient actif.",
"expiryNever": "N'expire pas",
"reviewLabel": "Me rappeler de la revoir",
"reviewHelp": "La décision reste en vigueur ; elle revient seulement à votre attention.",
"reviewNever": "Pas de rappel",
"expiry90": "90 jours",
"expiry180": "180 jours",
"expiry365": "1 an",
"cancel": "Annuler",
"confirm": "Accepter le risque"
},
"incomplete": "Preuves incomplètes",
"progress": "{completed} sur {total} vérifiés",
@@ -6085,6 +6093,10 @@
"unchanged": "{count} contrôles ont donné le même résultat qu'avant.",
"new": "Nouveaux",
"newNote": "signalés maintenant et pas avant",
"worse": "Aggravés",
"worseNote": "toujours signalés, et plus graves ou plus étendus qu'avant",
"better": "Améliorés",
"betterNote": "toujours signalés, mais moins graves ou moins étendus qu'avant",
"resolved": "Résolus",
"resolvedNote": "plus signalés, et personne ne les a acceptés",
"accepted": "Acceptés",
+27 -15
View File
@@ -2206,7 +2206,7 @@
"password": "Password",
"usernamePlaceholder": "Inserisci il tuo nome utente",
"passwordPlaceholder": "Inserisci la tua password",
"rememberMe": "Ricordati di me",
"rememberMe": "Ricorda",
"missingCredentials": "Inserisci nome utente e password",
"missingTotp": "Inserisci il tuo codice 2FA",
"invalidCredentials": "Nome utente o password errati",
@@ -5208,6 +5208,9 @@
"noFindings": "No findings match the current filter.",
"affectedCount": "{count} affected",
"acceptedNotice": "{count} accepted risk(s) recorded on this host.",
"reviewOn": "Da rivedere il: {when}",
"reviewDue": "Da rivedere — la decisione resta valida",
"reviewDueNotice": "{count} decisione/i accettata/e da rivedere.",
"states": {
"fail": "Failed",
"warn": "Warning",
@@ -5228,6 +5231,8 @@
},
"detail": {
"why": "Context",
"whatItMeans": "Che cosa significa",
"whatToDo": "Cosa fare",
"evidence": "Evidence",
"affected": "Affected",
"acceptedRisk": "Accepted risk",
@@ -5674,20 +5679,23 @@
},
"summaryFallback": "The check could not be evaluated",
"acceptRisk": {
"action": "Accept risk",
"revoke": "Return to active",
"title": "Accept this risk",
"reasonLabel": "Reason",
"reasonHelp": "Required. It is recorded together with the author and the date.",
"reasonPlaceholder": "e.g. Lab containers, not covered on purpose",
"expiryLabel": "Review after",
"expiryHelp": "When the period ends the finding becomes active again.",
"expiryNever": "Does not expire",
"expiry90": "90 days",
"expiry180": "180 days",
"expiry365": "1 year",
"cancel": "Cancel",
"confirm": "Accept risk"
"action": "Accetta il rischio",
"revoke": "Riporta tra gli attivi",
"title": "Accetta questo rischio",
"reasonLabel": "Motivo",
"reasonHelp": "Obbligatorio. Viene registrato insieme all'autore e alla data.",
"reasonPlaceholder": "es. Container di laboratorio, non coperti di proposito",
"expiryLabel": "Smette di applicarsi dopo",
"expiryHelp": "Alla fine del periodo il rilievo torna attivo.",
"expiryNever": "Non scade",
"reviewLabel": "Ricordami di rivederla",
"reviewHelp": "La decisione resta valida; torna solo alla tua attenzione.",
"reviewNever": "Nessun promemoria",
"expiry90": "90 giorni",
"expiry180": "180 giorni",
"expiry365": "1 anno",
"cancel": "Annulla",
"confirm": "Accetta il rischio"
},
"incomplete": "Evidenze incomplete",
"progress": "Verificati {completed} di {total}",
@@ -6085,6 +6093,10 @@
"unchanged": "{count} controlli hanno dato lo stesso risultato di prima.",
"new": "Nuovi",
"newNote": "segnalati ora e prima no",
"worse": "Peggiorati",
"worseNote": "ancora segnalati, e più gravi o più estesi di prima",
"better": "Migliorati",
"betterNote": "ancora segnalati, ma meno gravi o meno estesi di prima",
"resolved": "Risolti",
"resolvedNote": "non più segnalati, e nessuno li ha accettati",
"accepted": "Accettati",
+27 -15
View File
@@ -2206,7 +2206,7 @@
"password": "Senha",
"usernamePlaceholder": "Digite seu nome de usuário",
"passwordPlaceholder": "Digite sua senha",
"rememberMe": "Lembre de mim",
"rememberMe": "Lembrar",
"missingCredentials": "Por favor insira nome de usuário e senha",
"missingTotp": "Por favor, insira seu código 2FA",
"invalidCredentials": "Nome de usuário ou senha incorretos",
@@ -5208,6 +5208,9 @@
"noFindings": "No findings match the current filter.",
"affectedCount": "{count} affected",
"acceptedNotice": "{count} accepted risk(s) recorded on this host.",
"reviewOn": "Rever em: {when}",
"reviewDue": "A rever — a decisão continua em vigor",
"reviewDueNotice": "{count} decisão(ões) aceite(s) aguardam revisão.",
"states": {
"fail": "Failed",
"warn": "Warning",
@@ -5228,6 +5231,8 @@
},
"detail": {
"why": "Context",
"whatItMeans": "O que isto significa",
"whatToDo": "O que fazer",
"evidence": "Evidence",
"affected": "Affected",
"acceptedRisk": "Accepted risk",
@@ -5674,20 +5679,23 @@
},
"summaryFallback": "The check could not be evaluated",
"acceptRisk": {
"action": "Accept risk",
"revoke": "Return to active",
"title": "Accept this risk",
"reasonLabel": "Reason",
"reasonHelp": "Required. It is recorded together with the author and the date.",
"reasonPlaceholder": "e.g. Lab containers, not covered on purpose",
"expiryLabel": "Review after",
"expiryHelp": "When the period ends the finding becomes active again.",
"expiryNever": "Does not expire",
"expiry90": "90 days",
"expiry180": "180 days",
"expiry365": "1 year",
"cancel": "Cancel",
"confirm": "Accept risk"
"action": "Aceitar risco",
"revoke": "Voltar a ativo",
"title": "Aceitar este risco",
"reasonLabel": "Motivo",
"reasonHelp": "Obrigatório. É registado junto com o autor e a data.",
"reasonPlaceholder": "ex. Contentores de laboratório, não cobertos de propósito",
"expiryLabel": "Deixa de aplicar-se após",
"expiryHelp": "No fim do período o achado volta a ficar ativo.",
"expiryNever": "Não expira",
"reviewLabel": "Lembrar-me de rever",
"reviewHelp": "A decisão continua em vigor; apenas volta à sua atenção.",
"reviewNever": "Sem lembrete",
"expiry90": "90 dias",
"expiry180": "180 dias",
"expiry365": "1 ano",
"cancel": "Cancelar",
"confirm": "Aceitar risco"
},
"incomplete": "Evidência incompleta",
"progress": "Verificadas {completed} de {total}",
@@ -6085,6 +6093,10 @@
"unchanged": "{count} verificações deram o mesmo resultado que antes.",
"new": "Novos",
"newNote": "reportados agora e antes não",
"worse": "Pioraram",
"worseNote": "continuam a ser reportados, e são mais graves ou mais abrangentes do que antes",
"better": "Melhoraram",
"betterNote": "continuam a ser reportados, mas são menos graves ou menos abrangentes do que antes",
"resolved": "Resolvidos",
"resolvedNote": "já não são reportados, e ninguém os aceitou",
"accepted": "Aceites",
+12
View File
@@ -5208,6 +5208,9 @@
"noFindings": "Aktuálnemu filtru nezodpovedajú žiadne zistenia.",
"affectedCount": "ovplyvnené: {count}",
"acceptedNotice": "Na tomto serveri je zaznamenaných {count} prijatých rizík.",
"reviewOn": "Skontrolovať dňa: {when}",
"reviewDue": "Čaká na kontrolu — rozhodnutie stále platí",
"reviewDueNotice": "{count} prijaté rozhodnutie/a čaká na kontrolu.",
"states": {
"fail": "Zlyhalo",
"warn": "Upozornenie",
@@ -5228,6 +5231,8 @@
},
"detail": {
"why": "Súvislosti",
"whatItMeans": "Čo to znamená",
"whatToDo": "Čo urobiť",
"evidence": "Podklady",
"affected": "Ovplyvnené",
"acceptedRisk": "Prijaté riziko",
@@ -5683,6 +5688,9 @@
"expiryLabel": "Znova preveriť po",
"expiryHelp": "Po uplynutí obdobia bude zistenie opäť aktívne.",
"expiryNever": "Bez vypršania",
"reviewLabel": "Pripomenúť kontrolu",
"reviewHelp": "Rozhodnutie stále platí; iba sa znova dostane do pozornosti.",
"reviewNever": "Bez pripomienky",
"expiry90": "90 dní",
"expiry180": "180 dní",
"expiry365": "1 rok",
@@ -6085,6 +6093,10 @@
"unchanged": "{count} kontrol dalo rovnaký výsledok ako predtým.",
"new": "Nové",
"newNote": "hlásené teraz a predtým nie",
"worse": "Zhoršené",
"worseNote": "stále sa hlásia a sú závažnejšie alebo majú väčší rozsah než predtým",
"better": "Zlepšené",
"betterNote": "stále sa hlásia, ale sú menej závažné alebo majú menší rozsah než predtým",
"resolved": "Vyriešené",
"resolvedNote": "už sa nehlásia a nikto ich neprijal",
"accepted": "Prijaté",
+26 -14
View File
@@ -5208,6 +5208,9 @@
"noFindings": "No findings match the current filter.",
"affectedCount": "{count} affected",
"acceptedNotice": "{count} accepted risk(s) recorded on this host.",
"reviewOn": "Granska den: {when}",
"reviewDue": "Dags att granska — beslutet gäller fortfarande",
"reviewDueNotice": "{count} accepterade beslut väntar på granskning.",
"states": {
"fail": "Failed",
"warn": "Warning",
@@ -5228,6 +5231,8 @@
},
"detail": {
"why": "Context",
"whatItMeans": "Vad detta betyder",
"whatToDo": "Vad du gör",
"evidence": "Evidence",
"affected": "Affected",
"acceptedRisk": "Accepted risk",
@@ -5674,20 +5679,23 @@
},
"summaryFallback": "The check could not be evaluated",
"acceptRisk": {
"action": "Accept risk",
"revoke": "Return to active",
"title": "Accept this risk",
"reasonLabel": "Reason",
"reasonHelp": "Required. It is recorded together with the author and the date.",
"reasonPlaceholder": "e.g. Lab containers, not covered on purpose",
"expiryLabel": "Review after",
"expiryHelp": "When the period ends the finding becomes active again.",
"expiryNever": "Does not expire",
"expiry90": "90 days",
"expiry180": "180 days",
"expiry365": "1 year",
"cancel": "Cancel",
"confirm": "Accept risk"
"action": "Acceptera risken",
"revoke": "Återför till aktiva",
"title": "Acceptera den här risken",
"reasonLabel": "Orsak",
"reasonHelp": "Obligatorisk. Den sparas tillsammans med upphovsperson och datum.",
"reasonPlaceholder": "t.ex. Labbcontainrar, medvetet inte täckta",
"expiryLabel": "Slutar gälla efter",
"expiryHelp": "När perioden tar slut blir fyndet aktivt igen.",
"expiryNever": "Upphör inte",
"reviewLabel": "Påminn mig om att granska",
"reviewHelp": "Beslutet gäller fortfarande; det lyfts bara fram igen.",
"reviewNever": "Ingen påminnelse",
"expiry90": "90 dagar",
"expiry180": "180 dagar",
"expiry365": "1 år",
"cancel": "Avbryt",
"confirm": "Acceptera risken"
},
"incomplete": "Ofullständiga underlag",
"progress": "Kontrollerat {completed} av {total}",
@@ -6085,6 +6093,10 @@
"unchanged": "{count} kontroller gav samma resultat som förut.",
"new": "Nya",
"newNote": "rapporteras nu men inte förut",
"worse": "Försämrade",
"worseNote": "rapporteras fortfarande, och är allvarligare eller når längre än förut",
"better": "Förbättrade",
"betterNote": "rapporteras fortfarande, men är mindre allvarliga eller når kortare än förut",
"resolved": "Åtgärdade",
"resolvedNote": "rapporteras inte längre, och ingen accepterade dem",
"accepted": "Accepterade",