feat(studio): Doctor + Modules localized + sparse-store federation nudge (v0.25.0)
Two threads.
Translation expansion: every visible string on the Doctor
page (section headers, status text, button labels, daemon-
control card, daemon-files panel, update banner) and the
Modules page (recent-activity strip, capabilities label,
uninstall dialog + toast) flips between DE and EN with the
sidebar toggle. Adds ~50 ARB keys split between
`app_en.arb` / `app_de.arb`. Pluralised + parametrised
strings (`{n} events verified`, `Running on {name}: {endpoint}`)
use the standard ICU placeholder syntax so future locales
slot in without code changes.
Sparse-store federation nudge: the Store page renders an
inline banner above the grid when the operator has zero
federated entries — single biggest store-fullness lever is
configuring an MCP server / n8n endpoint, so the banner
says exactly that and the button opens Settings straight
to the editor. Banner dismisses automatically the next
render after a federated entry appears.
Coverage stand for translation: Doctor + Modules + sidebar
+ page titles + nav + Cmd+K labels are bilingual. Settings
dialog, Approvals cards, Audit drilldown, MCP/n8n editors,
Store search hint + filter chips remain English-literal.
The infrastructure (ARB plumbing, generator hookup,
locale-notifier) means each follow-up surface is a
one-line ARB edit + one call-site swap.
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
parent
ee83eb851a
commit
349619d68e
11 changed files with 1091 additions and 80 deletions
|
|
@ -61,6 +61,9 @@
|
|||
"@storeNResults": {
|
||||
"placeholders": { "n": { "type": "int" } }
|
||||
},
|
||||
"storeFederationNudgeTitle": "Mehr Capabilities?",
|
||||
"storeFederationNudgeBody": "MCP-Server oder n8n-Endpunkt unter Einstellungen → MCP-Clients / N8N-Endpunkte konfigurieren. Entdeckte Tools und Workflows tauchen hier als `mcp.<server>.<tool>`- und `n8n.<endpoint>.<workflow>`-Capabilities auf — jeder Anthropic-/Community-MCP-Server bringt mehrere auf einmal.",
|
||||
"storeFederationNudgeButton": "Einstellungen öffnen",
|
||||
|
||||
"auditTitle": "Protokoll",
|
||||
"auditNoEvents": "Noch keine Ereignisse",
|
||||
|
|
@ -68,7 +71,32 @@
|
|||
|
||||
"modulesTitle": "Module",
|
||||
"modulesNoneTitle": "Noch keine Module",
|
||||
"modulesNoneHint": "`fai install <capability-name>` ausführen oder ~/.fai/modules/ prüfen.",
|
||||
"modulesReloadTooltip": "Aktualisieren",
|
||||
"modulesRecentActivity": "LETZTE AKTIVITÄT",
|
||||
"modulesRecentActivityHint": "letzte {n} install/uninstall-Ereignisse aus dem Audit-Log",
|
||||
"@modulesRecentActivityHint": { "placeholders": { "n": { "type": "int" } } },
|
||||
"modulesActivityInstalled": "installiert",
|
||||
"modulesActivityUninstalled": "deinstalliert",
|
||||
"modulesCapabilitiesLabel": "Capabilities",
|
||||
"modulesUninstallTitle": "Modul deinstallieren?",
|
||||
"modulesUninstallBody": "Entfernt {name} v{version} von diesem Hub. Flows, die es verwenden, schlagen beim nächsten Lauf fehl. Ein `module.uninstalled`-Audit-Event wird festgehalten.",
|
||||
"@modulesUninstallBody": {
|
||||
"placeholders": {
|
||||
"name": { "type": "String" },
|
||||
"version": { "type": "String" }
|
||||
}
|
||||
},
|
||||
"modulesUninstalledToast": "{name} v{version} deinstalliert.",
|
||||
"@modulesUninstalledToast": {
|
||||
"placeholders": {
|
||||
"name": { "type": "String" },
|
||||
"version": { "type": "String" }
|
||||
}
|
||||
},
|
||||
"modulesUninstallFailed": "Deinstallation fehlgeschlagen: {error}",
|
||||
"@modulesUninstallFailed": { "placeholders": { "error": { "type": "String" } } },
|
||||
"modulesUninstalling": "Wird deinstalliert…",
|
||||
|
||||
"approvalsTitle": "Freigaben",
|
||||
"approvalsTabPending": "Offen",
|
||||
|
|
@ -77,6 +105,73 @@
|
|||
"approvalsInboxHint": "Alles erledigt. Neue `system.approval@^0`-Schritte landen automatisch hier.",
|
||||
|
||||
"doctorTitle": "Diagnose",
|
||||
"doctorRecheckTooltip": "Erneut prüfen",
|
||||
"doctorEventLogSection": "Audit-Log",
|
||||
"doctorModulesApprovalsSection": "Module & Freigaben",
|
||||
"doctorHostServicesSection": "Host-Dienste",
|
||||
"doctorDaemonFilesSection": "Daemon-Dateien",
|
||||
"doctorDaemonControlSection": "Daemon-Steuerung",
|
||||
"doctorChainIntact": "Hash-Chain intakt",
|
||||
"doctorChainIntactDetail": "{n} Ereignisse · prev_event_sha256 lückenlos verifiziert",
|
||||
"@doctorChainIntactDetail": { "placeholders": { "n": { "type": "int" } } },
|
||||
"doctorChainTampered": "Manipulation erkannt",
|
||||
"doctorChainTamperedDetail": "{verified} von {total} verifiziert vor Mismatch bei {id}",
|
||||
"@doctorChainTamperedDetail": {
|
||||
"placeholders": {
|
||||
"verified": { "type": "int" },
|
||||
"total": { "type": "int" },
|
||||
"id": { "type": "String" }
|
||||
}
|
||||
},
|
||||
"doctorChainPillOk": "WORM-1",
|
||||
"doctorChainPillTamper": "MANIPULIERT",
|
||||
"doctorVerifyNow": "Jetzt prüfen",
|
||||
"doctorRestart": "Neustart",
|
||||
"doctorStart": "Starten",
|
||||
"doctorStop": "Stoppen",
|
||||
"doctorStatusAction": "Status",
|
||||
"doctorRunningOn": "Läuft auf {name}: {endpoint}",
|
||||
"@doctorRunningOn": {
|
||||
"placeholders": {
|
||||
"name": { "type": "String" },
|
||||
"endpoint": { "type": "String" }
|
||||
}
|
||||
},
|
||||
"doctorStoppedOn": "{name}-Daemon gestoppt",
|
||||
"@doctorStoppedOn": { "placeholders": { "name": { "type": "String" } } },
|
||||
"doctorStatusUnknown": "Daemon-Status: …",
|
||||
"doctorPillRunning": "läuft",
|
||||
"doctorPillStopped": "gestoppt",
|
||||
"doctorDaemonControlHint": "Studio ruft das Platform-Binary auf — entspricht `fai daemon …`, sodass CLI und UI im Gleichschritt bleiben.",
|
||||
"doctorDaemonControlWorking": "Wird ausgeführt…",
|
||||
"doctorPathLog": "Log",
|
||||
"doctorPathConfig": "Konfig",
|
||||
"doctorPathDb": "Audit-DB",
|
||||
"doctorPathModules": "Module-Verzeichnis",
|
||||
"doctorPathFlows": "Flow-Verzeichnis",
|
||||
"doctorPathPid": "PID-Datei",
|
||||
"doctorPathsEmpty": "Daemon hat keine Datei-Pfade gemeldet. Hub aktualisieren via `fai daemon restart`.",
|
||||
"doctorOpenError": "Konnte nicht öffnen: {detail}",
|
||||
"@doctorOpenError": { "placeholders": { "detail": { "type": "String" } } },
|
||||
"doctorUpdateAvailable": "Update verfügbar — {version}",
|
||||
"@doctorUpdateAvailable": { "placeholders": { "version": { "type": "String" } } },
|
||||
"doctorUpdateBody": "Kanal {channel} bietet jetzt {version}. Per Button anwenden — Studio ruft `fai update apply --channel {channel}` auf.",
|
||||
"@doctorUpdateBody": {
|
||||
"placeholders": {
|
||||
"channel": { "type": "String" },
|
||||
"version": { "type": "String" }
|
||||
}
|
||||
},
|
||||
"doctorUpdateUnreachable": "Release-Host nicht erreichbar",
|
||||
"doctorUpdateUnreachableBody": "Release-Feed für {channel} konnte nicht erreicht werden.",
|
||||
"@doctorUpdateUnreachableBody": { "placeholders": { "channel": { "type": "String" } } },
|
||||
"doctorReleaseNotes": "Notes: {url}",
|
||||
"@doctorReleaseNotes": { "placeholders": { "url": { "type": "String" } } },
|
||||
"doctorPillNew": "neu",
|
||||
"doctorPillOffline": "offline",
|
||||
"doctorApplyUpdate": "Update anwenden",
|
||||
"doctorApplying": "Wird angewendet…",
|
||||
"doctorApplyDone": "Update angewendet. Studio neu starten, um die neue Daemon-Version zu sehen.",
|
||||
|
||||
"mcpHeader": "MCP-CLIENTS",
|
||||
"mcpHint": "Externe MCP-Server bringen ihre Tools als `mcp.<server>.<tool>` Capabilities ein. Einmal konfigurieren, im Store sichtbar.",
|
||||
|
|
|
|||
|
|
@ -62,6 +62,9 @@
|
|||
"@storeNResults": {
|
||||
"placeholders": { "n": { "type": "int" } }
|
||||
},
|
||||
"storeFederationNudgeTitle": "Want more capabilities?",
|
||||
"storeFederationNudgeBody": "Configure an MCP server or n8n endpoint in Settings → MCP Clients / N8N Endpoints. Discovered tools and workflows surface here as `mcp.<server>.<tool>` and `n8n.<endpoint>.<workflow>` capabilities — every Anthropic / community MCP server adds a handful at once.",
|
||||
"storeFederationNudgeButton": "Open Settings",
|
||||
|
||||
"auditTitle": "Audit",
|
||||
"auditNoEvents": "No events yet",
|
||||
|
|
@ -69,7 +72,32 @@
|
|||
|
||||
"modulesTitle": "Modules",
|
||||
"modulesNoneTitle": "No modules yet",
|
||||
"modulesNoneHint": "Run `fai install <capability-name>` or check ~/.fai/modules/.",
|
||||
"modulesReloadTooltip": "Reload",
|
||||
"modulesRecentActivity": "RECENT ACTIVITY",
|
||||
"modulesRecentActivityHint": "last {n} install/uninstall events from the audit log",
|
||||
"@modulesRecentActivityHint": { "placeholders": { "n": { "type": "int" } } },
|
||||
"modulesActivityInstalled": "installed",
|
||||
"modulesActivityUninstalled": "uninstalled",
|
||||
"modulesCapabilitiesLabel": "Capabilities",
|
||||
"modulesUninstallTitle": "Uninstall module?",
|
||||
"modulesUninstallBody": "Removes {name} v{version} from this hub. Flows that reference it will fail at the next run. A `module.uninstalled` audit event is recorded.",
|
||||
"@modulesUninstallBody": {
|
||||
"placeholders": {
|
||||
"name": { "type": "String" },
|
||||
"version": { "type": "String" }
|
||||
}
|
||||
},
|
||||
"modulesUninstalledToast": "Uninstalled {name} v{version}.",
|
||||
"@modulesUninstalledToast": {
|
||||
"placeholders": {
|
||||
"name": { "type": "String" },
|
||||
"version": { "type": "String" }
|
||||
}
|
||||
},
|
||||
"modulesUninstallFailed": "Uninstall failed: {error}",
|
||||
"@modulesUninstallFailed": { "placeholders": { "error": { "type": "String" } } },
|
||||
"modulesUninstalling": "Uninstalling…",
|
||||
|
||||
"approvalsTitle": "Approvals",
|
||||
"approvalsTabPending": "Pending",
|
||||
|
|
@ -78,6 +106,73 @@
|
|||
"approvalsInboxHint": "All caught up. New `system.approval@^0` steps land here automatically.",
|
||||
|
||||
"doctorTitle": "Doctor",
|
||||
"doctorRecheckTooltip": "Re-check",
|
||||
"doctorEventLogSection": "Event log",
|
||||
"doctorModulesApprovalsSection": "Modules & approvals",
|
||||
"doctorHostServicesSection": "Host services",
|
||||
"doctorDaemonFilesSection": "Daemon files",
|
||||
"doctorDaemonControlSection": "Daemon control",
|
||||
"doctorChainIntact": "Hash chain intact",
|
||||
"doctorChainIntactDetail": "{n} events · prev_event_sha256 verified end-to-end",
|
||||
"@doctorChainIntactDetail": { "placeholders": { "n": { "type": "int" } } },
|
||||
"doctorChainTampered": "Tampering detected",
|
||||
"doctorChainTamperedDetail": "{verified} of {total} verified before mismatch at {id}",
|
||||
"@doctorChainTamperedDetail": {
|
||||
"placeholders": {
|
||||
"verified": { "type": "int" },
|
||||
"total": { "type": "int" },
|
||||
"id": { "type": "String" }
|
||||
}
|
||||
},
|
||||
"doctorChainPillOk": "WORM-1",
|
||||
"doctorChainPillTamper": "TAMPER",
|
||||
"doctorVerifyNow": "Verify now",
|
||||
"doctorRestart": "Restart",
|
||||
"doctorStart": "Start",
|
||||
"doctorStop": "Stop",
|
||||
"doctorStatusAction": "Status",
|
||||
"doctorRunningOn": "Running on {name}: {endpoint}",
|
||||
"@doctorRunningOn": {
|
||||
"placeholders": {
|
||||
"name": { "type": "String" },
|
||||
"endpoint": { "type": "String" }
|
||||
}
|
||||
},
|
||||
"doctorStoppedOn": "{name} daemon stopped",
|
||||
"@doctorStoppedOn": { "placeholders": { "name": { "type": "String" } } },
|
||||
"doctorStatusUnknown": "Daemon status: …",
|
||||
"doctorPillRunning": "running",
|
||||
"doctorPillStopped": "stopped",
|
||||
"doctorDaemonControlHint": "Studio shells out to the platform binary — mirrors `fai daemon …` exactly so the CLI and UI stay in lockstep.",
|
||||
"doctorDaemonControlWorking": "Working…",
|
||||
"doctorPathLog": "Log",
|
||||
"doctorPathConfig": "Config",
|
||||
"doctorPathDb": "Audit DB",
|
||||
"doctorPathModules": "Modules dir",
|
||||
"doctorPathFlows": "Flows dir",
|
||||
"doctorPathPid": "PID file",
|
||||
"doctorPathsEmpty": "Daemon did not report file paths. Update the running hub via `fai daemon restart`.",
|
||||
"doctorOpenError": "Could not open: {detail}",
|
||||
"@doctorOpenError": { "placeholders": { "detail": { "type": "String" } } },
|
||||
"doctorUpdateAvailable": "Update available — {version}",
|
||||
"@doctorUpdateAvailable": { "placeholders": { "version": { "type": "String" } } },
|
||||
"doctorUpdateBody": "Channel {channel} now offers {version}. Apply via the button — Studio shells out to `fai update apply --channel {channel}`.",
|
||||
"@doctorUpdateBody": {
|
||||
"placeholders": {
|
||||
"channel": { "type": "String" },
|
||||
"version": { "type": "String" }
|
||||
}
|
||||
},
|
||||
"doctorUpdateUnreachable": "Release host unreachable",
|
||||
"doctorUpdateUnreachableBody": "Could not contact the release feed for {channel}.",
|
||||
"@doctorUpdateUnreachableBody": { "placeholders": { "channel": { "type": "String" } } },
|
||||
"doctorReleaseNotes": "notes: {url}",
|
||||
"@doctorReleaseNotes": { "placeholders": { "url": { "type": "String" } } },
|
||||
"doctorPillNew": "new",
|
||||
"doctorPillOffline": "offline",
|
||||
"doctorApplyUpdate": "Apply update",
|
||||
"doctorApplying": "Applying…",
|
||||
"doctorApplyDone": "Update applied. Restart Studio to see the new daemon version.",
|
||||
|
||||
"mcpHeader": "MCP CLIENTS",
|
||||
"mcpHint": "External MCP servers federate their tools as `mcp.<server>.<tool>` capabilities. Configure once, see them in the Store.",
|
||||
|
|
|
|||
|
|
@ -404,6 +404,24 @@ abstract class AppLocalizations {
|
|||
/// **'{n} result{n, plural, =1{} other{s}}'**
|
||||
String storeNResults(int n);
|
||||
|
||||
/// No description provided for @storeFederationNudgeTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Want more capabilities?'**
|
||||
String get storeFederationNudgeTitle;
|
||||
|
||||
/// No description provided for @storeFederationNudgeBody.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Configure an MCP server or n8n endpoint in Settings → MCP Clients / N8N Endpoints. Discovered tools and workflows surface here as `mcp.<server>.<tool>` and `n8n.<endpoint>.<workflow>` capabilities — every Anthropic / community MCP server adds a handful at once.'**
|
||||
String get storeFederationNudgeBody;
|
||||
|
||||
/// No description provided for @storeFederationNudgeButton.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Open Settings'**
|
||||
String get storeFederationNudgeButton;
|
||||
|
||||
/// No description provided for @auditTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
|
@ -434,12 +452,78 @@ abstract class AppLocalizations {
|
|||
/// **'No modules yet'**
|
||||
String get modulesNoneTitle;
|
||||
|
||||
/// No description provided for @modulesNoneHint.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Run `fai install <capability-name>` or check ~/.fai/modules/.'**
|
||||
String get modulesNoneHint;
|
||||
|
||||
/// No description provided for @modulesReloadTooltip.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Reload'**
|
||||
String get modulesReloadTooltip;
|
||||
|
||||
/// No description provided for @modulesRecentActivity.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'RECENT ACTIVITY'**
|
||||
String get modulesRecentActivity;
|
||||
|
||||
/// No description provided for @modulesRecentActivityHint.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'last {n} install/uninstall events from the audit log'**
|
||||
String modulesRecentActivityHint(int n);
|
||||
|
||||
/// No description provided for @modulesActivityInstalled.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'installed'**
|
||||
String get modulesActivityInstalled;
|
||||
|
||||
/// No description provided for @modulesActivityUninstalled.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'uninstalled'**
|
||||
String get modulesActivityUninstalled;
|
||||
|
||||
/// No description provided for @modulesCapabilitiesLabel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Capabilities'**
|
||||
String get modulesCapabilitiesLabel;
|
||||
|
||||
/// No description provided for @modulesUninstallTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Uninstall module?'**
|
||||
String get modulesUninstallTitle;
|
||||
|
||||
/// No description provided for @modulesUninstallBody.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Removes {name} v{version} from this hub. Flows that reference it will fail at the next run. A `module.uninstalled` audit event is recorded.'**
|
||||
String modulesUninstallBody(String name, String version);
|
||||
|
||||
/// No description provided for @modulesUninstalledToast.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Uninstalled {name} v{version}.'**
|
||||
String modulesUninstalledToast(String name, String version);
|
||||
|
||||
/// No description provided for @modulesUninstallFailed.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Uninstall failed: {error}'**
|
||||
String modulesUninstallFailed(String error);
|
||||
|
||||
/// No description provided for @modulesUninstalling.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Uninstalling…'**
|
||||
String get modulesUninstalling;
|
||||
|
||||
/// No description provided for @approvalsTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
|
@ -476,6 +560,258 @@ abstract class AppLocalizations {
|
|||
/// **'Doctor'**
|
||||
String get doctorTitle;
|
||||
|
||||
/// No description provided for @doctorRecheckTooltip.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Re-check'**
|
||||
String get doctorRecheckTooltip;
|
||||
|
||||
/// No description provided for @doctorEventLogSection.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Event log'**
|
||||
String get doctorEventLogSection;
|
||||
|
||||
/// No description provided for @doctorModulesApprovalsSection.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Modules & approvals'**
|
||||
String get doctorModulesApprovalsSection;
|
||||
|
||||
/// No description provided for @doctorHostServicesSection.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Host services'**
|
||||
String get doctorHostServicesSection;
|
||||
|
||||
/// No description provided for @doctorDaemonFilesSection.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Daemon files'**
|
||||
String get doctorDaemonFilesSection;
|
||||
|
||||
/// No description provided for @doctorDaemonControlSection.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Daemon control'**
|
||||
String get doctorDaemonControlSection;
|
||||
|
||||
/// No description provided for @doctorChainIntact.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Hash chain intact'**
|
||||
String get doctorChainIntact;
|
||||
|
||||
/// No description provided for @doctorChainIntactDetail.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'{n} events · prev_event_sha256 verified end-to-end'**
|
||||
String doctorChainIntactDetail(int n);
|
||||
|
||||
/// No description provided for @doctorChainTampered.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Tampering detected'**
|
||||
String get doctorChainTampered;
|
||||
|
||||
/// No description provided for @doctorChainTamperedDetail.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'{verified} of {total} verified before mismatch at {id}'**
|
||||
String doctorChainTamperedDetail(int verified, int total, String id);
|
||||
|
||||
/// No description provided for @doctorChainPillOk.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'WORM-1'**
|
||||
String get doctorChainPillOk;
|
||||
|
||||
/// No description provided for @doctorChainPillTamper.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'TAMPER'**
|
||||
String get doctorChainPillTamper;
|
||||
|
||||
/// No description provided for @doctorVerifyNow.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Verify now'**
|
||||
String get doctorVerifyNow;
|
||||
|
||||
/// No description provided for @doctorRestart.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Restart'**
|
||||
String get doctorRestart;
|
||||
|
||||
/// No description provided for @doctorStart.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Start'**
|
||||
String get doctorStart;
|
||||
|
||||
/// No description provided for @doctorStop.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Stop'**
|
||||
String get doctorStop;
|
||||
|
||||
/// No description provided for @doctorStatusAction.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Status'**
|
||||
String get doctorStatusAction;
|
||||
|
||||
/// No description provided for @doctorRunningOn.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Running on {name}: {endpoint}'**
|
||||
String doctorRunningOn(String name, String endpoint);
|
||||
|
||||
/// No description provided for @doctorStoppedOn.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'{name} daemon stopped'**
|
||||
String doctorStoppedOn(String name);
|
||||
|
||||
/// No description provided for @doctorStatusUnknown.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Daemon status: …'**
|
||||
String get doctorStatusUnknown;
|
||||
|
||||
/// No description provided for @doctorPillRunning.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'running'**
|
||||
String get doctorPillRunning;
|
||||
|
||||
/// No description provided for @doctorPillStopped.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'stopped'**
|
||||
String get doctorPillStopped;
|
||||
|
||||
/// No description provided for @doctorDaemonControlHint.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Studio shells out to the platform binary — mirrors `fai daemon …` exactly so the CLI and UI stay in lockstep.'**
|
||||
String get doctorDaemonControlHint;
|
||||
|
||||
/// No description provided for @doctorDaemonControlWorking.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Working…'**
|
||||
String get doctorDaemonControlWorking;
|
||||
|
||||
/// No description provided for @doctorPathLog.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Log'**
|
||||
String get doctorPathLog;
|
||||
|
||||
/// No description provided for @doctorPathConfig.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Config'**
|
||||
String get doctorPathConfig;
|
||||
|
||||
/// No description provided for @doctorPathDb.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Audit DB'**
|
||||
String get doctorPathDb;
|
||||
|
||||
/// No description provided for @doctorPathModules.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Modules dir'**
|
||||
String get doctorPathModules;
|
||||
|
||||
/// No description provided for @doctorPathFlows.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Flows dir'**
|
||||
String get doctorPathFlows;
|
||||
|
||||
/// No description provided for @doctorPathPid.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'PID file'**
|
||||
String get doctorPathPid;
|
||||
|
||||
/// No description provided for @doctorPathsEmpty.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Daemon did not report file paths. Update the running hub via `fai daemon restart`.'**
|
||||
String get doctorPathsEmpty;
|
||||
|
||||
/// No description provided for @doctorOpenError.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Could not open: {detail}'**
|
||||
String doctorOpenError(String detail);
|
||||
|
||||
/// No description provided for @doctorUpdateAvailable.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Update available — {version}'**
|
||||
String doctorUpdateAvailable(String version);
|
||||
|
||||
/// No description provided for @doctorUpdateBody.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Channel {channel} now offers {version}. Apply via the button — Studio shells out to `fai update apply --channel {channel}`.'**
|
||||
String doctorUpdateBody(String channel, String version);
|
||||
|
||||
/// No description provided for @doctorUpdateUnreachable.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Release host unreachable'**
|
||||
String get doctorUpdateUnreachable;
|
||||
|
||||
/// No description provided for @doctorUpdateUnreachableBody.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Could not contact the release feed for {channel}.'**
|
||||
String doctorUpdateUnreachableBody(String channel);
|
||||
|
||||
/// No description provided for @doctorReleaseNotes.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'notes: {url}'**
|
||||
String doctorReleaseNotes(String url);
|
||||
|
||||
/// No description provided for @doctorPillNew.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'new'**
|
||||
String get doctorPillNew;
|
||||
|
||||
/// No description provided for @doctorPillOffline.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'offline'**
|
||||
String get doctorPillOffline;
|
||||
|
||||
/// No description provided for @doctorApplyUpdate.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Apply update'**
|
||||
String get doctorApplyUpdate;
|
||||
|
||||
/// No description provided for @doctorApplying.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Applying…'**
|
||||
String get doctorApplying;
|
||||
|
||||
/// No description provided for @doctorApplyDone.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Update applied. Restart Studio to see the new daemon version.'**
|
||||
String get doctorApplyDone;
|
||||
|
||||
/// No description provided for @mcpHeader.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
|
|
|||
|
|
@ -166,6 +166,16 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||
return '$n Treffer';
|
||||
}
|
||||
|
||||
@override
|
||||
String get storeFederationNudgeTitle => 'Mehr Capabilities?';
|
||||
|
||||
@override
|
||||
String get storeFederationNudgeBody =>
|
||||
'MCP-Server oder n8n-Endpunkt unter Einstellungen → MCP-Clients / N8N-Endpunkte konfigurieren. Entdeckte Tools und Workflows tauchen hier als `mcp.<server>.<tool>`- und `n8n.<endpoint>.<workflow>`-Capabilities auf — jeder Anthropic-/Community-MCP-Server bringt mehrere auf einmal.';
|
||||
|
||||
@override
|
||||
String get storeFederationNudgeButton => 'Einstellungen öffnen';
|
||||
|
||||
@override
|
||||
String get auditTitle => 'Protokoll';
|
||||
|
||||
|
|
@ -182,9 +192,51 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||
@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 get approvalsTitle => 'Freigaben';
|
||||
|
||||
|
|
@ -204,6 +256,153 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||
@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';
|
||||
|
||||
|
|
|
|||
|
|
@ -172,6 +172,16 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||
return '$n result$_temp0';
|
||||
}
|
||||
|
||||
@override
|
||||
String get storeFederationNudgeTitle => 'Want more capabilities?';
|
||||
|
||||
@override
|
||||
String get storeFederationNudgeBody =>
|
||||
'Configure an MCP server or n8n endpoint in Settings → MCP Clients / N8N Endpoints. Discovered tools and workflows surface here as `mcp.<server>.<tool>` and `n8n.<endpoint>.<workflow>` capabilities — every Anthropic / community MCP server adds a handful at once.';
|
||||
|
||||
@override
|
||||
String get storeFederationNudgeButton => 'Open Settings';
|
||||
|
||||
@override
|
||||
String get auditTitle => 'Audit';
|
||||
|
||||
|
|
@ -188,9 +198,51 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||
@override
|
||||
String get modulesNoneTitle => 'No modules yet';
|
||||
|
||||
@override
|
||||
String get modulesNoneHint =>
|
||||
'Run `fai install <capability-name>` or check ~/.fai/modules/.';
|
||||
|
||||
@override
|
||||
String get modulesReloadTooltip => 'Reload';
|
||||
|
||||
@override
|
||||
String get modulesRecentActivity => 'RECENT ACTIVITY';
|
||||
|
||||
@override
|
||||
String modulesRecentActivityHint(int n) {
|
||||
return 'last $n install/uninstall events from the audit log';
|
||||
}
|
||||
|
||||
@override
|
||||
String get modulesActivityInstalled => 'installed';
|
||||
|
||||
@override
|
||||
String get modulesActivityUninstalled => 'uninstalled';
|
||||
|
||||
@override
|
||||
String get modulesCapabilitiesLabel => 'Capabilities';
|
||||
|
||||
@override
|
||||
String get modulesUninstallTitle => 'Uninstall module?';
|
||||
|
||||
@override
|
||||
String modulesUninstallBody(String name, String version) {
|
||||
return 'Removes $name v$version from this hub. Flows that reference it will fail at the next run. A `module.uninstalled` audit event is recorded.';
|
||||
}
|
||||
|
||||
@override
|
||||
String modulesUninstalledToast(String name, String version) {
|
||||
return 'Uninstalled $name v$version.';
|
||||
}
|
||||
|
||||
@override
|
||||
String modulesUninstallFailed(String error) {
|
||||
return 'Uninstall failed: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get modulesUninstalling => 'Uninstalling…';
|
||||
|
||||
@override
|
||||
String get approvalsTitle => 'Approvals';
|
||||
|
||||
|
|
@ -210,6 +262,153 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||
@override
|
||||
String get doctorTitle => 'Doctor';
|
||||
|
||||
@override
|
||||
String get doctorRecheckTooltip => 'Re-check';
|
||||
|
||||
@override
|
||||
String get doctorEventLogSection => 'Event log';
|
||||
|
||||
@override
|
||||
String get doctorModulesApprovalsSection => 'Modules & approvals';
|
||||
|
||||
@override
|
||||
String get doctorHostServicesSection => 'Host services';
|
||||
|
||||
@override
|
||||
String get doctorDaemonFilesSection => 'Daemon files';
|
||||
|
||||
@override
|
||||
String get doctorDaemonControlSection => 'Daemon control';
|
||||
|
||||
@override
|
||||
String get doctorChainIntact => 'Hash chain intact';
|
||||
|
||||
@override
|
||||
String doctorChainIntactDetail(int n) {
|
||||
return '$n events · prev_event_sha256 verified end-to-end';
|
||||
}
|
||||
|
||||
@override
|
||||
String get doctorChainTampered => 'Tampering detected';
|
||||
|
||||
@override
|
||||
String doctorChainTamperedDetail(int verified, int total, String id) {
|
||||
return '$verified of $total verified before mismatch at $id';
|
||||
}
|
||||
|
||||
@override
|
||||
String get doctorChainPillOk => 'WORM-1';
|
||||
|
||||
@override
|
||||
String get doctorChainPillTamper => 'TAMPER';
|
||||
|
||||
@override
|
||||
String get doctorVerifyNow => 'Verify now';
|
||||
|
||||
@override
|
||||
String get doctorRestart => 'Restart';
|
||||
|
||||
@override
|
||||
String get doctorStart => 'Start';
|
||||
|
||||
@override
|
||||
String get doctorStop => 'Stop';
|
||||
|
||||
@override
|
||||
String get doctorStatusAction => 'Status';
|
||||
|
||||
@override
|
||||
String doctorRunningOn(String name, String endpoint) {
|
||||
return 'Running on $name: $endpoint';
|
||||
}
|
||||
|
||||
@override
|
||||
String doctorStoppedOn(String name) {
|
||||
return '$name daemon stopped';
|
||||
}
|
||||
|
||||
@override
|
||||
String get doctorStatusUnknown => 'Daemon status: …';
|
||||
|
||||
@override
|
||||
String get doctorPillRunning => 'running';
|
||||
|
||||
@override
|
||||
String get doctorPillStopped => 'stopped';
|
||||
|
||||
@override
|
||||
String get doctorDaemonControlHint =>
|
||||
'Studio shells out to the platform binary — mirrors `fai daemon …` exactly so the CLI and UI stay in lockstep.';
|
||||
|
||||
@override
|
||||
String get doctorDaemonControlWorking => 'Working…';
|
||||
|
||||
@override
|
||||
String get doctorPathLog => 'Log';
|
||||
|
||||
@override
|
||||
String get doctorPathConfig => 'Config';
|
||||
|
||||
@override
|
||||
String get doctorPathDb => 'Audit DB';
|
||||
|
||||
@override
|
||||
String get doctorPathModules => 'Modules dir';
|
||||
|
||||
@override
|
||||
String get doctorPathFlows => 'Flows dir';
|
||||
|
||||
@override
|
||||
String get doctorPathPid => 'PID file';
|
||||
|
||||
@override
|
||||
String get doctorPathsEmpty =>
|
||||
'Daemon did not report file paths. Update the running hub via `fai daemon restart`.';
|
||||
|
||||
@override
|
||||
String doctorOpenError(String detail) {
|
||||
return 'Could not open: $detail';
|
||||
}
|
||||
|
||||
@override
|
||||
String doctorUpdateAvailable(String version) {
|
||||
return 'Update available — $version';
|
||||
}
|
||||
|
||||
@override
|
||||
String doctorUpdateBody(String channel, String version) {
|
||||
return 'Channel $channel now offers $version. Apply via the button — Studio shells out to `fai update apply --channel $channel`.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get doctorUpdateUnreachable => 'Release host unreachable';
|
||||
|
||||
@override
|
||||
String doctorUpdateUnreachableBody(String channel) {
|
||||
return 'Could not contact the release feed for $channel.';
|
||||
}
|
||||
|
||||
@override
|
||||
String doctorReleaseNotes(String url) {
|
||||
return 'notes: $url';
|
||||
}
|
||||
|
||||
@override
|
||||
String get doctorPillNew => 'new';
|
||||
|
||||
@override
|
||||
String get doctorPillOffline => 'offline';
|
||||
|
||||
@override
|
||||
String get doctorApplyUpdate => 'Apply update';
|
||||
|
||||
@override
|
||||
String get doctorApplying => 'Applying…';
|
||||
|
||||
@override
|
||||
String get doctorApplyDone =>
|
||||
'Update applied. Restart Studio to see the new daemon version.';
|
||||
|
||||
@override
|
||||
String get mcpHeader => 'MCP CLIENTS';
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue