chain-studio/lib/l10n/app_localizations_en.dart
flemming-it 0f93d90963
Some checks failed
Security / Security check (push) Failing after 2s
fix(studio): chain config dir + spawn path + doc URLs
Track the platform rename: the hub spawn path is now ~/.chain/bin/chain
(was ~/.fai/bin/fai.exe on Windows — both dir and binary were stale, so
Studio could not launch the hub after the config-dir rename), the
~/.fai/* help strings become ~/.chain/*, FAI_REGISTRY_TOKEN ->
CHAIN_REGISTRY_TOKEN, and the two in-app doc URLs point at the public
fai/chain repo (fai/platform was renamed to the private fai/chain-private).
The .fai module bundle extension is left unchanged (format phase).
flutter analyze: no issues.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-06-16 09:38:30 +02:00

2701 lines
68 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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 => 'Ch∆In Studio';
@override
String get navWelcome => 'Welcome';
@override
String get welcomeHeroTitle => 'Ch∆In 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 welcomeDocApprovalsTitle => 'Approvals';
@override
String get welcomeDocApprovalsBlurb =>
'Human-in-the-loop checkpoints — when to use them, how the audit log records them.';
@override
String get helpTooltip => 'Help';
@override
String get errApprovalRejected => 'Approval rejected by reviewer.';
@override
String get errApprovalRejectedHint =>
'The reviewer marked this step as rejected. Check the audit log for the reviewer\'s reason.';
@override
String get errApprovalTimedOut => 'Approval timed out.';
@override
String get errApprovalTimedOutHint =>
'No reviewer decided within the configured time. Raise `timeout_seconds` on the approval step or alert the reviewer.';
@override
String get errOutputTooLarge => 'Step output exceeded the size limit.';
@override
String get errOutputTooLargeHint =>
'Either trim the output (truncate text, downsample bytes) or raise `max_output_size_mb` in the operator config.';
@override
String get errServiceUnavailableForStep => 'Host service not configured.';
@override
String get errServiceUnavailableForStepHint =>
'The module requires a service (e.g. ollama, playwright) the operator hasn\'t declared. Add it under `services:` in ~/.chain/config.yaml.';
@override
String get errMissingValue => 'Required value is missing.';
@override
String get errMissingValueHint =>
'The step expected an input that wasn\'t wired up — either supply it at run time or fix the upstream `\$ref`.';
@override
String get errMcpUnreachable => 'MCP endpoint unreachable.';
@override
String get errMcpUnreachableHint =>
'The MCP server didn\'t respond. Check the endpoint in Settings → Integrations and confirm it\'s running.';
@override
String get errCapabilityNotInstalled =>
'Required capability is not installed.';
@override
String get errCapabilityNotInstalledHint =>
'Open the flow\'s Text tab — the analyzer\'s Fix button installs the capability if it\'s in the store.';
@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 =>
'Add an MCP source from the Store, or configure one under Settings → MCP Clients.';
@override
String get welcomeChecklistModule => 'Install a text module';
@override
String get welcomeChecklistModuleHint =>
'Install a module from the Store — pick whichever category fits your work. Modules are sandboxed Ch∆In components.';
@override
String get welcomeChecklistFlow => 'Run a saved flow';
@override
String get welcomeChecklistFlowHint =>
'Flows → pick one → Run. Studio ships a few demo flows; one of your own works too.';
@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 connectionTapToStart => 'tap to start';
@override
String get sidebarSettingsTooltip => 'Settings (⌘;)';
@override
String get sidebarChannelTooltip =>
'Active channel — click to switch in Settings (⌘;).\nproduction = stable · beta = pre-release · dev = rolling · local = workspace';
@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 buttonShowDetails => 'Show details';
@override
String get buttonHideDetails => 'Hide details';
@override
String get storeInstallableOnly => 'Installable only';
@override
String get storePillComingSoon => 'Coming soon';
@override
String storeNotInstallableInline(String status) {
return 'This module is on the roadmap (status: $status). It has no installable bundle yet — follow the repository for updates.';
}
@override
String get mcpSuggestionDeepwikiDesc =>
'Public HTTPS — GitHub repo documentation search (AI-powered). No Node, no API key.';
@override
String get mcpSuggestionSemgrepDesc =>
'Public HTTPS — security scanning for code vulnerabilities. No Node, no API key.';
@override
String get mcpSuggestionFilesystemDesc =>
'Anthropic — read / write files in /tmp. Edit the path before saving.';
@override
String get mcpSuggestionFetchDesc =>
'Anthropic — fetch arbitrary HTTP(S) URLs as markdown.';
@override
String get mcpSuggestionGithubDesc =>
'Anthropic — issues, PRs, repo files. Needs a GitHub PAT in the env var.';
@override
String get mcpSuggestionPuppeteerDesc =>
'Anthropic — headless browser automation for screenshots / scraping.';
@override
String get mcpSuggestionPostgresDesc =>
'Anthropic — read-only SQL queries against a Postgres database. Edit the URL.';
@override
String get mcpSuggestionSqliteDesc =>
'Anthropic — query a local SQLite file. Edit the path.';
@override
String get mcpSuggestionBraveSearchDesc =>
'Anthropic — web search via Brave. API key required.';
@override
String get mcpSuggestionMemoryDesc =>
'Anthropic — persistent knowledge graph for an agent\'s memory.';
@override
String get mcpSuggestionTimeDesc =>
'Anthropic — current time + timezone conversion.';
@override
String get mcpServerEnLanguageBadge =>
'Server text in English — Studio shows it as supplied.';
@override
String get themePluginHeader => 'Theme plugin (applies instantly)';
@override
String themeApplied(String name) {
return 'Theme applied: $name';
}
@override
String get themePluginFailed =>
'Theme plugin could not load — keeping previous theme.';
@override
String get themePluginNone => 'Built-in (no plugin)';
@override
String get themePluginHint =>
'Built-in and plugin tiles ship hand-curated palettes. The Custom tile derives a full Material 3 palette (primary, secondary, tertiary, surface, …) from one seed colour you pick — it\'s a complete theme, not a single-colour tweak.';
@override
String get themePluginEmpty =>
'No theme plugins installed. Open the Store and pick one in the studio-plugin category.';
@override
String get themePluginCustom => 'Custom colour';
@override
String get themePluginCustomDialogTitle =>
'Custom theme — pick a seed colour';
@override
String get themePluginCustomHexLabel => 'Hex colour';
@override
String get themePluginCustomPreview => 'Live preview';
@override
String get themePluginCustomCancel => 'Cancel';
@override
String get themePluginCustomApply => 'Apply';
@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 => 'Connect to endpoint';
@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 165535';
@override
String get channelsBlurb =>
'Switch hub channel (writes ~/.chain/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 Ch∆In 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 CHAIN_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 `chain install <capability-name>` or check ~/.chain/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 `chain 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 flowsInstallAuthWallButton => 'Add registry token';
@override
String get flowsOpenInEditorTooltip => 'Open in Studio\'s flow editor';
@override
String flowsOpenInEditorFailed(String error) {
return 'Could not open file: $error';
}
@override
String get registryCredentialsHeader => 'REGISTRY CREDENTIALS';
@override
String get registryCredentialsBlurb =>
'Token used to download .fai modules from a registry behind a signin wall (Forgejo, GitHub-private). Stored at ~/.chain/registry-token, mode 0600. The CHAIN_REGISTRY_TOKEN env var still wins when set.';
@override
String registryTokenStatusConfigured(int chars) {
return 'Configured ($chars chars)';
}
@override
String get registryTokenStatusNotSet => 'Not set';
@override
String get registryTokenFieldLabel => 'Token';
@override
String get registryTokenFieldHint =>
'Paste your Forgejo or GitHub personal access token';
@override
String get registryTokenSaveButton => 'Save';
@override
String get registryTokenClearButton => 'Clear';
@override
String get registryTokenStorageHint =>
'Saved locally to ~/.chain/registry-token. Never sent to a remote service.';
@override
String get registryTokenSavedToast => 'Registry token saved.';
@override
String get registryTokenClearedToast => 'Registry token cleared.';
@override
String registryTokenSaveFailedToast(String error) {
return 'Could not save: $error';
}
@override
String get hubAuthTokenHeader => 'HUB AUTHENTICATION';
@override
String get hubAuthTokenBlurb =>
'Bearer token used to authenticate Studio against a hub that has auth.tokens: configured (RBAC Level 2). Stored at ~/.chain/hub-auth-token, mode 0600. Studio sends it as Authorization: Bearer on every gRPC call.';
@override
String hubAuthTokenStatusConfigured(int chars) {
return 'Configured ($chars chars)';
}
@override
String get hubAuthTokenStatusNotSet => 'Not set (anonymous)';
@override
String get hubAuthTokenFieldLabel => 'Token';
@override
String get hubAuthTokenFieldHint =>
'Paste a token from the hub operator\'s auth.tokens entry';
@override
String get hubAuthTokenSaveButton => 'Save';
@override
String get hubAuthTokenClearButton => 'Clear';
@override
String get hubAuthTokenStorageHint =>
'Saved locally to ~/.chain/hub-auth-token. Studio reconnects after save so the new token takes effect immediately.';
@override
String get hubAuthTokenSavedToast => 'Hub auth token saved.';
@override
String get hubAuthTokenClearedToast => 'Hub auth token cleared.';
@override
String hubAuthTokenSaveFailedToast(String error) {
return 'Could not save: $error';
}
@override
String get storeAdvisoryVersionTooltip =>
'Federated upstream service — version is advisory; the upstream may break compatibility without bumping it.';
@override
String get uninstallVersionPickerTitle => 'Pick a version to uninstall';
@override
String uninstallVersionPickerBody(String module) {
return 'Several versions of `$module` are installed side-by-side. Select the exact version to remove — the others stay in place.';
}
@override
String get uninstallVersionPickerContinue => 'Continue';
@override
String get defaultScopeHeader => 'DEFAULT SCOPE';
@override
String get defaultScopeBlurb =>
'Ordered list of publisher segments the hub consults when a flow names a capability without an explicit `<provider>/` prefix. First match wins — promote the segments your team uses most to the top. Catalog-known publishers appear as chips; arbitrary entries are accepted for private segments.';
@override
String get defaultScopeAddLabel => 'Add publisher segment';
@override
String get defaultScopeAddHint => 'e.g. acme.team';
@override
String get defaultScopeAddButton => 'Add';
@override
String get defaultScopeSuggestions => 'Catalog suggestions:';
@override
String get defaultScopeSavedToast => 'Default scope updated.';
@override
String get defaultScopeLoadFailed => 'Could not load default scope.';
@override
String get defaultScopeNonEmptyError =>
'Default scope cannot be empty — keep at least one segment.';
@override
String get maintenanceHeader => 'HUB MAINTENANCE';
@override
String get maintenanceResetBlurb =>
'Wipe operator state and start over with a clean hub. Stops every running daemon, atomically backs ~/.chain/ up, then recreates it with the binary, channel state, MCP / n8n / system-AI config, and registry token preserved. Restore by moving the backup directory back.';
@override
String get maintenanceKeepModulesTitle => 'Keep installed modules';
@override
String get maintenanceKeepModulesSubtitle =>
'Default behaviour wipes ~/.chain/modules/ so a fresh install can verify the module-fetch path end-to-end.';
@override
String get maintenanceKeepDataTitle => 'Keep audit log + saved flows';
@override
String get maintenanceKeepDataSubtitle =>
'Default behaviour wipes ~/.chain/data/ so the audit chain restarts from a fresh genesis and the bundled sample flows re-import on first daemon start.';
@override
String get maintenanceResetButton => 'Reset hub state';
@override
String get maintenanceResetInProgress => 'Resetting…';
@override
String get maintenanceResetConfirmTitle => 'Reset hub state?';
@override
String get maintenanceResetConfirmBody =>
'This stops every daemon, moves ~/.chain/ to a timestamped backup, and starts fresh. The backup is fully restorable. Continue?';
@override
String get maintenanceResetConfirmButton => 'Reset';
@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 `chain 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 flowsResultTitle(String name) {
return '$name — result';
}
@override
String flowsErrorTitle(String name) {
return '$name — failed';
}
@override
String get flowsRunning => 'Flow running…';
@override
String get flowsNoOutputs => 'Flow completed with no declared outputs.';
@override
String get errGeneric => 'Something went wrong.';
@override
String get errInvalidArgument => 'Invalid input.';
@override
String get errInvalidArgumentHint => 'Check the form values and try again.';
@override
String get errNotFound => 'Not found.';
@override
String get errNotFoundHint =>
'The item you asked for isn\'t here — it may have been removed or never existed.';
@override
String get errAlreadyExists => 'Already exists.';
@override
String get errPermissionDenied => 'Permission denied.';
@override
String get errPermissionDeniedHint =>
'The hub\'s operator policy blocks this action. Check `~/.chain/config.yaml`.';
@override
String get errFailedPrecondition => 'Setup issue blocked this.';
@override
String get errFailedPreconditionHint =>
'The hub couldn\'t proceed because something it needs isn\'t ready. The detail below explains what.';
@override
String get errInternal => 'Unexpected internal error.';
@override
String get errInternalHint =>
'Check the hub logs at `~/.chain/logs/`. If this repeats, please report it.';
@override
String get errUnavailable => 'Hub not reachable.';
@override
String get errUnavailableHint =>
'Make sure `chain serve` (or `chain daemon start`) is running and the daemon endpoint matches Studio\'s settings.';
@override
String get errUnauthenticated => 'Authentication required.';
@override
String get errUnauthenticatedHint =>
'Set `CHAIN_REGISTRY_TOKEN` or sign in through Settings before retrying.';
@override
String get errCopyDetail => 'Copy detail';
@override
String get errDetailCopied => 'Detail copied to clipboard.';
@override
String get flowsOutputUnknown => 'Output payload variant not recognised.';
@override
String get flowsOutputBytesUnknownMime => 'binary';
@override
String get flowsOutputSaveAs => 'Save as…';
@override
String get flowsOutputSaveAsTitle => 'Save flow output';
@override
String flowsOutputSavedAt(String path) {
return 'Saved to $path';
}
@override
String flowsOutputSaveFailed(String error) {
return 'Save failed: $error';
}
@override
String get flowsOutputOpen => 'Open';
@override
String flowsOutputOpenFailed(String error) {
return 'Open failed: $error';
}
@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 ~/.chain/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 `chain 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 `chain 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 `chain 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 `chain 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';
}
@override
String storeProvenanceTemporal(String provider) {
return 'temporal · $provider';
}
@override
String get storeSourceTemporal => 'Temporal';
@override
String get navFlowEditor => 'Editor';
@override
String get flowEditorBackTooltip => 'Back';
@override
String get flowEditorNew => 'New flow';
@override
String get flowEditorSave => 'Save';
@override
String get flowEditorRun => 'Run';
@override
String get flowEditorRefresh => 'Refresh file list';
@override
String get flowEditorRunOutput => 'RUN OUTPUT';
@override
String get flowEditorEmptyTitle => 'No flow open';
@override
String get flowEditorEmptyBody =>
'Pick one from the left, or click New flow to start a fresh one.';
@override
String get flowEditorListEmptyTitle => 'No saved flows';
@override
String get flowEditorListEmptyBody =>
'Click New flow to scaffold one from a template.';
@override
String get flowEditorDiscardTitle => 'Discard unsaved changes?';
@override
String get flowEditorDiscardBody =>
'Switching files will throw away the edits you haven\'t saved.';
@override
String get flowEditorDiscardKeep => 'Keep editing';
@override
String get flowEditorDiscardThrow => 'Throw away';
@override
String get flowEditorNewDialogTitle => 'New flow';
@override
String get flowEditorNewDialogLabel => 'Flow name';
@override
String get flowEditorNewDialogHelper =>
'lowercase letters, digits, hyphen, underscore';
@override
String get flowEditorNewDialogCancel => 'Cancel';
@override
String get flowEditorNewDialogCreate => 'Create';
@override
String flowEditorNewTemplateComment(String name) {
return 'Generated by Studio\'s Flow editor. Edit, save, run.';
}
@override
String flowEditorAlreadyExists(String name) {
return 'A flow named \"$name\" already exists.';
}
@override
String get buttonView => 'View';
@override
String logViewerTitle(String title, int count) {
return '$title — last $count lines';
}
@override
String get logViewerEmpty => 'Log file is empty or does not exist yet.';
@override
String get logViewerCopyAll => 'Copy all';
@override
String get logViewerOpenExternal => 'Open in default editor';
@override
String logViewerLineCount(int count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count lines',
one: '1 line',
);
return '$_temp0';
}
@override
String get doctorPathStudioErrors => 'Studio errors';
@override
String get settingsCategoryGeneral => 'General';
@override
String get settingsCategoryAppearance => 'Appearance';
@override
String get settingsCategoryAi => 'System AI';
@override
String get settingsCategoryIntegrations => 'Integrations';
@override
String get settingsCategorySecurity => 'Security';
@override
String get settingsCategoryMaintenance => 'Maintenance';
@override
String get settingsAiPanelTitle => 'System AI';
@override
String get settingsAiPanelBody =>
'Operator-managed LLM endpoint used by Studio for the AI helpers (system-ai-edit, install-suggest, doctor-summary). No flow ever calls this; modules speak to their own LLM.';
@override
String get settingsIntegrationsPanelTitle => 'Integrations';
@override
String get settingsIntegrationsPanelBody =>
'External tool servers the hub federates capabilities from. MCP servers expose tool-shaped endpoints; n8n endpoints expose hosted workflows.';
@override
String get settingsSecurityPanelTitle => 'Security & credentials';
@override
String get settingsSecurityPanelBody =>
'Tokens the hub holds on the operator\'s behalf. Stored in ~/.chain/ with mode 0600; never sent in telemetry.';
@override
String get settingsMaintenancePanelTitle => 'Maintenance';
@override
String get settingsMaintenancePanelBody =>
'Destructive operations gated behind explicit confirm dialogs. Use when re-pilot-testing or debugging.';
@override
String get tooltipMoveUp => 'Move up';
@override
String get tooltipMoveDown => 'Move down';
@override
String get tooltipRemove => 'Remove';
@override
String get daemonActionEnableAutostart => 'enable autostart';
@override
String get daemonActionDisableAutostart => 'disable autostart';
@override
String get daemonActionRestart => 'daemon restart';
@override
String get daemonActionStart => 'daemon start';
@override
String get daemonActionStop => 'daemon stop';
@override
String get daemonActionStatus => 'daemon status';
@override
String daemonActionResultOk(String label) {
return 'OK · $label';
}
@override
String daemonActionResultFailed(String label) {
return 'Failed · $label';
}
@override
String get addSourceTitle => 'Add module source';
@override
String addSourceIntro(String capability) {
return '`$capability` is not in the public store. Point the hub at a `.fai` bundle URL or a local bundle path; the hub downloads, verifies (sha256 + signature) and installs it.';
}
@override
String get addSourceField => 'URL or path to .fai bundle';
@override
String get addSourceHint =>
'https://git.flemming.ai/your-org/your-module/releases/download/v0.1.0/foo-0.1.0.fai';
@override
String get addSourceHowItWorksTitle => 'How private modules work';
@override
String get addSourceHowItWorksBody =>
'A module is a directory with a module.yaml + the WASM artifact. To share it: pack it (`chain pack <dir>`) and host the resulting `.fai` bundle anywhere (your own Forgejo / GitHub / S3). The hub installs by URL and verifies the signature against its trust store.\n\nDeveloping locally? Use the CLI — Studio cannot install from an unpacked directory (yet):';
@override
String get addSourceCliExample => 'chain install --link /path/to/module';
@override
String get addSourceInstallButton => 'Install';
@override
String get addSourceCancel => 'Cancel';
@override
String installFailed(String error) {
return 'Install failed: $error';
}
@override
String get welcomeHubDownTitle => 'The hub isn\'t running yet';
@override
String get welcomeHubDownBody =>
'Studio talks to a local hub — the engine that loads modules and runs flows. It isn\'t reachable right now. Start it to begin.';
@override
String get welcomeHubDownStart => 'Start hub';
@override
String get welcomeHubDownStarting => 'Starting…';
@override
String get welcomeHubDownDocsLink =>
'Can\'t start it? Read the getting-started guide';
@override
String welcomeHubDownEndpoint(String endpoint) {
return 'Endpoint: $endpoint';
}
@override
String get daemonStartRequested => 'Daemon start requested. Reconnecting…';
@override
String daemonStartFailed(String detail) {
return 'Could not start daemon: $detail';
}
@override
String get faiBinaryNotFound =>
'Could not find the `fai` program on this machine.';
@override
String get faiBinaryNotFoundHint =>
'Install the Ch∆In platform, or point Studio at an existing `fai` binary.';
@override
String get faiBinaryLocateButton => 'Locate `fai` binary…';
@override
String get faiBinaryInstallDocsButton => 'Open install guide';
@override
String get faiBinaryPickerTitle => 'Select the `fai` binary';
@override
String faiBinarySetOk(String path) {
return 'Using `fai` binary at $path';
}
@override
String get sysAiFixParse =>
'The provider sent a response in an unexpected format. Providers that aren\'t OpenAI-compatible may need a translation proxy.';
@override
String sysAiFixUnknown(String kind) {
return 'Unexpected failure ($kind). See the System AI documentation.';
}
@override
String get sysAiFixDisabled =>
'Configure System AI in Settings (Cmd+,) → System AI panel.';
@override
String get sysAiFixEnvMissing =>
'The API-key environment variable is empty. Set it in your shell, then restart the daemon.';
@override
String get sysAiFixNetwork =>
'The hub can\'t reach the configured endpoint. Is your provider running?';
@override
String get sysAiFixHttp =>
'The provider returned a non-2xx status. Verify the endpoint, model name, and API key.';
@override
String get sysAiFixEmptyResponse =>
'The provider answered with no content. Try a different model or rephrase the prompt.';
@override
String channelSwitchOk(String name) {
return 'Switched active channel to \"$name\". Daemon restarted.';
}
@override
String channelSwitchFailed(String detail) {
return 'Channel switch failed: $detail';
}
@override
String get providerDescOllama =>
'Local `ollama serve`. Models stay on your machine. No API key needed.';
@override
String get providerDescOpenai =>
'OpenAI hosted API. Requires an API key. Data leaves your machine.';
@override
String get providerDescLmstudio =>
'Local LM Studio server. Models stay on your machine. No API key needed.';
@override
String get providerDescVllm =>
'Self-hosted vLLM or any other OpenAI-compatible server. Endpoint required.';
@override
String get providerDescCustom =>
'Anything else that speaks the OpenAI-compatible chat-completions wire (LiteLLM proxy, internal mirror, …).';
@override
String welcomeDocLoadFailedBody(
String slug,
String locale,
String attempted,
String underlying,
) {
return 'Could not load the bundled doc \"$slug\" ($locale).\nTried: $attempted\nUnderlying: $underlying\nThis usually means the Studio build on disk predates the doc bundle. Rebuild Studio or open the online copy.';
}
@override
String hubUnreachableBanner(String endpoint) {
return 'Can\'t reach $endpoint — open Settings';
}
@override
String get hubUnreachableOpenSettings => 'Open Settings';
@override
String get navFederation => 'Federation';
@override
String get federationTitle => 'Federation';
@override
String get federationReloadTooltip => 'Reload satellites';
@override
String get federationAddSatellite => 'Add satellite';
@override
String get federationEmptyTitle => 'No satellites connected';
@override
String get federationEmptyHint =>
'Connect another hub as a satellite to run capabilities on it. Issue an enrollment token to get started.';
@override
String get federationPillConnected => 'connected';
@override
String get federationRegionNone => 'no region';
@override
String federationCapabilities(int count) {
return '$count advertised capabilities';
}
@override
String get federationAddDialogTitle => 'Issue an enrollment token';
@override
String get federationNameLabel => 'Satellite name';
@override
String get federationIssueButton => 'Issue';
@override
String federationIssueFailed(String error) {
return 'Could not issue token: $error';
}
@override
String federationEnrollmentTitle(String name) {
return 'Enroll $name';
}
@override
String get federationTokenLabel => 'Bootstrap token (single use)';
@override
String get federationConfigLabel =>
'Satellite config (paste into the satellite)';
@override
String get federationCopied => 'Copied to clipboard';
@override
String get federationEnrollmentHint =>
'Hand the token to the satellite operator over a secure channel. The bundled CA makes the satellite\'s first connect tamper-proof.';
}