'Sichtbarkeit der Website', 'site_public' => 'Öffentlich', 'site_hidden' => 'Versteckt', 'site_public_body' => 'Website und Kundenportal sind für alle erreichbar und werden von Suchmaschinen erfasst.', 'site_hidden_body' => 'Besucher von außen sehen nur eine Platzhalterseite (Status 503, „noindex“). Über das VPN und als angemeldeter Mitarbeiter sehen Sie weiterhin alles. Die Konsole bleibt in jedem Fall erreichbar.', 'site_your_view' => 'Ihre Adresse :ip —', 'site_via_vpn' => 'über das VPN, Sie sehen immer die echte Seite.', 'site_not_vpn' => 'nicht im VPN. Als angemeldeter Mitarbeiter sehen Sie die echte Seite trotzdem.', 'site_hide' => 'Website verstecken', 'site_show' => 'Website veröffentlichen', 'site_now_public' => 'Website ist wieder öffentlich.', 'site_now_hidden' => 'Website ist jetzt versteckt.', 'title' => 'Einstellungen', 'subtitle' => 'Ihr Operator-Konto und die Verwaltung Ihres Teams.', 'save' => 'Speichern', 'account_title' => 'Mein Konto', 'name' => 'Name', 'email' => 'E-Mail', 'account_saved' => 'Konto aktualisiert.', 'staff_title' => 'Team & Zugriff', 'staff_sub' => 'Mitarbeiter einladen und deren Rolle festlegen. Nur der Inhaber kann das Team verwalten.', 'role' => 'Rolle', 'invite' => 'Einladen', // Kein Passwort mehr auf dem Bildschirm: der Eingeladene vergibt sein // eigenes am Link aus der Mail. Die Stundenzahl kommt aus der // Broker-Einstellung, damit hier nicht eine zweite Frist behauptet wird. 'invite_hint' => 'Wir schicken eine Einladung an diese Adresse. Der Link darin gilt :hours Stunden; das Passwort vergibt der Mitarbeiter selbst — niemand hier bekommt es zu sehen.', 'staff_invited' => 'Einladung verschickt.', // Nur solange der alte Link noch nie benutzt wurde (Settings::render(), // never_signed_in) — der Rückweg aus einer abgelaufenen Einladung, ohne // die Shell und ohne dabei zum Inhaber zu werden. 'resend_invitation' => 'Einladung erneut senden', 'invitation_resent' => 'Einladung erneut verschickt.', 'col_person' => 'Person', 'col_actions' => 'Aktionen', 'you' => 'Sie', 'revoke' => 'Zugriff entziehen', 'role_owner' => 'Inhaber', 'role_admin' => 'Administrator', 'role_support' => 'Support', 'role_billing' => 'Abrechnung', 'role_read-only' => 'Nur Lesen', 'role_developer' => 'Entwickler', 'role_updated' => 'Rolle aktualisiert.', 'staff_revoked' => 'Zugriff entzogen.', 'not_self' => 'Sie können Ihre eigene Rolle nicht ändern.', 'owner_only' => 'Nur ein Inhaber darf die Inhaber-Rolle vergeben oder entziehen.', 'last_owner' => 'Der letzte Inhaber kann nicht geändert oder entfernt werden.', 'not_staff' => 'Nur bestehende Mitarbeiter können bearbeitet werden.', 'is_customer' => 'Diese E-Mail gehört bereits zu einem Kundenkonto.', // Console network access — who may reach /admin at all. 'console_title' => 'Zugang zur Konsole', 'console_locked_badge' => 'Eingeschränkt', 'console_open_badge' => 'Offen', 'console_locked_body' => 'Nur das VPN und die unten gelisteten Adressen erreichen die Konsole. Alle anderen bekommen 404 — sie erfahren nicht einmal, dass es sie gibt.', 'console_open_body' => 'Die Konsole ist von überall erreichbar, wo ihr Hostname aufgerufen wird. Solange das so ist, schützt sie allein das Passwort.', 'console_your_ip' => 'Sie sehen diese Seite gerade von :ip', 'console_lock' => 'Einschränken', 'console_unlock' => 'Freigeben', 'console_always' => 'Immer erlaubt', 'console_vpn_note' => 'Management-VPN, nicht entfernbar', 'console_env_note' => 'Steht in TRUSTED_RANGES in der .env — gehört in die Liste darunter, wo du sie ändern kannst.', 'console_extra' => 'Zusätzlich erlaubt', 'console_none' => 'Noch keine weitere Adresse — ohne VPN kommt dann niemand herein.', 'console_add' => 'Hinzufügen', 'console_remove' => 'Entfernen', 'console_ip_hint' => 'Einzelne Adresse oder Bereich, z. B. 203.0.113.7 oder 203.0.113.0/24.', 'console_terminal_note' => 'Dieselben Adressen entscheiden auch, von wo aus das Terminal zum CluPilot-Server aufgeht — unabhängig davon, ob die Sperre oben ein- oder ausgeschaltet ist.', // Terminal zum Server selbst 'server_terminal_title' => 'Terminal zum Server', 'server_terminal_body' => 'Eine Root-Sitzung auf dem CluPilot-Server selbst — nicht auf einem Host. Wer sie öffnet, erreicht Datenbank, Tresor, DNS-Token und jede Kundeninstanz.', 'server_terminal_installed' => 'Eingerichtet am :when.', 'server_terminal_off_network' => 'Von :ip aus geht sie nicht auf. Nur aus dem Management-Netz oder von einer der Adressen oben.', 'server_terminal_no_key' => 'Es gibt noch keine Kennung. Sie wird hier erzeugt und danach einmal auf dem Server hinterlegt.', 'server_terminal_not_installed' => 'Die Kennung ist erzeugt, auf dem Server aber noch nicht hinterlegt. Dort einmal ausführen:', 'server_terminal_generate' => 'Kennung erzeugen', 'server_terminal_regenerate' => 'Kennung neu erzeugen', 'server_terminal_key_hint' => 'Eigener Schlüssel, getrennt vom Flottenschlüssel für die Hosts.', 'server_terminal_generated' => 'Neue Kennung erzeugt. Auf dem Server noch „sudo bash deploy/install-agent.sh" ausführen.', 'server_terminal_generate_title' => 'Neue Kennung für das Server-Terminal?', 'server_terminal_generate_body' => 'Die bisherige steht auf dem Server in /root/.ssh/authorized_keys und wird von hier aus nicht entfernt. Bis „sudo bash deploy/install-agent.sh" dort gelaufen ist, geht das Terminal zum Server nicht auf.', 'server_terminal_generate_confirm' => 'Neu erzeugen', 'console_ip_invalid' => 'Das ist keine gültige IP-Adresse und kein gültiger Bereich.', 'console_ip_added' => ':ip darf die Konsole jetzt erreichen.', 'console_ip_removed' => ':ip wurde entfernt.', 'console_ip_last' => 'Nicht entfernt: Sie greifen gerade selbst über :ip zu und würden sich aussperren.', 'console_locked' => 'Konsole eingeschränkt — nur noch VPN und gelistete Adressen.', 'console_unlocked' => 'Einschränkung aufgehoben.', 'console_lock_refused' => 'Nicht eingeschränkt: :ip steht auf keiner Liste, Sie hätten sich damit ausgesperrt.', // Two-factor policy — console.require_2fa. Enrolment selbst ist eine // eigene Seite, admin.two-factor-setup (App\Livewire\Admin\TwoFactorSetup) // — siehe RequireOperatorTwoFactor dafür, warum nur die Einrichtung und // nicht diese ganze Seite von der erzwungenen Weiterleitung ausgenommen ist. 'saved' => 'Gespeichert.', 'two_factor_title' => 'Zwei-Faktor-Pflicht', 'two_factor_body' => 'Gilt dann für jeden Mitarbeiter: Wer Zwei-Faktor nicht eingerichtet hat, kommt nur noch auf die Zwei-Faktor-Einrichtung.', 'two_factor_require' => 'Für alle verbindlich machen', 'two_factor_required' => 'Zwei-Faktor ist für die Konsole verbindlich. Bitte richten Sie sie hier ein.', 'two_factor_self_first' => 'Richten Sie zuerst Ihre eigene Zwei-Faktor-Bestätigung ein — sonst sperren Sie sich mit diesem Schalter selbst aus.', 'update_title' => 'Version & Aktualisierung', 'update_version' => 'Läuft', 'update_source' => 'Quelle', 'update_deployed' => 'Ausgerollt', 'update_checked' => 'Zuletzt geprüft', // Zwei eigenständige Aktionen statt einer, die beides tat: schauen soll // nicht erst durch eine echte Aktualisierung samt Wartungsfenster müssen. 'update_check' => 'Nach Aktualisierungen suchen', 'update_checking' => 'Prüfung läuft', 'update_now' => 'Jetzt aktualisieren', 'update_running' => 'Läuft gerade', 'update_available' => ':n Aktualisierung(en) verfügbar', // Mit Versionsnummer, sobald der Agent den Tag genannt hat: „Version 1.1.0 // verfügbar" ist etwas, worüber jemand entscheiden kann. 'update_available_release' => 'Version :version verfügbar', // Warum der Knopf grau ist. Aktualisiert wird nur auf eine Version mit Tag, // nie auf den Stand eines Branches — ein Commit auf main ist keine Freigabe. 'update_only_releases' => 'Aktualisiert wird nur auf eine freigegebene Version. Was auf main landet, ändert hier nichts, bis daraus eine Version mit Tag wird.', 'update_nothing_released' => 'Es gibt keine neuere freigegebene Version.', 'update_current' => 'Aktuell', 'update_unknown' => 'Unbekannt', // Kurz gehalten, ohne eigene Zeitangabe: der Live-Countdown, der direkt im // Anschluss erscheint (update_starts_in), trägt die Genauigkeit bereits. 'update_requested' => 'Aktualisierung angefordert.', 'update_check_requested' => 'Prüfung angefordert.', 'update_already_requested' => 'Es ist schon etwas angefordert — bitte kurz warten.', 'update_no_agent' => 'Der Update-Dienst auf dem Server läuft nicht. Einmalig auf dem Server einrichten: sudo bash /opt/clupilot/deploy/install-agent.sh', 'update_agent_blocked' => 'Der Update-Dienst läuft, kommt aber seit :since nicht an die Arbeit — ein anderer Vorgang hält die Sperre. Solange das so ist, stammen die Angaben oben von vorher. Löst es sich nicht von selbst, hilft ein Blick auf den Prozess unten.', 'update_log' => 'Protokoll des letzten Laufs', // ── Der Wächter ────────────────────────────────────────────────────── // Redet bisher nur ins Journal auf dem Wirt — die Konsole sah ihn bis // August 2026 gar nicht (App\Services\Deployment\WatchdogLog). 'watchdog_idle' => 'Zuletzt nachgesehen :when — nichts zu tun.', 'watchdog_healed' => 'Zuletzt eingegriffen :when: :what', // M3: die Sperre halten inzwischen mehr Vorgaenge als ein Update — // proxy-hosts, restart, archive-key, rescue-tunnel. „weil ein Update // lief" war damit schon falsch, sobald einer der anderen die Sperre hielt. 'watchdog_stood_down' => ':when zurückgetreten — ein anderer Vorgang hielt die Sperre.', // Fix-Runde 1 / Review-Runde 2: gegriffen, aber mindestens ein Griff // ohne Erfolg — auch wenn ein anderer im selben Lauf gewirkt hat (z. B. // fehlende Dienste kamen hoch, wg0 blieb trotz wg-quick up unten). Ohne // diesen Satz verschwand der Fall entweder in „nichts zu tun" // (watchdog_idle) oder, seit der ersten Fix-Runde, in „eingegriffen" // (watchdog_healed) — outcome traegt jetzt ein eigenes `tried`. 'watchdog_tried' => 'Zuletzt eingegriffen :when, ohne Erfolg: :what', 'watchdog_stale' => 'Der Wächter hat sich seit :when nicht gemeldet — er läuft vermutlich nicht mehr.', // ── Der Wirt-Helfer ────────────────────────────────────────────────── // Der root-eigene Helfer auf dem Wirt (UpdateChannel::state()['host_step_ok']). 'host_step_old' => 'Der Wirt-Helfer erfüllt Vertrag :have, gebraucht wird :needs. Einmalig auf diesem Wirt ausführen:', // ── Die Sperre lösen ───────────────────────────────────────────────── // Der Griff, der bisher per SSH auf dem Wirt lag. Er beendet einen // laufenden Prozess, deshalb nennt die Rückfrage ihn vorher beim Namen. 'update_release_lock' => 'Sperre lösen', 'release_lock_pending' => 'Wird gelöst …', 'release_lock_title' => 'Den Vorgang beenden, der die Sperre hält?', 'release_lock_body' => 'Der Update-Dienst kommt nicht an die Arbeit, weil dieser Vorgang auf dem Server die Sperre hält:', 'release_lock_note' => 'Er bekommt zuerst die Aufforderung, sich zu beenden; erst wenn er darauf nicht reagiert, wird er abgebrochen. Läuft gerade eine echte Aktualisierung, wird sie damit mittendrin abgebrochen.', 'release_lock_cancel' => 'Abbrechen', 'release_lock_confirm' => 'Vorgang beenden', 'release_lock_requested' => 'Wird gelöst — der Dienst meldet sich binnen einer Minute zurück.', 'release_lock_already_requested' => 'Ist schon angefordert — bitte kurz warten.', // ── Tunnel-Rettung ─────────────────────────────────────────────────── // deploy/rescue-tunnel.sh stand bisher in zwei Runbooks als Handarbeit. // Derselbe Postkasten wie jede andere Anfrageart // (UpdateChannel::KIND_RESCUE_TUNNEL) — kein zweiter Weg. 'rescue_action' => 'Tunnel retten', 'rescue_requested' => 'Tunnel-Rettung angefordert.', 'rescue_title' => 'Den Tunnel jetzt retten?', 'rescue_body' => 'Zieht das WireGuard-Interface auf dem Tunnel-Server neu hoch. Tut ausdrücklich nichts Zerstörerisches — kein Neubau, kein Neustart des Tunnel-Containers.', 'rescue_cancel' => 'Abbrechen', 'rescue_confirm' => 'Tunnel retten', // Fix-Runde 1: das Ergebnis war bisher unsichtbar — UpdateChannel::state() // lieferte `rescue_last_run`, aber kein Blade las es. 'rescue_last_run' => 'Letzte Tunnel-Rettung: :state, :when.', // Review-Runde 2 (C1 Teil 3): eigenes Wort statt update_state.succeeded // ("erfolgreich") — ein durchgelaufenes Skript hat nur geprüft, dass // jeder Griff ausgerichtet hat, was nötig war (deploy/rescue-tunnel.sh), // nicht dass der Tunnel jetzt wieder zweifelsfrei Daten empfängt. 'rescue_state_ok' => 'durchgelaufen', // Review-Runde 2 (C1 Teil 2): dasselbe Muster wie 'update_log', nur fürs // Protokoll der letzten Tunnel-Rettung (UpdateChannel::rescueLog()). 'rescue_log' => 'Protokoll der letzten Tunnel-Rettung', // ── Festnageln ──────────────────────────────────────────────────────── // Die Decke, die den Update-Agenten UND das Wartungsfenster begrenzt // (App\Services\Deployment\UpdateChannel::setCeiling()). Bestätigt wird // nur das Festnageln selbst im Modal (R23); das Auswahlfeld daneben // braucht keins (R20). 'release_pin_action' => 'Festnageln', 'release_pin_none' => 'Neueste Version (nicht festgenagelt)', 'release_pin_title' => 'Auf diese Version festnageln?', 'release_pin_body' => 'Dieser Server nimmt dann nichts Neueres als :version — auch nicht im Wartungsfenster. Zurück geht es nicht; die Decke begrenzt nur nach oben.', 'release_pin_cancel' => 'Abbrechen', 'release_pin_confirm' => 'Festnageln', 'release_pinned' => 'Festgenagelt.', 'release_pin_invalid' => 'Das ist keine gültige Version.', // Eigene Meldung für eine leere Bestätigung — nicht die Erfolgsmeldung // von oben. Eine leere Auswahl darf niemals als "Decke abnehmen" gelten, // nur weil setCeiling(null) genau das bedeutet. 'release_pin_empty' => 'Keine Version ausgewählt — nichts wurde geändert.', 'release_pinned_at' => 'Festgenagelt auf :version.', 'release_pinned_passed' => 'Festgenagelt auf :version — dieser Server ist bereits weiter. Die Decke hält nichts mehr zurück; zurück geht es nicht.', 'release_unpin_action' => 'Decke abnehmen', 'release_unpinned' => 'Decke abgenommen.', 'release_ceiling_ceiling_missing' => 'Die festgenagelte Version gibt es nicht (mehr). Es wird solange nichts installiert — bitte neu festnageln oder die Decke abnehmen.', 'release_ceiling_ceiling_invalid' => 'Die festgenagelte Version ist unlesbar. Es wird solange nichts installiert — bitte neu festnageln oder die Decke abnehmen.', 'update_error' => [ 'repo_unreachable' => 'Das Repository ist vom Server aus nicht erreichbar.', 'detached_no_release' => 'Der Checkout hängt an keinem Branch und ist auf keine Version gepinnt.', 'update_failed' => 'Die Aktualisierung ist fehlgeschlagen (Code :code). Siehe Protokoll.', 'restart_failed' => 'Der Neustart der Dienste ist fehlgeschlagen. Bitte manuell ausführen: docker compose restart queue scheduler reverb.', 'rescue_failed' => 'Die Tunnel-Rettung ist fehlgeschlagen. Protokoll auf dem Wirt: storage/app/deploy/rescue-last-run.log.', // Der Wirt kennt den Schritt noch nicht. Ein Knopf, der nichts tut und // nichts sagt, schickt den Betreiber genau dorthin zurück, wo er ohne // die Konsole schon war. 'unblock_helper_missing' => 'Der Server-Helfer fehlt. Einmalig auf dem Server einrichten: sudo bash /opt/clupilot/deploy/install-agent.sh', 'unblock_helper_old' => 'Der Server-Helfer kennt diesen Schritt noch nicht. Einmalig auf dem Server nachziehen: sudo bash /opt/clupilot/deploy/install-agent.sh', 'unblock_failed' => 'Der Vorgang ließ sich nicht beenden. Auf dem Server nachsehen: fuser -v /opt/clupilot/storage/app/deploy/.agent.lock', ], 'update_last_run' => 'Letzter Lauf: :state, :when.', 'update_state' => [ 'succeeded' => 'erfolgreich', 'failed' => 'fehlgeschlagen', 'running' => 'läuft', ], // Vollbild-Ansicht in der Konsolen-Hülle (layouts/admin.blade.php) — steht // auf jeder Konsolenseite, solange eine Aktualisierung läuft, nicht nur // auf der Einstellungsseite. 'update_overlay_title' => 'Aktualisierung läuft.', // Kein Countdown mehr, weder beim Prüfen noch beim Aktualisieren. Der alte // lief rückwärts vier Sekunden und sprang zurück auf eine Minute, weil das // Ziel bei jedem Poll neu gerechnet wurde und auf jedem Server, dessen // Timer länger ist als das gemeldete Intervall, in der Vergangenheit lag. // Und er wird nicht gebraucht: der Dienst wird beim Anfordern geweckt. 'update_starting' => 'Wird jetzt gestartet.', // Nur für Server, auf denen deploy/install-agent.sh noch nicht neu gelaufen // ist — dort holt der Timer die Anforderung ab, und das wird gesagt statt // eine Sofortigkeit zu versprechen, die dieser Server nicht liefert. 'update_starting_queued' => 'Wird gestartet, sobald der Dienst die Anforderung übernimmt.', 'update_step' => 'Schritt: :step', 'update_since' => 'Läuft seit :when', 'update_offline_hint' => 'Während der Aktualisierung ist die Seite kurz im Wartungsmodus — diese Anzeige bleibt so lange stehen und meldet sich danach von selbst zurück.', 'update_took' => 'Dauer: :duration', 'update_failed_at' => 'Abgebrochen beim Schritt: :step', // Die Schritte, die deploy/update.sh meldet. Das Skript schreibt Schlüssel, // damit hier übersetzt und nicht englisch durchgereicht wird. 'update_phase' => [ 'fetch' => 'Neue Version holen', 'maintenance_on' => 'Wartungsmodus einschalten', 'checkout' => 'Code übernehmen', 'image' => 'Container-Image neu bauen', 'composer' => 'PHP-Pakete installieren', 'npm' => 'JS-Pakete installieren', 'migrate' => 'Datenbank migrieren', 'assets' => 'Assets neu bauen', 'caches' => 'Caches neu aufbauen', 'restart' => 'Dienste neu starten', 'maintenance_off' => 'Wartungsmodus beenden', ], 'password_title' => 'Passwort ändern', 'password_sub' => 'Gilt sofort. Andere Sitzungen bleiben angemeldet.', 'password_current' => 'Aktuelles Passwort', 'password_new' => 'Neues Passwort', 'password_repeat' => 'Wiederholen', 'password_save' => 'Passwort ändern', 'password_wrong' => 'Das aktuelle Passwort stimmt nicht.', 'password_changed' => 'Passwort geändert.', // ── Automatik ──────────────────────────────────────────────────────── 'auto_title' => 'Automatisch aktualisieren', 'auto_hint' => 'Holt eine verfügbare Version im gewählten Zeitfenster von selbst. Von Hand geht es weiterhin jederzeit — und wer vorher schon aktualisiert hat, für den findet das Fenster nichts mehr zu tun.', 'auto_enabled' => 'Automatik einschalten', 'auto_days' => 'Wochentage', 'auto_from' => 'ab', 'auto_to' => 'bis', 'auto_saved' => 'Zeitfenster gespeichert.', 'auto_off' => 'Automatik ist aus — Updates nur von Hand.', 'auto_next' => 'Nächstes Fenster: :days, :from–:to Uhr.', 'update_by_schedule' => 'Automatik', 'weekday' => [ 1 => 'Mo', 2 => 'Di', 3 => 'Mi', 4 => 'Do', 5 => 'Fr', 6 => 'Sa', 7 => 'So', ], // The page's outline. It had none — eight cards of equal weight in one // column, with the operator's own password between two platform switches. 'group' => [ 'installation' => 'Installation', 'account' => 'Mein Konto', 'team' => 'Team & Zugriff', ], // The tab bar. Kept apart from `group` — those were the headings of a // scrolled page and read as such ("Installation" over a divider line); a // tab is a thing you click, and it has room for fewer words. 'password_policy_title' => 'Passwortrichtlinie', 'password_policy_body' => 'Gilt für Kunden und Mitarbeiter gleichermaßen — beim Registrieren, beim Zurücksetzen und beim Ändern.', 'password_min_length' => 'Mindestlänge (Zeichen)', 'password_min_length_hint' => 'Kürzer als :floor Zeichen ist nicht möglich. Länger ist jederzeit möglich und schadet nichts.', 'password_policy_saved' => 'Passwortrichtlinie gespeichert. Sie gilt ab dem nächsten Setzen eines Passworts.', 'tab' => [ 'installation' => 'Installation', 'account' => 'Mein Konto', 'two_factor' => 'Sicherheit', 'team' => 'Team', ], ];