feat(studio): Flows + Module sheet + System-AI editor i18n (v0.28.0)

- Localize Flows page: app-bar title and reload tooltip,
  hub-unreachable / no-saved-flows empty states, run-flow input
  dialog (title with flow name, description, hint, Cancel /
  Run), running dialog (title, "Flow running…" status, no-output
  message, Close button), flow-card Run button.
- Localize the module-sheet bottom sheet: failed-to-load text,
  Capabilities and "Declared permissions" section headers,
  no-permissions placeholder copy.
- Localize the System-AI configuration dialog: title, intro
  paragraph, provider dropdown label, endpoint label, API-key
  env-var label (required vs optional) and disclaimer, privacy
  mode header and three options (Off / Redacted / Full) plus
  their descriptions, test-result panel ("Connection ok" /
  "Connection failed", "Reply: …" prefix), model picker (label,
  hint fallback, helper text with Ollama variant, Refresh /
  Pull / Pulling… buttons, list errors and empty states),
  hardware banner ("Detected: …" + " · curation reviewed …"
  suffix), suitability legend (recommended / balanced / small /
  large / huge / unknown), cache row with pluralized count and
  Clear button, cache cleared / clear-failed toasts, pull-empty
  / pull-failed errors. Suitability label moved off a getter
  onto a `labelFor(BuildContext)` method so it can read the
  current locale.

Provider preset descriptions and modelHint strings stay in
English in `_ProviderPreset.all` — they're tightly coupled to
the wire-protocol identifiers and would require a runtime
factory rebuild rather than a const list.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
flemming-it 2026-05-08 02:59:08 +02:00
parent e2b2639a86
commit b5a4c74c4b
10 changed files with 1120 additions and 91 deletions

View file

