feat(studio): MCP suggestions + Approvals/Audit/Settings i18n (v0.26.0)

- Add curated catalogue of 9 official Anthropic MCP servers as
  click-to-prefill chips in the Add-MCP-server dialog. Operator
  still confirms via "Add + discover"; nothing is auto-spawned,
  preserving the regulated-environment trust model.
- Localize Approvals page: pending/history empty states, status
  pills, payload preview, approve/reject toasts, reject dialog,
  history detail dialog, expires-in pill.
- Localize Audit page: filter chips, clear-log dialog and toasts,
  no-events / hub-unreachable empty states, live-status bar with
  pluralized event count, hash-chain-verified badge, System AI
  panel (cached pill, latency, regenerate tooltip, asking
  state), event-detail dialog actions.
- Localize Settings dialog: hub-endpoint section, channel
  blurb + popup-menu items, System AI panel headers and
  off-blurb, MCP/N8N panel headers + pluralized counts +
  refresh/add/remove tooltips, Add-MCP and Add-n8n dialogs
  (intro, suggestions label, all field labels and hints, save
  buttons, toasts).

Field labels that map directly to JSON keys (event_id, flow,
step, module, provider, endpoint, model) stay English by design
— they're technical identifiers, not UI copy.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
flemming-it 2026-05-08 02:38:11 +02:00
parent 349619d68e
commit d25b4c87ae
9 changed files with 2022 additions and 209 deletions

View file

