chain-studio/lib/l10n/app_localizations_en.dart
flemming-it 10f38beafa
Some checks failed
Security / Security check (push) Failing after 2s
chore: 0.82.0 — switcher-rebuild changelog, anchor caption, capture harness
The anchor caption 'Projekt / Bereich' truncated uselessly at the
rail width — 'Kontext'/'Context' fits and the tooltip carries the
full explanation. workspace_shots_test renders the anchor, the
open menu (checkmark, aggregated why-line), and the switching /
in-area identity bar per theme as the visual-proof harness.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-08-28 00:28:02 +02:00

3979 lines
105 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 errModuleDownload => 'Module download failed';
@override
String get errModuleDownloadHint =>
'The module\'s bundle URL is unreachable (status code below). The hub is running fine — fix the URL/host or choose another store.';
@override
String storeFromSource(String store) {
return 'from $store';
}
@override
String get guidedSetupTitle => 'Setup assistant';
@override
String get guidedSetupIntro =>
'Answer three questions and Ch∆In assembles a tailored config, module set and starter flow.';
@override
String get guidedSetupScenario => 'Scenario';
@override
String get guidedSetupIntent => 'Task';
@override
String get guidedSetupTarget => 'Where will it run?';
@override
String get guidedSetupApproval =>
'Require a human approval step before the AI step';
@override
String get guidedSetupDataLocal =>
'Data must stay local (air-gapped posture)';
@override
String get guidedSetupReviewHeading => 'This is the plan Ch∆In will apply:';
@override
String get guidedSetupApply => 'Apply setup';
@override
String get guidedSetupApplied =>
'Setup applied. Finish with the steps below:';
@override
String get guidedSetupBack => 'Back';
@override
String get guidedSetupNext => 'Next';
@override
String get guidedSetupCancel => 'Cancel';
@override
String get guidedSetupClose => 'Close';
@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 data processing in regulated environments.';
@override
String get welcomePillarHubTitle => 'Hub';
@override
String get welcomePillarHubBody =>
'The program that runs everything. It works right on your machine, needs no extra software, and keeps everything important in a single file.';
@override
String get welcomePillarHubTech =>
'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 building block that does exactly one job — reading text out of documents, say. Every module states up front what it wants to touch; the hub allows nothing more.';
@override
String get welcomePillarModuleTech =>
'A small, sandboxed WebAssembly component. 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 recipe that connects modules into fixed steps. Inputs go in, steps run in order, the result comes out — and every step is recorded tamper-evidently.';
@override
String get welcomePillarFlowTech =>
'A YAML file that chains modules together; every step is recorded in a hash-chained audit log that the Diagnostics page verifies in full.';
@override
String get welcomePillarTechToggle => 'For the technically curious';
@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 makes later edits detectable — and what integrity level WORM-1 does (and does not) provide.';
@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 welcomeDocFederationTitle => 'Federation';
@override
String get welcomeDocFederationBlurb =>
'Connect other hubs (satellites) so their capabilities become usable here — what a satellite is and how enrolment works.';
@override
String get welcomeDocRunsTitle => 'Background runs';
@override
String get welcomeDocRunsBlurb =>
'Flows that keep working in the background — what they are for, how to switch the feature on and monitor the runs.';
@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 errNoStoreEntry => 'No store entry provides this capability.';
@override
String get errNoStoreEntryHint =>
'Three ways to get it: install a local module (chain install --link <path>), add the store that provides it (Settings → Stores), or configure the integration (MCP/n8n) that supplies it. If it was just published, refresh the Store page first.';
@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. The list shows the live state — refresh top right 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 => 'Connect a public tool catalog';
@override
String get welcomeChecklistMcpHint =>
'Connects a public tool catalog (the technical term is MCP) — its capabilities then appear in the Store. Add one there, or 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.\nproduction = stable · beta = pre-release · dev = rolling · local = workspace';
@override
String get buttonCancel => 'Cancel';
@override
String get buttonLearnMore => 'Learn more';
@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 storeStatusAlphaHelp =>
'Early version: it works, but it is still evolving and not cleared for regulated production use.';
@override
String get storeStatusPublishedHelp =>
'Cleared by the publisher for general use.';
@override
String get storeStatusPlannedHelp => 'Announced, but not available yet.';
@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 get storeCategoryDocument => 'Document';
@override
String get storeCatDocuments => 'Documents';
@override
String get storeCatTextLanguage => 'Text & Language';
@override
String get storeCatData => 'Data & Formats';
@override
String get storeCatAiLlm => 'AI & LLM';
@override
String get storeCatWebApi => 'Web & APIs';
@override
String get storeCatAnalysisDomain => 'Analysis & Domain';
@override
String get storeCatStudioThemes => 'Studio & Themes';
@override
String get storeCatExamplesDev => 'Examples & Dev';
@override
String get storeCatOther => 'Other';
@override
String get storeSegmentModules => 'Modules';
@override
String get storeSegmentStudio => 'Studio & Themes';
@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 storesManagerButton => 'Add store';
@override
String get storesManagerTitle => 'Module stores';
@override
String get storesManagerIntro =>
'The hub merges the modules from every store below into one index. Add a store\'s index URL to make its modules installable here.';
@override
String get storesManagerAddSection => 'Add a store';
@override
String get storesManagerNameLabel => 'Name';
@override
String get storesManagerUrlLabel => 'Index URL (https:// or file://)';
@override
String get storesManagerAddAction => 'Add store';
@override
String storesManagerBundled(int count) {
return '$count modules · bundled';
}
@override
String storesManagerModuleCount(int count) {
return '$count modules';
}
@override
String get storesManagerAddFailed => 'Could not add store';
@override
String get storesManagerRemoveFailed => 'Could not remove store';
@override
String get storesManagerSuggested => 'Suggested stores';
@override
String get storesManagerAddShort => 'Add';
@override
String get storesManagerPinnedKeyLabel => 'Pin a signing key (PEM, optional)';
@override
String get storesManagerPinnedKeyHint =>
'Only modules signed with this key are accepted from this source. Paste the publisher\'s public key (PEM) — used instead of the built-in vendor key.';
@override
String get storesManagerNotAvailable => 'Not available yet';
@override
String get storesManagerNotAvailableHint =>
'The provider hasn\'t published this store index yet. It will become installable once they do.';
@override
String get storesSuggestedReclaimDesc =>
'Recl∆Im — modules for law & duty reform-mapping';
@override
String get storeTodayBadge => 'TODAY';
@override
String get storeFeaturedBadge => 'FEATURED';
@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 auditFilterTooltip => 'Filter events';
@override
String get auditClearLogTooltip => 'Clear log (local/dev channels only)';
@override
String get auditMoreTooltip => 'More actions';
@override
String get auditSearchHint =>
'Search events (flow, step, module, error text …)';
@override
String get auditExportAction => 'Export current view as JSONL …';
@override
String get auditExportAllAction => 'Export full log as JSONL …';
@override
String get auditExportAllNothing => 'The log is empty — nothing to export.';
@override
String get auditExportNothing =>
'No events in the current view — nothing to export.';
@override
String auditExportSaved(int n, String path) {
return 'Exported $n events to $path';
}
@override
String get auditDevResetAction =>
'Development reset: clear log … (local/dev 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 auditClearReviewerHelper =>
'Recorded as an unchecked claim (prefix \"unverified:\") — the hub stores this name as sent.';
@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 .chain 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 authPolicyHeader => 'HUB ACCESS POLICY';
@override
String get authPolicyBlurb =>
'How the hub checks incoming calls: the active validator, the tokens and their scope grants. Secrets stay in environment variables — only their names appear here.';
@override
String get authPolicyValidatorStatic => 'Validator: static token list';
@override
String get authPolicyValidatorJwt =>
'Validator: JWT (RS256) via an external identity provider';
@override
String get authPolicyAnonymous =>
'No tokens configured — the hub accepts anonymous calls. Fine for local work; configure tokens in ~/.chain/config.yaml for production.';
@override
String get authPolicyReloadRequired =>
'The config file (or an environment variable) changed after loading — the hub still enforces the previous state. Use “Reload” below to apply the change.';
@override
String get authPolicyNeedsAdmin =>
'This view needs a token with the admin scope. Store it above under “Hub authentication” and reload.';
@override
String get authPolicyHubTooOld =>
'The connected hub does not know this view yet — it is older than Studio. Update the hub (chain update apply) and reload.';
@override
String get authPolicyRetry => 'Retry';
@override
String get authPolicyReload => 'Reload tokens';
@override
String authPolicyReloadDone(int n) {
return 'Reloaded — $n tokens active.';
}
@override
String get authPolicyEditHint =>
'The policy is edited in ~/.chain/config.yaml (auth: section). After a change or token rotation, reload here — the hub applies it without a restart.';
@override
String authPolicyEnvSet(String env) {
return 'Environment variable $env is set';
}
@override
String authPolicyEnvMissing(String env) {
return 'Environment variable $env is MISSING — the token is unusable';
}
@override
String authPolicyRateLimit(int n) {
return '$n/min';
}
@override
String get authPolicyJwtKeySource => 'Key source';
@override
String get authPolicyJwtAudience => 'Audience (aud)';
@override
String get authPolicyJwtIssuer => 'Issuer (iss)';
@override
String get authPolicyJwtScopeClaim => 'Scope claim';
@override
String get authPolicyNotChecked => 'not checked';
@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. When a flow asks for a human approval, the request appears 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 => 'DATA TO REVIEW';
@override
String get approvalsNoPayload =>
'No data was attached to this approval. You are deciding without a detail view — when in doubt, ask whoever set up the process. (Technical: the approval step\'s \"show:\" field controls what appears here.)';
@override
String get approvalsNoDataConfirmTitle => 'Approve without review data?';
@override
String get approvalsNoDataConfirmBody =>
'This flow deliberately attached no review data (no \"show:\" on its approval step). You can still approve — but you would be deciding without seeing the data behind this decision.';
@override
String get approvalsNoDataConfirmAction => 'Approve anyway';
@override
String get approvalsRequestFallback => 'Approval required for this step';
@override
String approvalsFlowStepMeta(String flow, String step) {
return 'Flow: $flow · Step: $step';
}
@override
String get approvalsIntroHelp =>
'Paused processes (flows) waiting for your decision. Each card shows which process is holding at which step and what data it puts in front of you — Approve resumes it, Reject stops it with your reason.';
@override
String get approvalsReviewerLabel => 'You are deciding as';
@override
String get approvalsReviewerUnverifiedPill => 'not verified';
@override
String approvalsReviewerRecordedAs(Object value) {
return 'Recorded as: $value';
}
@override
String get approvalsReviewerNoteAnonymous =>
'This hub accepts calls without credentials, so a decision cannot be proven to be anyone\'s. Studio therefore marks the name inside the record itself as an unchecked claim.';
@override
String get approvalsReviewerNoteAuthenticated =>
'The hub checks your access but records the name exactly as Studio sends it. Until the hub derives the identity from the checked access itself, Studio marks the name inside the record as an unchecked claim.';
@override
String get approvalsReviewerNoteUnknown =>
'Studio could not read this hub\'s access settings (that needs admin rights). The name is stored exactly as sent and is therefore marked inside the record as an unchecked claim.';
@override
String get approvalsReviewerUnverifiedTooltip =>
'Unchecked claim: this name comes from the deciding Studio, not from the hub.';
@override
String get approvalsRejectDialogHelp =>
'Rejecting stops the process at this step and is recorded with your reason in the audit trail.';
@override
String get approvalsRejectReasonHelper =>
'Required — recorded in the audit log.';
@override
String get approvalsBatchNoDataTitle => 'Approve without review data?';
@override
String approvalsBatchNoDataBody(num count, Object total) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other:
'$count of $total selected approvals have no review data. You are approving them without a detail view.',
one:
'1 of $total selected approvals has no review data. You are approving it without a detail view.',
);
return '$_temp0';
}
@override
String get approvalsCopyRun => 'Copy run id';
@override
String get approvalsRunCopied => 'Run id copied';
@override
String get approvalsUnknownReviewer => '(unknown)';
@override
String get approvalsOriginLabel => 'ORIGIN';
@override
String get approvalsOriginProject => 'Project';
@override
String get approvalsOriginRequested => 'Requested';
@override
String get approvalsOriginRun => 'Run';
@override
String get approvalsApproveTooltip => 'Resumes the flow at this step';
@override
String get approvalsRejectTooltip => 'Stops the flow — with your reason';
@override
String get approvalsApproveButton => 'Approve';
@override
String get approvalsRejectButton => 'Reject';
@override
String get approvalsRejectDialogTitle => 'Reject approval';
@override
String get approvalsRejectReasonLabel => 'Reason';
@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 => 'QUESTION';
@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) {
String _temp0 = intl.Intl.pluralLogic(
n,
locale: localeName,
other: '$n capabilities',
one: '1 capability',
);
return '$_temp0';
}
@override
String get doctorSummaryPending => 'pending';
@override
String doctorSummaryChain(int verified, int total) {
return '$verified of $total events verified';
}
@override
String get doctorSummaryDeclared => 'declared';
@override
String doctorOllamaSuggest(String endpoint) {
return 'The system AI uses Ollama at $endpoint — declare it as a host service so modules and the doctor know it?';
}
@override
String get doctorOllamaDeclareButton => 'Declare as host service';
@override
String get doctorOllamaDeclared =>
'Declared as host service \"ollama\" — takes effect after a daemon restart (button further down this page).';
@override
String updateHintBanner(String local, String latest) {
return 'Version $latest is available for the hub ($local).';
}
@override
String get updateHintOpenDoctor => 'Open Doctor';
@override
String get updateHintDismiss => 'Later';
@override
String get svcExposureLoopback => 'local only';
@override
String get svcExposurePrivate => 'private network';
@override
String get svcExposurePublic => 'publicly reachable';
@override
String get svcExposureUnknown => 'reach unknown';
@override
String get svcExposurePublicHint =>
'This service endpoint sits on a public address — make sure it is protected (TLS, auth, firewall).';
@override
String get svcExposureUnknownHint =>
'Hostname instead of an IP address — the hub deliberately does not resolve names to classify. Check yourself where the name resolves.';
@override
String get doctorLinkStore => 'Open the store';
@override
String get doctorLinkApprovals => 'Open approvals';
@override
String get doctorLinkAudit => 'Open the audit log';
@override
String get doctorLinkConfig => 'View the configuration';
@override
String get doctorLinkReleaseNotes => 'Open the release notes in the browser';
@override
String doctorModulesPanelSummary(int n, int m) {
String _temp0 = intl.Intl.pluralLogic(
n,
locale: localeName,
other: '$n modules',
one: '1 module',
);
String _temp1 = intl.Intl.pluralLogic(
m,
locale: localeName,
other: '$m capabilities',
one: '1 capability',
);
return '$_temp0 · $_temp1';
}
@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) {
String _temp0 = intl.Intl.pluralLogic(
n,
locale: localeName,
other: 'events',
one: 'event',
);
return '$n $_temp0 · linkage 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 => 'Hash chain verified';
@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 doctorConnLine(String endpoint, String transport, String auth) {
return 'Connection: $endpoint · $transport · $auth';
}
@override
String get doctorConnTls => 'TLS-encrypted';
@override
String get doctorConnPlainLocal => 'unencrypted (stays on this machine)';
@override
String get doctorConnPlainRemote => 'unencrypted';
@override
String doctorConnToken(int count) {
return 'token configured ($count characters)';
}
@override
String get doctorConnAnonymous => 'no token (anonymous)';
@override
String get doctorDbVolatileWarning =>
'The audit database is stored in a temporary folder the operating system may clean up at any time. For real evidence, move the hub\'s data directory to a permanent location.';
@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 hubViewTooOldTitle => 'This view needs a newer hub version';
@override
String get hubViewTooOldHint =>
'The hub is connected, but its version does not know this view yet. Update the hub (Doctor → Update) and the content will appear here.';
@override
String get hubViewLoadFailedTitle => 'This view could not be loaded';
@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 searchGroupWorkspace => 'Projects & areas';
@override
String get searchWorkspaceHint => 'switch context · ⌘P';
@override
String get searchWorkspaceSealedPickerHint => 'open the picker · ⌘P';
@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 settingsCategoryAbout => 'About';
@override
String get aboutPanelTitle => 'About Ch∆In';
@override
String get aboutPanelBody =>
'Product, vendor, and license details of this installation — every value is copyable.';
@override
String get aboutProduct => 'Product';
@override
String get aboutStudioVersion => 'Studio version';
@override
String get aboutHubVersion => 'Hub version';
@override
String get aboutHubVersionUnknown => 'not connected';
@override
String get aboutVendor => 'Vendor';
@override
String get aboutAuthor => 'Author';
@override
String get aboutLicense => 'License';
@override
String get aboutContact => 'Contact';
@override
String get aboutDocs => 'Documentation';
@override
String get aboutOpenLink => 'Open in browser';
@override
String get aboutCopyTooltip => 'Copy';
@override
String get aboutCopiedToast => 'Copied to the clipboard.';
@override
String get sidebarSearchLabel => 'Search & commands';
@override
String installConfirmTitle(String name) {
return 'Install \"$name\"?';
}
@override
String get installConfirmVersion => 'Version';
@override
String get installConfirmSource => 'Source';
@override
String get installConfirmSourceBundled => 'Bundled store index';
@override
String get installConfirmLicense => 'License';
@override
String get installConfirmStatus => 'Maturity';
@override
String get installConfirmNeedsServices => 'Required services';
@override
String get installConfirmNeedsCapabilities => 'Required capabilities';
@override
String get installConfirmTrustTitle => 'Trust & security';
@override
String get installConfirmTrustBody =>
'The module runs in a sandbox: it may only touch the network endpoints, files, and environment variables it declares itself — the hub enforces that list. The full permission list is visible in the module details after installation.';
@override
String get storeSectionMaintainers => 'Maintainers';
@override
String get storeMaintainersNone => 'not specified';
@override
String get installConfirmMaintainers => 'Maintainers';
@override
String get storePolicyUnverifiedNotice =>
'Signature enforcement is switched off in the hub policy — installs are not cryptographically verified. The install dialog shows the per-module status; enable security.require_signatures for verified installs.';
@override
String get verifPillBlocked => 'blocked';
@override
String get verifPinnedKey => 'Signature checked — pinned store key';
@override
String get verifPinnedKeyBody =>
'The hub verifies the bundle at install time against this source\'s pinned key. A tampered bundle is refused.';
@override
String get verifTrustedPublishers => 'Signature checked — trusted publishers';
@override
String get verifTrustedPublishersBody =>
'The hub verifies the signature at install time against the trusted-publisher list. A bundle without a valid signature is refused.';
@override
String get verifUnverified => 'Installs without signature checking';
@override
String get verifUnverifiedBody =>
'Signature enforcement is switched off in the hub policy — this bundle is not cryptographically verified at install time. Enable security.require_signatures for verified installs.';
@override
String get verifBlocked => 'An install would be refused';
@override
String get verifBlockedBody =>
'The policy requires signatures, but no key material applies to this source — the hub would refuse the install.';
@override
String get verifFederated =>
'Connected via an integration — no bundle signature';
@override
String get verifFederatedBody =>
'This entry is not an installable bundle; it runs through a configured integration (e.g. MCP or n8n). There is no bundle signature — trust follows the integration.';
@override
String get installConfirmSignatureNote =>
'The hub verifies signatures at install time whenever the security profile requires them. The store index does not yet show a per-entry signature status up front (alpha).';
@override
String get settingsSidebarPinnedTitle => 'Keep the navigation expanded';
@override
String get settingsSidebarPinnedBody =>
'Shows the sidebar labels permanently instead of only while hovering with the mouse.';
@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 .chain bundle URL or a local bundle path; the hub downloads, verifies (sha256 + signature) and installs it.';
}
@override
String get addSourceField => 'URL or path to .chain bundle';
@override
String get addSourceHint =>
'https://git.flemming.ai/your-org/your-module/releases/download/v0.1.0/foo-0.1.0.chain';
@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 .chain 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 chainBinaryNotFound =>
'Could not find the chain program on this machine.';
@override
String get chainBinaryNotFoundHint =>
'Install the Ch∆In platform, or point Studio at an existing chain binary.';
@override
String get chainBinaryLocateButton => 'Locate chain binary…';
@override
String get chainBinaryInstallDocsButton => 'Open install guide';
@override
String get chainBinaryPickerTitle => 'Select the chain binary';
@override
String chainBinarySetOk(String path) {
return 'Using chain 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 hubAuthRejectedBanner(String endpoint) {
return '$endpoint rejected the sign-in — check the access token';
}
@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 federationAddIntro =>
'A satellite is another hub this hub connects to — its capabilities then become usable here in flows. You give it a name and receive a one-time token the satellite uses to enrol with this hub.';
@override
String get federationNameHelp =>
'A free-form name to recognize this satellite in the list (e.g. its location or purpose). Display only — it changes nothing technical.';
@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 authenticates the satellite\'s first connect.';
@override
String get workspaceAll => 'All projects';
@override
String get workspaceDefaultProject => 'General';
@override
String get workspaceSwitcherTooltip =>
'Choose the working context — applies everywhere: filters flows, runs, audit and approvals, and stamps new runs with the selected project';
@override
String get workspaceAnchorCaption => 'Context';
@override
String workspaceStartConfirmTitle(String name) {
return 'Start area “$name”?';
}
@override
String get workspaceStartConfirmBody =>
'This sealed area is currently stopped. Studio starts its own hub instance on this machine and connects to it — running areas switch without this prompt.';
@override
String get workspaceStartConfirmAction => 'Start and connect';
@override
String get workspaceSealedAggregateWhy =>
'Names stay aggregated because they can reveal client identities.';
@override
String get workspaceSealedAggregateSettings =>
'Always show: Settings → Security';
@override
String get workspaceProtectedHint =>
'Protected: logically separated in the shared hub — no hard process barrier. Critical engagements use a sealed area.';
@override
String get runsTitle => 'Runs';
@override
String get runsReloadTooltip => 'Reload the runs list';
@override
String get runsEmptyTitle => 'No background runs';
@override
String get runsEmptyHint =>
'Runs that keep working in the background while you do something else appear here. The feature is optional and off by default — the guide shows step by step how to turn it on.';
@override
String get runsEmptyEnabledHint =>
'Background runs are switched on — none has been started yet. Start a flow with the \"run in background\" option and it will appear here.';
@override
String get runsEmptyGuideButton => 'Open the guide';
@override
String runsEmptyFilteredTitle(String name) {
return 'No runs in project “$name';
}
@override
String get runsEmptyFilteredHint =>
'The working context filters this list — other projects may have runs.';
@override
String get runsEmptyShowAll => 'Show all projects';
@override
String get runsHubTooOldTitle => 'This view needs a newer hub version';
@override
String get runsHubTooOldHint =>
'The hub is connected, but its version does not know the runs monitor yet. Update the hub and the runs will appear here.';
@override
String get runsHubTooOldButton => 'Open Doctor';
@override
String get runsHubUpdateButton => 'Update hub now';
@override
String get runsHubUpdateStarted => 'Updating hub…';
@override
String get runsLoadFailedTitle => 'Runs could not be loaded';
@override
String get runsCancelButton => 'Cancel';
@override
String runsCancelSignalled(String flow) {
return 'Cancel signalled for $flow.';
}
@override
String get runsCancelTooLate =>
'The run had already finished — nothing to cancel.';
@override
String runsCurrentStep(String step) {
return 'Step: $step';
}
@override
String get runsPhasePending => 'Pending';
@override
String get runsPhaseRunning => 'Running';
@override
String get runsPhaseSucceeded => 'Succeeded';
@override
String get runsPhaseFailed => 'Failed';
@override
String get runsPhaseCancelled => 'Cancelled';
@override
String get runsPhaseUnknown => 'Unknown';
@override
String get navRuns => 'Runs';
@override
String get workspaceSealedHeader => 'SEALED AREAS';
@override
String workspaceSealedAggregate(int n) {
String _temp0 = intl.Intl.pluralLogic(
n,
locale: localeName,
other: '$n sealed areas',
one: '1 sealed area',
);
return '$_temp0';
}
@override
String get workspaceSealedRevealAction => 'Show names';
@override
String get settingsSealedNamesTitle =>
'List sealed areas with their names right away';
@override
String get settingsSealedNamesBody =>
'Area names can be sensitive (client/mandate identity). By default the workspace switcher shows them aggregated; the names appear only after a click.';
@override
String get workspaceSealedRunning => 'running';
@override
String get workspaceSealedStopped => 'stopped';
@override
String get workspaceSealedRunningHint =>
'The sealed area runs as its own hub process. Selecting it switches in.';
@override
String get workspaceSealedStoppedHint =>
'The sealed area is not running right now. Selecting it starts it and switches in.';
@override
String workspaceSealedStarting(String name) {
return 'Starting sealed area “$name”…';
}
@override
String workspaceSealedStarted(String name) {
return 'Started sealed area “$name”.';
}
@override
String workspaceSealedSwitchFailed(String error) {
return 'Could not switch to the sealed area: $error';
}
@override
String get sealedIdentityBar =>
'Sealed area — isolated hub, own data and audit chain';
@override
String get sealedSwitchingBar =>
'Switching connection — data appears once the switch completes';
@override
String get sealedLeave => 'Leave';
@override
String setupStepOf(int n, int total) {
return 'Step $n of $total';
}
@override
String get setupStep1Title => 'What are the stakes?';
@override
String get setupStep2Title => 'What do you want to do first?';
@override
String get setupStep3Title => 'Where will it run?';
@override
String get setupReviewTitle => 'This is what Ch∆In will set up';
@override
String get setupChooseFreeText => 'Or just describe what you want to do';
@override
String get setupScenTryingOut => 'Just trying it out';
@override
String get setupScenTryingOutSub =>
'A straightforward workstation on this machine — no signature requirement, no write-protected audit log. You can upgrade any time: run the setup again and pick a regulated profile.';
@override
String get setupScenTeamHub => 'A shared team hub';
@override
String get setupScenTeamHubSub =>
'A secured hub for several people — signed modules, resource limits.';
@override
String get setupScenRegulated => 'Regulated production';
@override
String get setupScenRegulatedSub =>
'Signed modules, a complete tamper-evident audit trail, and a human approval before every AI step.';
@override
String get setupScenBuildModules => 'Building modules';
@override
String get setupScenBuildModulesSub =>
'A developer setup for writing and testing your own modules.';
@override
String get setupIntentHello => 'Run the hello example';
@override
String get setupIntentHelloSub => 'Just see one flow run end to end.';
@override
String get setupIntentExtract => 'Extract text from documents';
@override
String get setupIntentExtractSub =>
'Pull plain text out of PDF and DOCX files.';
@override
String get setupIntentExtractSummarize => 'Extract and summarize';
@override
String get setupIntentExtractSummarizeSub =>
'Extract text, then summarize it.';
@override
String get setupIntentClassify => 'Sort incoming documents';
@override
String get setupIntentClassifySub =>
'Extract text, then classify it with an AI step.';
@override
String get setupIntentBuildModule => 'Build my own module';
@override
String get setupIntentBuildModuleSub => 'Start from a module scaffold.';
@override
String get setupTargetLaptop => 'This computer';
@override
String get setupTargetLaptopSub =>
'Runs locally on the machine you are on now.';
@override
String get setupTargetHomeServer => 'An on-premise server';
@override
String get setupTargetHomeServerSub =>
'A server in your own house — starts on boot, runs in the background.';
@override
String get setupTargetAirgapped => 'A fully local server (no internet)';
@override
String get setupTargetAirgappedSub =>
'An isolated server with no internet — the strictest, most private posture.';
@override
String get setupTargetContainer => 'A container';
@override
String get setupTargetContainerSub =>
'Docker or Podman, with a ready-made compose snippet.';
@override
String get setupApprovalPlain =>
'Ask a person for approval before every AI step';
@override
String get setupDataLocalPlain =>
'Data must never leave the building (fully local)';
@override
String get setupPlanIntroDev => 'Ch∆In sets up a straightforward workspace.';
@override
String get setupPlanIntroEnterprise =>
'Ch∆In sets up a secured operation for a team.';
@override
String get setupPlanIntroAirgapped =>
'Ch∆In sets up a fully local, regulated operation.';
@override
String get setupPlanSignatures => 'Only signed modules are allowed.';
@override
String get setupPlanWorm =>
'The audit log is additionally sealed tamper-proof (WORM).';
@override
String get setupPlanApproval =>
'Before every AI step, the system asks a person for approval.';
@override
String setupPlanModules(String modules) {
return 'These modules are prepared: $modules.';
}
@override
String setupPlanFlow(String flow) {
return 'An example flow “$flow” is created.';
}
@override
String setupPlanFileChanged(String path) {
return 'Only one file is changed: $path.';
}
@override
String get setupPlanOverwriteWarn =>
'An existing configuration will be overwritten.';
@override
String get setupApplied => 'Done — Ch∆In is set up.';
@override
String get setupNextTitle => 'Next steps';
@override
String get setupNextHubStart => 'Start the hub';
@override
String get setupHubRunning => 'The hub is running.';
@override
String get setupStartHubFirst =>
'Start the hub first — then the modules can be installed right here.';
@override
String setupActionInstall(String module) {
return 'Install $module';
}
@override
String setupActionInstalled(String module) {
return '$module is installed.';
}
@override
String setupActionOpenFlow(String flow) {
return 'Open the “$flow” example flow';
}
@override
String get setupModulesOfflineHint =>
'The modules arrive as an offline bundle, without internet — the documentation explains this under “running without internet”.';
@override
String get setupModulesSignedHint =>
'The modules come from your own, signed source — not from the public store.';
@override
String get setupSigPublicStoreNotice =>
'This setup only accepts signed modules. The public store currently ships unsigned bundles — the prepared modules therefore come from your own, signed source.';
@override
String get setupAllowUnsigned => 'Allow installing from the public store';
@override
String get setupAllowUnsignedSub =>
'Deliberately relaxes the signature requirement. Fine for trying things out — re-enable it for regulated operation.';
@override
String get setupStartCta => 'Start setup';
@override
String get setupGateIntro =>
'Before you start: three questions, then Ch∆In sets this machine up to match. Nothing changes without your confirmation.';
@override
String get setupGateSkip => 'Set up later';
@override
String get settingsRunSetup => 'Run setup again…';
@override
String get settingsRunSetupHint =>
'Opens the setup assistant (three questions, preview, apply). Your existing configuration is only replaced after you confirm.';
@override
String get setupPlanRunbookLocal =>
'This machine is being set up; the hub runs locally and starts on demand.';
@override
String get setupPlanRunbookService =>
'This machine is being set up: the hub will start automatically on boot (background service). For a different server, run the setup there.';
@override
String get setupPlanRunbookAirgap =>
'Intended for an isolated server without internet — modules and updates arrive as offline bundles.';
@override
String get setupPlanRunbookContainer =>
'Intended for container operation — a ready-made compose example is included.';
@override
String get setupPlanAuditChain =>
'Every step lands in a gapless, hash-chained audit log — tampering becomes detectable.';
@override
String setupPlanDocs(int n) {
return 'A matching reading list ($n chapters) is stored with the setup record under ~/.chain/.';
}
@override
String get setupTrustedPublishersHint =>
'Important: when adding the source, pin the publisher\'s key (\"pin signing key\") — otherwise the hub accepts any formally valid signature, no matter whose.';
@override
String get setupAddSignedSource => 'Add a signed source…';
@override
String get setupApplyNotes => 'Notes from the setup';
@override
String get setupFreeTextHint =>
'e.g.: pre-screen incoming applications and flag incomplete ones';
@override
String get setupFreeTextSuggest => 'Suggest a setup';
@override
String setupFreeTextPrivacyLocal(String model) {
return 'Your description is processed right on this machine — by the local AI model $model. Nothing leaves the device.';
}
@override
String setupFreeTextPrivacyRemote(String model, String provider) {
return 'Your description is sent to the configured system AI: $model ($provider).';
}
@override
String get setupFreeTextUnavailable =>
'The free-text path needs a configured system AI (Settings → System AI). The choices above always work — no AI required.';
@override
String setupExecHint(String path) {
return 'For the preview and setup, Studio runs the “chain” program: $path';
}
@override
String setupExecHintTcc(String path) {
return 'The program lives at $path — macOS may ask once for access to that folder (e.g. “Documents”). That is expected and fine.';
}
@override
String get setupNoBinaryStepHint =>
'The “chain” program could not be found on this machine — the preview in the next step will fail. You can pick it under “Doctor”, or install Ch∆In.';
@override
String get setupNoBinary =>
'The “chain” program could not be found on this machine.';
@override
String get setupNoBinaryHint =>
'Without it the assistant cannot apply the setup. Pick it under “Doctor”, or reinstall Ch∆In.';
@override
String get setupCliTooOld =>
'The installed “chain” program is older than Studio and does not know this assistant yet.';
@override
String setupCliTooOldHint(String path) {
return 'Found: $path. Please update Ch∆In (“Doctor” page → update, or in a terminal: chain update apply) and reopen the assistant afterwards.';
}
@override
String get setupPreviewFailed =>
'The plan preview could not be created — the “chain” program reported an error.';
@override
String get setupApplyFailed =>
'The setup could not be applied — the “chain” program reported an error.';
@override
String setupCliUsedBinary(String path) {
return 'Executed: $path';
}
@override
String get setupFreeTextParseError =>
'The system AI did not return a usable suggestion. Pick from the menu above — or try again.';
@override
String get setupReflectionTitle => 'This is how I read your task';
@override
String setupReflectionScenario(String label) {
return 'What it is about: $label';
}
@override
String setupReflectionIntent(String label) {
return 'First task: $label';
}
@override
String setupReflectionTarget(String label) {
return 'Environment: $label';
}
@override
String get setupReflectionApproval =>
'A human is asked for approval before every AI step.';
@override
String get setupReflectionDataLocal => 'Data never leaves the building.';
@override
String get setupReflectionEditHint =>
'Nothing is changed without your confirmation. Adjust any point, or go straight to the preview.';
@override
String get setupReflectionAdjust => 'Adjust';
@override
String get setupReflectionToPreview => 'To the preview';
@override
String get setupProfileDev => 'straightforward workstation';
@override
String get setupProfileEnterprise => 'hardened team operation';
@override
String get setupProfileAirgapped => 'fully local, regulated operation';
@override
String welcomeChecklistSetupDone(String profile) {
return 'The setup assistant already took care of the basics ($profile) — this list shows what has actually happened on your hub.';
}
}