@ -263,6 +263,25 @@
"modulesUninstallFailed": "Deinstallation fehlgeschlagen: {error}",
"@modulesUninstallFailed": { "placeholders": { "error": { "type": "String" } } },
"modulesUninstalling": "Wird deinstalliert…",
"moduleSheetFailedToLoad": "Laden fehlgeschlagen: {error}",
"@moduleSheetFailedToLoad": { "placeholders": { "error": { "type": "String" } } },
"moduleSheetCapabilities": "Capabilities",
"moduleSheetPermissions": "Deklarierte Berechtigungen",
"moduleSheetNoPermissions": "(keine — reines Berechnungsmodul)",
"flowsTitle": "Flows",
"flowsReloadTooltip": "Aktualisieren",
"flowsNoneTitle": "Keine gespeicherten Flows",
"flowsNoneHint": "Flow speichern mit `fai admin flows save <name> <flow.yaml>`, dann taucht er hier auf.",
"flowsRunDialogTitle": "{name} ausführen",
"@flowsRunDialogTitle": { "placeholders": { "name": { "type": "String" } } },
"flowsRunDialogBody": "Eingaben als key=value, eine pro Zeile. Alle Werte werden als Text-Payloads gesendet. Für binäre Eingaben die `fai run` CLI nutzen.",
"flowsInputsHint": "name=World\ntarget_language=English\nsummary_style=three bullet points",
"flowsRunButton": "Starten",
"flowsRunningTitle": "{name} läuft",
"@flowsRunningTitle": { "placeholders": { "name": { "type": "String" } } },
"flowsRunning": "Flow läuft…",
"flowsNoOutputs": "Flow abgeschlossen ohne deklarierte Outputs.",
"approvalsTitle": "Freigaben",
"approvalsTabPending": "Offen",
@ -411,5 +430,65 @@
"@searchStoreHintWithTagline": { "placeholders": { "tagline": { "type": "String" } } },
"searchStoreHintWithCategory": "Store · {category}",
"@searchStoreHintWithCategory": { "placeholders": { "category": { "type": "String" } } },
"searchSavedFlowHint": "gespeicherter Flow"
"searchSavedFlowHint": "gespeicherter Flow",
"systemAiTitle": "System-AI",
"systemAiIntro": "Die hub-interne LLM, die die Plattform selbst für Fehlererklärungen und Operator-Hilfe nutzt. Standardmäßig aus; hier konfigurieren. Siehe docs/architecture/system-ai.md, was über die Leitung geht.",
"systemAiProviderLabel": "Provider",
"systemAiEndpointLabel": "Endpunkt-URL (bis /v1)",
"systemAiApiKeyRequired": "API-Key-Umgebungsvariable (erforderlich)",
"systemAiApiKeyOptional": "API-Key-Umgebungsvariable (optional)",
"systemAiApiKeyDisclaimer": "Studio liest oder speichert den Key-Wert nie — nur den Namen der Umgebungsvariable. Der Hub liest `${name}` zur Anfragezeit.",
"@systemAiApiKeyDisclaimer": { "placeholders": { "name": { "type": "String" } } },
"systemAiTestConnection": "Verbindung testen",
"systemAiTesting": "Teste…",
"systemAiSave": "Speichern",
"systemAiPrivacyHeader": "PRIVACY-MODUS",
"systemAiPrivacyOffLabel": "Aus",
"systemAiPrivacyOffDesc": "Feature deaktiviert. Keine Anfragen verlassen den Hub.",
"systemAiPrivacyRedactedLabel": "Redigiert",
"systemAiPrivacyRedactedDesc": "Nur event_type / error / Modul-Namen. KRITIS-freundlicher Standard.",
"systemAiPrivacyFullLabel": "Voll",
"systemAiPrivacyFullDesc": "Enthält das Audit-Detail-JSON (nur Hash — keine Roh-Payloads).",
"systemAiConnectionOk": "Verbindung ok",
"systemAiConnectionFailed": "Verbindung fehlgeschlagen",
"systemAiReplyPrefix": "Antwort: {text}",
"@systemAiReplyPrefix": { "placeholders": { "text": { "type": "String" } } },
"systemAiModelLabel": "Modell (erforderlich)",
"systemAiModelHintFallback": "Modell-Identifier, den der Provider erwartet",
"systemAiModelHelperBase": "Erforderlich: aus der Liste auswählen (Aktualisieren) oder eintippen.",
"systemAiModelHelperOllama": "Erforderlich: aus der Liste auswählen (Aktualisieren) oder eintippen. Mit Pull von Ollama herunterladen.",
"systemAiRefresh": "Aktualisieren",
"systemAiPull": "Pull",
"systemAiPulling": "Lade…",
"systemAiCouldNotListModels": "Modelle konnten nicht aufgelistet werden: {error}",
"@systemAiCouldNotListModels": { "placeholders": { "error": { "type": "String" } } },
"systemAiNoModelsOllama": "Noch keine Modelle auf dem Ollama-Server. Oben eintippen und Pull klicken.",
"systemAiNoModelsGeneric": "Provider lieferte keine Modelle.",
"systemAiSuitabilityRecommended": "empfohlen",
"systemAiSuitabilityBalanced": "ausgewogen",
"systemAiSuitabilitySmall": "klein — Qualität evtl. eingeschränkt",
"systemAiSuitabilityLarge": "groß — langsamer",
"systemAiSuitabilityHuge": "sehr groß — auf einem Laptop wahrscheinlich zu langsam",
"systemAiSuitabilityUnknown": "Größe unbekannt",
"systemAiHwDetected": "Erkannt: {summary}",
"@systemAiHwDetected": { "placeholders": { "summary": { "type": "String" } } },
"systemAiHwReviewed": " · Kuratierung geprüft {date}",
"@systemAiHwReviewed": { "placeholders": { "date": { "type": "String" } } },
"systemAiLegendRecommended": "empfohlen für diese Hardware{tier}",
"@systemAiLegendRecommended": { "placeholders": { "tier": { "type": "String" } } },
"systemAiLegendBalanced": "ausgewogen (4-8B)",
"systemAiLegendSmallLarge": "klein <3B / groß 9-15B / über Hardware",
"systemAiLegendHuge": "sehr groß >15B",
"systemAiLegendUnknown": "Größe unbekannt",
"systemAiCacheRow": "Cache: {n} {n, plural, =1{gespeicherte Erklärung} other{gespeicherte Erklärungen}}. Identische Prompts treffen den Cache; Modell- oder Privacy-Modus-Wechsel leeren ihn automatisch.",
"@systemAiCacheRow": { "placeholders": { "n": { "type": "int" } } },
"systemAiCacheClear": "Leeren",
"systemAiCacheClearedToast": "{n} gespeicherte System-AI-Erklärungen gelöscht.",
"@systemAiCacheClearedToast": { "placeholders": { "n": { "type": "int" } } },
"systemAiCacheClearFailed": "Cache-Löschen fehlgeschlagen: {error}",
"@systemAiCacheClearFailed": { "placeholders": { "error": { "type": "String" } } },
"systemAiPullEmptyError": "Erst eine Modell-ID eintippen (z.B. gemma3:4b).",
"systemAiPullFailedError": "Pull fehlgeschlagen: {error}",
"@systemAiPullFailedError": { "placeholders": { "error": { "type": "String" } } }
}