@ -36,6 +36,62 @@
"settingsSaveAndConnect": "Speichern & verbinden",
"settingsLanguage": "Sprache",
"settingsLanguageHint": "Sprache der App. Wirkt auf alle Seiten; mehrsprachige Store-Einträge folgen ebenfalls.",
"settingsHubEndpointHint": "Wohin soll Studio sich verbinden? Standard ist der lokale Hub auf 127.0.0.1:50051.",
"settingsTlsSubtitle": "https/grpc-secure",
"settingsPortError": "Port muss 165535 sein",
"channelsBlurb": "Hub-Kanal wechseln (schreibt ~/.fai/current-channel und startet den Daemon neu). Verbinden ändert nur die Wire von Studio.",
"channelsActionsTooltip": "Kanal-Aktionen",
"systemAiHeader": "SYSTEM-AI",
"systemAiEnabled": "aktiv",
"systemAiOff": "aus",
"systemAiEdit": "Bearbeiten…",
"systemAiConfigure": "Konfigurieren…",
"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.",
"mcpServersCount": "{n} {n, plural, =1{Server} other{Server}}",
"@mcpServersCount": { "placeholders": { "n": { "type": "int" } } },
"mcpRediscoverTooltip": "Discovery neu ausführen",
"mcpAddTooltip": "MCP-Server hinzufügen",
"mcpRemoveTooltip": "Server entfernen",
"mcpToolsCount": "{n} Tools",
"@mcpToolsCount": { "placeholders": { "n": { "type": "int" } } },
"n8nEndpointsCount": "{n} {n, plural, =1{Endpunkt} other{Endpunkte}}",
"@n8nEndpointsCount": { "placeholders": { "n": { "type": "int" } } },
"n8nWorkflowsCount": "{n} Workflows",
"@n8nWorkflowsCount": { "placeholders": { "n": { "type": "int" } } },
"n8nRediscoverTooltip": "Discovery neu ausführen",
"n8nAddTooltip": "n8n-Endpunkt hinzufügen",
"n8nRemoveTooltip": "Endpunkt entfernen",
"addMcpTitle": "MCP-Server hinzufügen",
"addMcpIntro": "Tools, die der Server via `tools/list` anbietet, erscheinen im Store als `mcp.<name>.<tool>`-Capabilities.",
"addMcpSuggestionsLabel": "Vorschläge — zum Vorausfüllen klicken",
"addMcpNameLabel": "Name (keine Punkte)",
"addMcpNameHint": "filesystem",
"addMcpEndpointLabel": "Endpunkt",
"addMcpEndpointHint": "http://127.0.0.1:3001/mcp",
"addMcpApiKeyLabel": "API-Key-Umgebungsvariable (optional)",
"addMcpApiKeyHint": "MCP_FILESYSTEM_TOKEN",
"addMcpNotesLabel": "Notizen (optional)",
"addMcpAddButton": "Hinzufügen + Discovery",
"addN8nTitle": "n8n-Endpunkt hinzufügen",
"addN8nIntro": "Aktive Workflows erscheinen im Store als `n8n.<name>.<workflow_slug>`-Capabilities.",
"addN8nNameLabel": "Name (keine Punkte)",
"addN8nNameHint": "ops",
"addN8nBaseUrlLabel": "Basis-URL (ohne /api/v1)",
"addN8nBaseUrlHint": "https://n8n.example.com",
"addN8nApiKeyLabel": "API-Key-Umgebungsvariable (optional)",
"addN8nApiKeyHint": "N8N_OPS_KEY",
"addN8nNotesLabel": "Notizen (optional)",
"addN8nAddButton": "Hinzufügen + Discovery",
"addedMcpToast": "MCP-Server „{name}\" hinzugefügt.",
"@addedMcpToast": { "placeholders": { "name": { "type": "String" } } },
"addedN8nToast": "n8n-Endpunkt „{name}\" hinzugefügt.",
"@addedN8nToast": { "placeholders": { "name": { "type": "String" } } },
"addFailedToast": "Hinzufügen fehlgeschlagen: {error}",
"@addFailedToast": { "placeholders": { "error": { "type": "String" } } },
"removeFailedToast": "Entfernen fehlgeschlagen: {error}",
"@removeFailedToast": { "placeholders": { "error": { "type": "String" } } },
"refreshFailedToast": "Aktualisieren fehlgeschlagen: {error}",
"@refreshFailedToast": { "placeholders": { "error": { "type": "String" } } },
"channelsHeader": "KANÄLE",
"channelsActive": "aktiv",
@ -68,6 +124,56 @@
"auditTitle": "Protokoll",
"auditNoEvents": "Noch keine Ereignisse",
"auditNoEventsHint": "Starte einen Flow, um den Audit-Stream zu füllen.\nEreignisse erscheinen innerhalb von Sekunden.",
"auditFilterAll": "alle",
"auditFilterFlow": "Flow",
"auditFilterStep": "Step",
"auditFilterModule": "Modul",
"auditClearLogTooltip": "Protokoll löschen (nur local/dev Kanal)",
"auditClearedToast": "{n} Ereignisse auf Kanal „{channel}\" gelöscht. Chain mit Marker neu geseedet.",
"@auditClearedToast": {
"placeholders": {
"n": { "type": "int" },
"channel": { "type": "String" }
}
},
"auditClearFailed": "Löschen fehlgeschlagen: {detail}",
"@auditClearFailed": { "placeholders": { "detail": { "type": "String" } } },
"auditExplain": "Erklären",
"auditReask": "Neu fragen",
"auditAsking": "Frage läuft…",
"auditSystemAi": "SYSTEM-AI",
"auditCachedPill": "gecacht",
"auditOriginalLatency": "ursprünglich {ms} ms",
"@auditOriginalLatency": { "placeholders": { "ms": { "type": "int" } } },
"auditLatency": "{ms} ms",
"@auditLatency": { "placeholders": { "ms": { "type": "int" } } },
"auditRegenerateTooltip": "Neu generieren — Cache überspringen, Modell erneut fragen",
"auditLiveStatus": "live · Abfrage alle 2s · {n} {n, plural, =1{Ereignis} other{Ereignisse}}",
"@auditLiveStatus": { "placeholders": { "n": { "type": "int" } } },
"auditDisconnected": "getrennt · {error}",
"@auditDisconnected": { "placeholders": { "error": { "type": "String" } } },
"auditHashChainVerified": "Hash-Chain verifiziert",
"auditDetailHeader": "DETAIL",
"auditAskingFull": "Frage an die konfigurierte System-AI läuft…",
"auditFixLabel": "FIX",
"auditCachedTooltipKnown": "Aus dem lokalen Cache geliefert. Ursprünglich erzeugt am {at}{hits}.",
"@auditCachedTooltipKnown": {
"placeholders": {
"at": { "type": "String" },
"hits": { "type": "String" }
}
},
"auditCachedTooltipUnknown": "Aus dem lokalen Cache geliefert. Ursprünglicher Zeitpunkt unbekannt{hits}.",
"@auditCachedTooltipUnknown": { "placeholders": { "hits": { "type": "String" } } },
"auditCachedTooltipHits": " · {n} Treffer",
"@auditCachedTooltipHits": { "placeholders": { "n": { "type": "int" } } },
"auditConfigureSystemAi": "System-AI unter Einstellungen konfigurieren (Cmd+,)",
"auditClearDialogTitle": "Audit-Log löschen?",
"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.",
"auditClearReviewerLabel": "Prüfer",
"auditClearReasonLabel": "Begründung (im chain.reset-Marker festgehalten)",
"auditClearReasonHelper": "Erforderlich — Auditoren werden das lesen.",
"auditClearLogButton": "Log löschen",
"modulesTitle": "Module",
"modulesNoneTitle": "Noch keine Module",
@ -103,6 +209,44 @@
"approvalsTabHistory": "Verlauf",
"approvalsInboxZero": "Posteingang leer",
"approvalsInboxHint": "Alles erledigt. Neue `system.approval@^0`-Schritte landen automatisch hier.",
"approvalsReloadTooltip": "Aktualisieren",
"approvalsPillPending": "offen",
"approvalsPillApproved": "freigegeben",
"approvalsPillRejected": "abgelehnt",
"approvalsPillExpired": "abgelaufen",
"approvalsPayloadPreview": "PAYLOAD-VORSCHAU",
"approvalsApproveButton": "Freigeben",
"approvalsRejectButton": "Ablehnen",
"approvalsRejectDialogTitle": "Freigabe ablehnen",
"approvalsRejectReasonLabel": "Begründung (im Audit-Log festgehalten)",
"approvalsApprovedToast": "freigegeben · {flow} {step}",
"@approvalsApprovedToast": {
"placeholders": {
"flow": { "type": "String" },
"step": { "type": "String" }
}
},
"approvalsRejectedToast": "abgelehnt · {flow} {step}",
"@approvalsRejectedToast": {
"placeholders": {
"flow": { "type": "String" },
"step": { "type": "String" }
}
},
"approvalsApproveFailed": "Freigabe fehlgeschlagen: {error}",
"@approvalsApproveFailed": { "placeholders": { "error": { "type": "String" } } },
"approvalsRejectFailed": "Ablehnung fehlgeschlagen: {error}",
"@approvalsRejectFailed": { "placeholders": { "error": { "type": "String" } } },
"approvalsHistoryEmpty": "Noch kein Verlauf",
"approvalsHistoryEmptyHint": "Entschiedene Freigaben (freigegeben / abgelehnt / abgelaufen) erscheinen hier.\nDas Audit-Log enthält den vollständigen hash-chained Datensatz.",
"approvalsDialogDecided": "entschieden",
"approvalsDialogCreated": "erstellt",
"approvalsDialogReason": "Begründung",
"approvalsDialogPrompt": "PROMPT",
"approvalsExpiresIn": "{minutes}m",
"@approvalsExpiresIn": { "placeholders": { "minutes": { "type": "int" } } },
"approvalsExpiresInHours": "{hours}h",
"@approvalsExpiresInHours": { "placeholders": { "hours": { "type": "int" } } },
"doctorTitle": "Diagnose",
"doctorRecheckTooltip": "Erneut prüfen",

View file

