chain-studio/lib/l10n/app_localizations_de.dart
flemming-it c7869870c4 feat(studio): plain-language ask bar + collapsible filter + AI search (v0.32.0)
Three changes against the user feedback "der text ist zu
zerhackt, die filter-leiste nimmt zu viel sicht weg, llm-suche
wenn das geht":

1. Today-Hero copy rewritten in flowing prose. The fallback
   story drops the code-fence templates ("`mcp.<server>.<tool>`")
   and reads as a single arc per language. Same trust model,
   gentler register.

2. Filter row collapses behind a single `_FilterButton` with a
   "Filter · N active" count badge. Status / Source / Installed
   chips now live inside `_FilterDialog` — invisible until the
   operator wants them, recovers a full row of viewport. The
   category strip stays inline because category is the most
   common cut and benefits from being one click away.

3. New `_AskBar` replaces the old single-line `_SearchField`:

   - Multi-line input (1-4 lines auto-grow) so questions don't
     overflow horizontally.
   - Cmd+Enter / Ctrl+Enter submits; bare Enter inserts a
     newline so the operator can write multi-line questions
     naturally.
   - Heuristic question detector (ends in `?` or ≥4 words)
     routes the submit to the System-AI's askAi RPC instead of
     the substring search. Live keystrokes still keyword-search
     for short queries; question-shaped input holds the grid
     steady until submit so the visible result set doesn't
     wipe with every space.
   - The LLM is asked for a strict-JSON ranking of up to 5
     modules with a one-phrase reason each. Unknown module
     names are dropped silently — operators must not see
     hallucinated entries.
   - The new `_AiAnswerCard` renders the LLM's answer plus the
     ranked match list above the grid; the grid filters to
     just those names so the answer and the visible cards
     stay coherent. Clearing the question collapses everything
     back.
   - Falls back to plain keyword search when System AI is off
     (with an explanatory hint instead of the AI hint).

The AI path uses the System-AI the operator already configured
in Settings; same privacy mode, same audit-log trail. Nothing
new leaves the hub.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-08 13:21:40 +02:00