View file

@ -264,6 +264,25 @@
"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",
@ -412,5 +431,65 @@
"@searchStoreHintWithTagline": { "placeholders": { "tagline": { "type": "String" } } },
"searchStoreHintWithCategory": "store · {category}",
"@searchStoreHintWithCategory": { "placeholders": { "category": { "type": "String" } } },
"searchSavedFlowHint": "saved flow"
"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" } } }
}

View file

@ -1196,6 +1196,96 @@ abstract class AppLocalizations {
/// **'Uninstalling…'**
String get modulesUninstalling;
/// No description provided for @moduleSheetFailedToLoad.
///
/// In en, this message translates to:
/// **'Failed to load: {error}'**
String moduleSheetFailedToLoad(String error);
/// No description provided for @moduleSheetCapabilities.
///
/// In en, this message translates to:
/// **'Capabilities'**
String get moduleSheetCapabilities;
/// No description provided for @moduleSheetPermissions.
///
/// In en, this message translates to:
/// **'Declared permissions'**
String get moduleSheetPermissions;
/// No description provided for @moduleSheetNoPermissions.
///
/// In en, this message translates to:
/// **'(none — pure-computation module)'**
String get moduleSheetNoPermissions;
/// No description provided for @flowsTitle.
///
/// In en, this message translates to:
/// **'Flows'**
String get flowsTitle;
/// No description provided for @flowsReloadTooltip.
///
/// In en, this message translates to:
/// **'Reload'**
String get flowsReloadTooltip;
/// No description provided for @flowsNoneTitle.
///
/// In en, this message translates to:
/// **'No saved flows'**
String get flowsNoneTitle;
/// No description provided for @flowsNoneHint.
///
/// In en, this message translates to:
/// **'Save a flow with `fai admin flows save <name> <flow.yaml>` and it shows up here.'**
String get flowsNoneHint;
/// No description provided for @flowsRunDialogTitle.
///
/// In en, this message translates to:
/// **'Run {name}'**
String flowsRunDialogTitle(String name);
/// No description provided for @flowsRunDialogBody.
///
/// In en, this message translates to:
/// **'Inputs as key=value, one per line. All values are sent as text payloads. For binary inputs use the `fai run` CLI.'**
String get flowsRunDialogBody;
/// No description provided for @flowsInputsHint.
///
/// In en, this message translates to:
/// **'name=World\ntarget_language=English\nsummary_style=three bullet points'**
String get flowsInputsHint;
/// No description provided for @flowsRunButton.
///
/// In en, this message translates to:
/// **'Run'**
String get flowsRunButton;
/// No description provided for @flowsRunningTitle.
///
/// In en, this message translates to:
/// **'Running {name}'**
String flowsRunningTitle(String name);
/// No description provided for @flowsRunning.
///
/// In en, this message translates to:
/// **'Flow running…'**
String get flowsRunning;
/// No description provided for @flowsNoOutputs.
///
/// In en, this message translates to:
/// **'Flow completed with no declared outputs.'**
String get flowsNoOutputs;
/// No description provided for @approvalsTitle.
///
/// In en, this message translates to:
@ -1783,6 +1873,300 @@ abstract class AppLocalizations {
/// In en, this message translates to:
/// **'saved flow'**
String get searchSavedFlowHint;
/// No description provided for @systemAiTitle.
///
/// In en, this message translates to:
/// **'System AI'**
String get systemAiTitle;
/// No description provided for @systemAiIntro.
///
/// In en, this message translates to:
/// **'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.'**
String get systemAiIntro;
/// No description provided for @systemAiProviderLabel.
///
/// In en, this message translates to:
/// **'Provider'**
String get systemAiProviderLabel;
/// No description provided for @systemAiEndpointLabel.
///
/// In en, this message translates to:
/// **'Endpoint URL (up to /v1)'**
String get systemAiEndpointLabel;
/// No description provided for @systemAiApiKeyRequired.
///
/// In en, this message translates to:
/// **'API key env var (required)'**
String get systemAiApiKeyRequired;
/// No description provided for @systemAiApiKeyOptional.
///
/// In en, this message translates to:
/// **'API key env var (optional)'**
String get systemAiApiKeyOptional;
/// No description provided for @systemAiApiKeyDisclaimer.
///
/// In en, this message translates to:
/// **'Studio never reads or stores the key value — only its env-var name. The hub reads `\${name}` at request time.'**
String systemAiApiKeyDisclaimer(String name);
/// No description provided for @systemAiTestConnection.
///
/// In en, this message translates to:
/// **'Test connection'**
String get systemAiTestConnection;
/// No description provided for @systemAiTesting.
///
/// In en, this message translates to:
/// **'Testing…'**
String get systemAiTesting;
/// No description provided for @systemAiSave.
///
/// In en, this message translates to:
/// **'Save'**
String get systemAiSave;
/// No description provided for @systemAiPrivacyHeader.
///
/// In en, this message translates to:
/// **'PRIVACY MODE'**
String get systemAiPrivacyHeader;
/// No description provided for @systemAiPrivacyOffLabel.
///
/// In en, this message translates to:
/// **'Off'**
String get systemAiPrivacyOffLabel;
/// No description provided for @systemAiPrivacyOffDesc.
///
/// In en, this message translates to:
/// **'Feature disabled. No requests leave the hub.'**
String get systemAiPrivacyOffDesc;
/// No description provided for @systemAiPrivacyRedactedLabel.
///
/// In en, this message translates to:
/// **'Redacted'**
String get systemAiPrivacyRedactedLabel;
/// No description provided for @systemAiPrivacyRedactedDesc.
///
/// In en, this message translates to:
/// **'Only event_type / error / module names. KRITIS-friendly default.'**
String get systemAiPrivacyRedactedDesc;
/// No description provided for @systemAiPrivacyFullLabel.
///
/// In en, this message translates to:
/// **'Full'**
String get systemAiPrivacyFullLabel;
/// No description provided for @systemAiPrivacyFullDesc.
///
/// In en, this message translates to:
/// **'Includes the audit detail JSON (hash-only — no raw payloads).'**
String get systemAiPrivacyFullDesc;
/// No description provided for @systemAiConnectionOk.
///
/// In en, this message translates to:
/// **'Connection ok'**
String get systemAiConnectionOk;
/// No description provided for @systemAiConnectionFailed.
///
/// In en, this message translates to:
/// **'Connection failed'**
String get systemAiConnectionFailed;
/// No description provided for @systemAiReplyPrefix.
///
/// In en, this message translates to:
/// **'Reply: {text}'**
String systemAiReplyPrefix(String text);
/// No description provided for @systemAiModelLabel.
///
/// In en, this message translates to:
/// **'Model (required)'**
String get systemAiModelLabel;
/// No description provided for @systemAiModelHintFallback.
///
/// In en, this message translates to:
/// **'model identifier the provider expects'**
String get systemAiModelHintFallback;
/// No description provided for @systemAiModelHelperBase.
///
/// In en, this message translates to:
/// **'Required: pick from the list (Refresh) or type one.'**
String get systemAiModelHelperBase;
/// No description provided for @systemAiModelHelperOllama.
///
/// In en, this message translates to:
/// **'Required: pick from the list (Refresh) or type one. Use Pull to download from Ollama.'**
String get systemAiModelHelperOllama;
/// No description provided for @systemAiRefresh.
///
/// In en, this message translates to:
/// **'Refresh'**
String get systemAiRefresh;
/// No description provided for @systemAiPull.
///
/// In en, this message translates to:
/// **'Pull'**
String get systemAiPull;
/// No description provided for @systemAiPulling.
///
/// In en, this message translates to:
/// **'Pulling…'**
String get systemAiPulling;
/// No description provided for @systemAiCouldNotListModels.
///
/// In en, this message translates to:
/// **'Could not list models: {error}'**
String systemAiCouldNotListModels(String error);
/// No description provided for @systemAiNoModelsOllama.
///
/// In en, this message translates to:
/// **'No models on the Ollama server yet. Type one above and click Pull.'**
String get systemAiNoModelsOllama;
/// No description provided for @systemAiNoModelsGeneric.
///
/// In en, this message translates to:
/// **'Provider returned no models.'**
String get systemAiNoModelsGeneric;
/// No description provided for @systemAiSuitabilityRecommended.
///
/// In en, this message translates to:
/// **'recommended'**
String get systemAiSuitabilityRecommended;
/// No description provided for @systemAiSuitabilityBalanced.
///
/// In en, this message translates to:
/// **'balanced'**
String get systemAiSuitabilityBalanced;
/// No description provided for @systemAiSuitabilitySmall.
///
/// In en, this message translates to:
/// **'small — quality may be limited'**
String get systemAiSuitabilitySmall;
/// No description provided for @systemAiSuitabilityLarge.
///
/// In en, this message translates to:
/// **'large — slower'**
String get systemAiSuitabilityLarge;
/// No description provided for @systemAiSuitabilityHuge.
///
/// In en, this message translates to:
/// **'huge — likely too slow on a laptop'**
String get systemAiSuitabilityHuge;
/// No description provided for @systemAiSuitabilityUnknown.
///
/// In en, this message translates to:
/// **'size unknown'**
String get systemAiSuitabilityUnknown;
/// No description provided for @systemAiHwDetected.
///
/// In en, this message translates to:
/// **'Detected: {summary}'**
String systemAiHwDetected(String summary);
/// No description provided for @systemAiHwReviewed.
///
/// In en, this message translates to:
/// **' · curation reviewed {date}'**
String systemAiHwReviewed(String date);
/// No description provided for @systemAiLegendRecommended.
///
/// In en, this message translates to:
/// **'recommended for this hardware{tier}'**
String systemAiLegendRecommended(String tier);
/// No description provided for @systemAiLegendBalanced.
///
/// In en, this message translates to:
/// **'balanced (4-8B)'**
String get systemAiLegendBalanced;
/// No description provided for @systemAiLegendSmallLarge.
///
/// In en, this message translates to:
/// **'small <3B / large 9-15B / above hardware'**
String get systemAiLegendSmallLarge;
/// No description provided for @systemAiLegendHuge.
///
/// In en, this message translates to:
/// **'huge >15B'**
String get systemAiLegendHuge;
/// No description provided for @systemAiLegendUnknown.
///
/// In en, this message translates to:
/// **'size unknown'**
String get systemAiLegendUnknown;
/// No description provided for @systemAiCacheRow.
///
/// In en, this message translates to:
/// **'Cache: {n} cached {n, plural, =1{explanation} other{explanations}}. Identical prompts hit the cache; switching model or privacy mode flushes automatically.'**
String systemAiCacheRow(int n);
/// No description provided for @systemAiCacheClear.
///
/// In en, this message translates to:
/// **'Clear'**
String get systemAiCacheClear;
/// No description provided for @systemAiCacheClearedToast.
///
/// In en, this message translates to:
/// **'Cleared {n} cached System-AI explanations.'**
String systemAiCacheClearedToast(int n);
/// No description provided for @systemAiCacheClearFailed.
///
/// In en, this message translates to:
/// **'Cache clear failed: {error}'**
String systemAiCacheClearFailed(String error);
/// No description provided for @systemAiPullEmptyError.
///
/// In en, this message translates to:
/// **'Type a model id (e.g. gemma3:4b) first.'**
String get systemAiPullEmptyError;
/// No description provided for @systemAiPullFailedError.
///
/// In en, this message translates to:
/// **'Pull failed: {error}'**
String systemAiPullFailedError(String error);
}
class _AppLocalizationsDelegate

View file

@ -663,6 +663,60 @@ class AppLocalizationsDe extends AppLocalizations {
@override
String get modulesUninstalling => 'Wird deinstalliert…';
@override
String moduleSheetFailedToLoad(String error) {
return 'Laden fehlgeschlagen: $error';
}
@override
String get moduleSheetCapabilities => 'Capabilities';
@override
String get moduleSheetPermissions => 'Deklarierte Berechtigungen';
@override
String get moduleSheetNoPermissions => '(keine — reines Berechnungsmodul)';
@override
String get flowsTitle => 'Flows';
@override
String get flowsReloadTooltip => 'Aktualisieren';
@override
String get flowsNoneTitle => 'Keine gespeicherten Flows';
@override
String get flowsNoneHint =>
'Flow speichern mit `fai admin flows save <name> <flow.yaml>`, dann taucht er hier auf.';
@override
String flowsRunDialogTitle(String name) {
return '$name ausführen';
}
@override
String get flowsRunDialogBody =>
'Eingaben als key=value, eine pro Zeile. Alle Werte werden als Text-Payloads gesendet. Für binäre Eingaben die `fai run` CLI nutzen.';
@override
String get flowsInputsHint =>
'name=World\ntarget_language=English\nsummary_style=three bullet points';
@override
String get flowsRunButton => 'Starten';
@override
String flowsRunningTitle(String name) {
return '$name läuft';
}
@override
String get flowsRunning => 'Flow läuft…';
@override
String get flowsNoOutputs => 'Flow abgeschlossen ohne deklarierte Outputs.';
@override
String get approvalsTitle => 'Freigaben';
@ -1005,4 +1059,189 @@ class AppLocalizationsDe extends AppLocalizations {
@override
String get searchSavedFlowHint => 'gespeicherter Flow';
@override
String get systemAiTitle => 'System-AI';
@override
String get systemAiIntro =>
'Die hub-interne LLM, die die Plattform selbst für Fehlererklärungen und Operator-Hilfe nutzt. Standardmäßig aus; hier konfigurieren. Siehe docs/architecture/system-ai.md, was über die Leitung geht.';
@override
String get systemAiProviderLabel => 'Provider';
@override
String get systemAiEndpointLabel => 'Endpunkt-URL (bis /v1)';
@override
String get systemAiApiKeyRequired =>
'API-Key-Umgebungsvariable (erforderlich)';
@override
String get systemAiApiKeyOptional => 'API-Key-Umgebungsvariable (optional)';
@override
String systemAiApiKeyDisclaimer(String name) {
return 'Studio liest oder speichert den Key-Wert nie — nur den Namen der Umgebungsvariable. Der Hub liest `\$$name` zur Anfragezeit.';
}
@override
String get systemAiTestConnection => 'Verbindung testen';
@override
String get systemAiTesting => 'Teste…';
@override
String get systemAiSave => 'Speichern';
@override
String get systemAiPrivacyHeader => 'PRIVACY-MODUS';
@override
String get systemAiPrivacyOffLabel => 'Aus';
@override
String get systemAiPrivacyOffDesc =>
'Feature deaktiviert. Keine Anfragen verlassen den Hub.';
@override
String get systemAiPrivacyRedactedLabel => 'Redigiert';
@override
String get systemAiPrivacyRedactedDesc =>
'Nur event_type / error / Modul-Namen. KRITIS-freundlicher Standard.';
@override
String get systemAiPrivacyFullLabel => 'Voll';
@override
String get systemAiPrivacyFullDesc =>
'Enthält das Audit-Detail-JSON (nur Hash — keine Roh-Payloads).';
@override
String get systemAiConnectionOk => 'Verbindung ok';
@override
String get systemAiConnectionFailed => 'Verbindung fehlgeschlagen';
@override
String systemAiReplyPrefix(String text) {
return 'Antwort: $text';
}
@override
String get systemAiModelLabel => 'Modell (erforderlich)';
@override
String get systemAiModelHintFallback =>
'Modell-Identifier, den der Provider erwartet';
@override
String get systemAiModelHelperBase =>
'Erforderlich: aus der Liste auswählen (Aktualisieren) oder eintippen.';
@override
String get systemAiModelHelperOllama =>
'Erforderlich: aus der Liste auswählen (Aktualisieren) oder eintippen. Mit Pull von Ollama herunterladen.';
@override
String get systemAiRefresh => 'Aktualisieren';
@override
String get systemAiPull => 'Pull';
@override
String get systemAiPulling => 'Lade…';
@override
String systemAiCouldNotListModels(String error) {
return 'Modelle konnten nicht aufgelistet werden: $error';
}
@override
String get systemAiNoModelsOllama =>
'Noch keine Modelle auf dem Ollama-Server. Oben eintippen und Pull klicken.';
@override
String get systemAiNoModelsGeneric => 'Provider lieferte keine Modelle.';
@override
String get systemAiSuitabilityRecommended => 'empfohlen';
@override
String get systemAiSuitabilityBalanced => 'ausgewogen';
@override
String get systemAiSuitabilitySmall => 'klein — Qualität evtl. eingeschränkt';
@override
String get systemAiSuitabilityLarge => 'groß — langsamer';
@override
String get systemAiSuitabilityHuge =>
'sehr groß — auf einem Laptop wahrscheinlich zu langsam';
@override
String get systemAiSuitabilityUnknown => 'Größe unbekannt';
@override
String systemAiHwDetected(String summary) {
return 'Erkannt: $summary';
}
@override
String systemAiHwReviewed(String date) {
return ' · Kuratierung geprüft $date';
}
@override
String systemAiLegendRecommended(String tier) {
return 'empfohlen für diese Hardware$tier';
}
@override
String get systemAiLegendBalanced => 'ausgewogen (4-8B)';
@override
String get systemAiLegendSmallLarge =>
'klein <3B / groß 9-15B / über Hardware';
@override
String get systemAiLegendHuge => 'sehr groß >15B';
@override
String get systemAiLegendUnknown => 'Größe unbekannt';
@override
String systemAiCacheRow(int n) {
String _temp0 = intl.Intl.pluralLogic(
n,
locale: localeName,
other: 'gespeicherte Erklärungen',
one: 'gespeicherte Erklärung',
);
return 'Cache: $n $_temp0. Identische Prompts treffen den Cache; Modell- oder Privacy-Modus-Wechsel leeren ihn automatisch.';
}
@override
String get systemAiCacheClear => 'Leeren';
@override
String systemAiCacheClearedToast(int n) {
return '$n gespeicherte System-AI-Erklärungen gelöscht.';
}
@override
String systemAiCacheClearFailed(String error) {
return 'Cache-Löschen fehlgeschlagen: $error';
}
@override
String get systemAiPullEmptyError =>
'Erst eine Modell-ID eintippen (z.B. gemma3:4b).';
@override
String systemAiPullFailedError(String error) {
return 'Pull fehlgeschlagen: $error';
}
}

View file

@ -679,6 +679,60 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get modulesUninstalling => 'Uninstalling…';
@override
String moduleSheetFailedToLoad(String error) {
return 'Failed to load: $error';
}
@override
String get moduleSheetCapabilities => 'Capabilities';
@override
String get moduleSheetPermissions => 'Declared permissions';
@override
String get moduleSheetNoPermissions => '(none — pure-computation module)';
@override
String get flowsTitle => 'Flows';
@override
String get flowsReloadTooltip => 'Reload';
@override
String get flowsNoneTitle => 'No saved flows';
@override
String get flowsNoneHint =>
'Save a flow with `fai admin flows save <name> <flow.yaml>` and it shows up here.';
@override
String flowsRunDialogTitle(String name) {
return 'Run $name';
}
@override
String get flowsRunDialogBody =>
'Inputs as key=value, one per line. All values are sent as text payloads. For binary inputs use the `fai run` CLI.';
@override
String get flowsInputsHint =>
'name=World\ntarget_language=English\nsummary_style=three bullet points';
@override
String get flowsRunButton => 'Run';
@override
String flowsRunningTitle(String name) {
return 'Running $name';
}
@override
String get flowsRunning => 'Flow running…';
@override
String get flowsNoOutputs => 'Flow completed with no declared outputs.';
@override
String get approvalsTitle => 'Approvals';
@ -1017,4 +1071,187 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get searchSavedFlowHint => 'saved flow';
@override
String get systemAiTitle => 'System AI';
@override
String get 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.';
@override
String get systemAiProviderLabel => 'Provider';
@override
String get systemAiEndpointLabel => 'Endpoint URL (up to /v1)';
@override
String get systemAiApiKeyRequired => 'API key env var (required)';
@override
String get systemAiApiKeyOptional => 'API key env var (optional)';
@override
String systemAiApiKeyDisclaimer(String name) {
return 'Studio never reads or stores the key value — only its env-var name. The hub reads `\$$name` at request time.';
}
@override
String get systemAiTestConnection => 'Test connection';
@override
String get systemAiTesting => 'Testing…';
@override
String get systemAiSave => 'Save';
@override
String get systemAiPrivacyHeader => 'PRIVACY MODE';
@override
String get systemAiPrivacyOffLabel => 'Off';
@override
String get systemAiPrivacyOffDesc =>
'Feature disabled. No requests leave the hub.';
@override
String get systemAiPrivacyRedactedLabel => 'Redacted';
@override
String get systemAiPrivacyRedactedDesc =>
'Only event_type / error / module names. KRITIS-friendly default.';
@override
String get systemAiPrivacyFullLabel => 'Full';
@override
String get systemAiPrivacyFullDesc =>
'Includes the audit detail JSON (hash-only — no raw payloads).';
@override
String get systemAiConnectionOk => 'Connection ok';
@override
String get systemAiConnectionFailed => 'Connection failed';
@override
String systemAiReplyPrefix(String text) {
return 'Reply: $text';
}
@override
String get systemAiModelLabel => 'Model (required)';
@override
String get systemAiModelHintFallback =>
'model identifier the provider expects';
@override
String get systemAiModelHelperBase =>
'Required: pick from the list (Refresh) or type one.';
@override
String get systemAiModelHelperOllama =>
'Required: pick from the list (Refresh) or type one. Use Pull to download from Ollama.';
@override
String get systemAiRefresh => 'Refresh';
@override
String get systemAiPull => 'Pull';
@override
String get systemAiPulling => 'Pulling…';
@override
String systemAiCouldNotListModels(String error) {
return 'Could not list models: $error';
}
@override
String get systemAiNoModelsOllama =>
'No models on the Ollama server yet. Type one above and click Pull.';
@override
String get systemAiNoModelsGeneric => 'Provider returned no models.';
@override
String get systemAiSuitabilityRecommended => 'recommended';
@override
String get systemAiSuitabilityBalanced => 'balanced';
@override
String get systemAiSuitabilitySmall => 'small — quality may be limited';
@override
String get systemAiSuitabilityLarge => 'large — slower';
@override
String get systemAiSuitabilityHuge => 'huge — likely too slow on a laptop';
@override
String get systemAiSuitabilityUnknown => 'size unknown';
@override
String systemAiHwDetected(String summary) {
return 'Detected: $summary';
}
@override
String systemAiHwReviewed(String date) {
return ' · curation reviewed $date';
}
@override
String systemAiLegendRecommended(String tier) {
return 'recommended for this hardware$tier';
}
@override
String get systemAiLegendBalanced => 'balanced (4-8B)';
@override
String get systemAiLegendSmallLarge =>
'small <3B / large 9-15B / above hardware';
@override
String get systemAiLegendHuge => 'huge >15B';
@override
String get systemAiLegendUnknown => 'size unknown';
@override
String systemAiCacheRow(int n) {
String _temp0 = intl.Intl.pluralLogic(
n,
locale: localeName,
other: 'explanations',
one: 'explanation',
);
return 'Cache: $n cached $_temp0. Identical prompts hit the cache; switching model or privacy mode flushes automatically.';
}
@override
String get systemAiCacheClear => 'Clear';
@override
String systemAiCacheClearedToast(int n) {
return 'Cleared $n cached System-AI explanations.';
}
@override
String systemAiCacheClearFailed(String error) {
return 'Cache clear failed: $error';
}
@override
String get systemAiPullEmptyError =>
'Type a model id (e.g. gemma3:4b) first.';
@override
String systemAiPullFailedError(String error) {
return 'Pull failed: $error';
}
}