@ -37,6 +37,62 @@
"settingsSaveAndConnect": "Save & connect",
"settingsLanguage": "Language",
"settingsLanguageHint": "App language. Affects every page; bilingual store entries also flip via this toggle.",
"settingsHubEndpointHint": "Where should Studio connect? Default is the local hub at 127.0.0.1:50051.",
"settingsTlsSubtitle": "https/grpc-secure",
"settingsPortError": "port must be 165535",
"channelsBlurb": "Switch hub channel (writes ~/.fai/current-channel and restarts the daemon). Connect just changes Studio's wire.",
"channelsActionsTooltip": "Channel actions",
"systemAiHeader": "SYSTEM AI",
"systemAiEnabled": "enabled",
"systemAiOff": "off",
"systemAiEdit": "Edit…",
"systemAiConfigure": "Configure…",
"systemAiOffBlurb": "Off — failure explanations on the audit page are disabled. Click Configure… to pick a provider (Ollama / OpenAI / LM Studio / vLLM / Custom). Operator config is rewritten in place; no daemon restart needed.",
"mcpServersCount": "{n} {n, plural, =1{server} other{servers}}",
"@mcpServersCount": { "placeholders": { "n": { "type": "int" } } },
"mcpRediscoverTooltip": "Re-run discovery",
"mcpAddTooltip": "Add MCP server",
"mcpRemoveTooltip": "Remove server",
"mcpToolsCount": "{n} {n, plural, =1{tool} other{tools}}",
"@mcpToolsCount": { "placeholders": { "n": { "type": "int" } } },
"n8nEndpointsCount": "{n} {n, plural, =1{endpoint} other{endpoints}}",
"@n8nEndpointsCount": { "placeholders": { "n": { "type": "int" } } },
"n8nWorkflowsCount": "{n} {n, plural, =1{workflow} other{workflows}}",
"@n8nWorkflowsCount": { "placeholders": { "n": { "type": "int" } } },
"n8nRediscoverTooltip": "Re-run discovery",
"n8nAddTooltip": "Add n8n endpoint",
"n8nRemoveTooltip": "Remove endpoint",
"addMcpTitle": "Add MCP server",
"addMcpIntro": "Tools the server advertises via `tools/list` appear in the Store as `mcp.<name>.<tool>` capabilities.",
"addMcpSuggestionsLabel": "Suggested servers — click to pre-fill",
"addMcpNameLabel": "Name (no dots)",
"addMcpNameHint": "filesystem",
"addMcpEndpointLabel": "Endpoint",
"addMcpEndpointHint": "http://127.0.0.1:3001/mcp",
"addMcpApiKeyLabel": "API key env var (optional)",
"addMcpApiKeyHint": "MCP_FILESYSTEM_TOKEN",
"addMcpNotesLabel": "Notes (optional)",
"addMcpAddButton": "Add + discover",
"addN8nTitle": "Add n8n endpoint",
"addN8nIntro": "Active workflows surface in the Store as `n8n.<name>.<workflow_slug>` capabilities.",
"addN8nNameLabel": "Name (no dots)",
"addN8nNameHint": "ops",
"addN8nBaseUrlLabel": "Base URL (without /api/v1)",
"addN8nBaseUrlHint": "https://n8n.example.com",
"addN8nApiKeyLabel": "API key env var (optional)",
"addN8nApiKeyHint": "N8N_OPS_KEY",
"addN8nNotesLabel": "Notes (optional)",
"addN8nAddButton": "Add + discover",
"addedMcpToast": "Added MCP server \"{name}\".",
"@addedMcpToast": { "placeholders": { "name": { "type": "String" } } },
"addedN8nToast": "Added n8n endpoint \"{name}\".",
"@addedN8nToast": { "placeholders": { "name": { "type": "String" } } },
"addFailedToast": "Add failed: {error}",
"@addFailedToast": { "placeholders": { "error": { "type": "String" } } },
"removeFailedToast": "Remove failed: {error}",
"@removeFailedToast": { "placeholders": { "error": { "type": "String" } } },
"refreshFailedToast": "Refresh failed: {error}",
"@refreshFailedToast": { "placeholders": { "error": { "type": "String" } } },
"channelsHeader": "CHANNELS",
"channelsActive": "active",
@ -69,6 +125,56 @@
"auditTitle": "Audit",
"auditNoEvents": "No events yet",
"auditNoEventsHint": "Run a flow to populate the audit stream.\nEvents appear here within seconds.",
"auditFilterAll": "all",
"auditFilterFlow": "flow",
"auditFilterStep": "step",
"auditFilterModule": "module",
"auditClearLogTooltip": "Clear log (local/dev channels only)",
"auditClearedToast": "Cleared {n} events on channel \"{channel}\". Chain reseeded with marker.",
"@auditClearedToast": {
"placeholders": {
"n": { "type": "int" },
"channel": { "type": "String" }
}
},
"auditClearFailed": "Clear failed: {detail}",
"@auditClearFailed": { "placeholders": { "detail": { "type": "String" } } },
"auditExplain": "Explain",
"auditReask": "Re-ask",
"auditAsking": "Asking…",
"auditSystemAi": "SYSTEM AI",
"auditCachedPill": "cached",
"auditOriginalLatency": "orig {ms} ms",
"@auditOriginalLatency": { "placeholders": { "ms": { "type": "int" } } },
"auditLatency": "{ms} ms",
"@auditLatency": { "placeholders": { "ms": { "type": "int" } } },
"auditRegenerateTooltip": "Regenerate — skip cache, ask the model again",
"auditLiveStatus": "live · polling 2s · {n} {n, plural, =1{event} other{events}}",
"@auditLiveStatus": { "placeholders": { "n": { "type": "int" } } },
"auditDisconnected": "disconnected · {error}",
"@auditDisconnected": { "placeholders": { "error": { "type": "String" } } },
"auditHashChainVerified": "hash chain verified",
"auditDetailHeader": "DETAIL",
"auditAskingFull": "Asking the configured System AI…",
"auditFixLabel": "FIX",
"auditCachedTooltipKnown": "Served from the local cache. Originally generated on {at}{hits}.",
"@auditCachedTooltipKnown": {
"placeholders": {
"at": { "type": "String" },
"hits": { "type": "String" }
}
},
"auditCachedTooltipUnknown": "Served from the local cache. Originally generated at unknown time{hits}.",
"@auditCachedTooltipUnknown": { "placeholders": { "hits": { "type": "String" } } },
"auditCachedTooltipHits": " · {n} hits",
"@auditCachedTooltipHits": { "placeholders": { "n": { "type": "int" } } },
"auditConfigureSystemAi": "Configure System AI in Settings (Cmd+,)",
"auditClearDialogTitle": "Clear audit log?",
"auditClearDialogBody": "Wipes every audit event on the active channel and seeds a fresh chain.reset marker carrying reviewer + reason. Refused on beta / production. Irreversible.",
"auditClearReviewerLabel": "Reviewer",
"auditClearReasonLabel": "Reason (recorded in chain.reset marker)",
"auditClearReasonHelper": "Required — auditors will read this.",
"auditClearLogButton": "Clear log",
"modulesTitle": "Modules",
"modulesNoneTitle": "No modules yet",
@ -104,6 +210,44 @@
"approvalsTabHistory": "History",
"approvalsInboxZero": "Inbox zero",
"approvalsInboxHint": "All caught up. New `system.approval@^0` steps land here automatically.",
"approvalsReloadTooltip": "Reload",
"approvalsPillPending": "pending",
"approvalsPillApproved": "approved",
"approvalsPillRejected": "rejected",
"approvalsPillExpired": "expired",
"approvalsPayloadPreview": "PAYLOAD PREVIEW",
"approvalsApproveButton": "Approve",
"approvalsRejectButton": "Reject",
"approvalsRejectDialogTitle": "Reject approval",
"approvalsRejectReasonLabel": "Reason (recorded in audit log)",
"approvalsApprovedToast": "approved · {flow} {step}",
"@approvalsApprovedToast": {
"placeholders": {
"flow": { "type": "String" },
"step": { "type": "String" }
}
},
"approvalsRejectedToast": "rejected · {flow} {step}",
"@approvalsRejectedToast": {
"placeholders": {
"flow": { "type": "String" },
"step": { "type": "String" }
}
},
"approvalsApproveFailed": "approve failed: {error}",
"@approvalsApproveFailed": { "placeholders": { "error": { "type": "String" } } },
"approvalsRejectFailed": "reject failed: {error}",
"@approvalsRejectFailed": { "placeholders": { "error": { "type": "String" } } },
"approvalsHistoryEmpty": "No history yet",
"approvalsHistoryEmptyHint": "Decided approvals (approved / rejected / expired) appear here.\nThe audit log keeps the full hash-chained record.",
"approvalsDialogDecided": "decided",
"approvalsDialogCreated": "created",
"approvalsDialogReason": "reason",
"approvalsDialogPrompt": "PROMPT",
"approvalsExpiresIn": "{minutes}m",
"@approvalsExpiresIn": { "placeholders": { "minutes": { "type": "int" } } },
"approvalsExpiresInHours": "{hours}h",
"@approvalsExpiresInHours": { "placeholders": { "hours": { "type": "int" } } },
"doctorTitle": "Doctor",
"doctorRecheckTooltip": "Re-check",

