When a saved flow is missing modules, each capability pill in the "Needs:" row is now clickable: tap one and a per-item progress dialog walks the bare capability name through installModule, then the flows page refreshes. When more than one capability is missing, an extra "Install all (N)" button runs the same dialog over the whole list sequentially so a fresh operator can take an unrunnable flow and one click later have its dependencies resolved. Also adds a pencil icon next to Run that hands the YAML path to the OS via SystemActions.openInOs — the operator's default editor for .yaml decides what opens. Makes the path next to the flow name actionable instead of decorative. The install dialog renders one row per spec with a status icon (pending circle / spinner / check / error), shows the installed version on success, and surfaces the full error in a copyable FaiErrorBox on failure so the operator can paste it back. Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
1831 lines
43 KiB
Dart
1831 lines
43 KiB
Dart
// ignore: unused_import
|
||
import 'package:intl/intl.dart' as intl;
|
||
import 'app_localizations.dart';
|
||
|
||
// ignore_for_file: type=lint
|
||
|
||
/// The translations for English (`en`).
|
||
class AppLocalizationsEn extends AppLocalizations {
|
||
AppLocalizationsEn([String locale = 'en']) : super(locale);
|
||
|
||
@override
|
||
String get appTitle => 'F∆I Studio';
|
||
|
||
@override
|
||
String get navWelcome => 'Welcome';
|
||
|
||
@override
|
||
String get welcomeHeroTitle => 'F∆I Platform';
|
||
|
||
@override
|
||
String get welcomeHeroSubtitle =>
|
||
'Deterministic workflow engine for AI-assisted document processing in regulated environments.';
|
||
|
||
@override
|
||
String get welcomePillarHubTitle => 'Hub';
|
||
|
||
@override
|
||
String get welcomePillarHubBody =>
|
||
'One Rust binary that loads modules and runs flows. SQLite for state. No Docker, no message broker, no background services to babysit.';
|
||
|
||
@override
|
||
String get welcomePillarModuleTitle => 'Module';
|
||
|
||
@override
|
||
String get welcomePillarModuleBody =>
|
||
'A small WebAssembly component that does one thing. Declares the network endpoints, files, and environment variables it touches; the hub enforces the list.';
|
||
|
||
@override
|
||
String get welcomePillarFlowTitle => 'Flow';
|
||
|
||
@override
|
||
String get welcomePillarFlowBody =>
|
||
'A YAML file that chains modules together. Inputs go in, modules run in declared order, outputs come out — every step recorded in a hash-chained audit log.';
|
||
|
||
@override
|
||
String get welcomeTrustHeader => 'TRUST POSTURE';
|
||
|
||
@override
|
||
String get welcomeTrustSandboxTitle => 'Sandbox by default';
|
||
|
||
@override
|
||
String get welcomeTrustSandboxBody =>
|
||
'Every module ships with an explicit permission list — network endpoints, files, environment variables. The hub enforces it; nothing reaches outside the sandbox without operator approval.';
|
||
|
||
@override
|
||
String get welcomeTrustAuditTitle => 'Tamper-evident audit log';
|
||
|
||
@override
|
||
String get welcomeTrustAuditBody =>
|
||
'Flow runs, install / uninstall actions, approval decisions — all of them write into a hash-chained audit log. The Doctor page verifies the chain end-to-end on every load.';
|
||
|
||
@override
|
||
String get welcomeTrustAirgapTitle => 'Air-gap ready';
|
||
|
||
@override
|
||
String get welcomeTrustAirgapBody =>
|
||
'The whole hub fits in a single binary that runs on Linux, macOS and Windows. Once a module is installed, the flow it powers runs without further network access — perfect for regulated environments.';
|
||
|
||
@override
|
||
String get welcomeDocsHeader => 'DOCUMENTATION';
|
||
|
||
@override
|
||
String get welcomeDocsBody =>
|
||
'Operator-facing explainers, rendered inline. No browser, no external link — air-gap-friendly.';
|
||
|
||
@override
|
||
String get welcomeDocArchitectureTitle => 'Architecture in one paragraph';
|
||
|
||
@override
|
||
String get welcomeDocArchitectureBlurb =>
|
||
'Hub, Module, Flow — and how the three fit together.';
|
||
|
||
@override
|
||
String get welcomeDocSecurityTitle => 'Sandbox model';
|
||
|
||
@override
|
||
String get welcomeDocSecurityBlurb =>
|
||
'What a module declares, what the operator caps, what the hub enforces.';
|
||
|
||
@override
|
||
String get welcomeDocAuditTitle => 'Tamper-evident audit log';
|
||
|
||
@override
|
||
String get welcomeDocAuditBlurb =>
|
||
'How the hash chain works and why WORM-1 is enough for KRITIS.';
|
||
|
||
@override
|
||
String get welcomeDocFlowsTitle => 'Flow composition';
|
||
|
||
@override
|
||
String get welcomeDocFlowsBlurb =>
|
||
'YAML basics, templating reference, the extract→summarize example.';
|
||
|
||
@override
|
||
String get welcomeDocClose => 'Close';
|
||
|
||
@override
|
||
String welcomeDocFailedToLoad(String error) {
|
||
return 'Could not load documentation: $error';
|
||
}
|
||
|
||
@override
|
||
String get welcomeChecklistHeader => 'GETTING STARTED';
|
||
|
||
@override
|
||
String get welcomeChecklistBody =>
|
||
'Four steps to a working hub. Live state — refresh after changing anything.';
|
||
|
||
@override
|
||
String get welcomeChecklistAi => 'Configure System AI';
|
||
|
||
@override
|
||
String get welcomeChecklistAiHint =>
|
||
'Settings → System AI. Required for the AI search and inline failure explanations.';
|
||
|
||
@override
|
||
String get welcomeChecklistMcp => 'Add a public capability source';
|
||
|
||
@override
|
||
String get welcomeChecklistMcpHint =>
|
||
'Store → Today hero, or Settings → MCP Clients. DeepWiki and Semgrep are one click each.';
|
||
|
||
@override
|
||
String get welcomeChecklistModule => 'Install a text module';
|
||
|
||
@override
|
||
String get welcomeChecklistModuleHint =>
|
||
'Store → search \"text\" → Install. Try text.extract for PDFs and DOCX.';
|
||
|
||
@override
|
||
String get welcomeChecklistFlow => 'Run a saved flow';
|
||
|
||
@override
|
||
String get welcomeChecklistFlowHint =>
|
||
'Flows → pick one → Run. The bundled extract-summarize.yaml is a good first run.';
|
||
|
||
@override
|
||
String get welcomeChecklistAllDone => 'All four steps complete.';
|
||
|
||
@override
|
||
String get welcomeChecklistDismiss => 'Hide checklist';
|
||
|
||
@override
|
||
String get welcomeChecklistRefresh => 'Refresh';
|
||
|
||
@override
|
||
String get welcomeChecklistRefreshing => 'Checking…';
|
||
|
||
@override
|
||
String get welcomeChecklistDone => 'Done';
|
||
|
||
@override
|
||
String get welcomeChecklistTodo => 'Pending';
|
||
|
||
@override
|
||
String get navDoctor => 'Doctor';
|
||
|
||
@override
|
||
String get navModules => 'Modules';
|
||
|
||
@override
|
||
String get navStore => 'Store';
|
||
|
||
@override
|
||
String get navFlows => 'Flows';
|
||
|
||
@override
|
||
String get navAudit => 'Audit';
|
||
|
||
@override
|
||
String get navApprovals => 'Approvals';
|
||
|
||
@override
|
||
String get connectionConnected => 'connected';
|
||
|
||
@override
|
||
String get connectionUnreachable => 'unreachable';
|
||
|
||
@override
|
||
String get connectionConnecting => 'connecting…';
|
||
|
||
@override
|
||
String get connectionStartHub => 'Start hub';
|
||
|
||
@override
|
||
String get buttonCancel => 'Cancel';
|
||
|
||
@override
|
||
String get buttonSave => 'Save';
|
||
|
||
@override
|
||
String get buttonClose => 'Close';
|
||
|
||
@override
|
||
String get buttonRetry => 'Retry';
|
||
|
||
@override
|
||
String get buttonRefresh => 'Refresh';
|
||
|
||
@override
|
||
String get buttonInstall => 'Install';
|
||
|
||
@override
|
||
String get buttonUninstall => 'Uninstall';
|
||
|
||
@override
|
||
String get buttonDetails => 'Details';
|
||
|
||
@override
|
||
String get buttonAdd => 'Add';
|
||
|
||
@override
|
||
String get buttonRemove => 'Remove';
|
||
|
||
@override
|
||
String get buttonOpen => 'Open';
|
||
|
||
@override
|
||
String get buttonExplain => 'Explain';
|
||
|
||
@override
|
||
String get buttonReadDocs => 'Read docs';
|
||
|
||
@override
|
||
String get buttonCopy => 'Copy to clipboard';
|
||
|
||
@override
|
||
String get buttonCopied => 'Copied';
|
||
|
||
@override
|
||
String get settingsTitle => 'Hub endpoint';
|
||
|
||
@override
|
||
String get settingsHost => 'Host';
|
||
|
||
@override
|
||
String get settingsPort => 'Port';
|
||
|
||
@override
|
||
String get settingsTls => 'TLS';
|
||
|
||
@override
|
||
String get settingsSaveAndConnect => 'Save & connect';
|
||
|
||
@override
|
||
String get settingsLanguage => 'Language';
|
||
|
||
@override
|
||
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 1–65535';
|
||
|
||
@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';
|
||
|
||
@override
|
||
String get channelsActive => 'active';
|
||
|
||
@override
|
||
String get channelsRunning => 'running';
|
||
|
||
@override
|
||
String get channelsStopped => 'stopped';
|
||
|
||
@override
|
||
String get channelsConnect => 'Connect Studio to this channel';
|
||
|
||
@override
|
||
String get channelsSwitch => 'Make this the active channel';
|
||
|
||
@override
|
||
String get channelsEnableAutostart => 'Enable autostart at login';
|
||
|
||
@override
|
||
String get channelsDisableAutostart => 'Disable autostart';
|
||
|
||
@override
|
||
String get storeSearchHint =>
|
||
'Search modules — name, tagline, tag, capability…';
|
||
|
||
@override
|
||
String get storeAskHint =>
|
||
'What do you need? Try \"a module that reads tabular data\" or just type a keyword.';
|
||
|
||
@override
|
||
String get storeAskSubmit => 'Search';
|
||
|
||
@override
|
||
String get storeAskAi => 'Ask the AI';
|
||
|
||
@override
|
||
String get storeAskClear => 'Clear question';
|
||
|
||
@override
|
||
String get storeAskAiThinking => 'Looking through modules…';
|
||
|
||
@override
|
||
String get storeAskAiUnavailable =>
|
||
'Configure a System AI in Settings to ask questions in plain language.';
|
||
|
||
@override
|
||
String get storeAskNoMatches =>
|
||
'No matches yet — refine the question or browse the grid below.';
|
||
|
||
@override
|
||
String get storeAskAnswerLabel => 'AI suggestion';
|
||
|
||
@override
|
||
String get storeAskAnswerWhy => 'Why this matches';
|
||
|
||
@override
|
||
String get storeAskMatchPill => 'match';
|
||
|
||
@override
|
||
String get storeFilterLabel => 'Filter';
|
||
|
||
@override
|
||
String storeFilterActiveCount(int n) {
|
||
return '$n active';
|
||
}
|
||
|
||
@override
|
||
String get storeFilterReset => 'Reset filters';
|
||
|
||
@override
|
||
String get storeFilterApply => 'Done';
|
||
|
||
@override
|
||
String get storeFilterStatusGroup => 'Status';
|
||
|
||
@override
|
||
String get storeFilterSourceGroup => 'Source';
|
||
|
||
@override
|
||
String get storeFilterInstalledGroup => 'Show only installed';
|
||
|
||
@override
|
||
String get storeFeatured => 'FEATURED';
|
||
|
||
@override
|
||
String get storeFeaturedHint => 'curated picks · click for details';
|
||
|
||
@override
|
||
String get storeNoMatches => 'No matches';
|
||
|
||
@override
|
||
String get storeNoMatchesHint =>
|
||
'Adjust the filters or clear the search to see all entries.';
|
||
|
||
@override
|
||
String get storeClearFilters => 'Clear filters';
|
||
|
||
@override
|
||
String get storeStatusAll => 'All';
|
||
|
||
@override
|
||
String get storeStatusPublished => 'stable';
|
||
|
||
@override
|
||
String get storeStatusAlpha => 'experimental';
|
||
|
||
@override
|
||
String get storeStatusPlanned => 'coming soon';
|
||
|
||
@override
|
||
String get storeInstalledOnly => 'Installed';
|
||
|
||
@override
|
||
String get storeCategoryLabel => 'Category';
|
||
|
||
@override
|
||
String get storeCategoryAll => 'All categories';
|
||
|
||
@override
|
||
String get storeCategoryBridge => 'Connectors';
|
||
|
||
@override
|
||
String get storeCategoryDebug => 'Sample modules';
|
||
|
||
@override
|
||
String get storeCategoryText => 'Text';
|
||
|
||
@override
|
||
String get storeCategoryLlm => 'AI models';
|
||
|
||
@override
|
||
String get storeCategorySystem => 'System';
|
||
|
||
@override
|
||
String get storeCategoryAuth => 'Authentication';
|
||
|
||
@override
|
||
String get storeCategoryStorage => 'Storage';
|
||
|
||
@override
|
||
String get storeCategoryChannel => 'Channels';
|
||
|
||
@override
|
||
String get storeCategoryWeb => 'Web';
|
||
|
||
@override
|
||
String get storeCategoryOrchestrator => 'Orchestration';
|
||
|
||
@override
|
||
String storeNResults(int n) {
|
||
String _temp0 = intl.Intl.pluralLogic(
|
||
n,
|
||
locale: localeName,
|
||
other: 's',
|
||
one: '',
|
||
);
|
||
return '$n result$_temp0';
|
||
}
|
||
|
||
@override
|
||
String get storeReloadTooltip => 'Reload';
|
||
|
||
@override
|
||
String get storeTodayBadge => 'TODAY';
|
||
|
||
@override
|
||
String get storeTodayDeck => 'From the F∆I editor';
|
||
|
||
@override
|
||
String get storeTodayDismissTooltip => 'Hide for this session';
|
||
|
||
@override
|
||
String get storePillInstalled => 'installed';
|
||
|
||
@override
|
||
String get storePillUpdate => 'update';
|
||
|
||
@override
|
||
String storeUpdateButton(String version) {
|
||
return 'Update to $version';
|
||
}
|
||
|
||
@override
|
||
String storeUpdateTooltip(String installed, String best) {
|
||
return 'Installed $installed — store has v$best';
|
||
}
|
||
|
||
@override
|
||
String get storeNoTagline => '(no tagline)';
|
||
|
||
@override
|
||
String get storeUninstallTitle => 'Uninstall module?';
|
||
|
||
@override
|
||
String storeUninstallBody(String name) {
|
||
return 'Removes $name from this hub. Flows that reference it will fail at the next run.';
|
||
}
|
||
|
||
@override
|
||
String storeInstalledToast(String name, String version) {
|
||
return '$name v$version installed.';
|
||
}
|
||
|
||
@override
|
||
String storeInstallFailedToast(String error) {
|
||
return 'Install failed: $error';
|
||
}
|
||
|
||
@override
|
||
String storeUninstalledToast(String name, String version) {
|
||
return '$name v$version uninstalled.';
|
||
}
|
||
|
||
@override
|
||
String storeUninstallFailedToast(String error) {
|
||
return 'Uninstall failed: $error';
|
||
}
|
||
|
||
@override
|
||
String storeOpenBrowserFailed(String error) {
|
||
return 'Could not open browser: $error';
|
||
}
|
||
|
||
@override
|
||
String get storeSectionTags => 'Tags';
|
||
|
||
@override
|
||
String get storeSectionRequiredCapabilities => 'Required capabilities';
|
||
|
||
@override
|
||
String get storeSectionRequiredHostServices => 'Required host services';
|
||
|
||
@override
|
||
String get storeSectionScreenshots => 'Screenshots';
|
||
|
||
@override
|
||
String get storeSectionDocumentation => 'Documentation';
|
||
|
||
@override
|
||
String get storeSectionSource => 'Source';
|
||
|
||
@override
|
||
String get storeSectionPermissions => 'Declared permissions';
|
||
|
||
@override
|
||
String get storeSectionDirectory => 'Module directory';
|
||
|
||
@override
|
||
String get storeSectionPermissionsNone => '(none — pure-computation module)';
|
||
|
||
@override
|
||
String get storeInstallingButton => 'Installing…';
|
||
|
||
@override
|
||
String get storeNotInstallable => 'Not installable';
|
||
|
||
@override
|
||
String storeNotInstallableTooltip(String status) {
|
||
return 'Status \"$status\" — install path not yet wired.';
|
||
}
|
||
|
||
@override
|
||
String storeInstallProgressTitle(String name) {
|
||
return 'Installing $name';
|
||
}
|
||
|
||
@override
|
||
String get storeInstallProgressBody => 'Fetching, verifying, unpacking…';
|
||
|
||
@override
|
||
String get storeLoadDocs => 'Load documentation';
|
||
|
||
@override
|
||
String get storeDocsHint =>
|
||
'README rendered inline; uses the hub\'s registry token when needed.';
|
||
|
||
@override
|
||
String get storeDocsFetching => 'Fetching README…';
|
||
|
||
@override
|
||
String get storeOpenRepoButton => 'Open repository in browser';
|
||
|
||
@override
|
||
String get storeDocsErrorNotFound =>
|
||
'This module is not in the hub\'s store index.';
|
||
|
||
@override
|
||
String get storeDocsErrorNoDocs =>
|
||
'No repository URL is recorded for this module.';
|
||
|
||
@override
|
||
String get storeDocsErrorAuth =>
|
||
'The registry requires authentication to fetch this README. Set FAI_REGISTRY_TOKEN in the daemon\'s environment and restart the hub.';
|
||
|
||
@override
|
||
String storeDocsErrorNetwork(String detail) {
|
||
return 'Network error while fetching the README. $detail';
|
||
}
|
||
|
||
@override
|
||
String get storeDocsErrorParse => 'README is not valid UTF-8.';
|
||
|
||
@override
|
||
String get storeDocsErrorGeneric => 'Could not load README.';
|
||
|
||
@override
|
||
String get storeSourceLabel => 'Source';
|
||
|
||
@override
|
||
String get storeSourceAll => 'All sources';
|
||
|
||
@override
|
||
String get storeSourceNative => 'Native';
|
||
|
||
@override
|
||
String get storeSourceMcp => 'MCP';
|
||
|
||
@override
|
||
String get storeSourceN8n => 'n8n';
|
||
|
||
@override
|
||
String get storeProvenanceNative => 'native';
|
||
|
||
@override
|
||
String storeProvenanceMcp(String provider) {
|
||
return 'mcp · $provider';
|
||
}
|
||
|
||
@override
|
||
String storeProvenanceN8n(String provider) {
|
||
return 'n8n · $provider';
|
||
}
|
||
|
||
@override
|
||
String get storeRecommendedTitle => 'Add a public source — one click';
|
||
|
||
@override
|
||
String get storeRecommendedBody =>
|
||
'Curated MCP servers reachable over HTTPS. No subprocess, no API key, no Node. Federated capabilities appear in the store immediately.';
|
||
|
||
@override
|
||
String get storeRecommendedAddTooltip => 'Add and discover';
|
||
|
||
@override
|
||
String get storeRecommendedAdding => 'Adding…';
|
||
|
||
@override
|
||
String get storeRecommendedDeepWikiTagline =>
|
||
'GitHub repo documentation search (AI-powered)';
|
||
|
||
@override
|
||
String get storeRecommendedSemgrepTagline =>
|
||
'Security scanning for code vulnerabilities';
|
||
|
||
@override
|
||
String storeProviderAddedToast(String name, int n) {
|
||
String _temp0 = intl.Intl.pluralLogic(
|
||
n,
|
||
locale: localeName,
|
||
other: 'capabilities',
|
||
one: 'capability',
|
||
);
|
||
return 'Added $name — $n federated $_temp0.';
|
||
}
|
||
|
||
@override
|
||
String storeProviderAddedZeroToast(String name) {
|
||
return '$name registered, but the server returned no capabilities yet. Open Settings → MCP Clients to retry discovery or check the server.';
|
||
}
|
||
|
||
@override
|
||
String storeProviderAddFailed(String name, String error) {
|
||
return 'Could not add $name: $error';
|
||
}
|
||
|
||
@override
|
||
String get auditTitle => 'Audit';
|
||
|
||
@override
|
||
String get auditNoEvents => 'No events yet';
|
||
|
||
@override
|
||
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';
|
||
|
||
@override
|
||
String get modulesNoneTitle => 'No modules yet';
|
||
|
||
@override
|
||
String get modulesNoneHint =>
|
||
'Run `fai install <capability-name>` or check ~/.fai/modules/.';
|
||
|
||
@override
|
||
String get modulesReloadTooltip => 'Reload';
|
||
|
||
@override
|
||
String get modulesRecentActivity => 'RECENT ACTIVITY';
|
||
|
||
@override
|
||
String modulesRecentActivityHint(int n) {
|
||
return 'last $n install/uninstall events from the audit log';
|
||
}
|
||
|
||
@override
|
||
String get modulesActivityInstalled => 'installed';
|
||
|
||
@override
|
||
String get modulesActivityUninstalled => 'uninstalled';
|
||
|
||
@override
|
||
String get modulesCapabilitiesLabel => 'Capabilities';
|
||
|
||
@override
|
||
String get modulesUninstallTitle => 'Uninstall module?';
|
||
|
||
@override
|
||
String modulesUninstallBody(String name, String version) {
|
||
return 'Removes $name v$version from this hub. Flows that reference it will fail at the next run. A `module.uninstalled` audit event is recorded.';
|
||
}
|
||
|
||
@override
|
||
String modulesUninstalledToast(String name, String version) {
|
||
return 'Uninstalled $name v$version.';
|
||
}
|
||
|
||
@override
|
||
String modulesUninstallFailed(String error) {
|
||
return 'Uninstall failed: $error';
|
||
}
|
||
|
||
@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 =>
|
||
'One field per declared input. Pick a file for bytes-shaped inputs; type plain text for the rest. The Run button enables when every required input is set.';
|
||
|
||
@override
|
||
String get flowsLoadingDefinition => 'Loading inputs…';
|
||
|
||
@override
|
||
String get flowsDefinitionFailed => 'Could not load flow definition';
|
||
|
||
@override
|
||
String get flowsNoInputs =>
|
||
'This flow declares no inputs. Click Run to start.';
|
||
|
||
@override
|
||
String get flowsTypeBytesPick => 'Choose file…';
|
||
|
||
@override
|
||
String get flowsTypeBytesChange => 'Change file';
|
||
|
||
@override
|
||
String get flowsTypeBytesNoFile => 'No file selected';
|
||
|
||
@override
|
||
String flowsTypeBytesSize(int n) {
|
||
return '$n bytes';
|
||
}
|
||
|
||
@override
|
||
String get flowsRunErrorTitle => 'Flow run failed';
|
||
|
||
@override
|
||
String flowsFileReadFailed(String path, String error) {
|
||
return 'Could not read \"$path\": $error';
|
||
}
|
||
|
||
@override
|
||
String get flowsMissingModulesLabel => 'Needs:';
|
||
|
||
@override
|
||
String get flowsRunDisabledTooltip => 'Install the missing modules first.';
|
||
|
||
@override
|
||
String flowsInstallAllButton(int n) {
|
||
return 'Install all ($n)';
|
||
}
|
||
|
||
@override
|
||
String get flowsInstallPillTooltip => 'Click to install';
|
||
|
||
@override
|
||
String get flowsInstallDepsTitle => 'Install dependencies';
|
||
|
||
@override
|
||
String get flowsInstallDepsBody =>
|
||
'Walking through the missing modules in order. Existing installs are left alone.';
|
||
|
||
@override
|
||
String get flowsInstallStatusPending => 'Pending';
|
||
|
||
@override
|
||
String get flowsInstallStatusInstalling => 'Installing…';
|
||
|
||
@override
|
||
String flowsInstallStatusDone(String version) {
|
||
return 'Installed v$version';
|
||
}
|
||
|
||
@override
|
||
String get flowsInstallStatusFailed => 'Failed';
|
||
|
||
@override
|
||
String flowsInstallStatusFailedDetail(String error) {
|
||
return '$error';
|
||
}
|
||
|
||
@override
|
||
String get flowsInstallDepsAllDone => 'All dependencies installed.';
|
||
|
||
@override
|
||
String flowsInstallDepsAnyFailed(int ok, int failed) {
|
||
return '$ok installed, $failed failed.';
|
||
}
|
||
|
||
@override
|
||
String get flowsOpenInEditorTooltip =>
|
||
'Open the YAML file in your default editor';
|
||
|
||
@override
|
||
String flowsOpenInEditorFailed(String error) {
|
||
return 'Could not open file: $error';
|
||
}
|
||
|
||
@override
|
||
String get welcomeChecklistAllSetTitle => 'You\'re set up.';
|
||
|
||
@override
|
||
String get welcomeChecklistAllSetBody => 'Three threads to pull on next:';
|
||
|
||
@override
|
||
String get welcomeChecklistNextAuditTitle => 'Read the audit log';
|
||
|
||
@override
|
||
String get welcomeChecklistNextAuditBody =>
|
||
'Every install, flow run, and approval lives in the hash-chained log. Open the Audit tab to see what your hub has been up to.';
|
||
|
||
@override
|
||
String get welcomeChecklistNextAuditButton => 'Open Audit';
|
||
|
||
@override
|
||
String get welcomeChecklistNextTodayTitle => 'Set up the daily Today story';
|
||
|
||
@override
|
||
String get welcomeChecklistNextTodayBody =>
|
||
'Run tools/today/propose.sh on a cron and the editorial card on the store auto-fills with operator-curated narratives.';
|
||
|
||
@override
|
||
String get welcomeChecklistNextTodayButton => 'Open Today docs';
|
||
|
||
@override
|
||
String get welcomeChecklistNextModuleTitle => 'Build your own module';
|
||
|
||
@override
|
||
String get welcomeChecklistNextModuleBody =>
|
||
'Generate a Rust+WASM scaffold with `fai new module <name>`. The module-sdk handles the WIT plumbing; you write a typed invoke.';
|
||
|
||
@override
|
||
String get welcomeChecklistNextModuleButton => 'Read the docs';
|
||
|
||
@override
|
||
String get auditGroupToday => 'TODAY';
|
||
|
||
@override
|
||
String get auditGroupYesterday => 'YESTERDAY';
|
||
|
||
@override
|
||
String get auditGroupThisWeek => 'EARLIER THIS WEEK';
|
||
|
||
@override
|
||
String get auditGroupOlder => 'OLDER';
|
||
|
||
@override
|
||
String get auditEventViewFlowRun => 'View flow run';
|
||
|
||
@override
|
||
String auditFlowRunDialogTitle(String flow) {
|
||
return 'Flow run · $flow';
|
||
}
|
||
|
||
@override
|
||
String auditFlowRunDialogSubtitle(int n, String execution) {
|
||
String _temp0 = intl.Intl.pluralLogic(
|
||
n,
|
||
locale: localeName,
|
||
other: 'events',
|
||
one: 'event',
|
||
);
|
||
return '$n $_temp0 for execution $execution';
|
||
}
|
||
|
||
@override
|
||
String get approvalsSelectAll => 'Select all';
|
||
|
||
@override
|
||
String get approvalsClearSelection => 'Clear';
|
||
|
||
@override
|
||
String approvalsBatchSelected(int n) {
|
||
return '$n selected';
|
||
}
|
||
|
||
@override
|
||
String get approvalsBatchApprove => 'Approve all';
|
||
|
||
@override
|
||
String get approvalsBatchReject => 'Reject all';
|
||
|
||
@override
|
||
String approvalsBatchApproveDoneToast(int n) {
|
||
return '$n approvals approved.';
|
||
}
|
||
|
||
@override
|
||
String approvalsBatchRejectDoneToast(int n) {
|
||
return '$n approvals rejected.';
|
||
}
|
||
|
||
@override
|
||
String approvalsBatchPartialFailure(int ok, int failed) {
|
||
return '$ok done, $failed failed.';
|
||
}
|
||
|
||
@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';
|
||
|
||
@override
|
||
String get approvalsTabPending => 'Pending';
|
||
|
||
@override
|
||
String get approvalsTabHistory => 'History';
|
||
|
||
@override
|
||
String get approvalsInboxZero => 'Inbox zero';
|
||
|
||
@override
|
||
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';
|
||
|
||
@override
|
||
String get doctorSummaryModules => 'Modules';
|
||
|
||
@override
|
||
String get doctorSummaryApprovals => 'Approvals';
|
||
|
||
@override
|
||
String get doctorSummaryAudit => 'Audit';
|
||
|
||
@override
|
||
String get doctorSummaryServices => 'Services';
|
||
|
||
@override
|
||
String doctorSummaryCapabilities(int n) {
|
||
return '$n capabilities';
|
||
}
|
||
|
||
@override
|
||
String get doctorSummaryPending => 'pending';
|
||
|
||
@override
|
||
String doctorSummaryChain(int verified, int total) {
|
||
return '$verified/$total chain';
|
||
}
|
||
|
||
@override
|
||
String get doctorSummaryDeclared => 'declared';
|
||
|
||
@override
|
||
String doctorModulesPanelSummary(int n, int m) {
|
||
return '$n modules · $m capabilities';
|
||
}
|
||
|
||
@override
|
||
String get doctorApprovalsNone => 'No pending approvals';
|
||
|
||
@override
|
||
String doctorApprovalsCount(int n) {
|
||
String _temp0 = intl.Intl.pluralLogic(
|
||
n,
|
||
locale: localeName,
|
||
other: '$n approvals awaiting review',
|
||
one: '1 approval awaiting review',
|
||
);
|
||
return '$_temp0';
|
||
}
|
||
|
||
@override
|
||
String get doctorApprovalsAttentionPill => 'attention';
|
||
|
||
@override
|
||
String get doctorServicesEmpty => 'No host services declared';
|
||
|
||
@override
|
||
String get doctorServicesEmptyHint =>
|
||
'add to ~/.fai/config.yaml under services:';
|
||
|
||
@override
|
||
String get doctorPillLoaded => 'loaded';
|
||
|
||
@override
|
||
String get doctorPillEmpty => 'empty';
|
||
|
||
@override
|
||
String get doctorRecheckTooltip => 'Re-check';
|
||
|
||
@override
|
||
String get doctorEventLogSection => 'Event log';
|
||
|
||
@override
|
||
String get doctorModulesApprovalsSection => 'Modules & approvals';
|
||
|
||
@override
|
||
String get doctorHostServicesSection => 'Host services';
|
||
|
||
@override
|
||
String get doctorDaemonFilesSection => 'Daemon files';
|
||
|
||
@override
|
||
String get doctorDaemonControlSection => 'Daemon control';
|
||
|
||
@override
|
||
String get doctorChainIntact => 'Hash chain intact';
|
||
|
||
@override
|
||
String doctorChainIntactDetail(int n) {
|
||
return '$n events · prev_event_sha256 verified end-to-end';
|
||
}
|
||
|
||
@override
|
||
String get doctorChainTampered => 'Tampering detected';
|
||
|
||
@override
|
||
String doctorChainTamperedDetail(int verified, int total, String id) {
|
||
return '$verified of $total verified before mismatch at $id';
|
||
}
|
||
|
||
@override
|
||
String get doctorChainPillOk => 'WORM-1';
|
||
|
||
@override
|
||
String get doctorChainPillTamper => 'TAMPER';
|
||
|
||
@override
|
||
String get doctorVerifyNow => 'Verify now';
|
||
|
||
@override
|
||
String get doctorRestart => 'Restart';
|
||
|
||
@override
|
||
String get doctorStart => 'Start';
|
||
|
||
@override
|
||
String get doctorStop => 'Stop';
|
||
|
||
@override
|
||
String get doctorStatusAction => 'Status';
|
||
|
||
@override
|
||
String doctorRunningOn(String name, String endpoint) {
|
||
return 'Running on $name: $endpoint';
|
||
}
|
||
|
||
@override
|
||
String doctorStoppedOn(String name) {
|
||
return '$name daemon stopped';
|
||
}
|
||
|
||
@override
|
||
String get doctorStatusUnknown => 'Daemon status: …';
|
||
|
||
@override
|
||
String get doctorPillRunning => 'running';
|
||
|
||
@override
|
||
String get doctorPillStopped => 'stopped';
|
||
|
||
@override
|
||
String get doctorDaemonControlHint =>
|
||
'Studio shells out to the platform binary — mirrors `fai daemon …` exactly so the CLI and UI stay in lockstep.';
|
||
|
||
@override
|
||
String get doctorDaemonControlWorking => 'Working…';
|
||
|
||
@override
|
||
String get doctorPathLog => 'Log';
|
||
|
||
@override
|
||
String get doctorPathConfig => 'Config';
|
||
|
||
@override
|
||
String get doctorPathDb => 'Audit DB';
|
||
|
||
@override
|
||
String get doctorPathModules => 'Modules dir';
|
||
|
||
@override
|
||
String get doctorPathFlows => 'Flows dir';
|
||
|
||
@override
|
||
String get doctorPathPid => 'PID file';
|
||
|
||
@override
|
||
String get doctorPathsEmpty =>
|
||
'Daemon did not report file paths. Update the running hub via `fai daemon restart`.';
|
||
|
||
@override
|
||
String doctorOpenError(String detail) {
|
||
return 'Could not open: $detail';
|
||
}
|
||
|
||
@override
|
||
String doctorUpdateAvailable(String version) {
|
||
return 'Update available — $version';
|
||
}
|
||
|
||
@override
|
||
String doctorUpdateBody(String channel, String version) {
|
||
return 'Channel $channel now offers $version. Apply via the button — Studio shells out to `fai update apply --channel $channel`.';
|
||
}
|
||
|
||
@override
|
||
String get doctorUpdateUnreachable => 'Release host unreachable';
|
||
|
||
@override
|
||
String doctorUpdateUnreachableBody(String channel) {
|
||
return 'Could not contact the release feed for $channel.';
|
||
}
|
||
|
||
@override
|
||
String doctorReleaseNotes(String url) {
|
||
return 'notes: $url';
|
||
}
|
||
|
||
@override
|
||
String get doctorPillNew => 'new';
|
||
|
||
@override
|
||
String get doctorPillOffline => 'offline';
|
||
|
||
@override
|
||
String get doctorApplyUpdate => 'Apply update';
|
||
|
||
@override
|
||
String get doctorApplying => 'Applying…';
|
||
|
||
@override
|
||
String get doctorApplyDone =>
|
||
'Update applied. Restart Studio to see the new daemon version.';
|
||
|
||
@override
|
||
String get mcpHeader => 'MCP CLIENTS';
|
||
|
||
@override
|
||
String get mcpHint =>
|
||
'External MCP servers federate their tools as `mcp.<server>.<tool>` capabilities. Configure once, see them in the Store.';
|
||
|
||
@override
|
||
String get mcpEmpty => 'No MCP servers configured. Click + to add one.';
|
||
|
||
@override
|
||
String get n8nHeader => 'N8N ENDPOINTS';
|
||
|
||
@override
|
||
String get n8nHint =>
|
||
'Active n8n workflows surface as `n8n.<endpoint>.<slug>` capabilities. Configure once, see them in the Store.';
|
||
|
||
@override
|
||
String get n8nEmpty => 'No n8n endpoints configured. Click + to add one.';
|
||
|
||
@override
|
||
String get hubUnreachable => 'Hub unreachable';
|
||
|
||
@override
|
||
String get hubUnreachableHint => 'Start the hub with `fai serve`.';
|
||
|
||
@override
|
||
String get languageEnglish => 'English';
|
||
|
||
@override
|
||
String get languageGerman => 'Deutsch';
|
||
|
||
@override
|
||
String get searchHint => 'Jump anywhere — modules, store, flows, pages…';
|
||
|
||
@override
|
||
String get searchIndexing => 'Indexing…';
|
||
|
||
@override
|
||
String get searchNoMatches => 'No matches.';
|
||
|
||
@override
|
||
String get searchHintNavigate => '↑↓ navigate';
|
||
|
||
@override
|
||
String get searchHintOpen => 'enter open';
|
||
|
||
@override
|
||
String get searchHintClose => 'esc close';
|
||
|
||
@override
|
||
String get searchGroupPages => 'Pages';
|
||
|
||
@override
|
||
String get searchGroupModules => 'Modules';
|
||
|
||
@override
|
||
String get searchGroupStore => 'Store';
|
||
|
||
@override
|
||
String get searchGroupFlows => 'Flows';
|
||
|
||
@override
|
||
String get searchSettingsLabel => 'Settings';
|
||
|
||
@override
|
||
String searchPageHint(int n) {
|
||
return 'page · ⌘$n';
|
||
}
|
||
|
||
@override
|
||
String get searchSettingsHint => 'hub endpoint, channels, system AI · ⌘;';
|
||
|
||
@override
|
||
String searchInstalledModuleHint(String version) {
|
||
return 'installed module · v$version';
|
||
}
|
||
|
||
@override
|
||
String get searchStoreUncategorized => 'uncategorized';
|
||
|
||
@override
|
||
String searchStoreHintWithTagline(String tagline) {
|
||
return 'store · $tagline';
|
||
}
|
||
|
||
@override
|
||
String searchStoreHintWithCategory(String category) {
|
||
return 'store · $category';
|
||
}
|
||
|
||
@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';
|
||
}
|
||
}
|