1368 lines
33 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ignore: unused_import
import 'package:intl/intl.dart' as intl;
import 'app_localizations.dart';
// ignore_for_file: type=lint
/// The translations for German (`de`).
class AppLocalizationsDe extends AppLocalizations {
AppLocalizationsDe([String locale = 'de']) : super(locale);
@override
String get appTitle => 'F∆I Studio';
@override
String get navDoctor => 'Diagnose';
@override
String get navModules => 'Module';
@override
String get navStore => 'Store';
@override
String get navFlows => 'Flows';
@override
String get navAudit => 'Protokoll';
@override
String get navApprovals => 'Freigaben';
@override
String get connectionConnected => 'verbunden';
@override
String get connectionUnreachable => 'nicht erreichbar';
@override
String get connectionConnecting => 'verbinde…';
@override
String get connectionStartHub => 'Hub starten';
@override
String get buttonCancel => 'Abbrechen';
@override
String get buttonSave => 'Speichern';
@override
String get buttonClose => 'Schließen';
@override
String get buttonRetry => 'Erneut versuchen';
@override
String get buttonRefresh => 'Aktualisieren';
@override
String get buttonInstall => 'Installieren';
@override
String get buttonUninstall => 'Deinstallieren';
@override
String get buttonDetails => 'Details';
@override
String get buttonAdd => 'Hinzufügen';
@override
String get buttonRemove => 'Entfernen';
@override
String get buttonOpen => 'Öffnen';
@override
String get buttonExplain => 'Erklären';
@override
String get buttonReadDocs => 'Doku öffnen';
@override
String get settingsTitle => 'Hub-Endpunkt';
@override
String get settingsHost => 'Host';
@override
String get settingsPort => 'Port';
@override
String get settingsTls => 'TLS';
@override
String get settingsSaveAndConnect => 'Speichern & verbinden';
@override
String get settingsLanguage => 'Sprache';
@override
String get settingsLanguageHint =>
'Sprache der App. Wirkt auf alle Seiten; mehrsprachige Store-Einträge folgen ebenfalls.';
@override
String get settingsHubEndpointHint =>
'Wohin soll Studio sich verbinden? Standard ist der lokale Hub auf 127.0.0.1:50051.';
@override
String get settingsTlsSubtitle => 'https/grpc-secure';
@override
String get settingsPortError => 'Port muss 165535 sein';
@override
String get channelsBlurb =>
'Hub-Kanal wechseln (schreibt ~/.fai/current-channel und startet den Daemon neu). Verbinden ändert nur die Wire von Studio.';
@override
String get channelsActionsTooltip => 'Kanal-Aktionen';
@override
String get systemAiHeader => 'SYSTEM-AI';
@override
String get systemAiEnabled => 'aktiv';
@override
String get systemAiOff => 'aus';
@override
String get systemAiEdit => 'Bearbeiten…';
@override
String get systemAiConfigure => 'Konfigurieren…';
@override
String get systemAiOffBlurb =>
'Aus — Fehlererklärungen auf der Protokoll-Seite sind deaktiviert. Klicke Konfigurieren…, um einen Provider zu wählen (Ollama / OpenAI / LM Studio / vLLM / Eigene). Die Operator-Konfig wird direkt überschrieben; kein Daemon-Neustart nötig.';
@override
String mcpServersCount(int n) {
String _temp0 = intl.Intl.pluralLogic(
n,
locale: localeName,
other: 'Server',
one: 'Server',
);
return '$n $_temp0';
}
@override
String get mcpRediscoverTooltip => 'Discovery neu ausführen';
@override
String get mcpAddTooltip => 'MCP-Server hinzufügen';
@override
String get mcpRemoveTooltip => 'Server entfernen';
@override
String mcpToolsCount(int n) {
return '$n Tools';
}
@override
String n8nEndpointsCount(int n) {
String _temp0 = intl.Intl.pluralLogic(
n,
locale: localeName,
other: 'Endpunkte',
one: 'Endpunkt',
);
return '$n $_temp0';
}
@override
String n8nWorkflowsCount(int n) {
return '$n Workflows';
}
@override
String get n8nRediscoverTooltip => 'Discovery neu ausführen';
@override
String get n8nAddTooltip => 'n8n-Endpunkt hinzufügen';
@override
String get n8nRemoveTooltip => 'Endpunkt entfernen';
@override
String get addMcpTitle => 'MCP-Server hinzufügen';
@override
String get addMcpIntro =>
'Tools, die der Server via `tools/list` anbietet, erscheinen im Store als `mcp.<name>.<tool>`-Capabilities.';
@override
String get addMcpSuggestionsLabel => 'Vorschläge — zum Vorausfüllen klicken';
@override
String get addMcpNameLabel => 'Name (keine Punkte)';
@override
String get addMcpNameHint => 'filesystem';
@override
String get addMcpEndpointLabel => 'Endpunkt';
@override
String get addMcpEndpointHint => 'http://127.0.0.1:3001/mcp';
@override
String get addMcpApiKeyLabel => 'API-Key-Umgebungsvariable (optional)';
@override
String get addMcpApiKeyHint => 'MCP_FILESYSTEM_TOKEN';
@override
String get addMcpNotesLabel => 'Notizen (optional)';
@override
String get addMcpAddButton => 'Hinzufügen + Discovery';
@override
String get addN8nTitle => 'n8n-Endpunkt hinzufügen';
@override
String get addN8nIntro =>
'Aktive Workflows erscheinen im Store als `n8n.<name>.<workflow_slug>`-Capabilities.';
@override
String get addN8nNameLabel => 'Name (keine Punkte)';
@override
String get addN8nNameHint => 'ops';
@override
String get addN8nBaseUrlLabel => 'Basis-URL (ohne /api/v1)';
@override
String get addN8nBaseUrlHint => 'https://n8n.example.com';
@override
String get addN8nApiKeyLabel => 'API-Key-Umgebungsvariable (optional)';
@override
String get addN8nApiKeyHint => 'N8N_OPS_KEY';
@override
String get addN8nNotesLabel => 'Notizen (optional)';
@override
String get addN8nAddButton => 'Hinzufügen + Discovery';
@override
String addedMcpToast(String name) {
return 'MCP-Server „$name\" hinzugefügt.';
}
@override
String addedN8nToast(String name) {
return 'n8n-Endpunkt „$name\" hinzugefügt.';
}
@override
String addFailedToast(String error) {
return 'Hinzufügen fehlgeschlagen: $error';
}
@override
String removeFailedToast(String error) {
return 'Entfernen fehlgeschlagen: $error';
}
@override
String refreshFailedToast(String error) {
return 'Aktualisieren fehlgeschlagen: $error';
}
@override
String get channelsHeader => 'KANÄLE';
@override
String get channelsActive => 'aktiv';
@override
String get channelsRunning => 'läuft';
@override
String get channelsStopped => 'gestoppt';
@override
String get channelsConnect => 'Studio mit diesem Kanal verbinden';
@override
String get channelsSwitch => 'Diesen Kanal aktivieren';
@override
String get channelsEnableAutostart => 'Autostart bei Anmeldung aktivieren';
@override
String get channelsDisableAutostart => 'Autostart deaktivieren';
@override
String get storeSearchHint =>
'Module suchen — Name, Tagline, Tag, Capability…';
@override
String get storeAskHint =>
'Was brauchst du? Versuch\'s mit „ein Modul, das tabellarische Daten liest\" oder tippe einfach einen Begriff.';
@override
String get storeAskSubmit => 'Suchen';
@override
String get storeAskAi => 'KI fragen';
@override
String get storeAskClear => 'Frage zurücksetzen';
@override
String get storeAskAiThinking => 'Module werden durchsucht…';
@override
String get storeAskAiUnavailable =>
'Konfiguriere eine System-AI in den Einstellungen, um Fragen in normaler Sprache zu stellen.';
@override
String get storeAskNoMatches =>
'Keine Treffer — Frage verfeinern oder im Grid unten stöbern.';
@override
String get storeAskAnswerLabel => 'KI-Vorschlag';
@override
String get storeAskAnswerWhy => 'Warum es passt';
@override
String get storeAskMatchPill => 'Treffer';
@override
String get storeFilterLabel => 'Filter';
@override
String storeFilterActiveCount(int n) {
return '$n aktiv';
}
@override
String get storeFilterReset => 'Filter zurücksetzen';
@override
String get storeFilterApply => 'Fertig';
@override
String get storeFilterStatusGroup => 'Status';
@override
String get storeFilterSourceGroup => 'Quelle';
@override
String get storeFilterInstalledGroup => 'Nur installierte zeigen';
@override
String get storeFeatured => 'EMPFOHLEN';
@override
String get storeFeaturedHint => 'kuratierte Auswahl · klicken für Details';
@override
String get storeNoMatches => 'Keine Treffer';
@override
String get storeNoMatchesHint =>
'Filter anpassen oder Suche leeren, um alle Einträge zu sehen.';
@override
String get storeClearFilters => 'Filter zurücksetzen';
@override
String get storeStatusAll => 'Alle';
@override
String get storeStatusPublished => 'Veröffentlicht';
@override
String get storeStatusAlpha => 'Alpha';
@override
String get storeStatusPlanned => 'Geplant';
@override
String get storeInstalledOnly => 'Installiert';
@override
String storeNResults(int n) {
return '$n Treffer';
}
@override
String get storeReloadTooltip => 'Aktualisieren';
@override
String get storeTodayBadge => 'HEUTE';
@override
String get storeTodayDeck => 'Von der F∆I-Redaktion';
@override
String get storeTodayDismissTooltip => 'Für diese Sitzung ausblenden';
@override
String get storePillInstalled => 'installiert';
@override
String get storePillUpdate => 'Update';
@override
String storeUpdateButton(String version) {
return 'Update auf $version';
}
@override
String storeUpdateTooltip(String installed, String best) {
return 'Installiert $installed — Store bietet v$best';
}
@override
String get storeNoTagline => '(keine Beschreibung)';
@override
String get storeUninstallTitle => 'Modul deinstallieren?';
@override
String storeUninstallBody(String name) {
return 'Entfernt $name aus diesem Hub. Flows, die es verwenden, schlagen beim nächsten Lauf fehl.';
}
@override
String storeInstalledToast(String name, String version) {
return '$name v$version installiert.';
}
@override
String storeInstallFailedToast(String error) {
return 'Installation fehlgeschlagen: $error';
}
@override
String storeUninstalledToast(String name, String version) {
return '$name v$version deinstalliert.';
}
@override
String storeUninstallFailedToast(String error) {
return 'Deinstallation fehlgeschlagen: $error';
}
@override
String storeOpenBrowserFailed(String error) {
return 'Browser konnte nicht geöffnet werden: $error';
}
@override
String get storeSectionTags => 'Tags';
@override
String get storeSectionRequiredCapabilities => 'Erforderliche Capabilities';
@override
String get storeSectionRequiredHostServices => 'Erforderliche Host-Dienste';
@override
String get storeSectionScreenshots => 'Screenshots';
@override
String get storeSectionDocumentation => 'Dokumentation';
@override
String get storeSectionSource => 'Quelle';
@override
String get storeInstallingButton => 'Installiere…';
@override
String get storeNotInstallable => 'Nicht installierbar';
@override
String storeNotInstallableTooltip(String status) {
return 'Status „$status\" — Installations-Pfad noch nicht verdrahtet.';
}
@override
String storeInstallProgressTitle(String name) {
return 'Installation von $name';
}
@override
String get storeInstallProgressBody => 'Holen, verifizieren, entpacken…';
@override
String get storeLoadDocs => 'Dokumentation laden';
@override
String get storeDocsHint =>
'README inline gerendert; nutzt das Registry-Token des Hubs, falls nötig.';
@override
String get storeDocsFetching => 'README wird geladen…';
@override
String get storeOpenRepoButton => 'Repository im Browser öffnen';
@override
String get storeDocsErrorNotFound =>
'Dieses Modul ist nicht im Store-Index des Hubs enthalten.';
@override
String get storeDocsErrorNoDocs =>
'Für dieses Modul ist keine Repository-URL hinterlegt.';
@override
String get storeDocsErrorAuth =>
'Die Registry erfordert Authentifizierung, um dieses README zu laden. Setze FAI_REGISTRY_TOKEN in der Umgebung des Daemons und starte den Hub neu.';
@override
String storeDocsErrorNetwork(String detail) {
return 'Netzwerkfehler beim Laden des README. $detail';
}
@override
String get storeDocsErrorParse => 'README ist kein gültiges UTF-8.';
@override
String get storeDocsErrorGeneric => 'README konnte nicht geladen werden.';
@override
String get storeSourceLabel => 'Quelle';
@override
String get storeSourceAll => 'Alle Quellen';
@override
String get storeSourceNative => 'Nativ';
@override
String get storeSourceMcp => 'MCP';
@override
String get storeSourceN8n => 'n8n';
@override
String get storeProvenanceNative => 'nativ';
@override
String storeProvenanceMcp(String provider) {
return 'mcp · $provider';
}
@override
String storeProvenanceN8n(String provider) {
return 'n8n · $provider';
}
@override
String get storeRecommendedTitle =>
'Öffentliche Quelle hinzufügen — ein Klick';
@override
String get storeRecommendedBody =>
'Kuratierte MCP-Server über HTTPS erreichbar. Kein Subprozess, kein API-Key, kein Node. Föderierte Capabilities erscheinen sofort im Store.';
@override
String get storeRecommendedAddTooltip => 'Hinzufügen und entdecken';
@override
String get storeRecommendedAdding => 'Wird hinzugefügt…';
@override
String get storeRecommendedDeepWikiTagline =>
'GitHub-Repo-Doku-Suche (KI-gestützt)';
@override
String get storeRecommendedSemgrepTagline =>
'Security-Scanning für Code-Schwachstellen';
@override
String storeProviderAddedToast(String name, int n) {
String _temp0 = intl.Intl.pluralLogic(
n,
locale: localeName,
other: 'föderierte Capabilities',
one: 'föderierte Capability',
);
return '$name hinzugefügt — $n $_temp0.';
}
@override
String storeProviderAddFailed(String name, String error) {
return '$name konnte nicht hinzugefügt werden: $error';
}
@override
String get auditTitle => 'Protokoll';
@override
String get auditNoEvents => 'Noch keine Ereignisse';
@override
String get auditNoEventsHint =>
'Starte einen Flow, um den Audit-Stream zu füllen.\nEreignisse erscheinen innerhalb von Sekunden.';
@override
String get auditFilterAll => 'alle';
@override
String get auditFilterFlow => 'Flow';
@override
String get auditFilterStep => 'Step';
@override
String get auditFilterModule => 'Modul';
@override
String get auditClearLogTooltip => 'Protokoll löschen (nur local/dev Kanal)';
@override
String auditClearedToast(int n, String channel) {
return '$n Ereignisse auf Kanal „$channel\" gelöscht. Chain mit Marker neu geseedet.';
}
@override
String auditClearFailed(String detail) {
return 'Löschen fehlgeschlagen: $detail';
}
@override
String get auditExplain => 'Erklären';
@override
String get auditReask => 'Neu fragen';
@override
String get auditAsking => 'Frage läuft…';
@override
String get auditSystemAi => 'SYSTEM-AI';
@override
String get auditCachedPill => 'gecacht';
@override
String auditOriginalLatency(int ms) {
return 'ursprünglich $ms ms';
}
@override
String auditLatency(int ms) {
return '$ms ms';
}
@override
String get auditRegenerateTooltip =>
'Neu generieren — Cache überspringen, Modell erneut fragen';
@override
String auditLiveStatus(int n) {
String _temp0 = intl.Intl.pluralLogic(
n,
locale: localeName,
other: 'Ereignisse',
one: 'Ereignis',
);
return 'live · Abfrage alle 2s · $n $_temp0';
}
@override
String auditDisconnected(String error) {
return 'getrennt · $error';
}
@override
String get auditHashChainVerified => 'Hash-Chain verifiziert';
@override
String get auditDetailHeader => 'DETAIL';
@override
String get auditAskingFull => 'Frage an die konfigurierte System-AI läuft…';
@override
String get auditFixLabel => 'FIX';
@override
String auditCachedTooltipKnown(String at, String hits) {
return 'Aus dem lokalen Cache geliefert. Ursprünglich erzeugt am $at$hits.';
}
@override
String auditCachedTooltipUnknown(String hits) {
return 'Aus dem lokalen Cache geliefert. Ursprünglicher Zeitpunkt unbekannt$hits.';
}
@override
String auditCachedTooltipHits(int n) {
return ' · $n Treffer';
}
@override
String get auditConfigureSystemAi =>
'System-AI unter Einstellungen konfigurieren (Cmd+,)';
@override
String get auditClearDialogTitle => 'Audit-Log löschen?';
@override
String get auditClearDialogBody =>
'Löscht jedes Audit-Event auf dem aktiven Kanal und seedet einen neuen chain.reset-Marker mit Prüfer und Begründung. Auf beta / production verweigert. Nicht umkehrbar.';
@override
String get auditClearReviewerLabel => 'Prüfer';
@override
String get auditClearReasonLabel =>
'Begründung (im chain.reset-Marker festgehalten)';
@override
String get auditClearReasonHelper =>
'Erforderlich — Auditoren werden das lesen.';
@override
String get auditClearLogButton => 'Log löschen';
@override
String get modulesTitle => 'Module';
@override
String get modulesNoneTitle => 'Noch keine Module';
@override
String get modulesNoneHint =>
'`fai install <capability-name>` ausführen oder ~/.fai/modules/ prüfen.';
@override
String get modulesReloadTooltip => 'Aktualisieren';
@override
String get modulesRecentActivity => 'LETZTE AKTIVITÄT';
@override
String modulesRecentActivityHint(int n) {
return 'letzte $n install/uninstall-Ereignisse aus dem Audit-Log';
}
@override
String get modulesActivityInstalled => 'installiert';
@override
String get modulesActivityUninstalled => 'deinstalliert';
@override
String get modulesCapabilitiesLabel => 'Capabilities';
@override
String get modulesUninstallTitle => 'Modul deinstallieren?';
@override
String modulesUninstallBody(String name, String version) {
return 'Entfernt $name v$version von diesem Hub. Flows, die es verwenden, schlagen beim nächsten Lauf fehl. Ein `module.uninstalled`-Audit-Event wird festgehalten.';
}
@override
String modulesUninstalledToast(String name, String version) {
return '$name v$version deinstalliert.';
}
@override
String modulesUninstallFailed(String error) {
return 'Deinstallation fehlgeschlagen: $error';
}
@override
String get modulesUninstalling => 'Wird deinstalliert…';
@override
String moduleSheetFailedToLoad(String error) {
return 'Laden fehlgeschlagen: $error';
}
@override
String get moduleSheetCapabilities => 'Capabilities';
@override
String get moduleSheetPermissions => 'Deklarierte Berechtigungen';
@override
String get moduleSheetNoPermissions => '(keine — reines Berechnungsmodul)';
@override
String get flowsTitle => 'Flows';
@override
String get flowsReloadTooltip => 'Aktualisieren';
@override
String get flowsNoneTitle => 'Keine gespeicherten Flows';
@override
String get flowsNoneHint =>
'Flow speichern mit `fai admin flows save <name> <flow.yaml>`, dann taucht er hier auf.';
@override
String flowsRunDialogTitle(String name) {
return '$name ausführen';
}
@override
String get flowsRunDialogBody =>
'Eingaben als key=value, eine pro Zeile. Alle Werte werden als Text-Payloads gesendet. Für binäre Eingaben die `fai run` CLI nutzen.';
@override
String get flowsInputsHint =>
'name=World\ntarget_language=English\nsummary_style=three bullet points';
@override
String get flowsRunButton => 'Starten';
@override
String flowsRunningTitle(String name) {
return '$name läuft';
}
@override
String get flowsRunning => 'Flow läuft…';
@override
String get flowsNoOutputs => 'Flow abgeschlossen ohne deklarierte Outputs.';
@override
String get approvalsTitle => 'Freigaben';
@override
String get approvalsTabPending => 'Offen';
@override
String get approvalsTabHistory => 'Verlauf';
@override
String get approvalsInboxZero => 'Posteingang leer';
@override
String get approvalsInboxHint =>
'Alles erledigt. Neue `system.approval@^0`-Schritte landen automatisch hier.';
@override
String get approvalsReloadTooltip => 'Aktualisieren';
@override
String get approvalsPillPending => 'offen';
@override
String get approvalsPillApproved => 'freigegeben';
@override
String get approvalsPillRejected => 'abgelehnt';
@override
String get approvalsPillExpired => 'abgelaufen';
@override
String get approvalsPayloadPreview => 'PAYLOAD-VORSCHAU';
@override
String get approvalsApproveButton => 'Freigeben';
@override
String get approvalsRejectButton => 'Ablehnen';
@override
String get approvalsRejectDialogTitle => 'Freigabe ablehnen';
@override
String get approvalsRejectReasonLabel =>
'Begründung (im Audit-Log festgehalten)';
@override
String approvalsApprovedToast(String flow, String step) {
return 'freigegeben · $flow $step';
}
@override
String approvalsRejectedToast(String flow, String step) {
return 'abgelehnt · $flow $step';
}
@override
String approvalsApproveFailed(String error) {
return 'Freigabe fehlgeschlagen: $error';
}
@override
String approvalsRejectFailed(String error) {
return 'Ablehnung fehlgeschlagen: $error';
}
@override
String get approvalsHistoryEmpty => 'Noch kein Verlauf';
@override
String get approvalsHistoryEmptyHint =>
'Entschiedene Freigaben (freigegeben / abgelehnt / abgelaufen) erscheinen hier.\nDas Audit-Log enthält den vollständigen hash-chained Datensatz.';
@override
String get approvalsDialogDecided => 'entschieden';
@override
String get approvalsDialogCreated => 'erstellt';
@override
String get approvalsDialogReason => 'Begründung';
@override
String get approvalsDialogPrompt => 'PROMPT';
@override
String approvalsExpiresIn(int minutes) {
return '${minutes}m';
}
@override
String approvalsExpiresInHours(int hours) {
return '${hours}h';
}
@override
String get doctorTitle => 'Diagnose';
@override
String get doctorRecheckTooltip => 'Erneut prüfen';
@override
String get doctorEventLogSection => 'Audit-Log';
@override
String get doctorModulesApprovalsSection => 'Module & Freigaben';
@override
String get doctorHostServicesSection => 'Host-Dienste';
@override
String get doctorDaemonFilesSection => 'Daemon-Dateien';
@override
String get doctorDaemonControlSection => 'Daemon-Steuerung';
@override
String get doctorChainIntact => 'Hash-Chain intakt';
@override
String doctorChainIntactDetail(int n) {
return '$n Ereignisse · prev_event_sha256 lückenlos verifiziert';
}
@override
String get doctorChainTampered => 'Manipulation erkannt';
@override
String doctorChainTamperedDetail(int verified, int total, String id) {
return '$verified von $total verifiziert vor Mismatch bei $id';
}
@override
String get doctorChainPillOk => 'WORM-1';
@override
String get doctorChainPillTamper => 'MANIPULIERT';
@override
String get doctorVerifyNow => 'Jetzt prüfen';
@override
String get doctorRestart => 'Neustart';
@override
String get doctorStart => 'Starten';
@override
String get doctorStop => 'Stoppen';
@override
String get doctorStatusAction => 'Status';
@override
String doctorRunningOn(String name, String endpoint) {
return 'Läuft auf $name: $endpoint';
}
@override
String doctorStoppedOn(String name) {
return '$name-Daemon gestoppt';
}
@override
String get doctorStatusUnknown => 'Daemon-Status: …';
@override
String get doctorPillRunning => 'läuft';
@override
String get doctorPillStopped => 'gestoppt';
@override
String get doctorDaemonControlHint =>
'Studio ruft das Platform-Binary auf — entspricht `fai daemon …`, sodass CLI und UI im Gleichschritt bleiben.';
@override
String get doctorDaemonControlWorking => 'Wird ausgeführt…';
@override
String get doctorPathLog => 'Log';
@override
String get doctorPathConfig => 'Konfig';
@override
String get doctorPathDb => 'Audit-DB';
@override
String get doctorPathModules => 'Module-Verzeichnis';
@override
String get doctorPathFlows => 'Flow-Verzeichnis';
@override
String get doctorPathPid => 'PID-Datei';
@override
String get doctorPathsEmpty =>
'Daemon hat keine Datei-Pfade gemeldet. Hub aktualisieren via `fai daemon restart`.';
@override
String doctorOpenError(String detail) {
return 'Konnte nicht öffnen: $detail';
}
@override
String doctorUpdateAvailable(String version) {
return 'Update verfügbar — $version';
}
@override
String doctorUpdateBody(String channel, String version) {
return 'Kanal $channel bietet jetzt $version. Per Button anwenden — Studio ruft `fai update apply --channel $channel` auf.';
}
@override
String get doctorUpdateUnreachable => 'Release-Host nicht erreichbar';
@override
String doctorUpdateUnreachableBody(String channel) {
return 'Release-Feed für $channel konnte nicht erreicht werden.';
}
@override
String doctorReleaseNotes(String url) {
return 'Notes: $url';
}
@override
String get doctorPillNew => 'neu';
@override
String get doctorPillOffline => 'offline';
@override
String get doctorApplyUpdate => 'Update anwenden';
@override
String get doctorApplying => 'Wird angewendet…';
@override
String get doctorApplyDone =>
'Update angewendet. Studio neu starten, um die neue Daemon-Version zu sehen.';
@override
String get mcpHeader => 'MCP-CLIENTS';
@override
String get mcpHint =>
'Externe MCP-Server bringen ihre Tools als `mcp.<server>.<tool>` Capabilities ein. Einmal konfigurieren, im Store sichtbar.';
@override
String get mcpEmpty =>
'Keine MCP-Server konfiguriert. + klicken zum Hinzufügen.';
@override
String get n8nHeader => 'N8N-ENDPUNKTE';
@override
String get n8nHint =>
'Aktive n8n-Workflows erscheinen als `n8n.<endpoint>.<slug>` Capabilities. Einmal konfigurieren, im Store sichtbar.';
@override
String get n8nEmpty =>
'Keine n8n-Endpunkte konfiguriert. + klicken zum Hinzufügen.';
@override
String get hubUnreachable => 'Hub nicht erreichbar';
@override
String get hubUnreachableHint => 'Hub starten mit `fai serve`.';
@override
String get languageEnglish => 'English';
@override
String get languageGerman => 'Deutsch';
@override
String get searchHint =>
'Springe überall hin — Module, Store, Flows, Seiten…';
@override
String get searchIndexing => 'Indiziere…';
@override
String get searchNoMatches => 'Keine Treffer.';
@override
String get searchHintNavigate => '↑↓ navigieren';
@override
String get searchHintOpen => 'Enter öffnen';
@override
String get searchHintClose => 'Esc schließen';
@override
String get searchGroupPages => 'Seiten';
@override
String get searchGroupModules => 'Module';
@override
String get searchGroupStore => 'Store';
@override
String get searchGroupFlows => 'Flows';
@override
String get searchSettingsLabel => 'Einstellungen';
@override
String searchPageHint(int n) {
return 'Seite · ⌘$n';
}
@override
String get searchSettingsHint => 'Hub-Endpunkt, Kanäle, System-AI · ⌘;';
@override
String searchInstalledModuleHint(String version) {
return 'installiertes Modul · v$version';
}
@override
String get searchStoreUncategorized => 'ohne Kategorie';
@override
String searchStoreHintWithTagline(String tagline) {
return 'Store · $tagline';
}
@override
String searchStoreHintWithCategory(String category) {
return 'Store · $category';
}
@override
String get searchSavedFlowHint => 'gespeicherter Flow';
@override
String get systemAiTitle => 'System-AI';
@override
String get systemAiIntro =>
'Die hub-interne LLM, die die Plattform selbst für Fehlererklärungen und Operator-Hilfe nutzt. Standardmäßig aus; hier konfigurieren. Siehe docs/architecture/system-ai.md, was über die Leitung geht.';
@override
String get systemAiProviderLabel => 'Provider';
@override
String get systemAiEndpointLabel => 'Endpunkt-URL (bis /v1)';
@override
String get systemAiApiKeyRequired =>
'API-Key-Umgebungsvariable (erforderlich)';
@override
String get systemAiApiKeyOptional => 'API-Key-Umgebungsvariable (optional)';
@override
String systemAiApiKeyDisclaimer(String name) {
return 'Studio liest oder speichert den Key-Wert nie — nur den Namen der Umgebungsvariable. Der Hub liest `\$$name` zur Anfragezeit.';
}
@override
String get systemAiTestConnection => 'Verbindung testen';
@override
String get systemAiTesting => 'Teste…';
@override
String get systemAiSave => 'Speichern';
@override
String get systemAiPrivacyHeader => 'PRIVACY-MODUS';
@override
String get systemAiPrivacyOffLabel => 'Aus';
@override
String get systemAiPrivacyOffDesc =>
'Feature deaktiviert. Keine Anfragen verlassen den Hub.';
@override
String get systemAiPrivacyRedactedLabel => 'Redigiert';
@override
String get systemAiPrivacyRedactedDesc =>
'Nur event_type / error / Modul-Namen. KRITIS-freundlicher Standard.';
@override
String get systemAiPrivacyFullLabel => 'Voll';
@override
String get systemAiPrivacyFullDesc =>
'Enthält das Audit-Detail-JSON (nur Hash — keine Roh-Payloads).';
@override
String get systemAiConnectionOk => 'Verbindung ok';
@override
String get systemAiConnectionFailed => 'Verbindung fehlgeschlagen';
@override
String systemAiReplyPrefix(String text) {
return 'Antwort: $text';
}
@override
String get systemAiModelLabel => 'Modell (erforderlich)';
@override
String get systemAiModelHintFallback =>
'Modell-Identifier, den der Provider erwartet';
@override
String get systemAiModelHelperBase =>
'Erforderlich: aus der Liste auswählen (Aktualisieren) oder eintippen.';
@override
String get systemAiModelHelperOllama =>
'Erforderlich: aus der Liste auswählen (Aktualisieren) oder eintippen. Mit Pull von Ollama herunterladen.';
@override
String get systemAiRefresh => 'Aktualisieren';
@override
String get systemAiPull => 'Pull';
@override
String get systemAiPulling => 'Lade…';
@override
String systemAiCouldNotListModels(String error) {
return 'Modelle konnten nicht aufgelistet werden: $error';
}
@override
String get systemAiNoModelsOllama =>
'Noch keine Modelle auf dem Ollama-Server. Oben eintippen und Pull klicken.';
@override
String get systemAiNoModelsGeneric => 'Provider lieferte keine Modelle.';
@override
String get systemAiSuitabilityRecommended => 'empfohlen';
@override
String get systemAiSuitabilityBalanced => 'ausgewogen';
@override
String get systemAiSuitabilitySmall => 'klein — Qualität evtl. eingeschränkt';
@override
String get systemAiSuitabilityLarge => 'groß — langsamer';
@override
String get systemAiSuitabilityHuge =>
'sehr groß — auf einem Laptop wahrscheinlich zu langsam';
@override
String get systemAiSuitabilityUnknown => 'Größe unbekannt';
@override
String systemAiHwDetected(String summary) {
return 'Erkannt: $summary';
}
@override
String systemAiHwReviewed(String date) {
return ' · Kuratierung geprüft $date';
}
@override
String systemAiLegendRecommended(String tier) {
return 'empfohlen für diese Hardware$tier';
}
@override
String get systemAiLegendBalanced => 'ausgewogen (4-8B)';
@override
String get systemAiLegendSmallLarge =>
'klein <3B / groß 9-15B / über Hardware';
@override
String get systemAiLegendHuge => 'sehr groß >15B';
@override
String get systemAiLegendUnknown => 'Größe unbekannt';
@override
String systemAiCacheRow(int n) {
String _temp0 = intl.Intl.pluralLogic(
n,
locale: localeName,
other: 'gespeicherte Erklärungen',
one: 'gespeicherte Erklärung',
);
return 'Cache: $n $_temp0. Identische Prompts treffen den Cache; Modell- oder Privacy-Modus-Wechsel leeren ihn automatisch.';
}
@override
String get systemAiCacheClear => 'Leeren';
@override
String systemAiCacheClearedToast(int n) {
return '$n gespeicherte System-AI-Erklärungen gelöscht.';
}
@override
String systemAiCacheClearFailed(String error) {
return 'Cache-Löschen fehlgeschlagen: $error';
}
@override
String get systemAiPullEmptyError =>
'Erst eine Modell-ID eintippen (z.B. gemma3:4b).';
@override
String systemAiPullFailedError(String error) {
return 'Pull fehlgeschlagen: $error';
}
}