View file

@ -284,6 +284,288 @@ abstract class AppLocalizations {
/// **'App language. Affects every page; bilingual store entries also flip via this toggle.'**
String get settingsLanguageHint;
/// No description provided for @settingsHubEndpointHint.
///
/// In en, this message translates to:
/// **'Where should Studio connect? Default is the local hub at 127.0.0.1:50051.'**
String get settingsHubEndpointHint;
/// No description provided for @settingsTlsSubtitle.
///
/// In en, this message translates to:
/// **'https/grpc-secure'**
String get settingsTlsSubtitle;
/// No description provided for @settingsPortError.
///
/// In en, this message translates to:
/// **'port must be 165535'**
String get settingsPortError;
/// No description provided for @channelsBlurb.
///
/// In en, this message translates to:
/// **'Switch hub channel (writes ~/.fai/current-channel and restarts the daemon). Connect just changes Studio\'s wire.'**
String get channelsBlurb;
/// No description provided for @channelsActionsTooltip.
///
/// In en, this message translates to:
/// **'Channel actions'**
String get channelsActionsTooltip;
/// No description provided for @systemAiHeader.
///
/// In en, this message translates to:
/// **'SYSTEM AI'**
String get systemAiHeader;
/// No description provided for @systemAiEnabled.
///
/// In en, this message translates to:
/// **'enabled'**
String get systemAiEnabled;
/// No description provided for @systemAiOff.
///
/// In en, this message translates to:
/// **'off'**
String get systemAiOff;
/// No description provided for @systemAiEdit.
///
/// In en, this message translates to:
/// **'Edit…'**
String get systemAiEdit;
/// No description provided for @systemAiConfigure.
///
/// In en, this message translates to:
/// **'Configure…'**
String get systemAiConfigure;
/// No description provided for @systemAiOffBlurb.
///
/// In en, this message translates to:
/// **'Off — failure explanations on the audit page are disabled. Click Configure… to pick a provider (Ollama / OpenAI / LM Studio / vLLM / Custom). Operator config is rewritten in place; no daemon restart needed.'**
String get systemAiOffBlurb;
/// No description provided for @mcpServersCount.
///
/// In en, this message translates to:
/// **'{n} {n, plural, =1{server} other{servers}}'**
String mcpServersCount(int n);
/// No description provided for @mcpRediscoverTooltip.
///
/// In en, this message translates to:
/// **'Re-run discovery'**
String get mcpRediscoverTooltip;
/// No description provided for @mcpAddTooltip.
///
/// In en, this message translates to:
/// **'Add MCP server'**
String get mcpAddTooltip;
/// No description provided for @mcpRemoveTooltip.
///
/// In en, this message translates to:
/// **'Remove server'**
String get mcpRemoveTooltip;
/// No description provided for @mcpToolsCount.
///
/// In en, this message translates to:
/// **'{n} {n, plural, =1{tool} other{tools}}'**
String mcpToolsCount(int n);
/// No description provided for @n8nEndpointsCount.
///
/// In en, this message translates to:
/// **'{n} {n, plural, =1{endpoint} other{endpoints}}'**
String n8nEndpointsCount(int n);
/// No description provided for @n8nWorkflowsCount.
///
/// In en, this message translates to:
/// **'{n} {n, plural, =1{workflow} other{workflows}}'**
String n8nWorkflowsCount(int n);
/// No description provided for @n8nRediscoverTooltip.
///
/// In en, this message translates to:
/// **'Re-run discovery'**
String get n8nRediscoverTooltip;
/// No description provided for @n8nAddTooltip.
///
/// In en, this message translates to:
/// **'Add n8n endpoint'**
String get n8nAddTooltip;
/// No description provided for @n8nRemoveTooltip.
///
/// In en, this message translates to:
/// **'Remove endpoint'**
String get n8nRemoveTooltip;
/// No description provided for @addMcpTitle.
///
/// In en, this message translates to:
/// **'Add MCP server'**
String get addMcpTitle;
/// No description provided for @addMcpIntro.
///
/// In en, this message translates to:
/// **'Tools the server advertises via `tools/list` appear in the Store as `mcp.<name>.<tool>` capabilities.'**
String get addMcpIntro;
/// No description provided for @addMcpSuggestionsLabel.
///
/// In en, this message translates to:
/// **'Suggested servers — click to pre-fill'**
String get addMcpSuggestionsLabel;
/// No description provided for @addMcpNameLabel.
///
/// In en, this message translates to:
/// **'Name (no dots)'**
String get addMcpNameLabel;
/// No description provided for @addMcpNameHint.
///
/// In en, this message translates to:
/// **'filesystem'**
String get addMcpNameHint;
/// No description provided for @addMcpEndpointLabel.
///
/// In en, this message translates to:
/// **'Endpoint'**
String get addMcpEndpointLabel;
/// No description provided for @addMcpEndpointHint.
///
/// In en, this message translates to:
/// **'http://127.0.0.1:3001/mcp'**
String get addMcpEndpointHint;
/// No description provided for @addMcpApiKeyLabel.
///
/// In en, this message translates to:
/// **'API key env var (optional)'**
String get addMcpApiKeyLabel;
/// No description provided for @addMcpApiKeyHint.
///
/// In en, this message translates to:
/// **'MCP_FILESYSTEM_TOKEN'**
String get addMcpApiKeyHint;
/// No description provided for @addMcpNotesLabel.
///
/// In en, this message translates to:
/// **'Notes (optional)'**
String get addMcpNotesLabel;
/// No description provided for @addMcpAddButton.
///
/// In en, this message translates to:
/// **'Add + discover'**
String get addMcpAddButton;
/// No description provided for @addN8nTitle.
///
/// In en, this message translates to:
/// **'Add n8n endpoint'**
String get addN8nTitle;
/// No description provided for @addN8nIntro.
///
/// In en, this message translates to:
/// **'Active workflows surface in the Store as `n8n.<name>.<workflow_slug>` capabilities.'**
String get addN8nIntro;
/// No description provided for @addN8nNameLabel.
///
/// In en, this message translates to:
/// **'Name (no dots)'**
String get addN8nNameLabel;
/// No description provided for @addN8nNameHint.
///
/// In en, this message translates to:
/// **'ops'**
String get addN8nNameHint;
/// No description provided for @addN8nBaseUrlLabel.
///
/// In en, this message translates to:
/// **'Base URL (without /api/v1)'**
String get addN8nBaseUrlLabel;
/// No description provided for @addN8nBaseUrlHint.
///
/// In en, this message translates to:
/// **'https://n8n.example.com'**
String get addN8nBaseUrlHint;
/// No description provided for @addN8nApiKeyLabel.
///
/// In en, this message translates to:
/// **'API key env var (optional)'**
String get addN8nApiKeyLabel;
/// No description provided for @addN8nApiKeyHint.
///
/// In en, this message translates to:
/// **'N8N_OPS_KEY'**
String get addN8nApiKeyHint;
/// No description provided for @addN8nNotesLabel.
///
/// In en, this message translates to:
/// **'Notes (optional)'**
String get addN8nNotesLabel;
/// No description provided for @addN8nAddButton.
///
/// In en, this message translates to:
/// **'Add + discover'**
String get addN8nAddButton;
/// No description provided for @addedMcpToast.
///
/// In en, this message translates to:
/// **'Added MCP server \"{name}\".'**
String addedMcpToast(String name);
/// No description provided for @addedN8nToast.
///
/// In en, this message translates to:
/// **'Added n8n endpoint \"{name}\".'**
String addedN8nToast(String name);
/// No description provided for @addFailedToast.
///
/// In en, this message translates to:
/// **'Add failed: {error}'**
String addFailedToast(String error);
/// No description provided for @removeFailedToast.
///
/// In en, this message translates to:
/// **'Remove failed: {error}'**
String removeFailedToast(String error);
/// No description provided for @refreshFailedToast.
///
/// In en, this message translates to:
/// **'Refresh failed: {error}'**
String refreshFailedToast(String error);
/// No description provided for @channelsHeader.
///
/// In en, this message translates to:
@ -440,6 +722,192 @@ abstract class AppLocalizations {
/// **'Run a flow to populate the audit stream.\nEvents appear here within seconds.'**
String get auditNoEventsHint;
/// No description provided for @auditFilterAll.
///
/// In en, this message translates to:
/// **'all'**
String get auditFilterAll;
/// No description provided for @auditFilterFlow.
///
/// In en, this message translates to:
/// **'flow'**
String get auditFilterFlow;
/// No description provided for @auditFilterStep.
///
/// In en, this message translates to:
/// **'step'**
String get auditFilterStep;
/// No description provided for @auditFilterModule.
///
/// In en, this message translates to:
/// **'module'**
String get auditFilterModule;
/// No description provided for @auditClearLogTooltip.
///
/// In en, this message translates to:
/// **'Clear log (local/dev channels only)'**
String get auditClearLogTooltip;
/// No description provided for @auditClearedToast.
///
/// In en, this message translates to:
/// **'Cleared {n} events on channel \"{channel}\". Chain reseeded with marker.'**
String auditClearedToast(int n, String channel);
/// No description provided for @auditClearFailed.
///
/// In en, this message translates to:
/// **'Clear failed: {detail}'**
String auditClearFailed(String detail);
/// No description provided for @auditExplain.
///
/// In en, this message translates to:
/// **'Explain'**
String get auditExplain;
/// No description provided for @auditReask.
///
/// In en, this message translates to:
/// **'Re-ask'**
String get auditReask;
/// No description provided for @auditAsking.
///
/// In en, this message translates to:
/// **'Asking…'**
String get auditAsking;
/// No description provided for @auditSystemAi.
///
/// In en, this message translates to:
/// **'SYSTEM AI'**
String get auditSystemAi;
/// No description provided for @auditCachedPill.
///
/// In en, this message translates to:
/// **'cached'**
String get auditCachedPill;
/// No description provided for @auditOriginalLatency.
///
/// In en, this message translates to:
/// **'orig {ms} ms'**
String auditOriginalLatency(int ms);
/// No description provided for @auditLatency.
///
/// In en, this message translates to:
/// **'{ms} ms'**
String auditLatency(int ms);
/// No description provided for @auditRegenerateTooltip.
///
/// In en, this message translates to:
/// **'Regenerate — skip cache, ask the model again'**
String get auditRegenerateTooltip;
/// No description provided for @auditLiveStatus.
///
/// In en, this message translates to:
/// **'live · polling 2s · {n} {n, plural, =1{event} other{events}}'**
String auditLiveStatus(int n);
/// No description provided for @auditDisconnected.
///
/// In en, this message translates to:
/// **'disconnected · {error}'**
String auditDisconnected(String error);
/// No description provided for @auditHashChainVerified.
///
/// In en, this message translates to:
/// **'hash chain verified'**
String get auditHashChainVerified;
/// No description provided for @auditDetailHeader.
///
/// In en, this message translates to:
/// **'DETAIL'**
String get auditDetailHeader;
/// No description provided for @auditAskingFull.
///
/// In en, this message translates to:
/// **'Asking the configured System AI…'**
String get auditAskingFull;
/// No description provided for @auditFixLabel.
///
/// In en, this message translates to:
/// **'FIX'**
String get auditFixLabel;
/// No description provided for @auditCachedTooltipKnown.
///
/// In en, this message translates to:
/// **'Served from the local cache. Originally generated on {at}{hits}.'**
String auditCachedTooltipKnown(String at, String hits);
/// No description provided for @auditCachedTooltipUnknown.
///
/// In en, this message translates to:
/// **'Served from the local cache. Originally generated at unknown time{hits}.'**
String auditCachedTooltipUnknown(String hits);
/// No description provided for @auditCachedTooltipHits.
///
/// In en, this message translates to:
/// **' · {n} hits'**
String auditCachedTooltipHits(int n);
/// No description provided for @auditConfigureSystemAi.
///
/// In en, this message translates to:
/// **'Configure System AI in Settings (Cmd+,)'**
String get auditConfigureSystemAi;
/// No description provided for @auditClearDialogTitle.
///
/// In en, this message translates to:
/// **'Clear audit log?'**
String get auditClearDialogTitle;
/// No description provided for @auditClearDialogBody.
///
/// In en, this message translates to:
/// **'Wipes every audit event on the active channel and seeds a fresh chain.reset marker carrying reviewer + reason. Refused on beta / production. Irreversible.'**
String get auditClearDialogBody;
/// No description provided for @auditClearReviewerLabel.
///
/// In en, this message translates to:
/// **'Reviewer'**
String get auditClearReviewerLabel;
/// No description provided for @auditClearReasonLabel.
///
/// In en, this message translates to:
/// **'Reason (recorded in chain.reset marker)'**
String get auditClearReasonLabel;
/// No description provided for @auditClearReasonHelper.
///
/// In en, this message translates to:
/// **'Required — auditors will read this.'**
String get auditClearReasonHelper;
/// No description provided for @auditClearLogButton.
///
/// In en, this message translates to:
/// **'Clear log'**
String get auditClearLogButton;
/// No description provided for @modulesTitle.
///
/// In en, this message translates to:
@ -554,6 +1022,138 @@ abstract class AppLocalizations {
/// **'All caught up. New `system.approval@^0` steps land here automatically.'**
String get approvalsInboxHint;
/// No description provided for @approvalsReloadTooltip.
///
/// In en, this message translates to:
/// **'Reload'**
String get approvalsReloadTooltip;
/// No description provided for @approvalsPillPending.
///
/// In en, this message translates to:
/// **'pending'**
String get approvalsPillPending;
/// No description provided for @approvalsPillApproved.
///
/// In en, this message translates to:
/// **'approved'**
String get approvalsPillApproved;
/// No description provided for @approvalsPillRejected.
///
/// In en, this message translates to:
/// **'rejected'**
String get approvalsPillRejected;
/// No description provided for @approvalsPillExpired.
///
/// In en, this message translates to:
/// **'expired'**
String get approvalsPillExpired;
/// No description provided for @approvalsPayloadPreview.
///
/// In en, this message translates to:
/// **'PAYLOAD PREVIEW'**
String get approvalsPayloadPreview;
/// No description provided for @approvalsApproveButton.
///
/// In en, this message translates to:
/// **'Approve'**
String get approvalsApproveButton;
/// No description provided for @approvalsRejectButton.
///
/// In en, this message translates to:
/// **'Reject'**
String get approvalsRejectButton;
/// No description provided for @approvalsRejectDialogTitle.
///
/// In en, this message translates to:
/// **'Reject approval'**
String get approvalsRejectDialogTitle;
/// No description provided for @approvalsRejectReasonLabel.
///
/// In en, this message translates to:
/// **'Reason (recorded in audit log)'**
String get approvalsRejectReasonLabel;
/// No description provided for @approvalsApprovedToast.
///
/// In en, this message translates to:
/// **'approved · {flow} {step}'**
String approvalsApprovedToast(String flow, String step);
/// No description provided for @approvalsRejectedToast.
///
/// In en, this message translates to:
/// **'rejected · {flow} {step}'**
String approvalsRejectedToast(String flow, String step);
/// No description provided for @approvalsApproveFailed.
///
/// In en, this message translates to:
/// **'approve failed: {error}'**
String approvalsApproveFailed(String error);
/// No description provided for @approvalsRejectFailed.
///
/// In en, this message translates to:
/// **'reject failed: {error}'**
String approvalsRejectFailed(String error);
/// No description provided for @approvalsHistoryEmpty.
///
/// In en, this message translates to:
/// **'No history yet'**
String get approvalsHistoryEmpty;
/// No description provided for @approvalsHistoryEmptyHint.
///
/// In en, this message translates to:
/// **'Decided approvals (approved / rejected / expired) appear here.\nThe audit log keeps the full hash-chained record.'**
String get approvalsHistoryEmptyHint;
/// No description provided for @approvalsDialogDecided.
///
/// In en, this message translates to:
/// **'decided'**
String get approvalsDialogDecided;
/// No description provided for @approvalsDialogCreated.
///
/// In en, this message translates to:
/// **'created'**
String get approvalsDialogCreated;
/// No description provided for @approvalsDialogReason.
///
/// In en, this message translates to:
/// **'reason'**
String get approvalsDialogReason;
/// No description provided for @approvalsDialogPrompt.
///
/// In en, this message translates to:
/// **'PROMPT'**
String get approvalsDialogPrompt;
/// No description provided for @approvalsExpiresIn.
///
/// In en, this message translates to:
/// **'{minutes}m'**
String approvalsExpiresIn(int minutes);
/// No description provided for @approvalsExpiresInHours.
///
/// In en, this message translates to:
/// **'{hours}h'**
String approvalsExpiresInHours(int hours);
/// No description provided for @doctorTitle.
///
/// In en, this message translates to:

View file

@ -102,6 +102,182 @@ class AppLocalizationsDe extends AppLocalizations {
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';
@ -186,6 +362,128 @@ class AppLocalizationsDe extends AppLocalizations {
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';
@ -253,6 +551,86 @@ class AppLocalizationsDe extends AppLocalizations {
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';

View file

@ -102,6 +102,194 @@ class AppLocalizationsEn extends AppLocalizations {
String get settingsLanguageHint =>
'App language. Affects every page; bilingual store entries also flip via this toggle.';
@override
String get settingsHubEndpointHint =>
'Where should Studio connect? Default is the local hub at 127.0.0.1:50051.';
@override
String get settingsTlsSubtitle => 'https/grpc-secure';
@override
String get settingsPortError => 'port must be 165535';
@override
String get channelsBlurb =>
'Switch hub channel (writes ~/.fai/current-channel and restarts the daemon). Connect just changes Studio\'s wire.';
@override
String get channelsActionsTooltip => 'Channel actions';
@override
String get systemAiHeader => 'SYSTEM AI';
@override
String get systemAiEnabled => 'enabled';
@override
String get systemAiOff => 'off';
@override
String get systemAiEdit => 'Edit…';
@override
String get systemAiConfigure => 'Configure…';
@override
String get systemAiOffBlurb =>
'Off — failure explanations on the audit page are disabled. Click Configure… to pick a provider (Ollama / OpenAI / LM Studio / vLLM / Custom). Operator config is rewritten in place; no daemon restart needed.';
@override
String mcpServersCount(int n) {
String _temp0 = intl.Intl.pluralLogic(
n,
locale: localeName,
other: 'servers',
one: 'server',
);
return '$n $_temp0';
}
@override
String get mcpRediscoverTooltip => 'Re-run discovery';
@override
String get mcpAddTooltip => 'Add MCP server';
@override
String get mcpRemoveTooltip => 'Remove server';
@override
String mcpToolsCount(int n) {
String _temp0 = intl.Intl.pluralLogic(
n,
locale: localeName,
other: 'tools',
one: 'tool',
);
return '$n $_temp0';
}
@override
String n8nEndpointsCount(int n) {
String _temp0 = intl.Intl.pluralLogic(
n,
locale: localeName,
other: 'endpoints',
one: 'endpoint',
);
return '$n $_temp0';
}
@override
String n8nWorkflowsCount(int n) {
String _temp0 = intl.Intl.pluralLogic(
n,
locale: localeName,
other: 'workflows',
one: 'workflow',
);
return '$n $_temp0';
}
@override
String get n8nRediscoverTooltip => 'Re-run discovery';
@override
String get n8nAddTooltip => 'Add n8n endpoint';
@override
String get n8nRemoveTooltip => 'Remove endpoint';
@override
String get addMcpTitle => 'Add MCP server';
@override
String get addMcpIntro =>
'Tools the server advertises via `tools/list` appear in the Store as `mcp.<name>.<tool>` capabilities.';
@override
String get addMcpSuggestionsLabel => 'Suggested servers — click to pre-fill';
@override
String get addMcpNameLabel => 'Name (no dots)';
@override
String get addMcpNameHint => 'filesystem';
@override
String get addMcpEndpointLabel => 'Endpoint';
@override
String get addMcpEndpointHint => 'http://127.0.0.1:3001/mcp';
@override
String get addMcpApiKeyLabel => 'API key env var (optional)';
@override
String get addMcpApiKeyHint => 'MCP_FILESYSTEM_TOKEN';
@override
String get addMcpNotesLabel => 'Notes (optional)';
@override
String get addMcpAddButton => 'Add + discover';
@override
String get addN8nTitle => 'Add n8n endpoint';
@override
String get addN8nIntro =>
'Active workflows surface in the Store as `n8n.<name>.<workflow_slug>` capabilities.';
@override
String get addN8nNameLabel => 'Name (no dots)';
@override
String get addN8nNameHint => 'ops';
@override
String get addN8nBaseUrlLabel => 'Base URL (without /api/v1)';
@override
String get addN8nBaseUrlHint => 'https://n8n.example.com';
@override
String get addN8nApiKeyLabel => 'API key env var (optional)';
@override
String get addN8nApiKeyHint => 'N8N_OPS_KEY';
@override
String get addN8nNotesLabel => 'Notes (optional)';
@override
String get addN8nAddButton => 'Add + discover';
@override
String addedMcpToast(String name) {
return 'Added MCP server \"$name\".';
}
@override
String addedN8nToast(String name) {
return 'Added n8n endpoint \"$name\".';
}
@override
String addFailedToast(String error) {
return 'Add failed: $error';
}
@override
String removeFailedToast(String error) {
return 'Remove failed: $error';
}
@override
String refreshFailedToast(String error) {
return 'Refresh failed: $error';
}
@override
String get channelsHeader => 'CHANNELS';
@ -192,6 +380,126 @@ class AppLocalizationsEn extends AppLocalizations {
String get auditNoEventsHint =>
'Run a flow to populate the audit stream.\nEvents appear here within seconds.';
@override
String get auditFilterAll => 'all';
@override
String get auditFilterFlow => 'flow';
@override
String get auditFilterStep => 'step';
@override
String get auditFilterModule => 'module';
@override
String get auditClearLogTooltip => 'Clear log (local/dev channels only)';
@override
String auditClearedToast(int n, String channel) {
return 'Cleared $n events on channel \"$channel\". Chain reseeded with marker.';
}
@override
String auditClearFailed(String detail) {
return 'Clear failed: $detail';
}
@override
String get auditExplain => 'Explain';
@override
String get auditReask => 'Re-ask';
@override
String get auditAsking => 'Asking…';
@override
String get auditSystemAi => 'SYSTEM AI';
@override
String get auditCachedPill => 'cached';
@override
String auditOriginalLatency(int ms) {
return 'orig $ms ms';
}
@override
String auditLatency(int ms) {
return '$ms ms';
}
@override
String get auditRegenerateTooltip =>
'Regenerate — skip cache, ask the model again';
@override
String auditLiveStatus(int n) {
String _temp0 = intl.Intl.pluralLogic(
n,
locale: localeName,
other: 'events',
one: 'event',
);
return 'live · polling 2s · $n $_temp0';
}
@override
String auditDisconnected(String error) {
return 'disconnected · $error';
}
@override
String get auditHashChainVerified => 'hash chain verified';
@override
String get auditDetailHeader => 'DETAIL';
@override
String get auditAskingFull => 'Asking the configured System AI…';
@override
String get auditFixLabel => 'FIX';
@override
String auditCachedTooltipKnown(String at, String hits) {
return 'Served from the local cache. Originally generated on $at$hits.';
}
@override
String auditCachedTooltipUnknown(String hits) {
return 'Served from the local cache. Originally generated at unknown time$hits.';
}
@override
String auditCachedTooltipHits(int n) {
return ' · $n hits';
}
@override
String get auditConfigureSystemAi =>
'Configure System AI in Settings (Cmd+,)';
@override
String get auditClearDialogTitle => 'Clear audit log?';
@override
String get auditClearDialogBody =>
'Wipes every audit event on the active channel and seeds a fresh chain.reset marker carrying reviewer + reason. Refused on beta / production. Irreversible.';
@override
String get auditClearReviewerLabel => 'Reviewer';
@override
String get auditClearReasonLabel => 'Reason (recorded in chain.reset marker)';
@override
String get auditClearReasonHelper => 'Required — auditors will read this.';
@override
String get auditClearLogButton => 'Clear log';
@override
String get modulesTitle => 'Modules';
@ -259,6 +567,85 @@ class AppLocalizationsEn extends AppLocalizations {
String get approvalsInboxHint =>
'All caught up. New `system.approval@^0` steps land here automatically.';
@override
String get approvalsReloadTooltip => 'Reload';
@override
String get approvalsPillPending => 'pending';
@override
String get approvalsPillApproved => 'approved';
@override
String get approvalsPillRejected => 'rejected';
@override
String get approvalsPillExpired => 'expired';
@override
String get approvalsPayloadPreview => 'PAYLOAD PREVIEW';
@override
String get approvalsApproveButton => 'Approve';
@override
String get approvalsRejectButton => 'Reject';
@override
String get approvalsRejectDialogTitle => 'Reject approval';
@override
String get approvalsRejectReasonLabel => 'Reason (recorded in audit log)';
@override
String approvalsApprovedToast(String flow, String step) {
return 'approved · $flow $step';
}
@override
String approvalsRejectedToast(String flow, String step) {
return 'rejected · $flow $step';
}
@override
String approvalsApproveFailed(String error) {
return 'approve failed: $error';
}
@override
String approvalsRejectFailed(String error) {
return 'reject failed: $error';
}
@override
String get approvalsHistoryEmpty => 'No history yet';
@override
String get approvalsHistoryEmptyHint =>
'Decided approvals (approved / rejected / expired) appear here.\nThe audit log keeps the full hash-chained record.';
@override
String get approvalsDialogDecided => 'decided';
@override
String get approvalsDialogCreated => 'created';
@override
String get approvalsDialogReason => 'reason';
@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 => 'Doctor';