diff --git a/frontend-modern/.bundlesize.json b/frontend-modern/.bundlesize.json index 1a8e7aa20..9358e2525 100644 --- a/frontend-modern/.bundlesize.json +++ b/frontend-modern/.bundlesize.json @@ -1,107 +1,119 @@ { "$comment": "Frontend bundle size baseline. Run 'npm run check:bundlesize' to validate. To update: run 'node scripts/check-bundle-size.mjs --update-baseline' after vite build.", "version": 1, - "generated": "2026-06-11", + "generated": "2026-06-14", "defaultThresholdPercent": 15, "chunks": { - "Alerts": { - "baselineGzip": 93457 - }, "index": { - "baselineGzip": 92914 + "baselineGzip": 105021 + }, + "Alerts": { + "baselineGzip": 88311 }, "sharedPlatformPage": { - "baselineGzip": 82135 + "baselineGzip": 87771 }, "Settings": { - "baselineGzip": 77260 + "baselineGzip": 75500 }, "InfrastructureWorkspace": { - "baselineGzip": 74074 + "baselineGzip": 73414 }, "Proxmox": { - "baselineGzip": 65241 + "baselineGzip": 67144 }, "Chat": { - "baselineGzip": 63244 + "baselineGzip": 63676 }, "WorkloadsSurface": { - "baselineGzip": 53519 + "baselineGzip": 52750 }, "AIIntelligence": { - "baselineGzip": 51719 + "baselineGzip": 50280 }, "vendor-ai": { - "baselineGzip": 20801 + "baselineGzip": 21151 }, "Docker": { - "baselineGzip": 19206 - }, - "Standalone": { - "baselineGzip": 17421 + "baselineGzip": 20862 }, "vendor-solid": { - "baselineGzip": 17399 + "baselineGzip": 17398 + }, + "Standalone": { + "baselineGzip": 17009 }, "Kubernetes": { - "baselineGzip": 15077 + "baselineGzip": 13756 + }, + "vendor-highlight": { + "baselineGzip": 13742 }, "TrueNAS": { - "baselineGzip": 14223 + "baselineGzip": 13490 }, "APIAccessPanel": { - "baselineGzip": 10741 + "baselineGzip": 10773 }, "vendor-icons": { - "baselineGzip": 10520 + "baselineGzip": 10755 }, "vendor": { - "baselineGzip": 9853 - }, - "Vmware": { - "baselineGzip": 9026 - }, - "ReportingPanel": { - "baselineGzip": 8989 + "baselineGzip": 9857 }, "AuditLogPanel": { - "baselineGzip": 8767 + "baselineGzip": 8696 }, - "discovery": { - "baselineGzip": 8386 + "ReportingPanel": { + "baselineGzip": 8561 + }, + "Vmware": { + "baselineGzip": 8491 + }, + "messages.de": { + "baselineGzip": 8043 + }, + "messages.es": { + "baselineGzip": 7835 + }, + "FormTextarea": { + "baselineGzip": 7693 }, "aiChat": { - "baselineGzip": 7629 + "baselineGzip": 7689 }, "UpdatesSettingsPanel": { - "baselineGzip": 7365 + "baselineGzip": 7293 }, "FilterBar": { - "baselineGzip": 6289 - }, - "AvailabilitySettingsPanel": { - "baselineGzip": 6080 + "baselineGzip": 6293 }, "SecurityAuthPanel": { - "baselineGzip": 5956 + "baselineGzip": 5797 + }, + "DrawerDiskListCard": { + "baselineGzip": 5796 + }, + "AvailabilitySettingsPanel": { + "baselineGzip": 5631 }, "DiagnosticsPanel": { - "baselineGzip": 5761 - }, - "HelpIcon": { - "baselineGzip": 5622 + "baselineGzip": 5565 }, "useUnifiedResources": { - "baselineGzip": 5528 + "baselineGzip": 5536 }, "SetupWizard": { - "baselineGzip": 5527 + "baselineGzip": 5521 + }, + "HelpIcon": { + "baselineGzip": 5500 }, "ResourceChangeSummary": { - "baselineGzip": 5501 + "baselineGzip": 5500 }, "OrganizationSharingPanel": { - "baselineGzip": 5440 + "baselineGzip": 5182 }, "truenasPageModel": { "baselineGzip": 5157 @@ -109,10 +121,10 @@ }, "totals": { "js": { - "baselineGzip": 1015839 + "baselineGzip": 1061883 }, "css": { - "baselineGzip": 25744 + "baselineGzip": 25895 } } } diff --git a/frontend-modern/public/docs/README.md b/frontend-modern/public/docs/README.md index 7f76df3f3..b8b0bc504 100644 --- a/frontend-modern/public/docs/README.md +++ b/frontend-modern/public/docs/README.md @@ -31,6 +31,10 @@ All other documents are supporting references unless explicitly required for evi ## 🚀 Getting Started +- **Localized getting started**: + [Deutsch](i18n/de/README.md) • [Español](i18n/es/README.md). + These first-wave pages cover the public install path and preserve commands, + config keys, image names, activation keys, and product identifiers exactly. - **[Installation Guide](INSTALL.md)** Step-by-step guides for Docker, Kubernetes, and bare metal. - **[Configuration](CONFIGURATION.md)** diff --git a/frontend-modern/public/docs/i18n/README.md b/frontend-modern/public/docs/i18n/README.md new file mode 100644 index 000000000..821166ac1 --- /dev/null +++ b/frontend-modern/public/docs/i18n/README.md @@ -0,0 +1,12 @@ +# Localized Pulse docs + +This directory contains first-wave localized getting-started docs for public +Pulse users. + +- [Deutsch](de/README.md) +- [Español](es/README.md) + +The canonical deep documentation remains the English docs tree. Localized docs +must preserve commands, image names, config keys, activation-key formats, +paths, API fields, product names, and resource names exactly unless the owning +English source changes. diff --git a/frontend-modern/public/docs/i18n/de/README.md b/frontend-modern/public/docs/i18n/de/README.md new file mode 100644 index 000000000..796c1561a --- /dev/null +++ b/frontend-modern/public/docs/i18n/de/README.md @@ -0,0 +1,127 @@ +# Pulse Einstieg auf Deutsch + +Diese Seite ist der deutschsprachige Einstieg für Installation, erste Anmeldung +und Planwahl. Die vollständige, kanonische Dokumentation bleibt in der +englischen Dokumentation unter [docs/README.md](../../README.md). Befehle, +Image-Namen, Konfigurationsschlüssel, Aktivierungsschlüssel und UI-Pfade bleiben +absichtlich unverändert. + +## Was ist Pulse? + +Pulse ist ein self-hosted Monitoring-Arbeitsbereich für Proxmox, Docker, +Kubernetes, TrueNAS und verwandte Infrastruktur. Community deckt das +Kernmonitoring kostenlos ab. Relay ergänzt sicheren Remote-Zugriff auf die +Pulse-Weboberfläche, Pulse-Mobile-Handoff-Pairing, Push-Benachrichtigungen und +14 Tage Verlauf. Pro ergänzt Ursachenanalyse, sichere Remediation-Workflows, +Operations-Werkzeuge, Governance-Funktionen und 90 Tage Verlauf. + +## Bezahlte Relay-, Pro- und Legacy-Kunden + +GitHub-Release-Assets und das öffentliche Docker-Image `rcourtman/pulse` sind +Community-Builds. Aktiviere deinen Lizenzschlüssel unter +**Settings → Plans → Existing purchases**, um Pro-Funktionen freizuschalten. + +Diese Community-Builds enthalten nicht die privaten Pulse-Pro-Runtime-Hooks +für Audit Log, Audit Webhooks, RBAC und governed remediation. Für diese +Runtime verwende mit einem +**v6 activation key**. Ein v6 activation key beginnt mit `ppk_live_`. Ein v5- +oder Legacy-Lizenzschlüssel ist kein `ppk_live_` activation key und +funktioniert auf dieser Download-Seite nicht. + +## Schnellstart: Proxmox LXC + +Wenn du Proxmox VE verwendest, ist der offizielle LXC-Installer der +Pulse-native Einstieg. Er installiert den Pulse-Server. Ersetze `vX.Y.Z` durch +den exakten Release-Tag, den du installieren möchtest, prüfe die signierte +Installer-Datei und führe den Installer auf deinem Proxmox-Host aus: + +```bash +export PULSE_VERSION=vX.Y.Z +curl -fsSLO "https://github.com/rcourtman/Pulse/releases/download/${PULSE_VERSION}/install.sh" +curl -fsSLO "https://github.com/rcourtman/Pulse/releases/download/${PULSE_VERSION}/install.sh.sshsig" +ssh-keygen -Y verify \ + -f <(printf '%s\n' 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMZd/DaH+BldzOkq1A8KVTcFk73nAyrE8aJOyf7i00jm pulse-installer') \ + -I pulse-installer \ + -n pulse-install \ + -s install.sh.sshsig < install.sh +bash install.sh --version "${PULSE_VERSION}" +rm -f install.sh install.sh.sshsig +``` + +Agent-Installationen und v5-zu-v6-Agent-Upgrades verwenden den Befehl, den +Pulse unter **Settings → Infrastructure → Install on a host** erzeugt. Dieser +Befehl wird von deinem Pulse-Server über `/install.sh` bereitgestellt. + +## Schnellstart: Docker + +Für Container-Umgebungen oder Tests kannst du Pulse direkt mit Docker starten: + +```bash +docker run -d \ + --name pulse \ + -p 7655:7655 \ + -v pulse_data:/data \ + --restart unless-stopped \ + rcourtman/pulse:vX.Y.Z +``` + +Öffne danach Pulse unter `http://:7655`. + +Für Docker Compose kann dieselbe Compose-Datei Community- und private Pro-Images +verwenden, wenn sie die `PULSE_IMAGE`-Variable nutzt: + +```yaml +services: + pulse: + image: ${PULSE_IMAGE:-rcourtman/pulse:vX.Y.Z} + container_name: pulse + restart: unless-stopped + ports: + - "7655:7655" + volumes: + - pulse_data:/data + environment: + - PULSE_AUTH_USER=admin + - PULSE_AUTH_PASS=secret123 + +volumes: + pulse_data: +``` + +## Erste Anmeldung + +Beim ersten Start musst du ein **Bootstrap Token** abrufen und damit den +Admin-Account erstellen. + +| Plattform | Befehl | +|---|---| +| Docker | `docker exec pulse /app/pulse bootstrap-token` | +| Kubernetes | `kubectl exec -it -- /app/pulse bootstrap-token` | +| Systemd | `sudo pulse bootstrap-token` | + +Füge den Token-String ein, den der Befehl ausgibt. Füge nicht direkt den Inhalt +der Datei `.bootstrap_token` ein. In v6 kann diese Datei einen verschlüsselten +JSON-Snapshot enthalten, nicht den verwendbaren Setup-Token. + +1. Öffne `http://:7655`. +2. Füge das **Bootstrap Token** ein. +3. Schließe den **Quick Security Setup**-Assistenten ab. +4. Öffne **Settings → Infrastructure → Install on a host**, wenn du den + unified agent auf Hosts installieren möchtest. + +Für Proxmox solltest du mit API-only Monitoring starten, wenn Inventar, +Node-Status, VM-/Container-Status und Storage-Metriken ausreichen. Agenten sind +für inside-guest Docker/Podman-Sichtbarkeit, Host-SMART-/Temperaturdaten, +lokale ZFS-/Ceph-/mdadm-Details oder andere Telemetrie nötig, die lokalen +Host-Zugriff braucht. + +## Wo geht es weiter? + +- [Installation Guide](../../INSTALL.md) für vollständige Installationspfade. +- [Configuration](../../CONFIGURATION.md) für Authentifizierung, + Benachrichtigungen und Systemeinstellungen. +- [Troubleshooting](../../TROUBLESHOOTING.md) für Logs und häufige Probleme. +- [Agent Security](../../AGENT_SECURITY.md) für Agent-Rechte, + Proxmox-API-only-Optionen und Signaturprüfung. +- [Plans and entitlements](../../PULSE_PRO.md) für Community, Relay, Pro und + Cloud. diff --git a/frontend-modern/public/docs/i18n/es/README.md b/frontend-modern/public/docs/i18n/es/README.md new file mode 100644 index 000000000..d9aaed020 --- /dev/null +++ b/frontend-modern/public/docs/i18n/es/README.md @@ -0,0 +1,128 @@ +# Primeros pasos con Pulse en español + +Esta página es la entrada en español para instalación, primer inicio de sesión y +elección de plan. La documentación completa y canónica sigue estando en la +documentación en inglés en [docs/README.md](../../README.md). Los comandos, +nombres de imágenes, claves de configuración, claves de activación y rutas de +la interfaz se conservan sin traducir de forma intencional. + +## ¿Qué es Pulse? + +Pulse es un workspace de monitoreo autohospedado para Proxmox, Docker, +Kubernetes, TrueNAS e infraestructura relacionada. Community incluye el +monitoreo principal gratis. Relay añade acceso remoto seguro a la interfaz web +de Pulse, emparejamiento con Pulse Mobile para handoff, notificaciones push e +historial de 14 días. Pro añade análisis de causa raíz, flujos de remediación +seguros, herramientas operativas, funciones de gobernanza e historial de 90 +días. + +## Clientes de pago Relay, Pro y legacy + +Los assets de GitHub Releases y la imagen pública de Docker `rcourtman/pulse` +son builds Community. Activa tu licencia en +**Settings → Plans → Existing purchases** para desbloquear funciones Pro. + +Estos builds Community no incluyen los hooks privados de runtime de Pulse Pro +para Audit Log, Audit Webhooks, RBAC y governed remediation. Para esa runtime, +usa con una **v6 activation key**. Una +v6 activation key empieza con `ppk_live_`. Una clave v5 o legacy no es una +activation key `ppk_live_` y no funcionará en esa página de descarga. + +## Inicio rápido: Proxmox LXC + +Si usas Proxmox VE, el instalador LXC oficial es el camino más nativo de Pulse. +Instala el servidor Pulse. Sustituye `vX.Y.Z` por la etiqueta exacta del +release que quieres instalar, verifica el instalador firmado y ejecútalo en tu +host Proxmox: + +```bash +export PULSE_VERSION=vX.Y.Z +curl -fsSLO "https://github.com/rcourtman/Pulse/releases/download/${PULSE_VERSION}/install.sh" +curl -fsSLO "https://github.com/rcourtman/Pulse/releases/download/${PULSE_VERSION}/install.sh.sshsig" +ssh-keygen -Y verify \ + -f <(printf '%s\n' 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMZd/DaH+BldzOkq1A8KVTcFk73nAyrE8aJOyf7i00jm pulse-installer') \ + -I pulse-installer \ + -n pulse-install \ + -s install.sh.sshsig < install.sh +bash install.sh --version "${PULSE_VERSION}" +rm -f install.sh install.sh.sshsig +``` + +Las instalaciones de agentes y las actualizaciones de agentes de v5 a v6 usan +el comando que Pulse genera en **Settings → Infrastructure → Install on a +host**. Ese comando se sirve desde tu servidor Pulse en `/install.sh`. + +## Inicio rápido: Docker + +Para entornos en contenedores o pruebas, puedes iniciar Pulse directamente con +Docker: + +```bash +docker run -d \ + --name pulse \ + -p 7655:7655 \ + -v pulse_data:/data \ + --restart unless-stopped \ + rcourtman/pulse:vX.Y.Z +``` + +Después abre Pulse en `http://:7655`. + +Con Docker Compose, el mismo archivo puede servir para imágenes Community y +Pro privadas si usa la variable `PULSE_IMAGE`: + +```yaml +services: + pulse: + image: ${PULSE_IMAGE:-rcourtman/pulse:vX.Y.Z} + container_name: pulse + restart: unless-stopped + ports: + - "7655:7655" + volumes: + - pulse_data:/data + environment: + - PULSE_AUTH_USER=admin + - PULSE_AUTH_PASS=secret123 + +volumes: + pulse_data: +``` + +## Primer inicio de sesión + +En el primer arranque debes recuperar un **Bootstrap Token** y usarlo para +crear la cuenta administradora. + +| Plataforma | Comando | +|---|---| +| Docker | `docker exec pulse /app/pulse bootstrap-token` | +| Kubernetes | `kubectl exec -it -- /app/pulse bootstrap-token` | +| Systemd | `sudo pulse bootstrap-token` | + +Pega la cadena de token que imprime el comando. No pegues directamente el +contenido del archivo `.bootstrap_token`. En v6 ese archivo puede contener un +snapshot JSON cifrado en vez del token utilizable para la configuración. + +1. Abre `http://:7655`. +2. Pega el **Bootstrap Token**. +3. Completa el asistente **Quick Security Setup**. +4. Abre **Settings → Infrastructure → Install on a host** si quieres instalar + el unified agent en hosts. + +Para Proxmox, empieza con monitoreo API-only si el inventario, estado de nodo, +estado de VMs/contenedores y métricas de storage son suficientes. Usa agentes +para visibilidad de Docker/Podman dentro de invitados, datos SMART/temperatura +del host, detalle local de ZFS/Ceph/mdadm u otra telemetría que requiera acceso +local al host. + +## Siguientes pasos + +- [Installation Guide](../../INSTALL.md) para rutas completas de instalación. +- [Configuration](../../CONFIGURATION.md) para autenticación, notificaciones y + ajustes del sistema. +- [Troubleshooting](../../TROUBLESHOOTING.md) para logs y problemas comunes. +- [Agent Security](../../AGENT_SECURITY.md) para privilegios de agentes, + opciones Proxmox API-only y verificación de firmas. +- [Plans and entitlements](../../PULSE_PRO.md) para Community, Relay, Pro y + Cloud. diff --git a/frontend-modern/src/components/SetupWizard/__tests__/SecurityStep.guardrails.test.ts b/frontend-modern/src/components/SetupWizard/__tests__/SecurityStep.guardrails.test.ts index b9d87d87a..eb7cb8541 100644 --- a/frontend-modern/src/components/SetupWizard/__tests__/SecurityStep.guardrails.test.ts +++ b/frontend-modern/src/components/SetupWizard/__tests__/SecurityStep.guardrails.test.ts @@ -1,4 +1,5 @@ import { describe, expect, it } from 'vitest'; +import { EN_MESSAGES } from '@/i18n/messages'; import securityStepSource from '../steps/SecurityStep.tsx?raw'; import welcomeStepSource from '../steps/WelcomeStep.tsx?raw'; @@ -10,10 +11,18 @@ describe('SecurityStep guardrails', () => { }); it('keeps security-step copy aligned with the source-choice setup model', () => { - expect(securityStepSource).toContain('choose the first infrastructure source'); - expect(securityStepSource).toContain('A secure 20-character password'); - expect(securityStepSource).not.toContain('install your first monitored host'); - expect(securityStepSource).not.toContain('16-character password'); + expect(securityStepSource).toContain("t('setup.security.description')"); + expect(securityStepSource).toContain("t('setup.security.generatedPasswordHelp')"); + + const securityStepMessages = [ + EN_MESSAGES['setup.security.description'], + EN_MESSAGES['setup.security.generatedPasswordHelp'], + ].join('\n'); + + expect(securityStepMessages).toContain('choose the first infrastructure source'); + expect(securityStepMessages).toContain('A secure 20-character password'); + expect(securityStepMessages).not.toContain('install your first monitored host'); + expect(securityStepMessages).not.toContain('16-character password'); }); it('does not cover first-run handoff screens with success toasts during normal step transitions', () => { diff --git a/frontend-modern/src/i18n/__tests__/i18n.test.ts b/frontend-modern/src/i18n/__tests__/i18n.test.ts index ec53502e4..e9c98e0fa 100644 --- a/frontend-modern/src/i18n/__tests__/i18n.test.ts +++ b/frontend-modern/src/i18n/__tests__/i18n.test.ts @@ -6,7 +6,6 @@ import { FIRST_SESSION_MONITORING_ALLOWED_IDENTICAL_TRANSLATIONS, FIRST_SESSION_MONITORING_NON_TRANSLATABLE_TOKENS, FIRST_LOCALIZATION_LOCALES, - I18N_MESSAGES, LOCALIZATION_FOUNDATION, LOCALIZED_ALERTS_OVERVIEW_JOURNEY_KEYS, LOCALIZED_FIRST_SESSION_MONITORING_JOURNEY_KEYS, @@ -28,6 +27,7 @@ import { t, type I18nMessageKey, } from '@/i18n'; +import { I18N_MESSAGES } from '@/i18n/catalogs'; import { STORAGE_KEYS } from '@/utils/localStorage'; describe('i18n foundation', () => { diff --git a/frontend-modern/src/i18n/catalogs.ts b/frontend-modern/src/i18n/catalogs.ts new file mode 100644 index 000000000..d4f53b0ba --- /dev/null +++ b/frontend-modern/src/i18n/catalogs.ts @@ -0,0 +1,15 @@ +import { EN_MESSAGES, type I18nCatalogs } from './messages'; +import { DE_MESSAGE_OVERRIDES } from './messages.de'; +import { ES_MESSAGE_OVERRIDES } from './messages.es'; + +export const I18N_MESSAGES: I18nCatalogs = { + en: EN_MESSAGES, + de: { + ...EN_MESSAGES, + ...DE_MESSAGE_OVERRIDES, + }, + es: { + ...EN_MESSAGES, + ...ES_MESSAGE_OVERRIDES, + }, +}; diff --git a/frontend-modern/src/i18n/index.ts b/frontend-modern/src/i18n/index.ts index 29f93b3e3..4332d2726 100644 --- a/frontend-modern/src/i18n/index.ts +++ b/frontend-modern/src/i18n/index.ts @@ -7,10 +7,20 @@ import { resolveSupportedLocale, type SupportedLocale, } from './locales'; -import { EN_MESSAGES, I18N_MESSAGES, type I18nMessageKey } from './messages'; +import { + EN_MESSAGES, + I18N_RUNTIME_MESSAGE_LOADERS, + type I18nCatalog, + type I18nMessageKey, +} from './messages'; type MessageParams = Record; type LocalePreferenceStorage = Pick; +type DeferredLocale = Exclude; + +const localeMessageOverrides: Partial>> = {}; +const pendingLocaleLoads = new Map>(); +const [catalogVersion, setCatalogVersion] = createSignal(0); function getDefaultStorage(): LocalePreferenceStorage | null { if (typeof window === 'undefined') return null; @@ -77,9 +87,60 @@ export function getInitialLocalePreference({ return getStoredLocalePreference(storage) ?? detectBrowserLocale(browserLocales); } -const [activeLocaleSignal, setActiveLocaleSignal] = createSignal( - getInitialLocalePreference(), -); +function getDeferredLocale(locale: SupportedLocale): DeferredLocale | null { + return locale === DEFAULT_LOCALE ? null : locale; +} + +function handleLocaleCatalogLoadFailure(locale: SupportedLocale, error: unknown): void { + if (typeof console === 'undefined') return; + console.warn(`Unable to load ${locale} locale catalog; falling back to English.`, error); +} + +function scheduleLocaleCatalogLoad(locale: SupportedLocale): void { + void loadLocaleCatalog(locale).catch((error: unknown) => { + handleLocaleCatalogLoadFailure(locale, error); + }); +} + +function getLocaleMessage(locale: SupportedLocale, key: I18nMessageKey): string | undefined { + const deferredLocale = getDeferredLocale(locale); + if (!deferredLocale) return EN_MESSAGES[key]; + return localeMessageOverrides[deferredLocale]?.[key]; +} + +export function isLocaleCatalogLoaded(locale: string | null | undefined): boolean { + const normalized = normalizeLocale(locale); + const deferredLocale = getDeferredLocale(normalized); + return !deferredLocale || Boolean(localeMessageOverrides[deferredLocale]); +} + +export function loadLocaleCatalog(locale: string | null | undefined): Promise { + const normalized = normalizeLocale(locale); + const deferredLocale = getDeferredLocale(normalized); + if (!deferredLocale || localeMessageOverrides[deferredLocale]) { + return Promise.resolve(normalized); + } + + const pendingLoad = pendingLocaleLoads.get(deferredLocale); + if (pendingLoad) return pendingLoad.then(() => normalized); + + const loadPromise = I18N_RUNTIME_MESSAGE_LOADERS[deferredLocale]() + .then((messageOverrides) => { + localeMessageOverrides[deferredLocale] = messageOverrides; + setCatalogVersion((version) => version + 1); + }) + .finally(() => { + pendingLocaleLoads.delete(deferredLocale); + }); + + pendingLocaleLoads.set(deferredLocale, loadPromise); + return loadPromise.then(() => normalized); +} + +const initialLocalePreference = getInitialLocalePreference(); +const [activeLocaleSignal, setActiveLocaleSignal] = + createSignal(initialLocalePreference); +scheduleLocaleCatalogLoad(initialLocalePreference); export const activeLocale = activeLocaleSignal; @@ -90,6 +151,7 @@ export function getActiveLocale(): SupportedLocale { export function setActiveLocale(locale: string | null | undefined): SupportedLocale { const normalized = normalizeLocale(locale); setActiveLocaleSignal(normalized); + scheduleLocaleCatalogLoad(normalized); return normalized; } @@ -107,10 +169,11 @@ export function translateMessage( params: MessageParams = {}, locale: string | null | undefined = activeLocaleSignal(), ): string { + catalogVersion(); const fallbackChain = getLocaleFallbackChain(locale); const template = fallbackChain.reduce( - (message, fallbackLocale) => message ?? I18N_MESSAGES[fallbackLocale][key], + (message, fallbackLocale) => message ?? getLocaleMessage(fallbackLocale, key), undefined, ) ?? EN_MESSAGES[key]; return template.replace(/\{([a-zA-Z0-9_]+)\}/g, (match, paramKey: string) => { @@ -122,7 +185,6 @@ export function translateMessage( export const t = translateMessage; export type { I18nMessageKey } from './messages'; -export { I18N_MESSAGES } from './messages'; export { DEFAULT_LOCALE, FIRST_LOCALIZATION_LOCALES, diff --git a/frontend-modern/src/i18n/messages.de.ts b/frontend-modern/src/i18n/messages.de.ts new file mode 100644 index 000000000..18541c9cb --- /dev/null +++ b/frontend-modern/src/i18n/messages.de.ts @@ -0,0 +1,452 @@ +import type { I18nCatalog } from './messages'; + +export const DE_MESSAGE_OVERRIDES = { + 'alerts.activation.label.enabled': 'Warnmeldungen aktiviert', + 'alerts.activation.label.disabled': 'Warnmeldungen deaktiviert', + 'alerts.activation.toast.activated': + 'Warnmeldungen aktiviert. Sie erhalten jetzt Warnungen, wenn Probleme erkannt werden.', + 'alerts.activation.toast.activateFailed': + 'Warnmeldungen konnten nicht aktiviert werden. Bitte versuchen Sie es erneut.', + 'alerts.activation.toast.deactivated': + 'Warnmeldungen deaktiviert. Es wird nichts gesendet, bis Sie sie wieder aktivieren.', + 'alerts.activation.toast.deactivateFailed': + 'Warnmeldungen konnten nicht deaktiviert werden. Bitte versuchen Sie es erneut.', + 'alerts.assistant.action.investigate': 'Warnmeldung {alertIdentifier} untersuchen', + 'alerts.assistant.button.full': 'Mit Pulse Assistant untersuchen', + 'alerts.assistant.button.text': 'Pulse Assistant fragen', + 'alerts.assistant.detail.currentMetric': + 'Aktueller Wert {currentValue}; Schwellwert {thresholdValue}', + 'alerts.assistant.detail.message': 'Meldung: {message}', + 'alerts.assistant.detail.node': 'Knoten: {node}', + 'alerts.assistant.duration.hoursMinutes': '{hours}h {minutes}m', + 'alerts.assistant.duration.minute': '{count} Min.', + 'alerts.assistant.duration.minutes': '{count} Min.', + 'alerts.assistant.duration.unknown': 'unbekannte Dauer', + 'alerts.assistant.level.critical': 'Kritisch', + 'alerts.assistant.level.info': 'Info', + 'alerts.assistant.level.warning': 'Warnung', + 'alerts.assistant.locked.proRequired': + 'Pro erforderlich, um Warnmeldungen mit Pulse Assistant zu untersuchen', + 'alerts.assistant.locked.unavailable': + 'Pulse Assistant-Warnungsanalyse ist fuer diese Warnmeldung nicht verfuegbar', + 'alerts.assistant.safetyNote': + 'Diagnosen und Behebungen erfordern die Freigabe durch einen Operator.', + 'alerts.assistant.sourceLabel': 'Pulse Alerts', + 'alerts.assistant.statusLabel': '{level}-Warnmeldung · Aktiv seit {duration}', + 'alerts.assistant.subject': '{level} {alertType} auf {resourceName}', + 'alerts.assistant.title': 'Warnungsanalyse angehaengt', + 'alerts.assistant.unlockedTitle': 'Pulse Assistant bitten, diese Warnmeldung zu untersuchen', + 'alerts.nav.ariaLabel': 'Warnmeldungsnavigation', + 'alerts.nav.collapseSidebar': 'Seitenleiste einklappen', + 'alerts.nav.expandSidebar': 'Seitenleiste ausklappen', + 'alerts.nav.title': 'Warnmeldungen', + 'alerts.nav.toggleAlerts': 'Warnmeldungen umschalten', + 'alerts.overview.action.acknowledge': 'Bestaetigen', + 'alerts.overview.action.acknowledgeAll': 'Alle bestaetigen ({count})', + 'alerts.overview.action.acknowledging': 'Wird bestaetigt...', + 'alerts.overview.action.hideAcknowledged': 'Bestaetigte ausblenden', + 'alerts.overview.action.hideTimeline': 'Zeitleiste ausblenden', + 'alerts.overview.action.processing': 'Wird verarbeitet...', + 'alerts.overview.action.showAcknowledged': 'Bestaetigte anzeigen', + 'alerts.overview.action.timeline': 'Zeitleiste', + 'alerts.overview.action.unacknowledge': 'Bestaetigung aufheben', + 'alerts.overview.acknowledgedBadge': 'Bestaetigt', + 'alerts.overview.empty.description': + 'Warnmeldungen erscheinen hier, wenn Schwellwerte ueberschritten werden', + 'alerts.overview.empty.title': 'Keine aktiven Warnmeldungen', + 'alerts.overview.filteredEmpty.all': 'Keine aktiven Warnmeldungen', + 'alerts.overview.filteredEmpty.unacknowledged': 'Keine unbestaetigten Warnmeldungen', + 'alerts.overview.nodePrefix': 'auf {node}', + 'alerts.overview.notification.acknowledged': 'Warnmeldung bestaetigt', + 'alerts.overview.notification.acknowledgeFailed': 'Warnmeldung konnte nicht bestaetigt werden', + 'alerts.overview.notification.bulkFailure.singular': + '{count} Warnmeldung konnte nicht bestaetigt werden.', + 'alerts.overview.notification.bulkFailure.plural': + '{count} Warnmeldungen konnten nicht bestaetigt werden.', + 'alerts.overview.notification.bulkFailureGeneric': + 'Warnmeldungen konnten nicht bestaetigt werden', + 'alerts.overview.notification.bulkSuccess.singular': '{count} Warnmeldung bestaetigt.', + 'alerts.overview.notification.bulkSuccess.plural': '{count} Warnmeldungen bestaetigt.', + 'alerts.overview.notification.restored': 'Warnmeldung wiederhergestellt', + 'alerts.overview.notification.restoreFailed': 'Warnmeldung konnte nicht wiederhergestellt werden', + 'alerts.overview.paused.description': + 'Schalten Sie Warnmeldungen ein, um die Ueberwachung fortzusetzen und Konfigurationstabs freizugeben', + 'alerts.overview.paused.title': 'Warnmeldungen sind pausiert', + 'alerts.overview.section.activeAlerts': 'Aktive Warnmeldungen', + 'alerts.overview.startedAt': 'Gestartet: {startedAt}', + 'alerts.overview.stats.acknowledged': 'Bestaetigt', + 'alerts.overview.stats.triggered24h': 'Ausgeloest (24h)', + 'alerts.overview.stats.workloadOverrides': 'Workload-Ausnahmen', + 'alerts.page.default.description': + 'Pruefen Sie aktive Vorfaelle, Warnungsverlauf, Schwellwerte, Benachrichtigungen und Zeitplaene.', + 'alerts.page.default.title': 'Warnmeldungen', + 'alerts.page.destinations.description': + 'Leiten Sie Warnmeldungen an E-Mail-, Apprise- und Webhook-Ziele weiter.', + 'alerts.page.destinations.title': 'Benachrichtigungen', + 'alerts.page.history.description': + 'Suchen Sie fruehere Warnmeldungen, pruefen Sie Vorfall-Zeitleisten und beobachten Sie Warnungshaeufigkeit ueber Zeit.', + 'alerts.page.history.title': 'Warnungsverlauf', + 'alerts.page.overview.description': + 'Pruefen Sie aktive Vorfaelle, Warnungsabdeckung und ob Warnmeldungen diese Installation aktiv ueberwachen.', + 'alerts.page.overview.title': 'Warnmeldungsuebersicht', + 'alerts.page.schedule.description': + 'Definieren Sie Ruhezeiten, Gruppierung, Abklingzeiten, Wiederherstellung und Eskalation fuer Warnmeldungen.', + 'alerts.page.schedule.title': 'Wartungszeitplan', + 'alerts.page.thresholds.description': + 'Passen Sie Schwellwerte und gezielte Ausnahmen fuer Infrastruktur, Workloads und Integrationen an.', + 'alerts.page.thresholds.title': 'Warnungsschwellwerte', + 'alerts.tabs.disabledTitle': + 'Aktivieren Sie Warnmeldungen, um diese Einstellung zu konfigurieren', + 'alerts.tabs.group.configuration': 'Konfiguration', + 'alerts.tabs.group.status': 'Status', + 'alerts.tabs.destinations': 'Benachrichtigungen', + 'alerts.tabs.history': 'Verlauf', + 'alerts.tabs.overview': 'Uebersicht', + 'alerts.tabs.schedule': 'Zeitplan', + 'alerts.tabs.thresholds': 'Schwellwerte', + 'alerts.timeline.acknowledged': 'bestaetigt', + 'alerts.timeline.closedAt': 'geschlossen {closedAt}', + 'alerts.timeline.empty': 'Noch keine Zeitleistenereignisse.', + 'alerts.timeline.failure': 'Zeitleiste konnte nicht geladen werden.', + 'alerts.timeline.filterEmpty': + 'Keine Zeitleistenereignisse entsprechen den ausgewaehlten Filtern.', + 'alerts.timeline.filterLabel.compact': 'Filter', + 'alerts.timeline.filterLabel.panel': 'Ereignisse filtern:', + 'alerts.timeline.heading': 'Vorfall', + 'alerts.timeline.loading': 'Zeitleiste wird geladen...', + 'alerts.timeline.event.alertAcknowledged': 'Bestaetigt', + 'alerts.timeline.event.alertFired': 'Ausgeloest', + 'alerts.timeline.event.alertResolved': 'Behoben', + 'alerts.timeline.event.alertUnacknowledged': 'Unbestaetigt', + 'alerts.timeline.event.aiAnalysis': 'Patrol', + 'alerts.timeline.event.command': 'Befehl', + 'alerts.timeline.event.note': 'Notiz', + 'alerts.timeline.event.runbook': 'Runbook', + 'alerts.timeline.noteLabel': 'Vorfallsnotiz', + 'alerts.timeline.notePlaceholder': 'Notiz fuer diesen Vorfall hinzufuegen...', + 'alerts.timeline.openedAt': 'geoeffnet {openedAt}', + 'alerts.timeline.quickFilter.all': 'Alle', + 'alerts.timeline.quickFilter.none': 'Keine', + 'alerts.timeline.retry': 'Erneut versuchen', + 'alerts.timeline.saveNote': 'Notiz speichern', + 'alerts.timeline.savingNote': 'Wird gespeichert...', + 'alerts.timeline.unavailable': 'Keine Vorfall-Zeitleiste verfuegbar.', + 'runtimeHome.openingWorkspace': 'Arbeitsbereich wird geoeffnet...', + 'setup.completion.action.addInfrastructure': 'Infrastruktur hinzufuegen', + 'setup.completion.action.downloadCredentials': 'Zugangsdaten herunterladen', + 'setup.completion.action.installAgent': 'Pulse Agent installieren', + 'setup.completion.action.openInfrastructure': 'Infrastruktur oeffnen', + 'setup.completion.connectedSummary.singular': 'Verbunden ({count} System)', + 'setup.completion.connectedSummary.plural': 'Verbunden ({count} Systeme)', + 'setup.completion.credentials.apiTokenLabel': 'Admin-API-Token', + 'setup.completion.credentials.badge': 'Waehrend der Einrichtung angezeigt', + 'setup.completion.credentials.continuation.empty': 'Infrastruktur hinzufuegen.', + 'setup.completion.credentials.continuation.connected': + 'Infrastruktur oder Infrastruktur hinzufuegen.', + 'setup.completion.credentials.description': + 'Speichern Sie Admin-Anmeldung und API-Token, bevor Sie diesen Bildschirm verlassen, und fahren Sie dann mit {destination} fort', + 'setup.completion.credentials.passwordLabel': 'Passwort', + 'setup.completion.credentials.title': 'Zugangsdaten jetzt speichern', + 'setup.completion.credentials.usernameLabel': 'Benutzername', + 'setup.completion.download.content': + 'Pulse-Zugangsdaten\n==================\nErstellt: {generatedAt}\n\nWeb-Anmeldung:\n----------\nURL: {baseUrl}\nBenutzername: {username}\nPasswort: {password}\n\nAdmin-API-Token:\n----------------\n{apiToken}\n\nInfrastruktur:\n---------------\n{infrastructureUrl}\n\nVerwenden Sie Infrastruktur hinzufuegen, um eine Plattform-API, Pulse Agent oder beides\nfuer das erste System auszuwaehlen, das Pulse ueberwachen soll.\n\nBewahren Sie diese Zugangsdaten sicher auf!\n', + 'setup.completion.hero.connected.description.agent': + 'Ihr Admin-Konto ist bereit und Pulse empfaengt bereits Telemetrie. Oeffnen Sie Infrastruktur, um das erste System zu pruefen, und kehren Sie zu Infrastruktur hinzufuegen zurueck, wenn Sie eine weitere Pulse Agent- oder Plattform-API-Quelle wollen.', + 'setup.completion.hero.connected.description.api': + 'Ihr Admin-Konto ist bereit und Pulse empfaengt bereits Telemetrie. Oeffnen Sie Infrastruktur, um das erste System zu pruefen, und kehren Sie zu Infrastruktur hinzufuegen zurueck, wenn Sie eine weitere Plattform-API- oder Pulse Agent-Quelle wollen.', + 'setup.completion.hero.connected.description.both': + 'Ihr Admin-Konto ist bereit und Pulse empfaengt bereits Telemetrie. Oeffnen Sie Infrastruktur, um das erste System zu pruefen, und kehren Sie zu Infrastruktur hinzufuegen zurueck, wenn Sie eine weitere Plattform-API- oder Agent-Quelle wollen.', + 'setup.completion.hero.connected.title': 'Erstes ueberwachtes System verbunden', + 'setup.completion.hero.empty.description': + 'Ihr Admin-Konto ist bereit. Waehlen Sie als Naechstes, wie das erste System in das einheitliche Infrastrukturmodell gelangt: Plattform-API-Inventar, Pulse Agent-Telemetrie oder beides.', + 'setup.completion.hero.empty.title': 'Erste Infrastrukturquelle waehlen', + 'setup.completion.nextStep.ariaLabel': 'Naechster Einrichtungsschritt', + 'setup.completion.nextStep.badge': 'Empfohlener naechster Schritt', + 'setup.completion.nextStep.detail.agent': + 'Infrastruktur hinzufuegen bleibt fuer weitere Pulse Agent-Systeme oder Plattform-API-Inventar verfuegbar, wenn eine Plattform die Umgebung verwaltet.', + 'setup.completion.nextStep.detail.api': + 'Infrastruktur hinzufuegen bleibt fuer weitere API-gestuetzte Systeme oder Pulse Agent-Telemetrie verfuegbar, wenn ein System lokale Knotenabdeckung braucht.', + 'setup.completion.nextStep.detail.both': + 'Infrastruktur hinzufuegen bleibt jederzeit verfuegbar, wenn Sie dieses erste System um eine weitere API-Quelle, Agent-Quelle oder beides erweitern wollen.', + 'setup.completion.nextStep.detail.empty': + 'Beginnen Sie mit einer Plattform-API, wenn eine Plattform die Umgebung verwaltet. Installieren Sie Pulse Agent, wenn das System selbst lokale Knotentelemetrie melden soll.', + 'setup.completion.nextStep.label': 'Naechster Schritt', + 'setup.completion.nextStep.summary.connected.singular': + 'Oeffnen Sie Infrastruktur, um Ihr erstes verbundenes System zu pruefen.', + 'setup.completion.nextStep.summary.connected.plural': + 'Oeffnen Sie Infrastruktur, um Ihre verbundenen Systeme zu pruefen.', + 'setup.completion.nextStep.summary.empty': + 'Oeffnen Sie Infrastruktur hinzufuegen, um eine Plattform-API, Pulse Agent oder beides zu waehlen.', + 'setup.completion.nextStep.title.connected': 'Infrastruktur oeffnen', + 'setup.completion.nextStep.title.empty': 'Strategie fuer erste Quelle waehlen', + 'setup.completion.resource.unknownName': 'Unbekannt', + 'setup.completion.sourceOptions.agent.description': + 'Knotenlokale Telemetrie fuer eigenstaendige Hosts, Dienste, Docker und Kubernetes.', + 'setup.completion.sourceOptions.agent.title': 'Pulse Agent', + 'setup.completion.sourceOptions.both.description': + 'Kombinieren Sie Plattforminventar mit Agent-Telemetrie, wenn vollstaendige Abdeckung wichtig ist.', + 'setup.completion.sourceOptions.both.title': 'Beides verwenden', + 'setup.completion.sourceOptions.platformApi.description': + 'Inventar und Zustand aus Proxmox, TrueNAS, VMware, PBS oder PMG.', + 'setup.completion.sourceOptions.platformApi.title': 'Plattform-API', + 'setup.completion.sourceOptions.title': 'Quellenoptionen', + 'setup.progress.ariaLabel': 'Einrichtungsfortschritt', + 'setup.progress.state.completed': ', abgeschlossen', + 'setup.progress.state.current': ', aktuell', + 'setup.progress.stepAriaLabel': 'Schritt {index}: {step}{state}', + 'setup.security.action.back': 'Zurueck', + 'setup.security.action.createAccount': 'Konto erstellen und fortfahren', + 'setup.security.action.settingUp': 'Einrichtung laeuft...', + 'setup.security.customPassword': 'Eigenes Passwort', + 'setup.security.description': + 'Der naechste Schritt ist die Auswahl der ersten Infrastrukturquelle.', + 'setup.security.error.passwordMismatch': 'Passwoerter stimmen nicht ueberein', + 'setup.security.error.passwordRequired': 'Bitte geben Sie ein Passwort ein', + 'setup.security.error.passwordTooShort': 'Das Passwort muss mindestens 12 Zeichen haben', + 'setup.security.error.setupFailed': 'Einrichtung fehlgeschlagen: {error}', + 'setup.security.generatedPasswordHelp': + 'Ein sicheres 20-Zeichen-Passwort wird erzeugt und auf dem naechsten Bildschirm angezeigt.', + 'setup.security.label.confirmPassword': 'Passwort bestaetigen', + 'setup.security.label.password': 'Passwort', + 'setup.security.label.username': 'Benutzername', + 'setup.security.minimumPasswordHelp': 'Mindestens 12 Zeichen.', + 'setup.security.nextScreen.itemApiToken': 'Ein Admin-API-Token fuer Automatisierung', + 'setup.security.nextScreen.itemCredentials': 'Ihr Benutzername und Passwort', + 'setup.security.nextScreen.saveOnce': + 'Speichern Sie sie vor dem Fortfahren; sie werden nur einmal angezeigt.', + 'setup.security.nextScreen.title': 'Auf dem naechsten Bildschirm', + 'setup.security.passwordMode.autoGenerate': 'Automatisch erzeugen', + 'setup.security.placeholder.password': 'Passwort (mind. 12 Zeichen)', + 'setup.security.placeholder.username': 'admin', + 'setup.security.showPassword.hide': 'Ausblenden', + 'setup.security.showPassword.show': 'Anzeigen', + 'setup.security.title': 'Admin-Konto erstellen', + 'setup.step.firstSource': 'Erste Quelle', + 'setup.step.security': 'Sicherheit', + 'setup.step.unlockServer': 'Server entsperren', + 'setup.wizard.ariaLabel': 'Pulse-Einrichtungsassistent', + 'setup.welcome.action.continueSecurity': 'Weiter zu Sicherheit', + 'setup.welcome.action.verifyToken': 'Bootstrap-Token pruefen', + 'setup.welcome.action.verifyingToken': 'Bootstrap-Token wird geprueft...', + 'setup.welcome.copyCommandTitle': 'Befehl kopieren', + 'setup.welcome.deploymentHint.containerized': + 'Pulse scheint in einer containerisierten Umgebung zu laufen. Fuehren Sie den Befehl auf dem Host aus, der den Container verwaltet, damit Sie das einmalige Setup-Token ausgeben koennen.', + 'setup.welcome.deploymentHint.direct': + 'Fuehren Sie den Befehl direkt in einer Shell auf dem Pulse-Server aus, um das einmalige Setup-Token auszugeben.', + 'setup.welcome.deploymentHint.dockerNamed': + 'Pulse scheint in Docker als Container "{containerName}" zu laufen. Fuehren Sie den Befehl auf dem Docker-Host aus, um das einmalige Setup-Token aus diesem Container auszugeben.', + 'setup.welcome.deploymentHint.dockerUnnamed': + 'Pulse scheint in Docker zu laufen. Fuehren Sie den Befehl auf dem Docker-Host aus und ersetzen Sie durch den Namen des laufenden Pulse-Containers.', + 'setup.welcome.deploymentHint.lxc': + 'Pulse scheint in LXC-Container {ctid} zu laufen. Fuehren Sie den Befehl auf dem Proxmox-Host aus, um in diesen Container zu wechseln und das einmalige Setup-Token auszugeben.', + 'setup.welcome.deploymentLabel.containerized': 'Containerisierte Bereitstellung', + 'setup.welcome.deploymentLabel.direct': 'Direkte Host-Installation', + 'setup.welcome.deploymentLabel.docker': 'Docker-Bereitstellung', + 'setup.welcome.deploymentLabel.lxc': 'LXC-Container', + 'setup.welcome.error.copyCommandFailed': 'Befehl konnte nicht kopiert werden', + 'setup.welcome.error.invalidBootstrapToken': + 'Ungueltiges Bootstrap-Token. Bitte pruefen und erneut versuchen.', + 'setup.welcome.error.invalidBootstrapTokenResponse': 'Ungueltiges Bootstrap-Token', + 'setup.welcome.error.missingBootstrapToken': 'Bitte geben Sie das Bootstrap-Token ein', + 'setup.welcome.error.snapshotPaste': + 'Das sieht nach dem verschluesselten Inhalt der Datei .bootstrap_token aus, nicht nach dem rohen Setup-Token. Fuehren Sie den obigen Befehl aus und fuegen Sie die ausgegebene Token-Zeichenfolge ein.', + 'setup.welcome.hero.coverage': + 'Verbinden Sie eine Plattform-API, installieren Sie Pulse Agent oder verwenden Sie beides fuer vollstaendige Abdeckung.', + 'setup.welcome.hero.step.admin': 'Admin-Konto erstellen', + 'setup.welcome.hero.step.source': 'Erste Quelle waehlen', + 'setup.welcome.hero.step.unlock': 'Diesen Pulse-Server entsperren', + 'setup.welcome.hero.stepsIntro': 'Drei Schritte:', + 'setup.welcome.hero.stepsThen': 'dann', + 'setup.welcome.hero.title': 'Willkommen bei Pulse', + 'setup.welcome.placeholder.bootstrapToken': 'Bootstrap-Token einfuegen', + 'setup.welcome.success.commandCopied': 'Befehl in Zwischenablage kopiert', + 'setup.welcome.tokenHelp.afterVerify': + 'Nachdem Pulse dieses Token geprueft hat, erstellen Sie im naechsten Schritt das Admin-Konto fuer diesen Server.', + 'setup.welcome.tokenHelp.docker': + 'Dieses einmalige Bootstrap-Token entsperrt nur die Ersteinrichtung. Fuehren Sie den obigen Befehl aus und fuegen Sie die ausgegebene Token-Zeichenfolge ein. Nach der Pruefung erstellen Sie das Admin-Konto, und Pulse erzeugt das langlebige API-Token separat.', + 'setup.welcome.tokenHelp.host': + 'Dieses einmalige Bootstrap-Token entsperrt nur die Ersteinrichtung auf diesem Pulse-Server. Fuehren Sie den obigen Befehl aus und fuegen Sie die ausgegebene Token-Zeichenfolge ein. Es ist nicht Ihr Admin-Passwort und nicht das API-Token, das Sie nach der Einrichtung verwenden.', + 'setup.welcome.tokenHelp.title': 'Was dieses Token macht', + 'setup.welcome.unlockTitle': 'Einrichtung entsperren', + 'settings.general.appearance.title': 'Darstellung', + 'settings.general.fullWidth.description': + 'Nutzen Sie auf grossen Monitoren die gesamte verfuegbare Bildschirmbreite.', + 'settings.general.fullWidth.title': 'Volle Breite', + 'settings.general.docker.envHint': 'Kann auch ueber Umgebungsvariable gesetzt werden:', + 'settings.general.docker.section.description': + 'Steuern Sie, wie {sourceLabel}-Updateaktionen in Pulse angezeigt werden.', + 'settings.general.docker.section.title': '{sourceLabel}-Updates', + 'settings.general.docker.toggle.description': + 'Wenn aktiviert, werden {sourceLabel}-Aktionen "Update" in Pulse ausgeblendet. Die Update-Erkennung laeuft weiter, sodass verfuegbare Updates sichtbar bleiben.', + 'settings.general.docker.toggle.title': 'Update-Schaltflaechen ausblenden', + 'settings.general.language.ariaLabel': 'App-Sprache', + 'settings.general.language.description': + 'Verwenden Sie diese Sprache fuer die App-Oberflaeche. Befehle, Ressourcennamen und API-Felder bleiben unveraendert.', + 'settings.general.language.title': 'Sprache', + 'settings.general.monitoringCadence.current': 'Aktueller Takt: {seconds} Sekunden ({duration})', + 'settings.general.monitoringCadence.custom.description': + 'Sekunden eingeben ({min}-{max}). Gilt fuer alle Cluster.', + 'settings.general.monitoringCadence.custom.title': 'Benutzerdefiniertes Abfrageintervall', + 'settings.general.monitoringCadence.description': + 'Kuerzere Intervalle liefern nahezu Echtzeit-Aktualisierungen auf Kosten hoeherer API- und CPU-Nutzung auf jedem Knoten. Waehlen Sie ein laengeres Intervall, um die Last auf ausgelasteten Clustern zu reduzieren.', + 'settings.general.monitoringCadence.duration.minute': '{count} Minute', + 'settings.general.monitoringCadence.duration.minutes': '{count} Minuten', + 'settings.general.monitoringCadence.duration.underMinute': 'unter einer Minute', + 'settings.general.monitoringCadence.envLocked': + 'Wird ueber Umgebungsvariable {envVar} verwaltet.', + 'settings.general.monitoringCadence.preset.balanced': 'Ausgewogen ({duration})', + 'settings.general.monitoringCadence.preset.custom': 'Benutzerdefiniert', + 'settings.general.monitoringCadence.preset.low': 'Niedrig ({duration})', + 'settings.general.monitoringCadence.preset.realtime': 'Echtzeit ({duration})', + 'settings.general.monitoringCadence.preset.veryLow': 'Sehr niedrig ({duration})', + 'settings.general.monitoringCadence.section.description': + 'Steuern Sie, wie oft Pulse Proxmox VE-Knoten abfragt.', + 'settings.general.monitoringCadence.section.title': 'Monitoring-Takt', + 'settings.general.temperature.description': 'Temperaturen in Celsius oder Fahrenheit anzeigen.', + 'settings.general.temperature.title': 'Temperatureinheit', + 'settings.general.telemetry.copyJson': 'JSON kopieren', + 'settings.general.telemetry.description': + 'Helfen Sie, Pulse zu verbessern, indem Sie anonyme ausgehende Nutzungsdaten teilen: eine rotierende Installations-ID, normalisierte Release-Identitaet, Laufzeitplattform, aggregierte Self-hosted-Nutzungszahlen und grobe Funktionsflags. Es werden keine Hostnamen, Zugangsdaten, Infrastrukturkennungen, Prompts, Chatnachrichten oder personenbezogenen Daten gesendet. Telemetriezeilen werden bis zu 90 Tage aufbewahrt, und IP-Adressen werden nicht in Telemetriezeilen gespeichert.', + 'settings.general.telemetry.disabledPreview': + 'Telemetrie ist derzeit deaktiviert. Diese Vorschau zeigt den Payload, den Pulse senden wuerde, wenn Sie sie aktivieren.', + 'settings.general.telemetry.fullDetails': 'Details', + 'settings.general.telemetry.payloadAriaLabel': 'Telemetrie-Payload-Vorschau', + 'settings.general.telemetry.payloadTitle': 'Aktueller Heartbeat-Payload', + 'settings.general.telemetry.previewPayload': 'Payload anzeigen', + 'settings.general.telemetry.refreshPayload': 'Payload aktualisieren', + 'settings.general.telemetry.resetId': 'ID zuruecksetzen', + 'settings.general.telemetry.section.description': + 'Steuern Sie anonyme ausgehende Telemetrie von dieser Pulse-Instanz.', + 'settings.general.telemetry.section.title': 'Nutzungsdaten und Datenschutz', + 'settings.general.telemetry.title': 'Anonyme ausgehende Telemetrie', + 'settings.general.theme.description': 'Waehlen Sie hell, dunkel oder die Systemeinstellung.', + 'settings.general.theme.option.dark': 'Dunkel', + 'settings.general.theme.option.light': 'Hell', + 'settings.general.theme.option.system': 'System', + 'settings.general.theme.title': 'Designpraeferenz', + 'settings.header.api.description': + 'Erstellen und verwalten Sie begrenzte Pulse-Tokens fuer Agents, Automatisierung und externe Integrationen.', + 'settings.header.api.title': 'API-Zugriff', + 'settings.header.infrastructure.description': + 'Fuegen Sie Infrastruktur hinzu, finden Sie sie automatisch, und pruefen Sie, was Pulse ueberwacht.', + 'settings.header.infrastructure.readOnlyDescription': + 'Pruefen Sie die aktuell ueberwachten Hauptsysteme und den Reporting-Status. Einrichtungsänderungen bleiben in dieser schreibgeschuetzten Sitzung nicht verfuegbar.', + 'settings.header.infrastructure.title': 'Infrastruktur', + 'settings.header.monitoringAvailability.description': + 'Ueberwachen Sie Endgeraete und Dienste nur ueber Ping-, TCP- und HTTP-Pruefungen.', + 'settings.header.monitoringAvailability.title': 'Verfuegbarkeitspruefungen', + 'settings.header.organizationAccess.description': + 'Verwalten Sie Einladungen, Mitgliederrollen und Eigentumsuebertragungen der Organisation.', + 'settings.header.organizationAccess.title': 'Organisationszugriff', + 'settings.header.organizationBilling.description': + 'Pruefen Sie Organisationsplan, geltende Nutzungsrichtlinien und Abonnementstatus fuer bezahlten Zugriff.', + 'settings.header.organizationBilling.title': 'Abrechnung & Nutzung', + 'settings.header.organizationBillingAdmin.description': + 'Pruefen und verwalten Sie den Abrechnungsstatus aller Mandanten (nur Hosted-Modus).', + 'settings.header.organizationBillingAdmin.title': 'Abrechnungsadmin', + 'settings.header.organizationOverview.description': + 'Pruefen Sie Organisationsdaten, Mitgliederumfang und Eigentum.', + 'settings.header.organizationOverview.title': 'Organisationsuebersicht', + 'settings.header.organizationSharing.description': + 'Teilen Sie Ressourcen zwischen Organisationen mit begrenztem Zugriff.', + 'settings.header.organizationSharing.title': 'Organisationsfreigabe', + 'settings.header.securityAudit.description': + 'Sehen Sie Sicherheitsereignisse, Anmeldeversuche und Konfigurationsaenderungen.', + 'settings.header.securityAudit.title': 'Audit-Protokoll', + 'settings.header.securityAuth.description': + 'Verwalten Sie passwortbasierte Authentifizierung und Zugangsdatenrotation.', + 'settings.header.securityAuth.title': 'Authentifizierung', + 'settings.header.securityDataHandling.description': + 'Sehen Sie, welche ueberwachten Ressourcendetails zusammengefasst werden duerfen, lokal bleiben muessen oder redigiert sind.', + 'settings.header.securityDataHandling.title': 'Ressourcenschutz', + 'settings.header.securityOverview.description': + 'Sehen Sie Ihre Sicherheitslage auf einen Blick und ueberwachen Sie den Authentifizierungsstatus.', + 'settings.header.securityOverview.title': 'Sicherheitsuebersicht', + 'settings.header.securityRoles.description': + 'Definieren Sie eigene Rollen und verwalten Sie granulare Berechtigungen fuer Benutzer und Tokens.', + 'settings.header.securityRoles.title': 'Rollen', + 'settings.header.securitySso.description': 'Konfigurieren Sie OIDC- und SAML-Identity-Provider.', + 'settings.header.securitySso.title': 'Single-Sign-On-Anbieter', + 'settings.header.securityUsers.description': + 'Weisen Sie Benutzern Rollen zu und sehen Sie effektive Berechtigungen in Ihrer Infrastruktur.', + 'settings.header.securityUsers.title': 'Benutzerzugriff', + 'settings.header.securityWebhooks.description': + 'Konfigurieren Sie die Echtzeit-Zustellung von Audit-Ereignissen an externe Systeme.', + 'settings.header.securityWebhooks.title': 'Audit-Webhooks', + 'settings.header.systemAi.description': + 'Konfigurieren Sie Anbieter und Modelle fuer Pulse Assistant und Patrol.', + 'settings.header.systemAi.title': 'Assistant & Patrol', + 'settings.header.systemBilling.description': + 'Pruefen Sie, welchen Plan diese Instanz nutzt und welche optionalen Funktionen damit verbunden sind.', + 'settings.header.systemBilling.title': 'Self-hosted-Plan', + 'settings.header.systemGeneral.description': + 'Verwalten Sie Darstellung, Layout und Standard-Monitoring-Takt.', + 'settings.header.systemGeneral.title': 'Allgemein', + 'settings.header.systemNetwork.description': + 'Konfigurieren Sie oeffentliche URL, CORS, Einbettung und Netzwerkgrenzen fuer Webhooks.', + 'settings.header.systemNetwork.title': 'Netzwerk', + 'settings.header.systemRecovery.description': + 'Verwalten Sie Backup-/Snapshot-Abfragen sowie Export- und Importablaeufe der Konfiguration.', + 'settings.header.systemRecovery.title': 'Wiederherstellung', + 'settings.header.systemRelay.description': + 'Konfigurieren Sie Pulse-Relay-Konnektivitaet fuer sicheren Remote-Zugriff und Pulse-Mobile-Kopplung.', + 'settings.header.systemRelay.title': 'Remote-Zugriff', + 'settings.header.systemUpdates.description': + 'Verwalten Sie Versionspruefungen, Update-Kanaele und automatisches Update-Verhalten.', + 'settings.header.systemUpdates.title': 'Updates', + 'settings.header.supportDiagnostics.description': + 'Fuehren Sie Zustandspruefungen aus, validieren Sie Verbindungen und exportieren Sie Troubleshooting-Snapshots.', + 'settings.header.supportDiagnostics.title': 'Diagnose & Zustand', + 'settings.header.supportLogs.description': + 'Pruefen Sie den Live-Pulse-Logstream und laden Sie den erfassten Puffer fuer Supportarbeit herunter.', + 'settings.header.supportLogs.title': 'Systemprotokolle', + 'settings.header.supportReporting.description': + 'Exportieren Sie Inventardaten und erstellen Sie Leistungsberichte aus der kanonischen Einstellungsoberflaeche.', + 'settings.header.supportReporting.title': 'Daten & Berichte', + 'settings.nav.group.infrastructure': 'Infrastruktur', + 'settings.nav.group.monitoring': 'Monitoring', + 'settings.nav.group.organization': 'Organisation', + 'settings.nav.group.security': 'Sicherheit', + 'settings.nav.group.support': 'Support', + 'settings.nav.group.system': 'System', + 'settings.nav.item.apiAccess': 'API-Zugriff', + 'settings.nav.item.auditLog': 'Audit-Protokoll', + 'settings.nav.item.auditWebhooks': 'Audit-Webhooks', + 'settings.nav.item.authentication': 'Authentifizierung', + 'settings.nav.item.availabilityChecks': 'Verfuegbarkeitspruefungen', + 'settings.nav.item.billing': 'Abrechnung', + 'settings.nav.item.billingAdmin': 'Abrechnungsadmin', + 'settings.nav.item.dataReports': 'Daten & Berichte', + 'settings.nav.item.diagnosticsHealth': 'Diagnose & Zustand', + 'settings.nav.item.general': 'Allgemein', + 'settings.nav.item.infrastructure': 'Infrastruktur', + 'settings.nav.item.network': 'Netzwerk', + 'settings.nav.item.organizationAccess': 'Zugriff', + 'settings.nav.item.organizationOverview': 'Uebersicht', + 'settings.nav.item.plans': 'Plaene', + 'settings.nav.item.recovery': 'Wiederherstellung', + 'settings.nav.item.remoteAccess': 'Remote-Zugriff', + 'settings.nav.item.resourcePrivacy': 'Ressourcenschutz', + 'settings.nav.item.roles': 'Rollen', + 'settings.nav.item.securityOverview': 'Sicherheitsuebersicht', + 'settings.nav.item.sharing': 'Freigabe', + 'settings.nav.item.singleSignOn': 'Single Sign-On', + 'settings.nav.item.systemLogs': 'Systemprotokolle', + 'settings.nav.item.updates': 'Updates', + 'settings.nav.item.users': 'Benutzer', + 'settings.nav.item.assistantPatrol': 'Assistant & Patrol', + 'settings.shell.collapseSidebarLabel': 'Einstellungsnavigation einklappen', + 'settings.shell.configurationLoading': 'Konfiguration wird geladen...', + 'settings.shell.discardLabel': 'Verwerfen', + 'settings.shell.expandSidebarLabel': 'Einstellungsnavigation ausklappen', + 'settings.shell.loading': 'Einstellungen werden geladen...', + 'settings.shell.mobileBackLabel': 'Einstellungen', + 'settings.shell.navigationAriaLabel': 'Einstellungsnavigation', + 'settings.shell.navigationTitle': 'Einstellungen', + 'settings.shell.saveChangesLabel': 'Aenderungen speichern', + 'settings.shell.searchEmpty': 'Keine Einstellungen fuer "{query}" gefunden', + 'settings.shell.searchPlaceholder': 'Einstellungen suchen...', + 'settings.shell.unsavedDescription': + 'Ihre Aenderungen gehen verloren, wenn Sie diese Seite verlassen.', + 'settings.shell.unsavedTitle': 'Nicht gespeicherte Aenderungen', +} as const satisfies Partial; diff --git a/frontend-modern/src/i18n/messages.es.ts b/frontend-modern/src/i18n/messages.es.ts new file mode 100644 index 000000000..75045fce3 --- /dev/null +++ b/frontend-modern/src/i18n/messages.es.ts @@ -0,0 +1,443 @@ +import type { I18nCatalog } from './messages'; + +export const ES_MESSAGE_OVERRIDES = { + 'alerts.activation.label.enabled': 'Alertas activadas', + 'alerts.activation.label.disabled': 'Alertas desactivadas', + 'alerts.activation.toast.activated': + 'Alertas activadas. Ahora recibiras avisos cuando se detecten problemas.', + 'alerts.activation.toast.activateFailed': + 'No se pudieron activar las alertas. Intentalo de nuevo.', + 'alerts.activation.toast.deactivated': + 'Alertas desactivadas. No se enviara nada hasta que las vuelvas a activar.', + 'alerts.activation.toast.deactivateFailed': + 'No se pudieron desactivar las alertas. Intentalo de nuevo.', + 'alerts.assistant.action.investigate': 'Investigar alerta {alertIdentifier}', + 'alerts.assistant.button.full': 'Investigar con Pulse Assistant', + 'alerts.assistant.button.text': 'Preguntar a Pulse Assistant', + 'alerts.assistant.detail.currentMetric': 'Valor actual {currentValue}; umbral {thresholdValue}', + 'alerts.assistant.detail.message': 'Mensaje: {message}', + 'alerts.assistant.detail.node': 'Nodo: {node}', + 'alerts.assistant.duration.hoursMinutes': '{hours}h {minutes}m', + 'alerts.assistant.duration.minute': '{count} min', + 'alerts.assistant.duration.minutes': '{count} min', + 'alerts.assistant.duration.unknown': 'duracion desconocida', + 'alerts.assistant.level.critical': 'Critica', + 'alerts.assistant.level.info': 'Informativa', + 'alerts.assistant.level.warning': 'Advertencia', + 'alerts.assistant.locked.proRequired': + 'Se requiere Pro para investigar alertas con Pulse Assistant', + 'alerts.assistant.locked.unavailable': + 'La investigacion de alertas de Pulse Assistant no esta disponible para esta alerta', + 'alerts.assistant.safetyNote': + 'Los diagnosticos y la correccion requieren aprobacion del operador.', + 'alerts.assistant.sourceLabel': 'Pulse Alerts', + 'alerts.assistant.statusLabel': '{level} alerta · Activa desde hace {duration}', + 'alerts.assistant.subject': '{level} {alertType} en {resourceName}', + 'alerts.assistant.title': 'Investigacion de alerta adjunta', + 'alerts.assistant.unlockedTitle': 'Pedir a Pulse Assistant que investigue esta alerta', + 'alerts.nav.ariaLabel': 'Navegacion de alertas', + 'alerts.nav.collapseSidebar': 'Contraer barra lateral', + 'alerts.nav.expandSidebar': 'Expandir barra lateral', + 'alerts.nav.title': 'Alertas', + 'alerts.nav.toggleAlerts': 'Alternar alertas', + 'alerts.overview.action.acknowledge': 'Reconocer', + 'alerts.overview.action.acknowledgeAll': 'Reconocer todas ({count})', + 'alerts.overview.action.acknowledging': 'Reconociendo...', + 'alerts.overview.action.hideAcknowledged': 'Ocultar reconocidas', + 'alerts.overview.action.hideTimeline': 'Ocultar linea de tiempo', + 'alerts.overview.action.processing': 'Procesando...', + 'alerts.overview.action.showAcknowledged': 'Mostrar reconocidas', + 'alerts.overview.action.timeline': 'Linea de tiempo', + 'alerts.overview.action.unacknowledge': 'Quitar reconocimiento', + 'alerts.overview.acknowledgedBadge': 'Reconocida', + 'alerts.overview.empty.description': 'Las alertas apareceran aqui cuando se superen los umbrales', + 'alerts.overview.empty.title': 'No hay alertas activas', + 'alerts.overview.filteredEmpty.all': 'No hay alertas activas', + 'alerts.overview.filteredEmpty.unacknowledged': 'No hay alertas sin reconocer', + 'alerts.overview.nodePrefix': 'en {node}', + 'alerts.overview.notification.acknowledged': 'Alerta reconocida', + 'alerts.overview.notification.acknowledgeFailed': 'No se pudo reconocer la alerta', + 'alerts.overview.notification.bulkFailure.singular': 'No se pudo reconocer {count} alerta.', + 'alerts.overview.notification.bulkFailure.plural': 'No se pudieron reconocer {count} alertas.', + 'alerts.overview.notification.bulkFailureGeneric': 'No se pudieron reconocer las alertas', + 'alerts.overview.notification.bulkSuccess.singular': '{count} alerta reconocida.', + 'alerts.overview.notification.bulkSuccess.plural': '{count} alertas reconocidas.', + 'alerts.overview.notification.restored': 'Alerta restaurada', + 'alerts.overview.notification.restoreFailed': 'No se pudo restaurar la alerta', + 'alerts.overview.paused.description': + 'Activa las alertas para reanudar la monitorizacion y desbloquear las pestañas de configuracion', + 'alerts.overview.paused.title': 'Las alertas estan pausadas', + 'alerts.overview.section.activeAlerts': 'Alertas activas', + 'alerts.overview.startedAt': 'Inicio: {startedAt}', + 'alerts.overview.stats.acknowledged': 'Reconocidas', + 'alerts.overview.stats.triggered24h': 'Activadas (24h)', + 'alerts.overview.stats.workloadOverrides': 'Excepciones de cargas', + 'alerts.page.default.description': + 'Revisa incidentes activos, el historial de alertas, umbrales, notificaciones y programaciones.', + 'alerts.page.default.title': 'Alertas', + 'alerts.page.destinations.description': + 'Enruta notificaciones de alerta a destinos de email, Apprise y webhook.', + 'alerts.page.destinations.title': 'Notificaciones', + 'alerts.page.history.description': + 'Busca alertas anteriores, revisa lineas de tiempo de incidentes e inspecciona la frecuencia de alertas.', + 'alerts.page.history.title': 'Historial de alertas', + 'alerts.page.overview.description': + 'Revisa incidentes activos, confirma la cobertura de alertas y controla si las alertas monitorizan activamente esta instalacion.', + 'alerts.page.overview.title': 'Resumen de alertas', + 'alerts.page.schedule.description': + 'Define horas de silencio, agrupacion, enfriamiento, recuperacion y escalado para la entrega de alertas.', + 'alerts.page.schedule.title': 'Programacion de mantenimiento', + 'alerts.page.thresholds.description': + 'Ajusta umbrales y excepciones especificas para infraestructura, cargas e integraciones.', + 'alerts.page.thresholds.title': 'Umbrales de alerta', + 'alerts.tabs.disabledTitle': 'Activa las alertas para configurar este ajuste', + 'alerts.tabs.group.configuration': 'Configuracion', + 'alerts.tabs.group.status': 'Estado', + 'alerts.tabs.destinations': 'Notificaciones', + 'alerts.tabs.history': 'Historial', + 'alerts.tabs.overview': 'Resumen', + 'alerts.tabs.schedule': 'Programacion', + 'alerts.tabs.thresholds': 'Umbrales', + 'alerts.timeline.acknowledged': 'reconocida', + 'alerts.timeline.closedAt': 'cerrado {closedAt}', + 'alerts.timeline.empty': 'Aun no hay eventos en la linea de tiempo.', + 'alerts.timeline.failure': 'No se pudo cargar la linea de tiempo.', + 'alerts.timeline.filterEmpty': + 'Ningun evento de la linea de tiempo coincide con los filtros seleccionados.', + 'alerts.timeline.filterLabel.compact': 'Filtros', + 'alerts.timeline.filterLabel.panel': 'Filtrar eventos:', + 'alerts.timeline.heading': 'Incidente', + 'alerts.timeline.loading': 'Cargando linea de tiempo...', + 'alerts.timeline.event.alertAcknowledged': 'Reconocida', + 'alerts.timeline.event.alertFired': 'Activada', + 'alerts.timeline.event.alertResolved': 'Resuelta', + 'alerts.timeline.event.alertUnacknowledged': 'Sin reconocer', + 'alerts.timeline.event.aiAnalysis': 'Patrol', + 'alerts.timeline.event.command': 'Comando', + 'alerts.timeline.event.note': 'Nota', + 'alerts.timeline.event.runbook': 'Runbook', + 'alerts.timeline.noteLabel': 'Nota del incidente', + 'alerts.timeline.notePlaceholder': 'Añade una nota para este incidente...', + 'alerts.timeline.openedAt': 'abierto {openedAt}', + 'alerts.timeline.quickFilter.all': 'Todas', + 'alerts.timeline.quickFilter.none': 'Ninguna', + 'alerts.timeline.retry': 'Reintentar', + 'alerts.timeline.saveNote': 'Guardar nota', + 'alerts.timeline.savingNote': 'Guardando...', + 'alerts.timeline.unavailable': 'No hay linea de tiempo de incidente disponible.', + 'runtimeHome.openingWorkspace': 'Abriendo el espacio de trabajo...', + 'setup.completion.action.addInfrastructure': 'Agregar infraestructura', + 'setup.completion.action.downloadCredentials': 'Descargar credenciales', + 'setup.completion.action.installAgent': 'Instalar Pulse Agent', + 'setup.completion.action.openInfrastructure': 'Abrir Infraestructura', + 'setup.completion.connectedSummary.singular': 'Conectado ({count} sistema)', + 'setup.completion.connectedSummary.plural': 'Conectados ({count} sistemas)', + 'setup.completion.credentials.apiTokenLabel': 'Token de API de administrador', + 'setup.completion.credentials.badge': 'Se muestra durante la configuración', + 'setup.completion.credentials.continuation.empty': 'Agregar infraestructura.', + 'setup.completion.credentials.continuation.connected': + 'Infraestructura o Agregar infraestructura.', + 'setup.completion.credentials.description': + 'Guarda el inicio de sesión de administrador y el token de API antes de salir de esta pantalla; luego continúa en {destination}', + 'setup.completion.credentials.passwordLabel': 'Contraseña', + 'setup.completion.credentials.title': 'Credenciales que debes guardar ahora', + 'setup.completion.credentials.usernameLabel': 'Usuario', + 'setup.completion.download.content': + 'Credenciales de Pulse\n==================\nGenerado: {generatedAt}\n\nInicio de sesión web:\n----------\nURL: {baseUrl}\nUsuario: {username}\nContraseña: {password}\n\nToken de API de administrador:\n----------------\n{apiToken}\n\nInfraestructura:\n---------------\n{infrastructureUrl}\n\nUsa Agregar infraestructura para elegir una API de plataforma, Pulse Agent o ambos\npara el primer sistema que Pulse debe supervisar.\n\nGuarda estas credenciales en un lugar seguro.\n', + 'setup.completion.hero.connected.description.agent': + 'Tu cuenta de administrador está lista y Pulse ya recibe telemetría. Abre Infraestructura para revisar el primer sistema; luego vuelve a Agregar infraestructura cuando quieras otra fuente Pulse Agent o API de plataforma.', + 'setup.completion.hero.connected.description.api': + 'Tu cuenta de administrador está lista y Pulse ya recibe telemetría. Abre Infraestructura para revisar el primer sistema; luego vuelve a Agregar infraestructura cuando quieras otra API de plataforma o fuente Pulse Agent.', + 'setup.completion.hero.connected.description.both': + 'Tu cuenta de administrador está lista y Pulse ya recibe telemetría. Abre Infraestructura para revisar el primer sistema; luego vuelve a Agregar infraestructura cuando quieras otra API de plataforma, fuente Agent o ambas.', + 'setup.completion.hero.connected.title': 'Primer sistema supervisado conectado', + 'setup.completion.hero.empty.description': + 'Tu cuenta de administrador está lista. Ahora elige cómo entrará el primer sistema en el modelo unificado de infraestructura: inventario por API de plataforma, telemetría de Pulse Agent o ambos.', + 'setup.completion.hero.empty.title': 'Elige tu primera fuente de infraestructura', + 'setup.completion.nextStep.ariaLabel': 'Siguiente paso de configuración', + 'setup.completion.nextStep.badge': 'Siguiente paso recomendado', + 'setup.completion.nextStep.detail.agent': + 'Agregar infraestructura queda disponible para más sistemas Pulse Agent o inventario por API de plataforma cuando una plataforma administra el entorno.', + 'setup.completion.nextStep.detail.api': + 'Agregar infraestructura queda disponible para más sistemas respaldados por API o telemetría de Pulse Agent cuando un sistema necesita cobertura local del nodo.', + 'setup.completion.nextStep.detail.both': + 'Agregar infraestructura queda disponible cuando quieras ampliar este primer sistema con otra fuente API, fuente Agent o ambas.', + 'setup.completion.nextStep.detail.empty': + 'Empieza con una API de plataforma cuando una plataforma administra el entorno. Instala Pulse Agent cuando el propio sistema deba informar telemetría local del nodo.', + 'setup.completion.nextStep.label': 'Siguiente paso', + 'setup.completion.nextStep.summary.connected.singular': + 'Abre Infraestructura para revisar tu primer sistema conectado.', + 'setup.completion.nextStep.summary.connected.plural': + 'Abre Infraestructura para revisar tus sistemas conectados.', + 'setup.completion.nextStep.summary.empty': + 'Abre Agregar infraestructura para elegir una API de plataforma, Pulse Agent o ambos.', + 'setup.completion.nextStep.title.connected': 'Abrir Infraestructura', + 'setup.completion.nextStep.title.empty': 'Elige la estrategia de primera fuente', + 'setup.completion.resource.unknownName': 'Desconocido', + 'setup.completion.sourceOptions.agent.description': + 'Telemetría local del nodo para hosts independientes, servicios, Docker y Kubernetes.', + 'setup.completion.sourceOptions.agent.title': 'Pulse Agent', + 'setup.completion.sourceOptions.both.description': + 'Combina inventario de plataforma con telemetría de Agent cuando importa la cobertura completa.', + 'setup.completion.sourceOptions.both.title': 'Usar ambos', + 'setup.completion.sourceOptions.platformApi.description': + 'Inventario y salud desde Proxmox, TrueNAS, VMware, PBS o PMG.', + 'setup.completion.sourceOptions.platformApi.title': 'API de plataforma', + 'setup.completion.sourceOptions.title': 'Opciones de fuente', + 'setup.progress.ariaLabel': 'Progreso de configuración', + 'setup.progress.state.completed': ', completado', + 'setup.progress.state.current': ', actual', + 'setup.progress.stepAriaLabel': 'Paso {index}: {step}{state}', + 'setup.security.action.back': 'Atrás', + 'setup.security.action.createAccount': 'Crear cuenta y continuar', + 'setup.security.action.settingUp': 'Configurando...', + 'setup.security.customPassword': 'Contraseña personalizada', + 'setup.security.description': 'El siguiente paso es elegir la primera fuente de infraestructura.', + 'setup.security.error.passwordMismatch': 'Las contraseñas no coinciden', + 'setup.security.error.passwordRequired': 'Ingresa una contraseña', + 'setup.security.error.passwordTooShort': 'La contraseña debe tener al menos 12 caracteres', + 'setup.security.error.setupFailed': 'La configuración falló: {error}', + 'setup.security.generatedPasswordHelp': + 'Se generará una contraseña segura de 20 caracteres y se mostrará en la siguiente pantalla.', + 'setup.security.label.confirmPassword': 'Confirmar contraseña', + 'setup.security.label.password': 'Contraseña', + 'setup.security.label.username': 'Usuario', + 'setup.security.minimumPasswordHelp': 'Mínimo 12 caracteres.', + 'setup.security.nextScreen.itemApiToken': 'Un token de API de administrador para automatización', + 'setup.security.nextScreen.itemCredentials': 'Tu usuario y contraseña', + 'setup.security.nextScreen.saveOnce': 'Guárdalos antes de continuar; se muestran una sola vez.', + 'setup.security.nextScreen.title': 'En la siguiente pantalla', + 'setup.security.passwordMode.autoGenerate': 'Generar automáticamente', + 'setup.security.placeholder.password': 'Contraseña (mínimo 12 caracteres)', + 'setup.security.placeholder.username': 'admin', + 'setup.security.showPassword.hide': 'Ocultar', + 'setup.security.showPassword.show': 'Mostrar', + 'setup.security.title': 'Crear tu cuenta de administrador', + 'setup.step.firstSource': 'Primera fuente', + 'setup.step.security': 'Seguridad', + 'setup.step.unlockServer': 'Desbloquear servidor', + 'setup.wizard.ariaLabel': 'Asistente de configuración de Pulse', + 'setup.welcome.action.continueSecurity': 'Continuar a Seguridad', + 'setup.welcome.action.verifyToken': 'Verificar token de bootstrap', + 'setup.welcome.action.verifyingToken': 'Verificando token de bootstrap...', + 'setup.welcome.copyCommandTitle': 'Copiar comando', + 'setup.welcome.deploymentHint.containerized': + 'Pulse parece ejecutarse en un entorno contenedorizado. Ejecuta el comando desde el host que administra el contenedor para imprimir el token de configuración de un solo uso.', + 'setup.welcome.deploymentHint.direct': + 'Ejecuta el comando directamente en una shell del servidor Pulse para imprimir el token de configuración de un solo uso.', + 'setup.welcome.deploymentHint.dockerNamed': + 'Pulse parece ejecutarse en Docker como contenedor "{containerName}". Ejecuta el comando en el host Docker para imprimir el token de configuración de un solo uso desde ese contenedor.', + 'setup.welcome.deploymentHint.dockerUnnamed': + 'Pulse parece ejecutarse en Docker. Ejecuta el comando en el host Docker y reemplaza por el nombre del contenedor Pulse en ejecución.', + 'setup.welcome.deploymentHint.lxc': + 'Pulse parece ejecutarse en el contenedor LXC {ctid}. Ejecuta el comando en el host Proxmox para entrar en ese contenedor e imprimir el token de configuración de un solo uso.', + 'setup.welcome.deploymentLabel.containerized': 'Despliegue contenedorizado', + 'setup.welcome.deploymentLabel.direct': 'Instalación directa en host', + 'setup.welcome.deploymentLabel.docker': 'Despliegue Docker', + 'setup.welcome.deploymentLabel.lxc': 'Contenedor LXC', + 'setup.welcome.error.copyCommandFailed': 'No se pudo copiar el comando', + 'setup.welcome.error.invalidBootstrapToken': + 'Token de bootstrap no válido. Revísalo e inténtalo de nuevo.', + 'setup.welcome.error.invalidBootstrapTokenResponse': 'Token de bootstrap no válido', + 'setup.welcome.error.missingBootstrapToken': 'Ingresa el token de bootstrap', + 'setup.welcome.error.snapshotPaste': + 'Eso parece el contenido cifrado del archivo .bootstrap_token, no el token de configuración sin procesar. Ejecuta el comando anterior y pega la cadena de token que imprime.', + 'setup.welcome.hero.coverage': + 'Conecta una API de plataforma, instala Pulse Agent o usa ambos para cobertura completa.', + 'setup.welcome.hero.step.admin': 'Crear la cuenta de administrador', + 'setup.welcome.hero.step.source': 'Elegir la primera fuente', + 'setup.welcome.hero.step.unlock': 'Desbloquear este servidor Pulse', + 'setup.welcome.hero.stepsIntro': 'Tres pasos:', + 'setup.welcome.hero.stepsThen': 'luego', + 'setup.welcome.hero.title': 'Bienvenido a Pulse', + 'setup.welcome.placeholder.bootstrapToken': 'Pega tu token de bootstrap', + 'setup.welcome.success.commandCopied': 'Comando copiado al portapapeles', + 'setup.welcome.tokenHelp.afterVerify': + 'Después de que Pulse verifique este token, el siguiente paso es crear la cuenta de administrador para este servidor.', + 'setup.welcome.tokenHelp.docker': + 'Este token de bootstrap de un solo uso solo desbloquea la configuración inicial. Ejecuta el comando anterior y pega la cadena de token que imprime. Después de la verificación, crearás la cuenta de administrador y Pulse generará el token de API de larga duración por separado.', + 'setup.welcome.tokenHelp.host': + 'Este token de bootstrap de un solo uso solo desbloquea la configuración inicial en este servidor Pulse. Ejecuta el comando anterior y pega la cadena de token que imprime. No es tu contraseña de administrador ni el token de API que usarás después de la configuración.', + 'setup.welcome.tokenHelp.title': 'Qué hace este token', + 'setup.welcome.unlockTitle': 'Desbloquear configuración', + 'settings.general.appearance.title': 'Apariencia', + 'settings.general.fullWidth.description': + 'Expande el contenido para usar todo el ancho disponible en monitores grandes.', + 'settings.general.fullWidth.title': 'Modo de ancho completo', + 'settings.general.docker.envHint': 'También se puede definir mediante variable de entorno:', + 'settings.general.docker.section.description': + 'Controla cómo aparecen las acciones de actualización de {sourceLabel} en Pulse.', + 'settings.general.docker.section.title': 'Actualizaciones de {sourceLabel}', + 'settings.general.docker.toggle.description': + 'Cuando está activado, las acciones "Update" de {sourceLabel} se ocultan en Pulse. La detección de actualizaciones sigue ejecutándose, por lo que las actualizaciones disponibles siguen visibles.', + 'settings.general.docker.toggle.title': 'Ocultar botones de actualización', + 'settings.general.language.ariaLabel': 'Idioma de la app', + 'settings.general.language.description': + 'Usa este idioma para la interfaz de la app. Los comandos, nombres de recursos y campos API no cambian.', + 'settings.general.language.title': 'Idioma', + 'settings.general.monitoringCadence.current': 'Cadencia actual: {seconds} segundos ({duration})', + 'settings.general.monitoringCadence.custom.description': + 'Introduce segundos ({min}-{max}). Se aplica a todos los clusters.', + 'settings.general.monitoringCadence.custom.title': 'Intervalo de sondeo personalizado', + 'settings.general.monitoringCadence.description': + 'Los intervalos más cortos ofrecen actualizaciones casi en tiempo real a costa de mayor uso de API y CPU en cada nodo. Usa un intervalo más largo para reducir la carga en clusters ocupados.', + 'settings.general.monitoringCadence.duration.minute': '{count} minuto', + 'settings.general.monitoringCadence.duration.minutes': '{count} minutos', + 'settings.general.monitoringCadence.duration.underMinute': 'menos de un minuto', + 'settings.general.monitoringCadence.envLocked': + 'Administrado mediante variable de entorno {envVar}.', + 'settings.general.monitoringCadence.preset.balanced': 'Equilibrado ({duration})', + 'settings.general.monitoringCadence.preset.custom': 'Personalizado', + 'settings.general.monitoringCadence.preset.low': 'Bajo ({duration})', + 'settings.general.monitoringCadence.preset.realtime': 'Tiempo real ({duration})', + 'settings.general.monitoringCadence.preset.veryLow': 'Muy bajo ({duration})', + 'settings.general.monitoringCadence.section.description': + 'Controla con qué frecuencia Pulse sondea nodos de Proxmox VE.', + 'settings.general.monitoringCadence.section.title': 'Cadencia de supervisión', + 'settings.general.temperature.description': 'Muestra temperaturas en Celsius o Fahrenheit.', + 'settings.general.temperature.title': 'Unidad de temperatura', + 'settings.general.telemetry.copyJson': 'Copiar JSON', + 'settings.general.telemetry.description': + 'Ayuda a mejorar Pulse compartiendo datos de uso salientes anónimos: un ID de instalación rotativo, identidad de versión normalizada, plataforma de ejecución, conteos agregados de adopción autohospedada y flags de funciones de alto nivel. No se envían hostnames, credenciales, identificadores de infraestructura, prompts, mensajes de chat ni información personal. Las filas de telemetría se conservan hasta 90 días y las direcciones IP no se guardan en filas de telemetría.', + 'settings.general.telemetry.disabledPreview': + 'La telemetría está desactivada. Esta vista previa muestra el payload que Pulse enviaría si la activas.', + 'settings.general.telemetry.fullDetails': 'Detalles completos', + 'settings.general.telemetry.payloadAriaLabel': 'Vista previa del payload de telemetría', + 'settings.general.telemetry.payloadTitle': 'Payload de heartbeat actual', + 'settings.general.telemetry.previewPayload': 'Vista previa del payload', + 'settings.general.telemetry.refreshPayload': 'Actualizar payload', + 'settings.general.telemetry.resetId': 'Restablecer ID', + 'settings.general.telemetry.section.description': + 'Controla telemetría saliente anónima de esta instancia de Pulse.', + 'settings.general.telemetry.section.title': 'Datos de uso y privacidad', + 'settings.general.telemetry.title': 'Telemetría saliente anónima', + 'settings.general.theme.description': 'Elige claro, oscuro o sincroniza con el tema del sistema.', + 'settings.general.theme.option.dark': 'Oscuro', + 'settings.general.theme.option.light': 'Claro', + 'settings.general.theme.option.system': 'Sistema', + 'settings.general.theme.title': 'Preferencia de tema', + 'settings.header.api.description': + 'Genera y administra tokens de Pulse con alcance limitado para agentes, automatización e integraciones externas.', + 'settings.header.api.title': 'Acceso API', + 'settings.header.infrastructure.description': + 'Agrega, descubre y verifica la infraestructura que Pulse supervisa.', + 'settings.header.infrastructure.readOnlyDescription': + 'Revisa los sistemas principales supervisados y el estado de informes. Los cambios de configuración no están disponibles en esta sesión de solo lectura.', + 'settings.header.infrastructure.title': 'Infraestructura', + 'settings.header.monitoringAvailability.description': + 'Supervisa dispositivos y servicios solo por endpoint con pruebas ping, TCP y HTTP.', + 'settings.header.monitoringAvailability.title': 'Comprobaciones de disponibilidad', + 'settings.header.organizationAccess.description': + 'Administra invitaciones, roles de miembros y transferencias de propiedad de la organización.', + 'settings.header.organizationAccess.title': 'Acceso de organización', + 'settings.header.organizationBilling.description': + 'Revisa el plan de la organización, las políticas de uso aplicables y el estado de suscripción para acceso de pago.', + 'settings.header.organizationBilling.title': 'Facturación y uso', + 'settings.header.organizationBillingAdmin.description': + 'Revisa y administra el estado de facturación de todos los tenants (solo modo alojado).', + 'settings.header.organizationBillingAdmin.title': 'Admin de facturación', + 'settings.header.organizationOverview.description': + 'Revisa metadatos, alcance de miembros y propiedad de la organización.', + 'settings.header.organizationOverview.title': 'Resumen de organización', + 'settings.header.organizationSharing.description': + 'Comparte recursos entre organizaciones con acceso delimitado.', + 'settings.header.organizationSharing.title': 'Uso compartido de organización', + 'settings.header.securityAudit.description': + 'Consulta eventos de seguridad, intentos de inicio de sesión y cambios de configuración.', + 'settings.header.securityAudit.title': 'Registro de auditoría', + 'settings.header.securityAuth.description': + 'Administra autenticación con contraseña y rotación de credenciales.', + 'settings.header.securityAuth.title': 'Autenticación', + 'settings.header.securityDataHandling.description': + 'Consulta qué detalles de recursos supervisados se pueden resumir, deben quedarse locales o están redactados.', + 'settings.header.securityDataHandling.title': 'Privacidad de recursos', + 'settings.header.securityOverview.description': + 'Consulta tu postura de seguridad de un vistazo y supervisa el estado de autenticación.', + 'settings.header.securityOverview.title': 'Resumen de seguridad', + 'settings.header.securityRoles.description': + 'Define roles personalizados y administra permisos granulares para usuarios y tokens.', + 'settings.header.securityRoles.title': 'Roles', + 'settings.header.securitySso.description': 'Configura proveedores de identidad OIDC y SAML.', + 'settings.header.securitySso.title': 'Proveedores de inicio de sesión único', + 'settings.header.securityUsers.description': + 'Asigna roles a usuarios y consulta permisos efectivos en tu infraestructura.', + 'settings.header.securityUsers.title': 'Acceso de usuarios', + 'settings.header.securityWebhooks.description': + 'Configura la entrega en tiempo real de eventos de auditoría a sistemas externos.', + 'settings.header.securityWebhooks.title': 'Webhooks de auditoría', + 'settings.header.systemAi.description': + 'Configura proveedores y modelos para Pulse Assistant y Patrol.', + 'settings.header.systemAi.title': 'Assistant y Patrol', + 'settings.header.systemBilling.description': + 'Revisa el plan que usa esta instancia y las capacidades opcionales conectadas.', + 'settings.header.systemBilling.title': 'Plan autohospedado', + 'settings.header.systemGeneral.description': + 'Administra apariencia, diseño y cadencia predeterminada de supervisión.', + 'settings.header.systemGeneral.title': 'General', + 'settings.header.systemNetwork.description': + 'Configura la URL pública, CORS, inserción y límites de red para webhooks.', + 'settings.header.systemNetwork.title': 'Red', + 'settings.header.systemRecovery.description': + 'Administra sondeos de copias/snapshots y flujos de exportación e importación de configuración.', + 'settings.header.systemRecovery.title': 'Recuperación', + 'settings.header.systemRelay.description': + 'Configura la conectividad de relay de Pulse para acceso remoto seguro y vinculación con Pulse Mobile.', + 'settings.header.systemRelay.title': 'Acceso remoto', + 'settings.header.systemUpdates.description': + 'Administra comprobaciones de versión, canales de actualización y comportamiento de actualización automática.', + 'settings.header.systemUpdates.title': 'Actualizaciones', + 'settings.header.supportDiagnostics.description': + 'Ejecuta comprobaciones de salud, valida conectividad y exporta snapshots de resolución de problemas.', + 'settings.header.supportDiagnostics.title': 'Diagnóstico y salud', + 'settings.header.supportLogs.description': + 'Inspecciona el flujo de logs de Pulse en vivo y descarga el búfer capturado para soporte.', + 'settings.header.supportLogs.title': 'Logs del sistema', + 'settings.header.supportReporting.description': + 'Exporta datos de inventario y genera informes de rendimiento desde la consola canónica de ajustes.', + 'settings.header.supportReporting.title': 'Datos e informes', + 'settings.nav.group.infrastructure': 'Infraestructura', + 'settings.nav.group.monitoring': 'Supervisión', + 'settings.nav.group.organization': 'Organización', + 'settings.nav.group.security': 'Seguridad', + 'settings.nav.group.support': 'Soporte', + 'settings.nav.group.system': 'Sistema', + 'settings.nav.item.apiAccess': 'Acceso API', + 'settings.nav.item.auditLog': 'Registro de auditoría', + 'settings.nav.item.auditWebhooks': 'Webhooks de auditoría', + 'settings.nav.item.authentication': 'Autenticación', + 'settings.nav.item.availabilityChecks': 'Comprobaciones de disponibilidad', + 'settings.nav.item.billing': 'Facturación', + 'settings.nav.item.billingAdmin': 'Admin de facturación', + 'settings.nav.item.dataReports': 'Datos e informes', + 'settings.nav.item.diagnosticsHealth': 'Diagnóstico y salud', + 'settings.nav.item.general': 'General', + 'settings.nav.item.infrastructure': 'Infraestructura', + 'settings.nav.item.network': 'Red', + 'settings.nav.item.organizationAccess': 'Acceso', + 'settings.nav.item.organizationOverview': 'Resumen', + 'settings.nav.item.plans': 'Planes', + 'settings.nav.item.recovery': 'Recuperación', + 'settings.nav.item.remoteAccess': 'Acceso remoto', + 'settings.nav.item.resourcePrivacy': 'Privacidad de recursos', + 'settings.nav.item.roles': 'Roles', + 'settings.nav.item.securityOverview': 'Resumen de seguridad', + 'settings.nav.item.sharing': 'Uso compartido', + 'settings.nav.item.singleSignOn': 'Inicio de sesión único', + 'settings.nav.item.systemLogs': 'Logs del sistema', + 'settings.nav.item.updates': 'Actualizaciones', + 'settings.nav.item.users': 'Usuarios', + 'settings.nav.item.assistantPatrol': 'Assistant y Patrol', + 'settings.shell.collapseSidebarLabel': 'Contraer navegación de ajustes', + 'settings.shell.configurationLoading': 'Cargando configuración...', + 'settings.shell.discardLabel': 'Descartar', + 'settings.shell.expandSidebarLabel': 'Expandir navegación de ajustes', + 'settings.shell.loading': 'Cargando ajustes...', + 'settings.shell.mobileBackLabel': 'Ajustes', + 'settings.shell.navigationAriaLabel': 'Navegación de ajustes', + 'settings.shell.navigationTitle': 'Ajustes', + 'settings.shell.saveChangesLabel': 'Guardar cambios', + 'settings.shell.searchEmpty': 'No se encontraron ajustes para "{query}"', + 'settings.shell.searchPlaceholder': 'Buscar ajustes...', + 'settings.shell.unsavedDescription': 'Tus cambios se perderán si sales.', + 'settings.shell.unsavedTitle': 'Cambios sin guardar', +} as const satisfies Partial; diff --git a/frontend-modern/src/i18n/messages.ts b/frontend-modern/src/i18n/messages.ts index 457c33faa..9ee468f57 100644 --- a/frontend-modern/src/i18n/messages.ts +++ b/frontend-modern/src/i18n/messages.ts @@ -713,906 +713,7 @@ export const ALERTS_OVERVIEW_MIGRATED_MESSAGE_KEYS = [ 'alerts.timeline.unavailable', ] as const satisfies readonly I18nMessageKey[]; -export const I18N_MESSAGES: I18nCatalogs = { - en: EN_MESSAGES, - de: { - ...EN_MESSAGES, - 'alerts.activation.label.enabled': 'Warnmeldungen aktiviert', - 'alerts.activation.label.disabled': 'Warnmeldungen deaktiviert', - 'alerts.activation.toast.activated': - 'Warnmeldungen aktiviert. Sie erhalten jetzt Warnungen, wenn Probleme erkannt werden.', - 'alerts.activation.toast.activateFailed': - 'Warnmeldungen konnten nicht aktiviert werden. Bitte versuchen Sie es erneut.', - 'alerts.activation.toast.deactivated': - 'Warnmeldungen deaktiviert. Es wird nichts gesendet, bis Sie sie wieder aktivieren.', - 'alerts.activation.toast.deactivateFailed': - 'Warnmeldungen konnten nicht deaktiviert werden. Bitte versuchen Sie es erneut.', - 'alerts.assistant.action.investigate': 'Warnmeldung {alertIdentifier} untersuchen', - 'alerts.assistant.button.full': 'Mit Pulse Assistant untersuchen', - 'alerts.assistant.button.text': 'Pulse Assistant fragen', - 'alerts.assistant.detail.currentMetric': - 'Aktueller Wert {currentValue}; Schwellwert {thresholdValue}', - 'alerts.assistant.detail.message': 'Meldung: {message}', - 'alerts.assistant.detail.node': 'Knoten: {node}', - 'alerts.assistant.duration.hoursMinutes': '{hours}h {minutes}m', - 'alerts.assistant.duration.minute': '{count} Min.', - 'alerts.assistant.duration.minutes': '{count} Min.', - 'alerts.assistant.duration.unknown': 'unbekannte Dauer', - 'alerts.assistant.level.critical': 'Kritisch', - 'alerts.assistant.level.info': 'Info', - 'alerts.assistant.level.warning': 'Warnung', - 'alerts.assistant.locked.proRequired': - 'Pro erforderlich, um Warnmeldungen mit Pulse Assistant zu untersuchen', - 'alerts.assistant.locked.unavailable': - 'Pulse Assistant-Warnungsanalyse ist fuer diese Warnmeldung nicht verfuegbar', - 'alerts.assistant.safetyNote': - 'Diagnosen und Behebungen erfordern die Freigabe durch einen Operator.', - 'alerts.assistant.sourceLabel': 'Pulse Alerts', - 'alerts.assistant.statusLabel': '{level}-Warnmeldung · Aktiv seit {duration}', - 'alerts.assistant.subject': '{level} {alertType} auf {resourceName}', - 'alerts.assistant.title': 'Warnungsanalyse angehaengt', - 'alerts.assistant.unlockedTitle': 'Pulse Assistant bitten, diese Warnmeldung zu untersuchen', - 'alerts.nav.ariaLabel': 'Warnmeldungsnavigation', - 'alerts.nav.collapseSidebar': 'Seitenleiste einklappen', - 'alerts.nav.expandSidebar': 'Seitenleiste ausklappen', - 'alerts.nav.title': 'Warnmeldungen', - 'alerts.nav.toggleAlerts': 'Warnmeldungen umschalten', - 'alerts.overview.action.acknowledge': 'Bestaetigen', - 'alerts.overview.action.acknowledgeAll': 'Alle bestaetigen ({count})', - 'alerts.overview.action.acknowledging': 'Wird bestaetigt...', - 'alerts.overview.action.hideAcknowledged': 'Bestaetigte ausblenden', - 'alerts.overview.action.hideTimeline': 'Zeitleiste ausblenden', - 'alerts.overview.action.processing': 'Wird verarbeitet...', - 'alerts.overview.action.showAcknowledged': 'Bestaetigte anzeigen', - 'alerts.overview.action.timeline': 'Zeitleiste', - 'alerts.overview.action.unacknowledge': 'Bestaetigung aufheben', - 'alerts.overview.acknowledgedBadge': 'Bestaetigt', - 'alerts.overview.empty.description': - 'Warnmeldungen erscheinen hier, wenn Schwellwerte ueberschritten werden', - 'alerts.overview.empty.title': 'Keine aktiven Warnmeldungen', - 'alerts.overview.filteredEmpty.all': 'Keine aktiven Warnmeldungen', - 'alerts.overview.filteredEmpty.unacknowledged': 'Keine unbestaetigten Warnmeldungen', - 'alerts.overview.nodePrefix': 'auf {node}', - 'alerts.overview.notification.acknowledged': 'Warnmeldung bestaetigt', - 'alerts.overview.notification.acknowledgeFailed': 'Warnmeldung konnte nicht bestaetigt werden', - 'alerts.overview.notification.bulkFailure.singular': - '{count} Warnmeldung konnte nicht bestaetigt werden.', - 'alerts.overview.notification.bulkFailure.plural': - '{count} Warnmeldungen konnten nicht bestaetigt werden.', - 'alerts.overview.notification.bulkFailureGeneric': - 'Warnmeldungen konnten nicht bestaetigt werden', - 'alerts.overview.notification.bulkSuccess.singular': '{count} Warnmeldung bestaetigt.', - 'alerts.overview.notification.bulkSuccess.plural': '{count} Warnmeldungen bestaetigt.', - 'alerts.overview.notification.restored': 'Warnmeldung wiederhergestellt', - 'alerts.overview.notification.restoreFailed': - 'Warnmeldung konnte nicht wiederhergestellt werden', - 'alerts.overview.paused.description': - 'Schalten Sie Warnmeldungen ein, um die Ueberwachung fortzusetzen und Konfigurationstabs freizugeben', - 'alerts.overview.paused.title': 'Warnmeldungen sind pausiert', - 'alerts.overview.section.activeAlerts': 'Aktive Warnmeldungen', - 'alerts.overview.startedAt': 'Gestartet: {startedAt}', - 'alerts.overview.stats.acknowledged': 'Bestaetigt', - 'alerts.overview.stats.triggered24h': 'Ausgeloest (24h)', - 'alerts.overview.stats.workloadOverrides': 'Workload-Ausnahmen', - 'alerts.page.default.description': - 'Pruefen Sie aktive Vorfaelle, Warnungsverlauf, Schwellwerte, Benachrichtigungen und Zeitplaene.', - 'alerts.page.default.title': 'Warnmeldungen', - 'alerts.page.destinations.description': - 'Leiten Sie Warnmeldungen an E-Mail-, Apprise- und Webhook-Ziele weiter.', - 'alerts.page.destinations.title': 'Benachrichtigungen', - 'alerts.page.history.description': - 'Suchen Sie fruehere Warnmeldungen, pruefen Sie Vorfall-Zeitleisten und beobachten Sie Warnungshaeufigkeit ueber Zeit.', - 'alerts.page.history.title': 'Warnungsverlauf', - 'alerts.page.overview.description': - 'Pruefen Sie aktive Vorfaelle, Warnungsabdeckung und ob Warnmeldungen diese Installation aktiv ueberwachen.', - 'alerts.page.overview.title': 'Warnmeldungsuebersicht', - 'alerts.page.schedule.description': - 'Definieren Sie Ruhezeiten, Gruppierung, Abklingzeiten, Wiederherstellung und Eskalation fuer Warnmeldungen.', - 'alerts.page.schedule.title': 'Wartungszeitplan', - 'alerts.page.thresholds.description': - 'Passen Sie Schwellwerte und gezielte Ausnahmen fuer Infrastruktur, Workloads und Integrationen an.', - 'alerts.page.thresholds.title': 'Warnungsschwellwerte', - 'alerts.tabs.disabledTitle': - 'Aktivieren Sie Warnmeldungen, um diese Einstellung zu konfigurieren', - 'alerts.tabs.group.configuration': 'Konfiguration', - 'alerts.tabs.group.status': 'Status', - 'alerts.tabs.destinations': 'Benachrichtigungen', - 'alerts.tabs.history': 'Verlauf', - 'alerts.tabs.overview': 'Uebersicht', - 'alerts.tabs.schedule': 'Zeitplan', - 'alerts.tabs.thresholds': 'Schwellwerte', - 'alerts.timeline.acknowledged': 'bestaetigt', - 'alerts.timeline.closedAt': 'geschlossen {closedAt}', - 'alerts.timeline.empty': 'Noch keine Zeitleistenereignisse.', - 'alerts.timeline.failure': 'Zeitleiste konnte nicht geladen werden.', - 'alerts.timeline.filterEmpty': - 'Keine Zeitleistenereignisse entsprechen den ausgewaehlten Filtern.', - 'alerts.timeline.filterLabel.compact': 'Filter', - 'alerts.timeline.filterLabel.panel': 'Ereignisse filtern:', - 'alerts.timeline.heading': 'Vorfall', - 'alerts.timeline.loading': 'Zeitleiste wird geladen...', - 'alerts.timeline.event.alertAcknowledged': 'Bestaetigt', - 'alerts.timeline.event.alertFired': 'Ausgeloest', - 'alerts.timeline.event.alertResolved': 'Behoben', - 'alerts.timeline.event.alertUnacknowledged': 'Unbestaetigt', - 'alerts.timeline.event.aiAnalysis': 'Patrol', - 'alerts.timeline.event.command': 'Befehl', - 'alerts.timeline.event.note': 'Notiz', - 'alerts.timeline.event.runbook': 'Runbook', - 'alerts.timeline.noteLabel': 'Vorfallsnotiz', - 'alerts.timeline.notePlaceholder': 'Notiz fuer diesen Vorfall hinzufuegen...', - 'alerts.timeline.openedAt': 'geoeffnet {openedAt}', - 'alerts.timeline.quickFilter.all': 'Alle', - 'alerts.timeline.quickFilter.none': 'Keine', - 'alerts.timeline.retry': 'Erneut versuchen', - 'alerts.timeline.saveNote': 'Notiz speichern', - 'alerts.timeline.savingNote': 'Wird gespeichert...', - 'alerts.timeline.unavailable': 'Keine Vorfall-Zeitleiste verfuegbar.', - 'runtimeHome.openingWorkspace': 'Arbeitsbereich wird geoeffnet...', - 'setup.completion.action.addInfrastructure': 'Infrastruktur hinzufuegen', - 'setup.completion.action.downloadCredentials': 'Zugangsdaten herunterladen', - 'setup.completion.action.installAgent': 'Pulse Agent installieren', - 'setup.completion.action.openInfrastructure': 'Infrastruktur oeffnen', - 'setup.completion.connectedSummary.singular': 'Verbunden ({count} System)', - 'setup.completion.connectedSummary.plural': 'Verbunden ({count} Systeme)', - 'setup.completion.credentials.apiTokenLabel': 'Admin-API-Token', - 'setup.completion.credentials.badge': 'Waehrend der Einrichtung angezeigt', - 'setup.completion.credentials.continuation.empty': 'Infrastruktur hinzufuegen.', - 'setup.completion.credentials.continuation.connected': - 'Infrastruktur oder Infrastruktur hinzufuegen.', - 'setup.completion.credentials.description': - 'Speichern Sie Admin-Anmeldung und API-Token, bevor Sie diesen Bildschirm verlassen, und fahren Sie dann mit {destination} fort', - 'setup.completion.credentials.passwordLabel': 'Passwort', - 'setup.completion.credentials.title': 'Zugangsdaten jetzt speichern', - 'setup.completion.credentials.usernameLabel': 'Benutzername', - 'setup.completion.download.content': - 'Pulse-Zugangsdaten\n==================\nErstellt: {generatedAt}\n\nWeb-Anmeldung:\n----------\nURL: {baseUrl}\nBenutzername: {username}\nPasswort: {password}\n\nAdmin-API-Token:\n----------------\n{apiToken}\n\nInfrastruktur:\n---------------\n{infrastructureUrl}\n\nVerwenden Sie Infrastruktur hinzufuegen, um eine Plattform-API, Pulse Agent oder beides\nfuer das erste System auszuwaehlen, das Pulse ueberwachen soll.\n\nBewahren Sie diese Zugangsdaten sicher auf!\n', - 'setup.completion.hero.connected.description.agent': - 'Ihr Admin-Konto ist bereit und Pulse empfaengt bereits Telemetrie. Oeffnen Sie Infrastruktur, um das erste System zu pruefen, und kehren Sie zu Infrastruktur hinzufuegen zurueck, wenn Sie eine weitere Pulse Agent- oder Plattform-API-Quelle wollen.', - 'setup.completion.hero.connected.description.api': - 'Ihr Admin-Konto ist bereit und Pulse empfaengt bereits Telemetrie. Oeffnen Sie Infrastruktur, um das erste System zu pruefen, und kehren Sie zu Infrastruktur hinzufuegen zurueck, wenn Sie eine weitere Plattform-API- oder Pulse Agent-Quelle wollen.', - 'setup.completion.hero.connected.description.both': - 'Ihr Admin-Konto ist bereit und Pulse empfaengt bereits Telemetrie. Oeffnen Sie Infrastruktur, um das erste System zu pruefen, und kehren Sie zu Infrastruktur hinzufuegen zurueck, wenn Sie eine weitere Plattform-API- oder Agent-Quelle wollen.', - 'setup.completion.hero.connected.title': 'Erstes ueberwachtes System verbunden', - 'setup.completion.hero.empty.description': - 'Ihr Admin-Konto ist bereit. Waehlen Sie als Naechstes, wie das erste System in das einheitliche Infrastrukturmodell gelangt: Plattform-API-Inventar, Pulse Agent-Telemetrie oder beides.', - 'setup.completion.hero.empty.title': 'Erste Infrastrukturquelle waehlen', - 'setup.completion.nextStep.ariaLabel': 'Naechster Einrichtungsschritt', - 'setup.completion.nextStep.badge': 'Empfohlener naechster Schritt', - 'setup.completion.nextStep.detail.agent': - 'Infrastruktur hinzufuegen bleibt fuer weitere Pulse Agent-Systeme oder Plattform-API-Inventar verfuegbar, wenn eine Plattform die Umgebung verwaltet.', - 'setup.completion.nextStep.detail.api': - 'Infrastruktur hinzufuegen bleibt fuer weitere API-gestuetzte Systeme oder Pulse Agent-Telemetrie verfuegbar, wenn ein System lokale Knotenabdeckung braucht.', - 'setup.completion.nextStep.detail.both': - 'Infrastruktur hinzufuegen bleibt jederzeit verfuegbar, wenn Sie dieses erste System um eine weitere API-Quelle, Agent-Quelle oder beides erweitern wollen.', - 'setup.completion.nextStep.detail.empty': - 'Beginnen Sie mit einer Plattform-API, wenn eine Plattform die Umgebung verwaltet. Installieren Sie Pulse Agent, wenn das System selbst lokale Knotentelemetrie melden soll.', - 'setup.completion.nextStep.label': 'Naechster Schritt', - 'setup.completion.nextStep.summary.connected.singular': - 'Oeffnen Sie Infrastruktur, um Ihr erstes verbundenes System zu pruefen.', - 'setup.completion.nextStep.summary.connected.plural': - 'Oeffnen Sie Infrastruktur, um Ihre verbundenen Systeme zu pruefen.', - 'setup.completion.nextStep.summary.empty': - 'Oeffnen Sie Infrastruktur hinzufuegen, um eine Plattform-API, Pulse Agent oder beides zu waehlen.', - 'setup.completion.nextStep.title.connected': 'Infrastruktur oeffnen', - 'setup.completion.nextStep.title.empty': 'Strategie fuer erste Quelle waehlen', - 'setup.completion.resource.unknownName': 'Unbekannt', - 'setup.completion.sourceOptions.agent.description': - 'Knotenlokale Telemetrie fuer eigenstaendige Hosts, Dienste, Docker und Kubernetes.', - 'setup.completion.sourceOptions.agent.title': 'Pulse Agent', - 'setup.completion.sourceOptions.both.description': - 'Kombinieren Sie Plattforminventar mit Agent-Telemetrie, wenn vollstaendige Abdeckung wichtig ist.', - 'setup.completion.sourceOptions.both.title': 'Beides verwenden', - 'setup.completion.sourceOptions.platformApi.description': - 'Inventar und Zustand aus Proxmox, TrueNAS, VMware, PBS oder PMG.', - 'setup.completion.sourceOptions.platformApi.title': 'Plattform-API', - 'setup.completion.sourceOptions.title': 'Quellenoptionen', - 'setup.progress.ariaLabel': 'Einrichtungsfortschritt', - 'setup.progress.state.completed': ', abgeschlossen', - 'setup.progress.state.current': ', aktuell', - 'setup.progress.stepAriaLabel': 'Schritt {index}: {step}{state}', - 'setup.security.action.back': 'Zurueck', - 'setup.security.action.createAccount': 'Konto erstellen und fortfahren', - 'setup.security.action.settingUp': 'Einrichtung laeuft...', - 'setup.security.customPassword': 'Eigenes Passwort', - 'setup.security.description': - 'Der naechste Schritt ist die Auswahl der ersten Infrastrukturquelle.', - 'setup.security.error.passwordMismatch': 'Passwoerter stimmen nicht ueberein', - 'setup.security.error.passwordRequired': 'Bitte geben Sie ein Passwort ein', - 'setup.security.error.passwordTooShort': 'Das Passwort muss mindestens 12 Zeichen haben', - 'setup.security.error.setupFailed': 'Einrichtung fehlgeschlagen: {error}', - 'setup.security.generatedPasswordHelp': - 'Ein sicheres 20-Zeichen-Passwort wird erzeugt und auf dem naechsten Bildschirm angezeigt.', - 'setup.security.label.confirmPassword': 'Passwort bestaetigen', - 'setup.security.label.password': 'Passwort', - 'setup.security.label.username': 'Benutzername', - 'setup.security.minimumPasswordHelp': 'Mindestens 12 Zeichen.', - 'setup.security.nextScreen.itemApiToken': 'Ein Admin-API-Token fuer Automatisierung', - 'setup.security.nextScreen.itemCredentials': 'Ihr Benutzername und Passwort', - 'setup.security.nextScreen.saveOnce': - 'Speichern Sie sie vor dem Fortfahren; sie werden nur einmal angezeigt.', - 'setup.security.nextScreen.title': 'Auf dem naechsten Bildschirm', - 'setup.security.passwordMode.autoGenerate': 'Automatisch erzeugen', - 'setup.security.placeholder.password': 'Passwort (mind. 12 Zeichen)', - 'setup.security.placeholder.username': 'admin', - 'setup.security.showPassword.hide': 'Ausblenden', - 'setup.security.showPassword.show': 'Anzeigen', - 'setup.security.title': 'Admin-Konto erstellen', - 'setup.step.firstSource': 'Erste Quelle', - 'setup.step.security': 'Sicherheit', - 'setup.step.unlockServer': 'Server entsperren', - 'setup.wizard.ariaLabel': 'Pulse-Einrichtungsassistent', - 'setup.welcome.action.continueSecurity': 'Weiter zu Sicherheit', - 'setup.welcome.action.verifyToken': 'Bootstrap-Token pruefen', - 'setup.welcome.action.verifyingToken': 'Bootstrap-Token wird geprueft...', - 'setup.welcome.copyCommandTitle': 'Befehl kopieren', - 'setup.welcome.deploymentHint.containerized': - 'Pulse scheint in einer containerisierten Umgebung zu laufen. Fuehren Sie den Befehl auf dem Host aus, der den Container verwaltet, damit Sie das einmalige Setup-Token ausgeben koennen.', - 'setup.welcome.deploymentHint.direct': - 'Fuehren Sie den Befehl direkt in einer Shell auf dem Pulse-Server aus, um das einmalige Setup-Token auszugeben.', - 'setup.welcome.deploymentHint.dockerNamed': - 'Pulse scheint in Docker als Container "{containerName}" zu laufen. Fuehren Sie den Befehl auf dem Docker-Host aus, um das einmalige Setup-Token aus diesem Container auszugeben.', - 'setup.welcome.deploymentHint.dockerUnnamed': - 'Pulse scheint in Docker zu laufen. Fuehren Sie den Befehl auf dem Docker-Host aus und ersetzen Sie durch den Namen des laufenden Pulse-Containers.', - 'setup.welcome.deploymentHint.lxc': - 'Pulse scheint in LXC-Container {ctid} zu laufen. Fuehren Sie den Befehl auf dem Proxmox-Host aus, um in diesen Container zu wechseln und das einmalige Setup-Token auszugeben.', - 'setup.welcome.deploymentLabel.containerized': 'Containerisierte Bereitstellung', - 'setup.welcome.deploymentLabel.direct': 'Direkte Host-Installation', - 'setup.welcome.deploymentLabel.docker': 'Docker-Bereitstellung', - 'setup.welcome.deploymentLabel.lxc': 'LXC-Container', - 'setup.welcome.error.copyCommandFailed': 'Befehl konnte nicht kopiert werden', - 'setup.welcome.error.invalidBootstrapToken': - 'Ungueltiges Bootstrap-Token. Bitte pruefen und erneut versuchen.', - 'setup.welcome.error.invalidBootstrapTokenResponse': 'Ungueltiges Bootstrap-Token', - 'setup.welcome.error.missingBootstrapToken': 'Bitte geben Sie das Bootstrap-Token ein', - 'setup.welcome.error.snapshotPaste': - 'Das sieht nach dem verschluesselten Inhalt der Datei .bootstrap_token aus, nicht nach dem rohen Setup-Token. Fuehren Sie den obigen Befehl aus und fuegen Sie die ausgegebene Token-Zeichenfolge ein.', - 'setup.welcome.hero.coverage': - 'Verbinden Sie eine Plattform-API, installieren Sie Pulse Agent oder verwenden Sie beides fuer vollstaendige Abdeckung.', - 'setup.welcome.hero.step.admin': 'Admin-Konto erstellen', - 'setup.welcome.hero.step.source': 'Erste Quelle waehlen', - 'setup.welcome.hero.step.unlock': 'Diesen Pulse-Server entsperren', - 'setup.welcome.hero.stepsIntro': 'Drei Schritte:', - 'setup.welcome.hero.stepsThen': 'dann', - 'setup.welcome.hero.title': 'Willkommen bei Pulse', - 'setup.welcome.placeholder.bootstrapToken': 'Bootstrap-Token einfuegen', - 'setup.welcome.success.commandCopied': 'Befehl in Zwischenablage kopiert', - 'setup.welcome.tokenHelp.afterVerify': - 'Nachdem Pulse dieses Token geprueft hat, erstellen Sie im naechsten Schritt das Admin-Konto fuer diesen Server.', - 'setup.welcome.tokenHelp.docker': - 'Dieses einmalige Bootstrap-Token entsperrt nur die Ersteinrichtung. Fuehren Sie den obigen Befehl aus und fuegen Sie die ausgegebene Token-Zeichenfolge ein. Nach der Pruefung erstellen Sie das Admin-Konto, und Pulse erzeugt das langlebige API-Token separat.', - 'setup.welcome.tokenHelp.host': - 'Dieses einmalige Bootstrap-Token entsperrt nur die Ersteinrichtung auf diesem Pulse-Server. Fuehren Sie den obigen Befehl aus und fuegen Sie die ausgegebene Token-Zeichenfolge ein. Es ist nicht Ihr Admin-Passwort und nicht das API-Token, das Sie nach der Einrichtung verwenden.', - 'setup.welcome.tokenHelp.title': 'Was dieses Token macht', - 'setup.welcome.unlockTitle': 'Einrichtung entsperren', - 'settings.general.appearance.title': 'Darstellung', - 'settings.general.fullWidth.description': - 'Nutzen Sie auf grossen Monitoren die gesamte verfuegbare Bildschirmbreite.', - 'settings.general.fullWidth.title': 'Volle Breite', - 'settings.general.docker.envHint': 'Kann auch ueber Umgebungsvariable gesetzt werden:', - 'settings.general.docker.section.description': - 'Steuern Sie, wie {sourceLabel}-Updateaktionen in Pulse angezeigt werden.', - 'settings.general.docker.section.title': '{sourceLabel}-Updates', - 'settings.general.docker.toggle.description': - 'Wenn aktiviert, werden {sourceLabel}-Aktionen "Update" in Pulse ausgeblendet. Die Update-Erkennung laeuft weiter, sodass verfuegbare Updates sichtbar bleiben.', - 'settings.general.docker.toggle.title': 'Update-Schaltflaechen ausblenden', - 'settings.general.language.ariaLabel': 'App-Sprache', - 'settings.general.language.description': - 'Verwenden Sie diese Sprache fuer die App-Oberflaeche. Befehle, Ressourcennamen und API-Felder bleiben unveraendert.', - 'settings.general.language.title': 'Sprache', - 'settings.general.monitoringCadence.current': 'Aktueller Takt: {seconds} Sekunden ({duration})', - 'settings.general.monitoringCadence.custom.description': - 'Sekunden eingeben ({min}-{max}). Gilt fuer alle Cluster.', - 'settings.general.monitoringCadence.custom.title': 'Benutzerdefiniertes Abfrageintervall', - 'settings.general.monitoringCadence.description': - 'Kuerzere Intervalle liefern nahezu Echtzeit-Aktualisierungen auf Kosten hoeherer API- und CPU-Nutzung auf jedem Knoten. Waehlen Sie ein laengeres Intervall, um die Last auf ausgelasteten Clustern zu reduzieren.', - 'settings.general.monitoringCadence.duration.minute': '{count} Minute', - 'settings.general.monitoringCadence.duration.minutes': '{count} Minuten', - 'settings.general.monitoringCadence.duration.underMinute': 'unter einer Minute', - 'settings.general.monitoringCadence.envLocked': - 'Wird ueber Umgebungsvariable {envVar} verwaltet.', - 'settings.general.monitoringCadence.preset.balanced': 'Ausgewogen ({duration})', - 'settings.general.monitoringCadence.preset.custom': 'Benutzerdefiniert', - 'settings.general.monitoringCadence.preset.low': 'Niedrig ({duration})', - 'settings.general.monitoringCadence.preset.realtime': 'Echtzeit ({duration})', - 'settings.general.monitoringCadence.preset.veryLow': 'Sehr niedrig ({duration})', - 'settings.general.monitoringCadence.section.description': - 'Steuern Sie, wie oft Pulse Proxmox VE-Knoten abfragt.', - 'settings.general.monitoringCadence.section.title': 'Monitoring-Takt', - 'settings.general.temperature.description': 'Temperaturen in Celsius oder Fahrenheit anzeigen.', - 'settings.general.temperature.title': 'Temperatureinheit', - 'settings.general.telemetry.copyJson': 'JSON kopieren', - 'settings.general.telemetry.description': - 'Helfen Sie, Pulse zu verbessern, indem Sie anonyme ausgehende Nutzungsdaten teilen: eine rotierende Installations-ID, normalisierte Release-Identitaet, Laufzeitplattform, aggregierte Self-hosted-Nutzungszahlen und grobe Funktionsflags. Es werden keine Hostnamen, Zugangsdaten, Infrastrukturkennungen, Prompts, Chatnachrichten oder personenbezogenen Daten gesendet. Telemetriezeilen werden bis zu 90 Tage aufbewahrt, und IP-Adressen werden nicht in Telemetriezeilen gespeichert.', - 'settings.general.telemetry.disabledPreview': - 'Telemetrie ist derzeit deaktiviert. Diese Vorschau zeigt den Payload, den Pulse senden wuerde, wenn Sie sie aktivieren.', - 'settings.general.telemetry.fullDetails': 'Details', - 'settings.general.telemetry.payloadAriaLabel': 'Telemetrie-Payload-Vorschau', - 'settings.general.telemetry.payloadTitle': 'Aktueller Heartbeat-Payload', - 'settings.general.telemetry.previewPayload': 'Payload anzeigen', - 'settings.general.telemetry.refreshPayload': 'Payload aktualisieren', - 'settings.general.telemetry.resetId': 'ID zuruecksetzen', - 'settings.general.telemetry.section.description': - 'Steuern Sie anonyme ausgehende Telemetrie von dieser Pulse-Instanz.', - 'settings.general.telemetry.section.title': 'Nutzungsdaten und Datenschutz', - 'settings.general.telemetry.title': 'Anonyme ausgehende Telemetrie', - 'settings.general.theme.description': 'Waehlen Sie hell, dunkel oder die Systemeinstellung.', - 'settings.general.theme.option.dark': 'Dunkel', - 'settings.general.theme.option.light': 'Hell', - 'settings.general.theme.option.system': 'System', - 'settings.general.theme.title': 'Designpraeferenz', - 'settings.header.api.description': - 'Erstellen und verwalten Sie begrenzte Pulse-Tokens fuer Agents, Automatisierung und externe Integrationen.', - 'settings.header.api.title': 'API-Zugriff', - 'settings.header.infrastructure.description': - 'Fuegen Sie Infrastruktur hinzu, finden Sie sie automatisch, und pruefen Sie, was Pulse ueberwacht.', - 'settings.header.infrastructure.readOnlyDescription': - 'Pruefen Sie die aktuell ueberwachten Hauptsysteme und den Reporting-Status. Einrichtungsänderungen bleiben in dieser schreibgeschuetzten Sitzung nicht verfuegbar.', - 'settings.header.infrastructure.title': 'Infrastruktur', - 'settings.header.monitoringAvailability.description': - 'Ueberwachen Sie Endgeraete und Dienste nur ueber Ping-, TCP- und HTTP-Pruefungen.', - 'settings.header.monitoringAvailability.title': 'Verfuegbarkeitspruefungen', - 'settings.header.organizationAccess.description': - 'Verwalten Sie Einladungen, Mitgliederrollen und Eigentumsuebertragungen der Organisation.', - 'settings.header.organizationAccess.title': 'Organisationszugriff', - 'settings.header.organizationBilling.description': - 'Pruefen Sie Organisationsplan, geltende Nutzungsrichtlinien und Abonnementstatus fuer bezahlten Zugriff.', - 'settings.header.organizationBilling.title': 'Abrechnung & Nutzung', - 'settings.header.organizationBillingAdmin.description': - 'Pruefen und verwalten Sie den Abrechnungsstatus aller Mandanten (nur Hosted-Modus).', - 'settings.header.organizationBillingAdmin.title': 'Abrechnungsadmin', - 'settings.header.organizationOverview.description': - 'Pruefen Sie Organisationsdaten, Mitgliederumfang und Eigentum.', - 'settings.header.organizationOverview.title': 'Organisationsuebersicht', - 'settings.header.organizationSharing.description': - 'Teilen Sie Ressourcen zwischen Organisationen mit begrenztem Zugriff.', - 'settings.header.organizationSharing.title': 'Organisationsfreigabe', - 'settings.header.securityAudit.description': - 'Sehen Sie Sicherheitsereignisse, Anmeldeversuche und Konfigurationsaenderungen.', - 'settings.header.securityAudit.title': 'Audit-Protokoll', - 'settings.header.securityAuth.description': - 'Verwalten Sie passwortbasierte Authentifizierung und Zugangsdatenrotation.', - 'settings.header.securityAuth.title': 'Authentifizierung', - 'settings.header.securityDataHandling.description': - 'Sehen Sie, welche ueberwachten Ressourcendetails zusammengefasst werden duerfen, lokal bleiben muessen oder redigiert sind.', - 'settings.header.securityDataHandling.title': 'Ressourcenschutz', - 'settings.header.securityOverview.description': - 'Sehen Sie Ihre Sicherheitslage auf einen Blick und ueberwachen Sie den Authentifizierungsstatus.', - 'settings.header.securityOverview.title': 'Sicherheitsuebersicht', - 'settings.header.securityRoles.description': - 'Definieren Sie eigene Rollen und verwalten Sie granulare Berechtigungen fuer Benutzer und Tokens.', - 'settings.header.securityRoles.title': 'Rollen', - 'settings.header.securitySso.description': - 'Konfigurieren Sie OIDC- und SAML-Identity-Provider.', - 'settings.header.securitySso.title': 'Single-Sign-On-Anbieter', - 'settings.header.securityUsers.description': - 'Weisen Sie Benutzern Rollen zu und sehen Sie effektive Berechtigungen in Ihrer Infrastruktur.', - 'settings.header.securityUsers.title': 'Benutzerzugriff', - 'settings.header.securityWebhooks.description': - 'Konfigurieren Sie die Echtzeit-Zustellung von Audit-Ereignissen an externe Systeme.', - 'settings.header.securityWebhooks.title': 'Audit-Webhooks', - 'settings.header.systemAi.description': - 'Konfigurieren Sie Anbieter und Modelle fuer Pulse Assistant und Patrol.', - 'settings.header.systemAi.title': 'Assistant & Patrol', - 'settings.header.systemBilling.description': - 'Pruefen Sie, welchen Plan diese Instanz nutzt und welche optionalen Funktionen damit verbunden sind.', - 'settings.header.systemBilling.title': 'Self-hosted-Plan', - 'settings.header.systemGeneral.description': - 'Verwalten Sie Darstellung, Layout und Standard-Monitoring-Takt.', - 'settings.header.systemGeneral.title': 'Allgemein', - 'settings.header.systemNetwork.description': - 'Konfigurieren Sie oeffentliche URL, CORS, Einbettung und Netzwerkgrenzen fuer Webhooks.', - 'settings.header.systemNetwork.title': 'Netzwerk', - 'settings.header.systemRecovery.description': - 'Verwalten Sie Backup-/Snapshot-Abfragen sowie Export- und Importablaeufe der Konfiguration.', - 'settings.header.systemRecovery.title': 'Wiederherstellung', - 'settings.header.systemRelay.description': - 'Konfigurieren Sie Pulse-Relay-Konnektivitaet fuer sicheren Remote-Zugriff und Pulse-Mobile-Kopplung.', - 'settings.header.systemRelay.title': 'Remote-Zugriff', - 'settings.header.systemUpdates.description': - 'Verwalten Sie Versionspruefungen, Update-Kanaele und automatisches Update-Verhalten.', - 'settings.header.systemUpdates.title': 'Updates', - 'settings.header.supportDiagnostics.description': - 'Fuehren Sie Zustandspruefungen aus, validieren Sie Verbindungen und exportieren Sie Troubleshooting-Snapshots.', - 'settings.header.supportDiagnostics.title': 'Diagnose & Zustand', - 'settings.header.supportLogs.description': - 'Pruefen Sie den Live-Pulse-Logstream und laden Sie den erfassten Puffer fuer Supportarbeit herunter.', - 'settings.header.supportLogs.title': 'Systemprotokolle', - 'settings.header.supportReporting.description': - 'Exportieren Sie Inventardaten und erstellen Sie Leistungsberichte aus der kanonischen Einstellungsoberflaeche.', - 'settings.header.supportReporting.title': 'Daten & Berichte', - 'settings.nav.group.infrastructure': 'Infrastruktur', - 'settings.nav.group.monitoring': 'Monitoring', - 'settings.nav.group.organization': 'Organisation', - 'settings.nav.group.security': 'Sicherheit', - 'settings.nav.group.support': 'Support', - 'settings.nav.group.system': 'System', - 'settings.nav.item.apiAccess': 'API-Zugriff', - 'settings.nav.item.auditLog': 'Audit-Protokoll', - 'settings.nav.item.auditWebhooks': 'Audit-Webhooks', - 'settings.nav.item.authentication': 'Authentifizierung', - 'settings.nav.item.availabilityChecks': 'Verfuegbarkeitspruefungen', - 'settings.nav.item.billing': 'Abrechnung', - 'settings.nav.item.billingAdmin': 'Abrechnungsadmin', - 'settings.nav.item.dataReports': 'Daten & Berichte', - 'settings.nav.item.diagnosticsHealth': 'Diagnose & Zustand', - 'settings.nav.item.general': 'Allgemein', - 'settings.nav.item.infrastructure': 'Infrastruktur', - 'settings.nav.item.network': 'Netzwerk', - 'settings.nav.item.organizationAccess': 'Zugriff', - 'settings.nav.item.organizationOverview': 'Uebersicht', - 'settings.nav.item.plans': 'Plaene', - 'settings.nav.item.recovery': 'Wiederherstellung', - 'settings.nav.item.remoteAccess': 'Remote-Zugriff', - 'settings.nav.item.resourcePrivacy': 'Ressourcenschutz', - 'settings.nav.item.roles': 'Rollen', - 'settings.nav.item.securityOverview': 'Sicherheitsuebersicht', - 'settings.nav.item.sharing': 'Freigabe', - 'settings.nav.item.singleSignOn': 'Single Sign-On', - 'settings.nav.item.systemLogs': 'Systemprotokolle', - 'settings.nav.item.updates': 'Updates', - 'settings.nav.item.users': 'Benutzer', - 'settings.nav.item.assistantPatrol': 'Assistant & Patrol', - 'settings.shell.collapseSidebarLabel': 'Einstellungsnavigation einklappen', - 'settings.shell.configurationLoading': 'Konfiguration wird geladen...', - 'settings.shell.discardLabel': 'Verwerfen', - 'settings.shell.expandSidebarLabel': 'Einstellungsnavigation ausklappen', - 'settings.shell.loading': 'Einstellungen werden geladen...', - 'settings.shell.mobileBackLabel': 'Einstellungen', - 'settings.shell.navigationAriaLabel': 'Einstellungsnavigation', - 'settings.shell.navigationTitle': 'Einstellungen', - 'settings.shell.saveChangesLabel': 'Aenderungen speichern', - 'settings.shell.searchEmpty': 'Keine Einstellungen fuer "{query}" gefunden', - 'settings.shell.searchPlaceholder': 'Einstellungen suchen...', - 'settings.shell.unsavedDescription': - 'Ihre Aenderungen gehen verloren, wenn Sie diese Seite verlassen.', - 'settings.shell.unsavedTitle': 'Nicht gespeicherte Aenderungen', - }, - es: { - ...EN_MESSAGES, - 'alerts.activation.label.enabled': 'Alertas activadas', - 'alerts.activation.label.disabled': 'Alertas desactivadas', - 'alerts.activation.toast.activated': - 'Alertas activadas. Ahora recibiras avisos cuando se detecten problemas.', - 'alerts.activation.toast.activateFailed': - 'No se pudieron activar las alertas. Intentalo de nuevo.', - 'alerts.activation.toast.deactivated': - 'Alertas desactivadas. No se enviara nada hasta que las vuelvas a activar.', - 'alerts.activation.toast.deactivateFailed': - 'No se pudieron desactivar las alertas. Intentalo de nuevo.', - 'alerts.assistant.action.investigate': 'Investigar alerta {alertIdentifier}', - 'alerts.assistant.button.full': 'Investigar con Pulse Assistant', - 'alerts.assistant.button.text': 'Preguntar a Pulse Assistant', - 'alerts.assistant.detail.currentMetric': 'Valor actual {currentValue}; umbral {thresholdValue}', - 'alerts.assistant.detail.message': 'Mensaje: {message}', - 'alerts.assistant.detail.node': 'Nodo: {node}', - 'alerts.assistant.duration.hoursMinutes': '{hours}h {minutes}m', - 'alerts.assistant.duration.minute': '{count} min', - 'alerts.assistant.duration.minutes': '{count} min', - 'alerts.assistant.duration.unknown': 'duracion desconocida', - 'alerts.assistant.level.critical': 'Critica', - 'alerts.assistant.level.info': 'Informativa', - 'alerts.assistant.level.warning': 'Advertencia', - 'alerts.assistant.locked.proRequired': - 'Se requiere Pro para investigar alertas con Pulse Assistant', - 'alerts.assistant.locked.unavailable': - 'La investigacion de alertas de Pulse Assistant no esta disponible para esta alerta', - 'alerts.assistant.safetyNote': - 'Los diagnosticos y la correccion requieren aprobacion del operador.', - 'alerts.assistant.sourceLabel': 'Pulse Alerts', - 'alerts.assistant.statusLabel': '{level} alerta · Activa desde hace {duration}', - 'alerts.assistant.subject': '{level} {alertType} en {resourceName}', - 'alerts.assistant.title': 'Investigacion de alerta adjunta', - 'alerts.assistant.unlockedTitle': 'Pedir a Pulse Assistant que investigue esta alerta', - 'alerts.nav.ariaLabel': 'Navegacion de alertas', - 'alerts.nav.collapseSidebar': 'Contraer barra lateral', - 'alerts.nav.expandSidebar': 'Expandir barra lateral', - 'alerts.nav.title': 'Alertas', - 'alerts.nav.toggleAlerts': 'Alternar alertas', - 'alerts.overview.action.acknowledge': 'Reconocer', - 'alerts.overview.action.acknowledgeAll': 'Reconocer todas ({count})', - 'alerts.overview.action.acknowledging': 'Reconociendo...', - 'alerts.overview.action.hideAcknowledged': 'Ocultar reconocidas', - 'alerts.overview.action.hideTimeline': 'Ocultar linea de tiempo', - 'alerts.overview.action.processing': 'Procesando...', - 'alerts.overview.action.showAcknowledged': 'Mostrar reconocidas', - 'alerts.overview.action.timeline': 'Linea de tiempo', - 'alerts.overview.action.unacknowledge': 'Quitar reconocimiento', - 'alerts.overview.acknowledgedBadge': 'Reconocida', - 'alerts.overview.empty.description': - 'Las alertas apareceran aqui cuando se superen los umbrales', - 'alerts.overview.empty.title': 'No hay alertas activas', - 'alerts.overview.filteredEmpty.all': 'No hay alertas activas', - 'alerts.overview.filteredEmpty.unacknowledged': 'No hay alertas sin reconocer', - 'alerts.overview.nodePrefix': 'en {node}', - 'alerts.overview.notification.acknowledged': 'Alerta reconocida', - 'alerts.overview.notification.acknowledgeFailed': 'No se pudo reconocer la alerta', - 'alerts.overview.notification.bulkFailure.singular': 'No se pudo reconocer {count} alerta.', - 'alerts.overview.notification.bulkFailure.plural': 'No se pudieron reconocer {count} alertas.', - 'alerts.overview.notification.bulkFailureGeneric': 'No se pudieron reconocer las alertas', - 'alerts.overview.notification.bulkSuccess.singular': '{count} alerta reconocida.', - 'alerts.overview.notification.bulkSuccess.plural': '{count} alertas reconocidas.', - 'alerts.overview.notification.restored': 'Alerta restaurada', - 'alerts.overview.notification.restoreFailed': 'No se pudo restaurar la alerta', - 'alerts.overview.paused.description': - 'Activa las alertas para reanudar la monitorizacion y desbloquear las pestañas de configuracion', - 'alerts.overview.paused.title': 'Las alertas estan pausadas', - 'alerts.overview.section.activeAlerts': 'Alertas activas', - 'alerts.overview.startedAt': 'Inicio: {startedAt}', - 'alerts.overview.stats.acknowledged': 'Reconocidas', - 'alerts.overview.stats.triggered24h': 'Activadas (24h)', - 'alerts.overview.stats.workloadOverrides': 'Excepciones de cargas', - 'alerts.page.default.description': - 'Revisa incidentes activos, el historial de alertas, umbrales, notificaciones y programaciones.', - 'alerts.page.default.title': 'Alertas', - 'alerts.page.destinations.description': - 'Enruta notificaciones de alerta a destinos de email, Apprise y webhook.', - 'alerts.page.destinations.title': 'Notificaciones', - 'alerts.page.history.description': - 'Busca alertas anteriores, revisa lineas de tiempo de incidentes e inspecciona la frecuencia de alertas.', - 'alerts.page.history.title': 'Historial de alertas', - 'alerts.page.overview.description': - 'Revisa incidentes activos, confirma la cobertura de alertas y controla si las alertas monitorizan activamente esta instalacion.', - 'alerts.page.overview.title': 'Resumen de alertas', - 'alerts.page.schedule.description': - 'Define horas de silencio, agrupacion, enfriamiento, recuperacion y escalado para la entrega de alertas.', - 'alerts.page.schedule.title': 'Programacion de mantenimiento', - 'alerts.page.thresholds.description': - 'Ajusta umbrales y excepciones especificas para infraestructura, cargas e integraciones.', - 'alerts.page.thresholds.title': 'Umbrales de alerta', - 'alerts.tabs.disabledTitle': 'Activa las alertas para configurar este ajuste', - 'alerts.tabs.group.configuration': 'Configuracion', - 'alerts.tabs.group.status': 'Estado', - 'alerts.tabs.destinations': 'Notificaciones', - 'alerts.tabs.history': 'Historial', - 'alerts.tabs.overview': 'Resumen', - 'alerts.tabs.schedule': 'Programacion', - 'alerts.tabs.thresholds': 'Umbrales', - 'alerts.timeline.acknowledged': 'reconocida', - 'alerts.timeline.closedAt': 'cerrado {closedAt}', - 'alerts.timeline.empty': 'Aun no hay eventos en la linea de tiempo.', - 'alerts.timeline.failure': 'No se pudo cargar la linea de tiempo.', - 'alerts.timeline.filterEmpty': - 'Ningun evento de la linea de tiempo coincide con los filtros seleccionados.', - 'alerts.timeline.filterLabel.compact': 'Filtros', - 'alerts.timeline.filterLabel.panel': 'Filtrar eventos:', - 'alerts.timeline.heading': 'Incidente', - 'alerts.timeline.loading': 'Cargando linea de tiempo...', - 'alerts.timeline.event.alertAcknowledged': 'Reconocida', - 'alerts.timeline.event.alertFired': 'Activada', - 'alerts.timeline.event.alertResolved': 'Resuelta', - 'alerts.timeline.event.alertUnacknowledged': 'Sin reconocer', - 'alerts.timeline.event.aiAnalysis': 'Patrol', - 'alerts.timeline.event.command': 'Comando', - 'alerts.timeline.event.note': 'Nota', - 'alerts.timeline.event.runbook': 'Runbook', - 'alerts.timeline.noteLabel': 'Nota del incidente', - 'alerts.timeline.notePlaceholder': 'Añade una nota para este incidente...', - 'alerts.timeline.openedAt': 'abierto {openedAt}', - 'alerts.timeline.quickFilter.all': 'Todas', - 'alerts.timeline.quickFilter.none': 'Ninguna', - 'alerts.timeline.retry': 'Reintentar', - 'alerts.timeline.saveNote': 'Guardar nota', - 'alerts.timeline.savingNote': 'Guardando...', - 'alerts.timeline.unavailable': 'No hay linea de tiempo de incidente disponible.', - 'runtimeHome.openingWorkspace': 'Abriendo el espacio de trabajo...', - 'setup.completion.action.addInfrastructure': 'Agregar infraestructura', - 'setup.completion.action.downloadCredentials': 'Descargar credenciales', - 'setup.completion.action.installAgent': 'Instalar Pulse Agent', - 'setup.completion.action.openInfrastructure': 'Abrir Infraestructura', - 'setup.completion.connectedSummary.singular': 'Conectado ({count} sistema)', - 'setup.completion.connectedSummary.plural': 'Conectados ({count} sistemas)', - 'setup.completion.credentials.apiTokenLabel': 'Token de API de administrador', - 'setup.completion.credentials.badge': 'Se muestra durante la configuración', - 'setup.completion.credentials.continuation.empty': 'Agregar infraestructura.', - 'setup.completion.credentials.continuation.connected': - 'Infraestructura o Agregar infraestructura.', - 'setup.completion.credentials.description': - 'Guarda el inicio de sesión de administrador y el token de API antes de salir de esta pantalla; luego continúa en {destination}', - 'setup.completion.credentials.passwordLabel': 'Contraseña', - 'setup.completion.credentials.title': 'Credenciales que debes guardar ahora', - 'setup.completion.credentials.usernameLabel': 'Usuario', - 'setup.completion.download.content': - 'Credenciales de Pulse\n==================\nGenerado: {generatedAt}\n\nInicio de sesión web:\n----------\nURL: {baseUrl}\nUsuario: {username}\nContraseña: {password}\n\nToken de API de administrador:\n----------------\n{apiToken}\n\nInfraestructura:\n---------------\n{infrastructureUrl}\n\nUsa Agregar infraestructura para elegir una API de plataforma, Pulse Agent o ambos\npara el primer sistema que Pulse debe supervisar.\n\nGuarda estas credenciales en un lugar seguro.\n', - 'setup.completion.hero.connected.description.agent': - 'Tu cuenta de administrador está lista y Pulse ya recibe telemetría. Abre Infraestructura para revisar el primer sistema; luego vuelve a Agregar infraestructura cuando quieras otra fuente Pulse Agent o API de plataforma.', - 'setup.completion.hero.connected.description.api': - 'Tu cuenta de administrador está lista y Pulse ya recibe telemetría. Abre Infraestructura para revisar el primer sistema; luego vuelve a Agregar infraestructura cuando quieras otra API de plataforma o fuente Pulse Agent.', - 'setup.completion.hero.connected.description.both': - 'Tu cuenta de administrador está lista y Pulse ya recibe telemetría. Abre Infraestructura para revisar el primer sistema; luego vuelve a Agregar infraestructura cuando quieras otra API de plataforma, fuente Agent o ambas.', - 'setup.completion.hero.connected.title': 'Primer sistema supervisado conectado', - 'setup.completion.hero.empty.description': - 'Tu cuenta de administrador está lista. Ahora elige cómo entrará el primer sistema en el modelo unificado de infraestructura: inventario por API de plataforma, telemetría de Pulse Agent o ambos.', - 'setup.completion.hero.empty.title': 'Elige tu primera fuente de infraestructura', - 'setup.completion.nextStep.ariaLabel': 'Siguiente paso de configuración', - 'setup.completion.nextStep.badge': 'Siguiente paso recomendado', - 'setup.completion.nextStep.detail.agent': - 'Agregar infraestructura queda disponible para más sistemas Pulse Agent o inventario por API de plataforma cuando una plataforma administra el entorno.', - 'setup.completion.nextStep.detail.api': - 'Agregar infraestructura queda disponible para más sistemas respaldados por API o telemetría de Pulse Agent cuando un sistema necesita cobertura local del nodo.', - 'setup.completion.nextStep.detail.both': - 'Agregar infraestructura queda disponible cuando quieras ampliar este primer sistema con otra fuente API, fuente Agent o ambas.', - 'setup.completion.nextStep.detail.empty': - 'Empieza con una API de plataforma cuando una plataforma administra el entorno. Instala Pulse Agent cuando el propio sistema deba informar telemetría local del nodo.', - 'setup.completion.nextStep.label': 'Siguiente paso', - 'setup.completion.nextStep.summary.connected.singular': - 'Abre Infraestructura para revisar tu primer sistema conectado.', - 'setup.completion.nextStep.summary.connected.plural': - 'Abre Infraestructura para revisar tus sistemas conectados.', - 'setup.completion.nextStep.summary.empty': - 'Abre Agregar infraestructura para elegir una API de plataforma, Pulse Agent o ambos.', - 'setup.completion.nextStep.title.connected': 'Abrir Infraestructura', - 'setup.completion.nextStep.title.empty': 'Elige la estrategia de primera fuente', - 'setup.completion.resource.unknownName': 'Desconocido', - 'setup.completion.sourceOptions.agent.description': - 'Telemetría local del nodo para hosts independientes, servicios, Docker y Kubernetes.', - 'setup.completion.sourceOptions.agent.title': 'Pulse Agent', - 'setup.completion.sourceOptions.both.description': - 'Combina inventario de plataforma con telemetría de Agent cuando importa la cobertura completa.', - 'setup.completion.sourceOptions.both.title': 'Usar ambos', - 'setup.completion.sourceOptions.platformApi.description': - 'Inventario y salud desde Proxmox, TrueNAS, VMware, PBS o PMG.', - 'setup.completion.sourceOptions.platformApi.title': 'API de plataforma', - 'setup.completion.sourceOptions.title': 'Opciones de fuente', - 'setup.progress.ariaLabel': 'Progreso de configuración', - 'setup.progress.state.completed': ', completado', - 'setup.progress.state.current': ', actual', - 'setup.progress.stepAriaLabel': 'Paso {index}: {step}{state}', - 'setup.security.action.back': 'Atrás', - 'setup.security.action.createAccount': 'Crear cuenta y continuar', - 'setup.security.action.settingUp': 'Configurando...', - 'setup.security.customPassword': 'Contraseña personalizada', - 'setup.security.description': - 'El siguiente paso es elegir la primera fuente de infraestructura.', - 'setup.security.error.passwordMismatch': 'Las contraseñas no coinciden', - 'setup.security.error.passwordRequired': 'Ingresa una contraseña', - 'setup.security.error.passwordTooShort': 'La contraseña debe tener al menos 12 caracteres', - 'setup.security.error.setupFailed': 'La configuración falló: {error}', - 'setup.security.generatedPasswordHelp': - 'Se generará una contraseña segura de 20 caracteres y se mostrará en la siguiente pantalla.', - 'setup.security.label.confirmPassword': 'Confirmar contraseña', - 'setup.security.label.password': 'Contraseña', - 'setup.security.label.username': 'Usuario', - 'setup.security.minimumPasswordHelp': 'Mínimo 12 caracteres.', - 'setup.security.nextScreen.itemApiToken': - 'Un token de API de administrador para automatización', - 'setup.security.nextScreen.itemCredentials': 'Tu usuario y contraseña', - 'setup.security.nextScreen.saveOnce': 'Guárdalos antes de continuar; se muestran una sola vez.', - 'setup.security.nextScreen.title': 'En la siguiente pantalla', - 'setup.security.passwordMode.autoGenerate': 'Generar automáticamente', - 'setup.security.placeholder.password': 'Contraseña (mínimo 12 caracteres)', - 'setup.security.placeholder.username': 'admin', - 'setup.security.showPassword.hide': 'Ocultar', - 'setup.security.showPassword.show': 'Mostrar', - 'setup.security.title': 'Crear tu cuenta de administrador', - 'setup.step.firstSource': 'Primera fuente', - 'setup.step.security': 'Seguridad', - 'setup.step.unlockServer': 'Desbloquear servidor', - 'setup.wizard.ariaLabel': 'Asistente de configuración de Pulse', - 'setup.welcome.action.continueSecurity': 'Continuar a Seguridad', - 'setup.welcome.action.verifyToken': 'Verificar token de bootstrap', - 'setup.welcome.action.verifyingToken': 'Verificando token de bootstrap...', - 'setup.welcome.copyCommandTitle': 'Copiar comando', - 'setup.welcome.deploymentHint.containerized': - 'Pulse parece ejecutarse en un entorno contenedorizado. Ejecuta el comando desde el host que administra el contenedor para imprimir el token de configuración de un solo uso.', - 'setup.welcome.deploymentHint.direct': - 'Ejecuta el comando directamente en una shell del servidor Pulse para imprimir el token de configuración de un solo uso.', - 'setup.welcome.deploymentHint.dockerNamed': - 'Pulse parece ejecutarse en Docker como contenedor "{containerName}". Ejecuta el comando en el host Docker para imprimir el token de configuración de un solo uso desde ese contenedor.', - 'setup.welcome.deploymentHint.dockerUnnamed': - 'Pulse parece ejecutarse en Docker. Ejecuta el comando en el host Docker y reemplaza por el nombre del contenedor Pulse en ejecución.', - 'setup.welcome.deploymentHint.lxc': - 'Pulse parece ejecutarse en el contenedor LXC {ctid}. Ejecuta el comando en el host Proxmox para entrar en ese contenedor e imprimir el token de configuración de un solo uso.', - 'setup.welcome.deploymentLabel.containerized': 'Despliegue contenedorizado', - 'setup.welcome.deploymentLabel.direct': 'Instalación directa en host', - 'setup.welcome.deploymentLabel.docker': 'Despliegue Docker', - 'setup.welcome.deploymentLabel.lxc': 'Contenedor LXC', - 'setup.welcome.error.copyCommandFailed': 'No se pudo copiar el comando', - 'setup.welcome.error.invalidBootstrapToken': - 'Token de bootstrap no válido. Revísalo e inténtalo de nuevo.', - 'setup.welcome.error.invalidBootstrapTokenResponse': 'Token de bootstrap no válido', - 'setup.welcome.error.missingBootstrapToken': 'Ingresa el token de bootstrap', - 'setup.welcome.error.snapshotPaste': - 'Eso parece el contenido cifrado del archivo .bootstrap_token, no el token de configuración sin procesar. Ejecuta el comando anterior y pega la cadena de token que imprime.', - 'setup.welcome.hero.coverage': - 'Conecta una API de plataforma, instala Pulse Agent o usa ambos para cobertura completa.', - 'setup.welcome.hero.step.admin': 'Crear la cuenta de administrador', - 'setup.welcome.hero.step.source': 'Elegir la primera fuente', - 'setup.welcome.hero.step.unlock': 'Desbloquear este servidor Pulse', - 'setup.welcome.hero.stepsIntro': 'Tres pasos:', - 'setup.welcome.hero.stepsThen': 'luego', - 'setup.welcome.hero.title': 'Bienvenido a Pulse', - 'setup.welcome.placeholder.bootstrapToken': 'Pega tu token de bootstrap', - 'setup.welcome.success.commandCopied': 'Comando copiado al portapapeles', - 'setup.welcome.tokenHelp.afterVerify': - 'Después de que Pulse verifique este token, el siguiente paso es crear la cuenta de administrador para este servidor.', - 'setup.welcome.tokenHelp.docker': - 'Este token de bootstrap de un solo uso solo desbloquea la configuración inicial. Ejecuta el comando anterior y pega la cadena de token que imprime. Después de la verificación, crearás la cuenta de administrador y Pulse generará el token de API de larga duración por separado.', - 'setup.welcome.tokenHelp.host': - 'Este token de bootstrap de un solo uso solo desbloquea la configuración inicial en este servidor Pulse. Ejecuta el comando anterior y pega la cadena de token que imprime. No es tu contraseña de administrador ni el token de API que usarás después de la configuración.', - 'setup.welcome.tokenHelp.title': 'Qué hace este token', - 'setup.welcome.unlockTitle': 'Desbloquear configuración', - 'settings.general.appearance.title': 'Apariencia', - 'settings.general.fullWidth.description': - 'Expande el contenido para usar todo el ancho disponible en monitores grandes.', - 'settings.general.fullWidth.title': 'Modo de ancho completo', - 'settings.general.docker.envHint': 'También se puede definir mediante variable de entorno:', - 'settings.general.docker.section.description': - 'Controla cómo aparecen las acciones de actualización de {sourceLabel} en Pulse.', - 'settings.general.docker.section.title': 'Actualizaciones de {sourceLabel}', - 'settings.general.docker.toggle.description': - 'Cuando está activado, las acciones "Update" de {sourceLabel} se ocultan en Pulse. La detección de actualizaciones sigue ejecutándose, por lo que las actualizaciones disponibles siguen visibles.', - 'settings.general.docker.toggle.title': 'Ocultar botones de actualización', - 'settings.general.language.ariaLabel': 'Idioma de la app', - 'settings.general.language.description': - 'Usa este idioma para la interfaz de la app. Los comandos, nombres de recursos y campos API no cambian.', - 'settings.general.language.title': 'Idioma', - 'settings.general.monitoringCadence.current': - 'Cadencia actual: {seconds} segundos ({duration})', - 'settings.general.monitoringCadence.custom.description': - 'Introduce segundos ({min}-{max}). Se aplica a todos los clusters.', - 'settings.general.monitoringCadence.custom.title': 'Intervalo de sondeo personalizado', - 'settings.general.monitoringCadence.description': - 'Los intervalos más cortos ofrecen actualizaciones casi en tiempo real a costa de mayor uso de API y CPU en cada nodo. Usa un intervalo más largo para reducir la carga en clusters ocupados.', - 'settings.general.monitoringCadence.duration.minute': '{count} minuto', - 'settings.general.monitoringCadence.duration.minutes': '{count} minutos', - 'settings.general.monitoringCadence.duration.underMinute': 'menos de un minuto', - 'settings.general.monitoringCadence.envLocked': - 'Administrado mediante variable de entorno {envVar}.', - 'settings.general.monitoringCadence.preset.balanced': 'Equilibrado ({duration})', - 'settings.general.monitoringCadence.preset.custom': 'Personalizado', - 'settings.general.monitoringCadence.preset.low': 'Bajo ({duration})', - 'settings.general.monitoringCadence.preset.realtime': 'Tiempo real ({duration})', - 'settings.general.monitoringCadence.preset.veryLow': 'Muy bajo ({duration})', - 'settings.general.monitoringCadence.section.description': - 'Controla con qué frecuencia Pulse sondea nodos de Proxmox VE.', - 'settings.general.monitoringCadence.section.title': 'Cadencia de supervisión', - 'settings.general.temperature.description': 'Muestra temperaturas en Celsius o Fahrenheit.', - 'settings.general.temperature.title': 'Unidad de temperatura', - 'settings.general.telemetry.copyJson': 'Copiar JSON', - 'settings.general.telemetry.description': - 'Ayuda a mejorar Pulse compartiendo datos de uso salientes anónimos: un ID de instalación rotativo, identidad de versión normalizada, plataforma de ejecución, conteos agregados de adopción autohospedada y flags de funciones de alto nivel. No se envían hostnames, credenciales, identificadores de infraestructura, prompts, mensajes de chat ni información personal. Las filas de telemetría se conservan hasta 90 días y las direcciones IP no se guardan en filas de telemetría.', - 'settings.general.telemetry.disabledPreview': - 'La telemetría está desactivada. Esta vista previa muestra el payload que Pulse enviaría si la activas.', - 'settings.general.telemetry.fullDetails': 'Detalles completos', - 'settings.general.telemetry.payloadAriaLabel': 'Vista previa del payload de telemetría', - 'settings.general.telemetry.payloadTitle': 'Payload de heartbeat actual', - 'settings.general.telemetry.previewPayload': 'Vista previa del payload', - 'settings.general.telemetry.refreshPayload': 'Actualizar payload', - 'settings.general.telemetry.resetId': 'Restablecer ID', - 'settings.general.telemetry.section.description': - 'Controla telemetría saliente anónima de esta instancia de Pulse.', - 'settings.general.telemetry.section.title': 'Datos de uso y privacidad', - 'settings.general.telemetry.title': 'Telemetría saliente anónima', - 'settings.general.theme.description': - 'Elige claro, oscuro o sincroniza con el tema del sistema.', - 'settings.general.theme.option.dark': 'Oscuro', - 'settings.general.theme.option.light': 'Claro', - 'settings.general.theme.option.system': 'Sistema', - 'settings.general.theme.title': 'Preferencia de tema', - 'settings.header.api.description': - 'Genera y administra tokens de Pulse con alcance limitado para agentes, automatización e integraciones externas.', - 'settings.header.api.title': 'Acceso API', - 'settings.header.infrastructure.description': - 'Agrega, descubre y verifica la infraestructura que Pulse supervisa.', - 'settings.header.infrastructure.readOnlyDescription': - 'Revisa los sistemas principales supervisados y el estado de informes. Los cambios de configuración no están disponibles en esta sesión de solo lectura.', - 'settings.header.infrastructure.title': 'Infraestructura', - 'settings.header.monitoringAvailability.description': - 'Supervisa dispositivos y servicios solo por endpoint con pruebas ping, TCP y HTTP.', - 'settings.header.monitoringAvailability.title': 'Comprobaciones de disponibilidad', - 'settings.header.organizationAccess.description': - 'Administra invitaciones, roles de miembros y transferencias de propiedad de la organización.', - 'settings.header.organizationAccess.title': 'Acceso de organización', - 'settings.header.organizationBilling.description': - 'Revisa el plan de la organización, las políticas de uso aplicables y el estado de suscripción para acceso de pago.', - 'settings.header.organizationBilling.title': 'Facturación y uso', - 'settings.header.organizationBillingAdmin.description': - 'Revisa y administra el estado de facturación de todos los tenants (solo modo alojado).', - 'settings.header.organizationBillingAdmin.title': 'Admin de facturación', - 'settings.header.organizationOverview.description': - 'Revisa metadatos, alcance de miembros y propiedad de la organización.', - 'settings.header.organizationOverview.title': 'Resumen de organización', - 'settings.header.organizationSharing.description': - 'Comparte recursos entre organizaciones con acceso delimitado.', - 'settings.header.organizationSharing.title': 'Uso compartido de organización', - 'settings.header.securityAudit.description': - 'Consulta eventos de seguridad, intentos de inicio de sesión y cambios de configuración.', - 'settings.header.securityAudit.title': 'Registro de auditoría', - 'settings.header.securityAuth.description': - 'Administra autenticación con contraseña y rotación de credenciales.', - 'settings.header.securityAuth.title': 'Autenticación', - 'settings.header.securityDataHandling.description': - 'Consulta qué detalles de recursos supervisados se pueden resumir, deben quedarse locales o están redactados.', - 'settings.header.securityDataHandling.title': 'Privacidad de recursos', - 'settings.header.securityOverview.description': - 'Consulta tu postura de seguridad de un vistazo y supervisa el estado de autenticación.', - 'settings.header.securityOverview.title': 'Resumen de seguridad', - 'settings.header.securityRoles.description': - 'Define roles personalizados y administra permisos granulares para usuarios y tokens.', - 'settings.header.securityRoles.title': 'Roles', - 'settings.header.securitySso.description': 'Configura proveedores de identidad OIDC y SAML.', - 'settings.header.securitySso.title': 'Proveedores de inicio de sesión único', - 'settings.header.securityUsers.description': - 'Asigna roles a usuarios y consulta permisos efectivos en tu infraestructura.', - 'settings.header.securityUsers.title': 'Acceso de usuarios', - 'settings.header.securityWebhooks.description': - 'Configura la entrega en tiempo real de eventos de auditoría a sistemas externos.', - 'settings.header.securityWebhooks.title': 'Webhooks de auditoría', - 'settings.header.systemAi.description': - 'Configura proveedores y modelos para Pulse Assistant y Patrol.', - 'settings.header.systemAi.title': 'Assistant y Patrol', - 'settings.header.systemBilling.description': - 'Revisa el plan que usa esta instancia y las capacidades opcionales conectadas.', - 'settings.header.systemBilling.title': 'Plan autohospedado', - 'settings.header.systemGeneral.description': - 'Administra apariencia, diseño y cadencia predeterminada de supervisión.', - 'settings.header.systemGeneral.title': 'General', - 'settings.header.systemNetwork.description': - 'Configura la URL pública, CORS, inserción y límites de red para webhooks.', - 'settings.header.systemNetwork.title': 'Red', - 'settings.header.systemRecovery.description': - 'Administra sondeos de copias/snapshots y flujos de exportación e importación de configuración.', - 'settings.header.systemRecovery.title': 'Recuperación', - 'settings.header.systemRelay.description': - 'Configura la conectividad de relay de Pulse para acceso remoto seguro y vinculación con Pulse Mobile.', - 'settings.header.systemRelay.title': 'Acceso remoto', - 'settings.header.systemUpdates.description': - 'Administra comprobaciones de versión, canales de actualización y comportamiento de actualización automática.', - 'settings.header.systemUpdates.title': 'Actualizaciones', - 'settings.header.supportDiagnostics.description': - 'Ejecuta comprobaciones de salud, valida conectividad y exporta snapshots de resolución de problemas.', - 'settings.header.supportDiagnostics.title': 'Diagnóstico y salud', - 'settings.header.supportLogs.description': - 'Inspecciona el flujo de logs de Pulse en vivo y descarga el búfer capturado para soporte.', - 'settings.header.supportLogs.title': 'Logs del sistema', - 'settings.header.supportReporting.description': - 'Exporta datos de inventario y genera informes de rendimiento desde la consola canónica de ajustes.', - 'settings.header.supportReporting.title': 'Datos e informes', - 'settings.nav.group.infrastructure': 'Infraestructura', - 'settings.nav.group.monitoring': 'Supervisión', - 'settings.nav.group.organization': 'Organización', - 'settings.nav.group.security': 'Seguridad', - 'settings.nav.group.support': 'Soporte', - 'settings.nav.group.system': 'Sistema', - 'settings.nav.item.apiAccess': 'Acceso API', - 'settings.nav.item.auditLog': 'Registro de auditoría', - 'settings.nav.item.auditWebhooks': 'Webhooks de auditoría', - 'settings.nav.item.authentication': 'Autenticación', - 'settings.nav.item.availabilityChecks': 'Comprobaciones de disponibilidad', - 'settings.nav.item.billing': 'Facturación', - 'settings.nav.item.billingAdmin': 'Admin de facturación', - 'settings.nav.item.dataReports': 'Datos e informes', - 'settings.nav.item.diagnosticsHealth': 'Diagnóstico y salud', - 'settings.nav.item.general': 'General', - 'settings.nav.item.infrastructure': 'Infraestructura', - 'settings.nav.item.network': 'Red', - 'settings.nav.item.organizationAccess': 'Acceso', - 'settings.nav.item.organizationOverview': 'Resumen', - 'settings.nav.item.plans': 'Planes', - 'settings.nav.item.recovery': 'Recuperación', - 'settings.nav.item.remoteAccess': 'Acceso remoto', - 'settings.nav.item.resourcePrivacy': 'Privacidad de recursos', - 'settings.nav.item.roles': 'Roles', - 'settings.nav.item.securityOverview': 'Resumen de seguridad', - 'settings.nav.item.sharing': 'Uso compartido', - 'settings.nav.item.singleSignOn': 'Inicio de sesión único', - 'settings.nav.item.systemLogs': 'Logs del sistema', - 'settings.nav.item.updates': 'Actualizaciones', - 'settings.nav.item.users': 'Usuarios', - 'settings.nav.item.assistantPatrol': 'Assistant y Patrol', - 'settings.shell.collapseSidebarLabel': 'Contraer navegación de ajustes', - 'settings.shell.configurationLoading': 'Cargando configuración...', - 'settings.shell.discardLabel': 'Descartar', - 'settings.shell.expandSidebarLabel': 'Expandir navegación de ajustes', - 'settings.shell.loading': 'Cargando ajustes...', - 'settings.shell.mobileBackLabel': 'Ajustes', - 'settings.shell.navigationAriaLabel': 'Navegación de ajustes', - 'settings.shell.navigationTitle': 'Ajustes', - 'settings.shell.saveChangesLabel': 'Guardar cambios', - 'settings.shell.searchEmpty': 'No se encontraron ajustes para "{query}"', - 'settings.shell.searchPlaceholder': 'Buscar ajustes...', - 'settings.shell.unsavedDescription': 'Tus cambios se perderán si sales.', - 'settings.shell.unsavedTitle': 'Cambios sin guardar', - }, -}; +export const I18N_RUNTIME_MESSAGE_LOADERS = { + de: () => import('./messages.de').then((module) => module.DE_MESSAGE_OVERRIDES), + es: () => import('./messages.es').then((module) => module.ES_MESSAGE_OVERRIDES), +} as const; diff --git a/frontend-modern/src/test/setup.ts b/frontend-modern/src/test/setup.ts index 927ec4ec4..81e3ae7fa 100644 --- a/frontend-modern/src/test/setup.ts +++ b/frontend-modern/src/test/setup.ts @@ -1,5 +1,5 @@ import '@testing-library/jest-dom'; -import { beforeEach } from 'vitest'; +import { beforeAll, beforeEach } from 'vitest'; type StorageValue = string | null; @@ -74,6 +74,11 @@ const ensureLocalStorage = () => { }; ensureLocalStorage(); +beforeAll(async () => { + const { FIRST_LOCALIZATION_LOCALES, loadLocaleCatalog } = await import('@/i18n'); + await Promise.all(FIRST_LOCALIZATION_LOCALES.map((locale) => loadLocaleCatalog(locale))); +}); + beforeEach(() => { ensureLocalStorage(); }); diff --git a/frontend-modern/src/utils/__tests__/docsLinks.test.ts b/frontend-modern/src/utils/__tests__/docsLinks.test.ts index 722f84043..8acce76dd 100644 --- a/frontend-modern/src/utils/__tests__/docsLinks.test.ts +++ b/frontend-modern/src/utils/__tests__/docsLinks.test.ts @@ -76,10 +76,22 @@ describe('docsLinks', () => { it('keeps shipped docs content synced with repo docs', () => { const docPairs = [ { source: path.join(repoRoot, 'docs', 'README.md'), target: 'README.md' }, - { source: path.join(repoRoot, 'docs', 'MIGRATION_UNIFIED_NAV.md'), target: 'MIGRATION_UNIFIED_NAV.md' }, + { + source: path.join(repoRoot, 'docs', 'MIGRATION_UNIFIED_NAV.md'), + target: 'MIGRATION_UNIFIED_NAV.md', + }, { source: path.join(repoRoot, 'docs', 'PRIVACY.md'), target: 'PRIVACY.md' }, { source: path.join(repoRoot, 'docs', 'CONFIGURATION.md'), target: 'CONFIGURATION.md' }, { source: path.join(repoRoot, 'docs', 'PROXY_AUTH.md'), target: 'PROXY_AUTH.md' }, + { source: path.join(repoRoot, 'docs', 'i18n', 'README.md'), target: 'i18n/README.md' }, + { + source: path.join(repoRoot, 'docs', 'i18n', 'de', 'README.md'), + target: 'i18n/de/README.md', + }, + { + source: path.join(repoRoot, 'docs', 'i18n', 'es', 'README.md'), + target: 'i18n/es/README.md', + }, { source: path.join(repoRoot, 'SECURITY.md'), target: 'SECURITY.md' }, { source: path.join(repoRoot, 'TERMS.md'), target: 'TERMS.md' }, ]; @@ -94,7 +106,9 @@ describe('docsLinks', () => { it('routes runtime docs links through shipped local docs instead of GitHub main', () => { expect(apiAccessPanelSource).toContain('API_TOKEN_SCOPES_DOC_URL'); - expect(apiAccessPanelSource).not.toContain('https://github.com/rcourtman/Pulse/blob/main/docs/'); + expect(apiAccessPanelSource).not.toContain( + 'https://github.com/rcourtman/Pulse/blob/main/docs/', + ); expect(apiTokenManagerModelSource).toContain("from '@/utils/docsLinks'"); expect(apiTokenManagerModelSource).toContain('SHIPPED_API_TOKEN_SCOPES_DOC_URL'); expect(apiTokenManagerModelSource).toContain('export const API_TOKEN_SCOPES_DOC_URL ='); @@ -119,15 +133,19 @@ describe('docsLinks', () => { ); }); - it('keeps non-test frontend runtime files free of GitHub main doc links', () => { - const runtimeFiles = getRuntimeSourceFiles(path.join(frontendRoot, 'src')); + it( + 'keeps non-test frontend runtime files free of GitHub main doc links', + () => { + const runtimeFiles = getRuntimeSourceFiles(path.join(frontendRoot, 'src')); - for (const filePath of runtimeFiles) { - const source = readFileSync(filePath, 'utf8'); - expect( - source, - `${path.relative(frontendRoot, filePath)} should use shipped/local docs owners`, - ).not.toContain('https://github.com/rcourtman/Pulse/blob/main/'); - } - }, runtimeDocsLinkScanTimeoutMs); + for (const filePath of runtimeFiles) { + const source = readFileSync(filePath, 'utf8'); + expect( + source, + `${path.relative(frontendRoot, filePath)} should use shipped/local docs owners`, + ).not.toContain('https://github.com/rcourtman/Pulse/blob/main/'); + } + }, + runtimeDocsLinkScanTimeoutMs, + ); });