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
|
|
@ -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.",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue