feat(studio): de-jargonize, reveal-in-OS, copyable errors, today carousel, AppBar alignment, F∆I window title (v0.34.0)

Sweeping pass against six user reports collected this session.

1. "Capabilities ist nicht deutsch, Chain auch nicht."
   The DE locale still leaked English vocabulary. Replaced
   "Capabilities" → "Fähigkeiten" and "Chain" / "Hash-Chain"
   → "Kette" / "Hash-Kette" everywhere — store search hint,
   recommended-source body, federated toast, doctor summary
   chain row, modules panel summary, MCP / n8n hints, the
   approvals history blurb. Wire-level identifiers
   (`chain.reset`) stay as code.

2. "Bei Fehlern unten muss man die auch ins clipboard
   kopieren können." New `FaiErrorBox` widget: selectable
   monospace block with a small copy-to-clipboard icon
   button that flips to a checkmark for two seconds after
   click. Applied to the Doctor update banner output and
   the Settings channel toast — the two places long
   stderr / stdout lands.

3. "Öffnen bei Log kann es nicht öffnen. Audit-DB auch
   nicht. PID auch nicht."
   Cause: `SystemActions.openInOs` shells out to `open` /
   `xdg-open` on file paths the OS has no default handler
   for (SQLite DB, PID file, log without an .ext that
   binds). New `revealInOs` uses `open -R` on macOS,
   `explorer /select,` on Windows, and the parent
   directory via `xdg-open` on Linux. Doctor's path rows
   carry an `isDirectory` flag that routes through the new
   `openOrReveal` so files reveal in Finder / Explorer
   instead of failing silently.

4. "Oben im Store könnte man diesen Redaktionshinweis auch
   so bauen, dass man mit pfeil nach rechts links auch
   weitere anzeigen kann."
   The Today-Hero became a carousel. Curated fallback
   list grew from one entry to four (public sources, the
   sandbox-by-default permission story, the hash-chained
   audit story, the air-gap-ready single-binary pitch).
   Hero gets prev / next chevrons plus a dot indicator
   when the current snapshot has more than one slide.
   Operator-accepted stories stay single — the carousel
   collapses when there's only one to show.

5. "Ich fände es schöner wenn rechts und links im Store
   die Abstände konsistent sind, das Reload-Symbol rechts
   ist zu weit rechts und Store links auch nicht bündig."
   AppBar now has `titleSpacing: FaiSpace.xl` so the
   title's left edge sits flush with the body's left
   padding (24 dp), and the trailing `SizedBox` after the
   reload icon shrunk so the icon's outer edge meets the
   right edge of the rightmost grid card.

6. "Oben der Titel zeigt fai_studio an, das sollte F∆I
   Studio sein." The OS window title was the
   pubspec-derived "fai_studio". Macos/Linux/Windows
   runners now hard-code "F∆I Studio" (with the U+2206
   triangle escape so the C++ source stays ASCII). macOS
   bundle name and display name lifted out of the
   PRODUCT_NAME variable for the same reason.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
flemming-it 2026-05-08 14:48:33 +02:00
parent 22a851b7e2
commit 3b5fb027c3
17 changed files with 454 additions and 119 deletions

View file

@ -28,6 +28,8 @@
"buttonOpen": "Öffnen",
"buttonExplain": "Erklären",
"buttonReadDocs": "Doku öffnen",
"buttonCopy": "In Zwischenablage kopieren",
"buttonCopied": "Kopiert",
"settingsTitle": "Hub-Endpunkt",
"settingsHost": "Host",
@ -62,7 +64,7 @@
"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.",
"addMcpIntro": "Tools, die der Server via `tools/list` anbietet, erscheinen im Store als `mcp.<name>.<tool>`-Fähigkeiten.",
"addMcpSuggestionsLabel": "Vorschläge — zum Vorausfüllen klicken",
"addMcpNameLabel": "Name (keine Punkte)",
"addMcpNameHint": "filesystem",
@ -73,7 +75,7 @@
"addMcpNotesLabel": "Notizen (optional)",
"addMcpAddButton": "Hinzufügen + Discovery",
"addN8nTitle": "n8n-Endpunkt hinzufügen",
"addN8nIntro": "Aktive Workflows erscheinen im Store als `n8n.<name>.<workflow_slug>`-Capabilities.",
"addN8nIntro": "Aktive Workflows erscheinen im Store als `n8n.<name>.<workflow_slug>`-Fähigkeiten.",
"addN8nNameLabel": "Name (keine Punkte)",
"addN8nNameHint": "ops",
"addN8nBaseUrlLabel": "Basis-URL (ohne /api/v1)",
@ -102,7 +104,7 @@
"channelsEnableAutostart": "Autostart bei Anmeldung aktivieren",
"channelsDisableAutostart": "Autostart deaktivieren",
"storeSearchHint": "Module suchen — Name, Tagline, Tag, Capability…",
"storeSearchHint": "Module suchen — Name, Tagline, Tag, Fähigkeit…",
"storeAskHint": "Was brauchst du? Versuch's mit „ein Modul, das tabellarische Daten liest\" oder tippe einfach einen Begriff.",
"storeAskSubmit": "Suchen",
"storeAskAi": "KI fragen",
@ -187,7 +189,7 @@
"storeOpenBrowserFailed": "Browser konnte nicht geöffnet werden: {error}",
"@storeOpenBrowserFailed": { "placeholders": { "error": { "type": "String" } } },
"storeSectionTags": "Tags",
"storeSectionRequiredCapabilities": "Erforderliche Capabilities",
"storeSectionRequiredCapabilities": "Erforderliche Fähigkeiten",
"storeSectionRequiredHostServices": "Erforderliche Host-Dienste",
"storeSectionScreenshots": "Screenshots",
"storeSectionDocumentation": "Dokumentation",
@ -221,19 +223,19 @@
"storeProvenanceN8n": "n8n · {provider}",
"@storeProvenanceN8n": { "placeholders": { "provider": { "type": "String" } } },
"storeRecommendedTitle": "Öffentliche Quelle hinzufügen — ein Klick",
"storeRecommendedBody": "Kuratierte MCP-Server über HTTPS erreichbar. Kein Subprozess, kein API-Key, kein Node. Föderierte Capabilities erscheinen sofort im Store.",
"storeRecommendedBody": "Kuratierte MCP-Server über HTTPS erreichbar. Kein Subprozess, kein API-Key, kein Node. Föderierte Fähigkeiten erscheinen sofort im Store.",
"storeRecommendedAddTooltip": "Hinzufügen und entdecken",
"storeRecommendedAdding": "Wird hinzugefügt…",
"storeRecommendedDeepWikiTagline": "GitHub-Repo-Doku-Suche (KI-gestützt)",
"storeRecommendedSemgrepTagline": "Security-Scanning für Code-Schwachstellen",
"storeProviderAddedToast": "{name} hinzugefügt — {n} {n, plural, =1{föderierte Capability} other{föderierte Capabilities}}.",
"storeProviderAddedToast": "{name} hinzugefügt — {n} {n, plural, =1{föderierte Fähigkeit} other{föderierte Fähigkeiten}}.",
"@storeProviderAddedToast": {
"placeholders": {
"name": { "type": "String" },
"n": { "type": "int" }
}
},
"storeProviderAddedZeroToast": "{name} ist eingetragen, aber der Server hat noch keine Capabilities geliefert. Öffne Einstellungen → MCP-Clients, um Discovery erneut zu versuchen oder den Server zu prüfen.",
"storeProviderAddedZeroToast": "{name} ist eingetragen, aber der Server hat noch keine Fähigkeiten geliefert. Öffne Einstellungen → MCP-Clients, um Discovery erneut zu versuchen oder den Server zu prüfen.",
"@storeProviderAddedZeroToast": {
"placeholders": { "name": { "type": "String" } }
},
@ -253,7 +255,7 @@
"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": "{n} Ereignisse auf Kanal „{channel}\" gelöscht. Kette mit Marker neu geseedet.",
"@auditClearedToast": {
"placeholders": {
"n": { "type": "int" },
@ -276,7 +278,7 @@
"@auditLiveStatus": { "placeholders": { "n": { "type": "int" } } },
"auditDisconnected": "getrennt · {error}",
"@auditDisconnected": { "placeholders": { "error": { "type": "String" } } },
"auditHashChainVerified": "Hash-Chain verifiziert",
"auditHashChainVerified": "Hash-Kette verifiziert",
"auditDetailHeader": "DETAIL",
"auditAskingFull": "Frage an die konfigurierte System-AI läuft…",
"auditFixLabel": "FIX",
@ -308,7 +310,7 @@
"@modulesRecentActivityHint": { "placeholders": { "n": { "type": "int" } } },
"modulesActivityInstalled": "installiert",
"modulesActivityUninstalled": "deinstalliert",
"modulesCapabilitiesLabel": "Capabilities",
"modulesCapabilitiesLabel": "Fähigkeiten",
"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": {
@ -329,7 +331,7 @@
"modulesUninstalling": "Wird deinstalliert…",
"moduleSheetFailedToLoad": "Laden fehlgeschlagen: {error}",
"@moduleSheetFailedToLoad": { "placeholders": { "error": { "type": "String" } } },
"moduleSheetCapabilities": "Capabilities",
"moduleSheetCapabilities": "Fähigkeiten",
"moduleSheetPermissions": "Deklarierte Berechtigungen",
"moduleSheetNoPermissions": "(keine — reines Berechnungsmodul)",
@ -381,7 +383,7 @@
"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.",
"approvalsHistoryEmptyHint": "Entschiedene Freigaben (freigegeben / abgelehnt / abgelaufen) erscheinen hier.\nDas Audit-Log enthält den vollständigen hash-verketteten Datensatz.",
"approvalsDialogDecided": "entschieden",
"approvalsDialogCreated": "erstellt",
"approvalsDialogReason": "Begründung",
@ -396,10 +398,10 @@
"doctorSummaryApprovals": "Freigaben",
"doctorSummaryAudit": "Protokoll",
"doctorSummaryServices": "Dienste",
"doctorSummaryCapabilities": "{n} Capabilities",
"doctorSummaryCapabilities": "{n} Fähigkeiten",
"@doctorSummaryCapabilities": { "placeholders": { "n": { "type": "int" } } },
"doctorSummaryPending": "offen",
"doctorSummaryChain": "{verified}/{total} Chain",
"doctorSummaryChain": "{verified}/{total} Kette",
"@doctorSummaryChain": {
"placeholders": {
"verified": { "type": "int" },
@ -407,7 +409,7 @@
}
},
"doctorSummaryDeclared": "deklariert",
"doctorModulesPanelSummary": "{n} Module · {m} Capabilities",
"doctorModulesPanelSummary": "{n} Module · {m} Fähigkeiten",
"@doctorModulesPanelSummary": {
"placeholders": {
"n": { "type": "int" },
@ -428,7 +430,7 @@
"doctorHostServicesSection": "Host-Dienste",
"doctorDaemonFilesSection": "Daemon-Dateien",
"doctorDaemonControlSection": "Daemon-Steuerung",
"doctorChainIntact": "Hash-Chain intakt",
"doctorChainIntact": "Hash-Kette intakt",
"doctorChainIntactDetail": "{n} Ereignisse · prev_event_sha256 lückenlos verifiziert",
"@doctorChainIntactDetail": { "placeholders": { "n": { "type": "int" } } },
"doctorChainTampered": "Manipulation erkannt",
@ -491,10 +493,10 @@
"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.",
"mcpHint": "Externe MCP-Server bringen ihre Tools als `mcp.<server>.<tool>` Fähigkeiten ein. Einmal konfigurieren, im Store sichtbar.",
"mcpEmpty": "Keine MCP-Server konfiguriert. + klicken zum Hinzufügen.",
"n8nHeader": "N8N-ENDPUNKTE",
"n8nHint": "Aktive n8n-Workflows erscheinen als `n8n.<endpoint>.<slug>` Capabilities. Einmal konfigurieren, im Store sichtbar.",
"n8nHint": "Aktive n8n-Workflows erscheinen als `n8n.<endpoint>.<slug>` Fähigkeiten. Einmal konfigurieren, im Store sichtbar.",
"n8nEmpty": "Keine n8n-Endpunkte konfiguriert. + klicken zum Hinzufügen.",
"hubUnreachable": "Hub nicht erreichbar",