The store had three structural problems flagged in user feedback: 1. "Lernkurve zu hoch — alle bridge, debug, alpha, planned, keiner weiß was das heißt." Wire-level enum values bled through into the UI: `bridge`, `debug`, `published`, `alpha`, `planned`. Operators don't share the data model. 2. "Filter / Kategorien sollten oben in die Leiste neben Store zum ausklappen, der Body soll übersichtlicher werden." A chip-row plus category strip plus result-count line ate a full row of viewport on every screen. 3. "Suche passt besser an den unteren Bildschirmrand." The chat-style ask bar belongs at the bottom — Claude / ChatGPT / Slack pattern — not at the top where it competes with the Today hero. Plus: "Es gibt noch ganz viele overflows in den Beschreibungen." Changes: - Plain-language display names. New ARB keys for category labels (Connectors / Sample modules / AI models / Storage / Channels / Authentication / Orchestration / …) and updated status values (stable / experimental / coming soon). Wire ids stay in StoreEntry, RPCs, seed.yaml — only the rendered pills and dropdowns get translated. Helpers `_categoryDisplayName` and `_statusDisplayName` keep the mapping in one place. - Toolbar moves into the AppBar. The new `_CategoryDropdown` hosts the category picker as a popup-menu with localised labels; the existing `_FilterButton` lives next to it; the reload icon stays where it always was. The body no longer carries any chip strip or result-count line. - Bottom-anchored `_AskBar`. The Scaffold body becomes a Column of `Expanded(scrollable content)` plus a pinned composer row at the foot of the viewport, with a top divider matching the chat-input pattern of modern AI assistants. AI answers now render at the top of the scroll (above the Today-Hero) so the operator sees them right after submitting the question at the bottom. - Overflow sweep on descriptions. Today-Hero header row becomes a Wrap (badge + deck flow naturally on narrow windows), the title is bound to 3 lines, the body to 6. Card category text gets `maxLines: 1, ellipsis` in both StoreCard and FeaturedTile. Recommended-source card title gets the same treatment. - Better toast for the "added but zero capabilities" path. When MCP discovery succeeds but returns no tools (typical Streamable-HTTP servers without Mcp-Session-Id support, or servers that need `notifications/initialized`), the toast now explains the situation in plain language and points the operator at Settings → MCP Clients to retry. Old pluralised toast still fires when N > 0. Hub-side `notifications/initialized` for HTTP MCP and Mcp-Session-Id support are out of scope for this commit; tracked as a separate fai_hub follow-up. Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
559 lines
27 KiB
Text
559 lines
27 KiB
Text
{
|
||
"@@locale": "en",
|
||
|
||
"appTitle": "F∆I Studio",
|
||
"@appTitle": { "description": "App-bar title in the OS task switcher." },
|
||
|
||
"navDoctor": "Doctor",
|
||
"navModules": "Modules",
|
||
"navStore": "Store",
|
||
"navFlows": "Flows",
|
||
"navAudit": "Audit",
|
||
"navApprovals": "Approvals",
|
||
|
||
"connectionConnected": "connected",
|
||
"connectionUnreachable": "unreachable",
|
||
"connectionConnecting": "connecting…",
|
||
"connectionStartHub": "Start hub",
|
||
|
||
"buttonCancel": "Cancel",
|
||
"buttonSave": "Save",
|
||
"buttonClose": "Close",
|
||
"buttonRetry": "Retry",
|
||
"buttonRefresh": "Refresh",
|
||
"buttonInstall": "Install",
|
||
"buttonUninstall": "Uninstall",
|
||
"buttonDetails": "Details",
|
||
"buttonAdd": "Add",
|
||
"buttonRemove": "Remove",
|
||
"buttonOpen": "Open",
|
||
"buttonExplain": "Explain",
|
||
"buttonReadDocs": "Read docs",
|
||
|
||
"settingsTitle": "Hub endpoint",
|
||
"settingsHost": "Host",
|
||
"settingsPort": "Port",
|
||
"settingsTls": "TLS",
|
||
"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 1–65535",
|
||
"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",
|
||
"channelsRunning": "running",
|
||
"channelsStopped": "stopped",
|
||
"channelsConnect": "Connect Studio to this channel",
|
||
"channelsSwitch": "Make this the active channel",
|
||
"channelsEnableAutostart": "Enable autostart at login",
|
||
"channelsDisableAutostart": "Disable autostart",
|
||
|
||
"storeSearchHint": "Search modules — name, tagline, tag, capability…",
|
||
"storeAskHint": "What do you need? Try \"a module that reads tabular data\" or just type a keyword.",
|
||
"storeAskSubmit": "Search",
|
||
"storeAskAi": "Ask the AI",
|
||
"storeAskClear": "Clear question",
|
||
"storeAskAiThinking": "Looking through modules…",
|
||
"storeAskAiUnavailable": "Configure a System AI in Settings to ask questions in plain language.",
|
||
"storeAskNoMatches": "No matches yet — refine the question or browse the grid below.",
|
||
"storeAskAnswerLabel": "AI suggestion",
|
||
"storeAskAnswerWhy": "Why this matches",
|
||
"storeAskMatchPill": "match",
|
||
"storeFilterLabel": "Filter",
|
||
"storeFilterActiveCount": "{n} active",
|
||
"@storeFilterActiveCount": { "placeholders": { "n": { "type": "int" } } },
|
||
"storeFilterReset": "Reset filters",
|
||
"storeFilterApply": "Done",
|
||
"storeFilterStatusGroup": "Status",
|
||
"storeFilterSourceGroup": "Source",
|
||
"storeFilterInstalledGroup": "Show only installed",
|
||
"storeFeatured": "FEATURED",
|
||
"storeFeaturedHint": "curated picks · click for details",
|
||
"storeNoMatches": "No matches",
|
||
"storeNoMatchesHint": "Adjust the filters or clear the search to see all entries.",
|
||
"storeClearFilters": "Clear filters",
|
||
"storeStatusAll": "All",
|
||
"storeStatusPublished": "stable",
|
||
"storeStatusAlpha": "experimental",
|
||
"storeStatusPlanned": "coming soon",
|
||
"storeInstalledOnly": "Installed",
|
||
"storeCategoryLabel": "Category",
|
||
"storeCategoryAll": "All categories",
|
||
"storeCategoryBridge": "Connectors",
|
||
"storeCategoryDebug": "Sample modules",
|
||
"storeCategoryText": "Text",
|
||
"storeCategoryLlm": "AI models",
|
||
"storeCategorySystem": "System",
|
||
"storeCategoryAuth": "Authentication",
|
||
"storeCategoryStorage": "Storage",
|
||
"storeCategoryChannel": "Channels",
|
||
"storeCategoryWeb": "Web",
|
||
"storeCategoryOrchestrator": "Orchestration",
|
||
"storeNResults": "{n} result{n, plural, =1{} other{s}}",
|
||
"@storeNResults": {
|
||
"placeholders": { "n": { "type": "int" } }
|
||
},
|
||
"storeReloadTooltip": "Reload",
|
||
"storeTodayBadge": "TODAY",
|
||
"storeTodayDeck": "From the F∆I editor",
|
||
"storeTodayDismissTooltip": "Hide for this session",
|
||
"storePillInstalled": "installed",
|
||
"storePillUpdate": "update",
|
||
"storeUpdateButton": "Update to {version}",
|
||
"@storeUpdateButton": { "placeholders": { "version": { "type": "String" } } },
|
||
"storeUpdateTooltip": "Installed {installed} — store has v{best}",
|
||
"@storeUpdateTooltip": {
|
||
"placeholders": {
|
||
"installed": { "type": "String" },
|
||
"best": { "type": "String" }
|
||
}
|
||
},
|
||
"storeNoTagline": "(no tagline)",
|
||
"storeUninstallTitle": "Uninstall module?",
|
||
"storeUninstallBody": "Removes {name} from this hub. Flows that reference it will fail at the next run.",
|
||
"@storeUninstallBody": { "placeholders": { "name": { "type": "String" } } },
|
||
"storeInstalledToast": "{name} v{version} installed.",
|
||
"@storeInstalledToast": {
|
||
"placeholders": {
|
||
"name": { "type": "String" },
|
||
"version": { "type": "String" }
|
||
}
|
||
},
|
||
"storeInstallFailedToast": "Install failed: {error}",
|
||
"@storeInstallFailedToast": { "placeholders": { "error": { "type": "String" } } },
|
||
"storeUninstalledToast": "{name} v{version} uninstalled.",
|
||
"@storeUninstalledToast": {
|
||
"placeholders": {
|
||
"name": { "type": "String" },
|
||
"version": { "type": "String" }
|
||
}
|
||
},
|
||
"storeUninstallFailedToast": "Uninstall failed: {error}",
|
||
"@storeUninstallFailedToast": { "placeholders": { "error": { "type": "String" } } },
|
||
"storeOpenBrowserFailed": "Could not open browser: {error}",
|
||
"@storeOpenBrowserFailed": { "placeholders": { "error": { "type": "String" } } },
|
||
"storeSectionTags": "Tags",
|
||
"storeSectionRequiredCapabilities": "Required capabilities",
|
||
"storeSectionRequiredHostServices": "Required host services",
|
||
"storeSectionScreenshots": "Screenshots",
|
||
"storeSectionDocumentation": "Documentation",
|
||
"storeSectionSource": "Source",
|
||
"storeInstallingButton": "Installing…",
|
||
"storeNotInstallable": "Not installable",
|
||
"storeNotInstallableTooltip": "Status \"{status}\" — install path not yet wired.",
|
||
"@storeNotInstallableTooltip": { "placeholders": { "status": { "type": "String" } } },
|
||
"storeInstallProgressTitle": "Installing {name}",
|
||
"@storeInstallProgressTitle": { "placeholders": { "name": { "type": "String" } } },
|
||
"storeInstallProgressBody": "Fetching, verifying, unpacking…",
|
||
"storeLoadDocs": "Load documentation",
|
||
"storeDocsHint": "README rendered inline; uses the hub's registry token when needed.",
|
||
"storeDocsFetching": "Fetching README…",
|
||
"storeOpenRepoButton": "Open repository in browser",
|
||
"storeDocsErrorNotFound": "This module is not in the hub's store index.",
|
||
"storeDocsErrorNoDocs": "No repository URL is recorded for this module.",
|
||
"storeDocsErrorAuth": "The registry requires authentication to fetch this README. Set FAI_REGISTRY_TOKEN in the daemon's environment and restart the hub.",
|
||
"storeDocsErrorNetwork": "Network error while fetching the README. {detail}",
|
||
"@storeDocsErrorNetwork": { "placeholders": { "detail": { "type": "String" } } },
|
||
"storeDocsErrorParse": "README is not valid UTF-8.",
|
||
"storeDocsErrorGeneric": "Could not load README.",
|
||
"storeSourceLabel": "Source",
|
||
"storeSourceAll": "All sources",
|
||
"storeSourceNative": "Native",
|
||
"storeSourceMcp": "MCP",
|
||
"storeSourceN8n": "n8n",
|
||
"storeProvenanceNative": "native",
|
||
"storeProvenanceMcp": "mcp · {provider}",
|
||
"@storeProvenanceMcp": { "placeholders": { "provider": { "type": "String" } } },
|
||
"storeProvenanceN8n": "n8n · {provider}",
|
||
"@storeProvenanceN8n": { "placeholders": { "provider": { "type": "String" } } },
|
||
"storeRecommendedTitle": "Add a public source — one click",
|
||
"storeRecommendedBody": "Curated MCP servers reachable over HTTPS. No subprocess, no API key, no Node. Federated capabilities appear in the store immediately.",
|
||
"storeRecommendedAddTooltip": "Add and discover",
|
||
"storeRecommendedAdding": "Adding…",
|
||
"storeRecommendedDeepWikiTagline": "GitHub repo documentation search (AI-powered)",
|
||
"storeRecommendedSemgrepTagline": "Security scanning for code vulnerabilities",
|
||
"storeProviderAddedToast": "Added {name} — {n} federated {n, plural, =1{capability} other{capabilities}}.",
|
||
"@storeProviderAddedToast": {
|
||
"placeholders": {
|
||
"name": { "type": "String" },
|
||
"n": { "type": "int" }
|
||
}
|
||
},
|
||
"storeProviderAddedZeroToast": "{name} registered, but the server returned no capabilities yet. Open Settings → MCP Clients to retry discovery or check the server.",
|
||
"@storeProviderAddedZeroToast": {
|
||
"placeholders": { "name": { "type": "String" } }
|
||
},
|
||
"storeProviderAddFailed": "Could not add {name}: {error}",
|
||
"@storeProviderAddFailed": {
|
||
"placeholders": {
|
||
"name": { "type": "String" },
|
||
"error": { "type": "String" }
|
||
}
|
||
},
|
||
|
||
"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",
|
||
"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…",
|
||
"moduleSheetFailedToLoad": "Failed to load: {error}",
|
||
"@moduleSheetFailedToLoad": { "placeholders": { "error": { "type": "String" } } },
|
||
"moduleSheetCapabilities": "Capabilities",
|
||
"moduleSheetPermissions": "Declared permissions",
|
||
"moduleSheetNoPermissions": "(none — pure-computation module)",
|
||
|
||
"flowsTitle": "Flows",
|
||
"flowsReloadTooltip": "Reload",
|
||
"flowsNoneTitle": "No saved flows",
|
||
"flowsNoneHint": "Save a flow with `fai admin flows save <name> <flow.yaml>` and it shows up here.",
|
||
"flowsRunDialogTitle": "Run {name}",
|
||
"@flowsRunDialogTitle": { "placeholders": { "name": { "type": "String" } } },
|
||
"flowsRunDialogBody": "Inputs as key=value, one per line. All values are sent as text payloads. For binary inputs use the `fai run` CLI.",
|
||
"flowsInputsHint": "name=World\ntarget_language=English\nsummary_style=three bullet points",
|
||
"flowsRunButton": "Run",
|
||
"flowsRunningTitle": "Running {name}",
|
||
"@flowsRunningTitle": { "placeholders": { "name": { "type": "String" } } },
|
||
"flowsRunning": "Flow running…",
|
||
"flowsNoOutputs": "Flow completed with no declared outputs.",
|
||
|
||
"approvalsTitle": "Approvals",
|
||
"approvalsTabPending": "Pending",
|
||
"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",
|
||
"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.",
|
||
"mcpEmpty": "No MCP servers configured. Click + to add one.",
|
||
"n8nHeader": "N8N ENDPOINTS",
|
||
"n8nHint": "Active n8n workflows surface as `n8n.<endpoint>.<slug>` capabilities. Configure once, see them in the Store.",
|
||
"n8nEmpty": "No n8n endpoints configured. Click + to add one.",
|
||
|
||
"hubUnreachable": "Hub unreachable",
|
||
"hubUnreachableHint": "Start the hub with `fai serve`.",
|
||
|
||
"languageEnglish": "English",
|
||
"languageGerman": "Deutsch",
|
||
|
||
"searchHint": "Jump anywhere — modules, store, flows, pages…",
|
||
"searchIndexing": "Indexing…",
|
||
"searchNoMatches": "No matches.",
|
||
"searchHintNavigate": "↑↓ navigate",
|
||
"searchHintOpen": "enter open",
|
||
"searchHintClose": "esc close",
|
||
"searchGroupPages": "Pages",
|
||
"searchGroupModules": "Modules",
|
||
"searchGroupStore": "Store",
|
||
"searchGroupFlows": "Flows",
|
||
"searchSettingsLabel": "Settings",
|
||
"searchPageHint": "page · ⌘{n}",
|
||
"@searchPageHint": { "placeholders": { "n": { "type": "int" } } },
|
||
"searchSettingsHint": "hub endpoint, channels, system AI · ⌘;",
|
||
"searchInstalledModuleHint": "installed module · v{version}",
|
||
"@searchInstalledModuleHint": { "placeholders": { "version": { "type": "String" } } },
|
||
"searchStoreUncategorized": "uncategorized",
|
||
"searchStoreHintWithTagline": "store · {tagline}",
|
||
"@searchStoreHintWithTagline": { "placeholders": { "tagline": { "type": "String" } } },
|
||
"searchStoreHintWithCategory": "store · {category}",
|
||
"@searchStoreHintWithCategory": { "placeholders": { "category": { "type": "String" } } },
|
||
"searchSavedFlowHint": "saved flow",
|
||
|
||
"systemAiTitle": "System AI",
|
||
"systemAiIntro": "The hub-internal LLM the platform itself uses for inline failure explanations and operator help. Off by default; configure here. See docs/architecture/system-ai.md for what crosses the wire.",
|
||
"systemAiProviderLabel": "Provider",
|
||
"systemAiEndpointLabel": "Endpoint URL (up to /v1)",
|
||
"systemAiApiKeyRequired": "API key env var (required)",
|
||
"systemAiApiKeyOptional": "API key env var (optional)",
|
||
"systemAiApiKeyDisclaimer": "Studio never reads or stores the key value — only its env-var name. The hub reads `${name}` at request time.",
|
||
"@systemAiApiKeyDisclaimer": { "placeholders": { "name": { "type": "String" } } },
|
||
"systemAiTestConnection": "Test connection",
|
||
"systemAiTesting": "Testing…",
|
||
"systemAiSave": "Save",
|
||
"systemAiPrivacyHeader": "PRIVACY MODE",
|
||
"systemAiPrivacyOffLabel": "Off",
|
||
"systemAiPrivacyOffDesc": "Feature disabled. No requests leave the hub.",
|
||
"systemAiPrivacyRedactedLabel": "Redacted",
|
||
"systemAiPrivacyRedactedDesc": "Only event_type / error / module names. KRITIS-friendly default.",
|
||
"systemAiPrivacyFullLabel": "Full",
|
||
"systemAiPrivacyFullDesc": "Includes the audit detail JSON (hash-only — no raw payloads).",
|
||
"systemAiConnectionOk": "Connection ok",
|
||
"systemAiConnectionFailed": "Connection failed",
|
||
"systemAiReplyPrefix": "Reply: {text}",
|
||
"@systemAiReplyPrefix": { "placeholders": { "text": { "type": "String" } } },
|
||
"systemAiModelLabel": "Model (required)",
|
||
"systemAiModelHintFallback": "model identifier the provider expects",
|
||
"systemAiModelHelperBase": "Required: pick from the list (Refresh) or type one.",
|
||
"systemAiModelHelperOllama": "Required: pick from the list (Refresh) or type one. Use Pull to download from Ollama.",
|
||
"systemAiRefresh": "Refresh",
|
||
"systemAiPull": "Pull",
|
||
"systemAiPulling": "Pulling…",
|
||
"systemAiCouldNotListModels": "Could not list models: {error}",
|
||
"@systemAiCouldNotListModels": { "placeholders": { "error": { "type": "String" } } },
|
||
"systemAiNoModelsOllama": "No models on the Ollama server yet. Type one above and click Pull.",
|
||
"systemAiNoModelsGeneric": "Provider returned no models.",
|
||
"systemAiSuitabilityRecommended": "recommended",
|
||
"systemAiSuitabilityBalanced": "balanced",
|
||
"systemAiSuitabilitySmall": "small — quality may be limited",
|
||
"systemAiSuitabilityLarge": "large — slower",
|
||
"systemAiSuitabilityHuge": "huge — likely too slow on a laptop",
|
||
"systemAiSuitabilityUnknown": "size unknown",
|
||
"systemAiHwDetected": "Detected: {summary}",
|
||
"@systemAiHwDetected": { "placeholders": { "summary": { "type": "String" } } },
|
||
"systemAiHwReviewed": " · curation reviewed {date}",
|
||
"@systemAiHwReviewed": { "placeholders": { "date": { "type": "String" } } },
|
||
"systemAiLegendRecommended": "recommended for this hardware{tier}",
|
||
"@systemAiLegendRecommended": { "placeholders": { "tier": { "type": "String" } } },
|
||
"systemAiLegendBalanced": "balanced (4-8B)",
|
||
"systemAiLegendSmallLarge": "small <3B / large 9-15B / above hardware",
|
||
"systemAiLegendHuge": "huge >15B",
|
||
"systemAiLegendUnknown": "size unknown",
|
||
"systemAiCacheRow": "Cache: {n} cached {n, plural, =1{explanation} other{explanations}}. Identical prompts hit the cache; switching model or privacy mode flushes automatically.",
|
||
"@systemAiCacheRow": { "placeholders": { "n": { "type": "int" } } },
|
||
"systemAiCacheClear": "Clear",
|
||
"systemAiCacheClearedToast": "Cleared {n} cached System-AI explanations.",
|
||
"@systemAiCacheClearedToast": { "placeholders": { "n": { "type": "int" } } },
|
||
"systemAiCacheClearFailed": "Cache clear failed: {error}",
|
||
"@systemAiCacheClearFailed": { "placeholders": { "error": { "type": "String" } } },
|
||
"systemAiPullEmptyError": "Type a model id (e.g. gemma3:4b) first.",
|
||
"systemAiPullFailedError": "Pull failed: {error}",
|
||
"@systemAiPullFailedError": { "placeholders": { "error": { "type": "String" } } }
|
||
}
|