Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3aebfa7ec3 | ||
|
|
ea340ef141 |
@@ -38,6 +38,15 @@ heading, and (b) bumping `pubspec.yaml` `version:` in the same commit.
|
||||
locale under `assets/i18n/<locale>/`. A new language is a drop-in folder;
|
||||
en_US behaviour is unchanged. (T-462)
|
||||
|
||||
## [2.8.1] — 2026-06-22
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Localized the remaining Claude-pane strings.** Running-indicator verbs, the
|
||||
primary/secondary session titles and banner role, tool-card titles, the
|
||||
step/edit/agent counters, and the folded-activity ticker now resolve through
|
||||
the catalog — completing i18n coverage of the conversation surface. (T-462)
|
||||
|
||||
## [2.7.1] — 2026-06-18
|
||||
|
||||
### Changed
|
||||
|
||||
@@ -6,13 +6,37 @@
|
||||
"status.primary-exited": { "translation": "session exited — restart clide to retry" },
|
||||
"banner.title": { "translation": "Claude" },
|
||||
"banner.warmingUp": { "translation": "Warming up — your conversation will appear here." },
|
||||
"banner.role.primary": { "translation": "primary" },
|
||||
"banner.role.secondary": { "translation": "session {index}" },
|
||||
"composer.hint": { "translation": "Message Claude… (Enter to send · Shift+Enter for newline)" },
|
||||
"composer.stop": { "translation": "Stop ⎋" },
|
||||
"composer.stop.hint": { "translation": "Interrupt the running turn (Escape)" },
|
||||
"composer.removeAttachment": { "translation": "Remove {name}" },
|
||||
"pane.title.primary": { "translation": "claude — primary" },
|
||||
"pane.title.secondary": { "translation": "claude — secondary {index}" },
|
||||
"pane.starting": { "translation": "starting…" },
|
||||
"pane.modeBadge.semantics": { "translation": "permission mode: {mode}" },
|
||||
"running.semantics": { "translation": "Claude is running" },
|
||||
"running.verb.pondering": { "translation": "Pondering" },
|
||||
"running.verb.conjuring": { "translation": "Conjuring" },
|
||||
"running.verb.brewing": { "translation": "Brewing" },
|
||||
"running.verb.tinkering": { "translation": "Tinkering" },
|
||||
"running.verb.noodling": { "translation": "Noodling" },
|
||||
"running.verb.percolating": { "translation": "Percolating" },
|
||||
"running.verb.computing": { "translation": "Computing" },
|
||||
"running.verb.wrangling": { "translation": "Wrangling" },
|
||||
"running.verb.untangling": { "translation": "Untangling" },
|
||||
"running.verb.synthesizing": { "translation": "Synthesizing" },
|
||||
"running.verb.cogitating": { "translation": "Cogitating" },
|
||||
"running.verb.whirring": { "translation": "Whirring" },
|
||||
"running.verb.mincing": { "translation": "Mincing" },
|
||||
"running.verb.boiling": { "translation": "Boiling" },
|
||||
"running.verb.humming": { "translation": "Humming" },
|
||||
"running.verb.buzzing": { "translation": "Buzzing" },
|
||||
"running.verb.magicking": { "translation": "Magicking" },
|
||||
"running.verb.cliding": { "translation": "Cliding" },
|
||||
"running.verb.zooming": { "translation": "Zooming" },
|
||||
"running.verb.bouncing": { "translation": "Bouncing" },
|
||||
"conversation.empty": { "translation": "Waiting for Claude…" },
|
||||
"conversation.label.you": { "translation": "you" },
|
||||
"conversation.label.claude": { "translation": "claude" },
|
||||
@@ -39,6 +63,12 @@
|
||||
"conversation.bashTail.label": { "translation": "live tail" },
|
||||
"conversation.cluster.activity": { "translation": "Activity" },
|
||||
"conversation.cluster.edits": { "translation": "Edits" },
|
||||
"conversation.counter.step": { "translation": "1 step" },
|
||||
"conversation.counter.steps": { "translation": "{count} steps" },
|
||||
"conversation.counter.edit": { "translation": "1 edit" },
|
||||
"conversation.counter.edits": { "translation": "{count} edits" },
|
||||
"conversation.counter.starting": { "translation": "starting" },
|
||||
"conversation.counter.agents": { "translation": "{done}/{total} agents" },
|
||||
"prompt.permission.allow": { "translation": "1. Allow" },
|
||||
"prompt.permission.allowRemember": { "translation": "2. Allow & don't ask again" },
|
||||
"prompt.permission.deny": { "translation": "{n}. Deny" },
|
||||
@@ -62,6 +92,16 @@
|
||||
"tool.edit.before": { "translation": "— before" },
|
||||
"tool.edit.after": { "translation": "+ after" },
|
||||
"tool.bash.background": { "translation": "background" },
|
||||
"tool.name.Read": { "translation": "Read" },
|
||||
"tool.name.Edit": { "translation": "Edit" },
|
||||
"tool.name.MultiEdit": { "translation": "MultiEdit" },
|
||||
"tool.name.Write": { "translation": "Write" },
|
||||
"tool.name.NotebookEdit": { "translation": "NotebookEdit" },
|
||||
"tool.name.WebFetch": { "translation": "WebFetch" },
|
||||
"tool.name.WebSearch": { "translation": "WebSearch" },
|
||||
"tool.name.Task": { "translation": "Task" },
|
||||
"tool.name.TodoWrite": { "translation": "TodoWrite" },
|
||||
"tool.name.ExitPlanMode": { "translation": "ExitPlanMode" },
|
||||
"permissionControl.semantics": { "translation": "permission mode: {mode}. Activate to change." },
|
||||
"permissionControl.tooltip": { "translation": "Permission mode: {mode} — change (Ctrl/Cmd+M cycles)" },
|
||||
"permissionBadge.tooltip": { "translation": "Permission mode: {mode}. Click to cycle default/acceptEdits/plan; Shift-click for bypassPermissions." },
|
||||
|
||||
@@ -6,13 +6,37 @@
|
||||
"status.primary-exited": { "translation": "sessie beëindigd — herstart clide om opnieuw te proberen" },
|
||||
"banner.title": { "translation": "Claude" },
|
||||
"banner.warmingUp": { "translation": "Opstarten — je gesprek verschijnt hier." },
|
||||
"banner.role.primary": { "translation": "primair" },
|
||||
"banner.role.secondary": { "translation": "sessie {index}" },
|
||||
"composer.hint": { "translation": "Bericht aan Claude… (Enter om te verzenden · Shift+Enter voor een nieuwe regel)" },
|
||||
"composer.stop": { "translation": "Stop ⎋" },
|
||||
"composer.stop.hint": { "translation": "Onderbreek de lopende beurt (Escape)" },
|
||||
"composer.removeAttachment": { "translation": "{name} verwijderen" },
|
||||
"pane.title.primary": { "translation": "claude — primair" },
|
||||
"pane.title.secondary": { "translation": "claude — secundair {index}" },
|
||||
"pane.starting": { "translation": "starten…" },
|
||||
"pane.modeBadge.semantics": { "translation": "permissiemodus: {mode}" },
|
||||
"running.semantics": { "translation": "Claude is bezig" },
|
||||
"running.verb.pondering": { "translation": "Peinzen" },
|
||||
"running.verb.conjuring": { "translation": "Toveren" },
|
||||
"running.verb.brewing": { "translation": "Brouwen" },
|
||||
"running.verb.tinkering": { "translation": "Knutselen" },
|
||||
"running.verb.noodling": { "translation": "Prutsen" },
|
||||
"running.verb.percolating": { "translation": "Pruttelen" },
|
||||
"running.verb.computing": { "translation": "Rekenen" },
|
||||
"running.verb.wrangling": { "translation": "Worstelen" },
|
||||
"running.verb.untangling": { "translation": "Ontwarren" },
|
||||
"running.verb.synthesizing": { "translation": "Synthetiseren" },
|
||||
"running.verb.cogitating": { "translation": "Overpeinzen" },
|
||||
"running.verb.whirring": { "translation": "Snorren" },
|
||||
"running.verb.mincing": { "translation": "Hakken" },
|
||||
"running.verb.boiling": { "translation": "Koken" },
|
||||
"running.verb.humming": { "translation": "Neuriën" },
|
||||
"running.verb.buzzing": { "translation": "Zoemen" },
|
||||
"running.verb.magicking": { "translation": "Goochelen" },
|
||||
"running.verb.cliding": { "translation": "Cliden" },
|
||||
"running.verb.zooming": { "translation": "Zoeven" },
|
||||
"running.verb.bouncing": { "translation": "Stuiteren" },
|
||||
"conversation.empty": { "translation": "Wachten op Claude…" },
|
||||
"conversation.label.you": { "translation": "jij" },
|
||||
"conversation.label.claude": { "translation": "claude" },
|
||||
@@ -39,6 +63,12 @@
|
||||
"conversation.bashTail.label": { "translation": "live tail" },
|
||||
"conversation.cluster.activity": { "translation": "Activiteit" },
|
||||
"conversation.cluster.edits": { "translation": "Wijzigingen" },
|
||||
"conversation.counter.step": { "translation": "1 stap" },
|
||||
"conversation.counter.steps": { "translation": "{count} stappen" },
|
||||
"conversation.counter.edit": { "translation": "1 wijziging" },
|
||||
"conversation.counter.edits": { "translation": "{count} wijzigingen" },
|
||||
"conversation.counter.starting": { "translation": "starten" },
|
||||
"conversation.counter.agents": { "translation": "{done}/{total} agents" },
|
||||
"prompt.permission.allow": { "translation": "1. Toestaan" },
|
||||
"prompt.permission.allowRemember": { "translation": "2. Toestaan en niet meer vragen" },
|
||||
"prompt.permission.deny": { "translation": "{n}. Weigeren" },
|
||||
@@ -62,6 +92,16 @@
|
||||
"tool.edit.before": { "translation": "— voor" },
|
||||
"tool.edit.after": { "translation": "+ na" },
|
||||
"tool.bash.background": { "translation": "achtergrond" },
|
||||
"tool.name.Read": { "translation": "Lezen" },
|
||||
"tool.name.Edit": { "translation": "Bewerken" },
|
||||
"tool.name.MultiEdit": { "translation": "Meervoudig bewerken" },
|
||||
"tool.name.Write": { "translation": "Schrijven" },
|
||||
"tool.name.NotebookEdit": { "translation": "Notebook bewerken" },
|
||||
"tool.name.WebFetch": { "translation": "Web ophalen" },
|
||||
"tool.name.WebSearch": { "translation": "Web zoeken" },
|
||||
"tool.name.Task": { "translation": "Taak" },
|
||||
"tool.name.TodoWrite": { "translation": "Takenlijst" },
|
||||
"tool.name.ExitPlanMode": { "translation": "Planmodus verlaten" },
|
||||
"permissionControl.semantics": { "translation": "permissiemodus: {mode}. Activeer om te wijzigen." },
|
||||
"permissionControl.tooltip": { "translation": "Permissiemodus: {mode} — wijzigen (Ctrl/Cmd+M wisselt)" },
|
||||
"permissionBadge.tooltip": { "translation": "Permissiemodus: {mode}. Klik om te wisselen tussen default/acceptEdits/plan; Shift-klik voor bypassPermissions." },
|
||||
|
||||
@@ -39,7 +39,7 @@ self:
|
||||
# Auto-synced from pubspec.yaml `version:` by `make gen-build-info`
|
||||
# (runs implicitly on every build/run/test). Don't hand-edit; bump
|
||||
# pubspec instead.
|
||||
version: "2.8.0"
|
||||
version: "2.8.1"
|
||||
homepage: https://github.com/postmeridiem/clide
|
||||
license: MIT
|
||||
license_file: assets/LICENSE
|
||||
|
||||
@@ -728,7 +728,15 @@ class _ClaudePaneState extends State<ClaudePane> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final title = widget.isPrimary ? 'claude — primary' : 'claude — secondary ${widget.secondaryIndex}';
|
||||
final title = widget.isPrimary
|
||||
? ClideSettings.i18n.string(context, 'pane.title.primary', namespace: 'builtin.claude', placeholder: 'claude — primary')
|
||||
: ClideSettings.i18n.interpolated(
|
||||
context,
|
||||
'pane.title.secondary',
|
||||
namespace: 'builtin.claude',
|
||||
placeholder: 'claude — secondary ${widget.secondaryIndex}',
|
||||
replacers: [I18nReplacer(from: '{index}', replace: '${widget.secondaryIndex}')],
|
||||
);
|
||||
final tokens = ClideSettings.theme.of(context).surface;
|
||||
|
||||
final Widget body;
|
||||
@@ -761,7 +769,15 @@ class _ClaudePaneState extends State<ClaudePane> {
|
||||
quietErrorToolUseIds: _session?.quietErrorToolUseIds ?? const <String>{},
|
||||
workflows: _session?.workflows ?? const <String, WorkflowRun>{},
|
||||
emptyState: ClaudeBanner(
|
||||
role: widget.isPrimary ? 'primary' : 'session ${widget.secondaryIndex}',
|
||||
role: widget.isPrimary
|
||||
? ClideSettings.i18n.string(context, 'banner.role.primary', namespace: 'builtin.claude', placeholder: 'primary')
|
||||
: ClideSettings.i18n.interpolated(
|
||||
context,
|
||||
'banner.role.secondary',
|
||||
namespace: 'builtin.claude',
|
||||
placeholder: 'session ${widget.secondaryIndex}',
|
||||
replacers: [I18nReplacer(from: '{index}', replace: '${widget.secondaryIndex}')],
|
||||
),
|
||||
workspace: _repoRoot,
|
||||
statusLine: _statusLine,
|
||||
),
|
||||
|
||||
@@ -800,10 +800,10 @@ class _ConversationTurn extends StatelessWidget {
|
||||
final outcome = toolUseOutcomes[t.toolUseId];
|
||||
final color = outcome == null ? tokens.globalFocus : (outcome ? tokens.statusSuccess : tokens.statusError);
|
||||
final collapser = ClideCollapserCard(
|
||||
label: t.name,
|
||||
label: _toolNameLabel(context, t.name),
|
||||
color: color,
|
||||
collapsedSummary: _toolUseSummary(t),
|
||||
counter: '1 step',
|
||||
counter: _stepsCounter(context, 1),
|
||||
status: _toolRunStatus(t),
|
||||
children: [_toolContentCard(context, t)],
|
||||
);
|
||||
@@ -818,8 +818,8 @@ class _ConversationTurn extends StatelessWidget {
|
||||
padding: const EdgeInsets.only(left: 12),
|
||||
child: ClideCollapserCard(
|
||||
label: ClideSettings.i18n.string(context, 'conversation.label.agentRun', namespace: 'builtin.claude', placeholder: 'agent run'),
|
||||
collapsedSummary: _summarizeActivity(runItems.last),
|
||||
counter: runItems.length == 1 ? '1 step' : '${runItems.length} steps',
|
||||
collapsedSummary: _summarizeActivity(context, runItems.last),
|
||||
counter: _stepsCounter(context, runItems.length),
|
||||
children: [
|
||||
for (final r in runItems)
|
||||
_ConversationTurn(
|
||||
@@ -849,7 +849,18 @@ class _ConversationTurn extends StatelessWidget {
|
||||
Widget _workflowCard(BuildContext context, AssistantToolUse t, WorkflowRun run) {
|
||||
final title = run.name ?? ClideSettings.i18n.string(context, 'conversation.label.workflow', namespace: 'builtin.claude', placeholder: 'workflow');
|
||||
final color = run.done ? tokens.statusSuccess : tokens.globalFocus;
|
||||
final counter = run.agentCount == 0 ? 'starting' : '${run.doneCount}/${run.agentCount} agents';
|
||||
final counter = run.agentCount == 0
|
||||
? ClideSettings.i18n.string(context, 'conversation.counter.starting', namespace: 'builtin.claude', placeholder: 'starting')
|
||||
: ClideSettings.i18n.interpolated(
|
||||
context,
|
||||
'conversation.counter.agents',
|
||||
namespace: 'builtin.claude',
|
||||
placeholder: '${run.doneCount}/${run.agentCount} agents',
|
||||
replacers: [
|
||||
I18nReplacer(from: '{done}', replace: '${run.doneCount}'),
|
||||
I18nReplacer(from: '{total}', replace: '${run.agentCount}'),
|
||||
],
|
||||
);
|
||||
final detail = run.done ? (run.summary ?? run.description) : run.description;
|
||||
final collapsedSummary = (detail == null || detail == title) ? title : '$title · $detail';
|
||||
return ClideCollapserCard(
|
||||
@@ -990,7 +1001,7 @@ class _ConversationTurn extends StatelessWidget {
|
||||
variant: ConversationCardVariant.bordered,
|
||||
accent: accent,
|
||||
borderColor: outcome == null ? null : accent,
|
||||
label: t.name,
|
||||
label: _toolNameLabel(context, t.name),
|
||||
copyText: const JsonEncoder.withIndent(' ').convert(t.input),
|
||||
status: status,
|
||||
body: toolInputBody(context, tokens, t.name, t.input, mono),
|
||||
@@ -1047,7 +1058,7 @@ class _ConversationTurn extends StatelessWidget {
|
||||
variant: ConversationCardVariant.bordered,
|
||||
accent: quiet ? tokens.globalTextMuted : accent,
|
||||
borderColor: quiet ? tokens.panelBorder : tokens.statusError,
|
||||
label: paired != null ? '${paired.name} · $errLabel' : errLabel,
|
||||
label: paired != null ? '${_toolNameLabel(context, paired.name)} · $errLabel' : errLabel,
|
||||
copyText: t.content,
|
||||
collapsible: quiet || multiline,
|
||||
collapsedByDefault: quiet, // genuine errors stay expanded; a denial folds
|
||||
@@ -1061,7 +1072,7 @@ class _ConversationTurn extends StatelessWidget {
|
||||
// For Write/Edit, the result is usually "OK" — keep it as plain text.
|
||||
final multiline = t.content.contains('\n');
|
||||
final isOutputTool = paired != null && const {'Bash', 'Read', 'Grep', 'LS'}.contains(paired.name);
|
||||
final resultLabel = paired != null ? '${paired.name} · $label' : label;
|
||||
final resultLabel = paired != null ? '${_toolNameLabel(context, paired.name)} · $label' : label;
|
||||
return ConversationCard(
|
||||
variant: ConversationCardVariant.bordered,
|
||||
accent: accent,
|
||||
@@ -1127,8 +1138,8 @@ class _ActivityCard extends StatelessWidget {
|
||||
final count = items.length;
|
||||
return ClideCollapserCard(
|
||||
label: ClideSettings.i18n.string(context, 'conversation.cluster.activity', namespace: 'builtin.claude', placeholder: 'Activity'),
|
||||
collapsedSummary: _summarizeActivity(items.last),
|
||||
counter: count == 1 ? '1 step' : '$count steps',
|
||||
collapsedSummary: _summarizeActivity(context, items.last),
|
||||
counter: _stepsCounter(context, count),
|
||||
status: _runStatus(items, resultByToolUseId),
|
||||
children: [
|
||||
for (final item in items)
|
||||
@@ -1150,6 +1161,35 @@ class _ActivityCard extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
/// Localized display label for a tool name (T-462). File/web/task operations
|
||||
/// have natural translations; command/proper-name tools (Bash, Grep, Glob, LS)
|
||||
/// have no catalog key and fall back to the raw name via the placeholder.
|
||||
String _toolNameLabel(BuildContext context, String name) =>
|
||||
ClideSettings.i18n.string(context, 'tool.name.$name', namespace: 'builtin.claude', placeholder: name);
|
||||
|
||||
/// Localized "N steps" counter for a collapser header (T-462). Singular and
|
||||
/// plural are distinct catalog keys; the English forms double as the fallback.
|
||||
String _stepsCounter(BuildContext context, int n) => n == 1
|
||||
? ClideSettings.i18n.string(context, 'conversation.counter.step', namespace: 'builtin.claude', placeholder: '1 step')
|
||||
: ClideSettings.i18n.interpolated(
|
||||
context,
|
||||
'conversation.counter.steps',
|
||||
namespace: 'builtin.claude',
|
||||
placeholder: '$n steps',
|
||||
replacers: [I18nReplacer(from: '{count}', replace: '$n')],
|
||||
);
|
||||
|
||||
/// Localized "N edits" counter for the edit-run collapser header (T-462).
|
||||
String _editsCounter(BuildContext context, int n) => n == 1
|
||||
? ClideSettings.i18n.string(context, 'conversation.counter.edit', namespace: 'builtin.claude', placeholder: '1 edit')
|
||||
: ClideSettings.i18n.interpolated(
|
||||
context,
|
||||
'conversation.counter.edits',
|
||||
namespace: 'builtin.claude',
|
||||
placeholder: '$n edits',
|
||||
replacers: [I18nReplacer(from: '{count}', replace: '$n')],
|
||||
);
|
||||
|
||||
/// Aggregate live status for a run's header tick (T-296): error if any tool in
|
||||
/// the run failed, else running while its last tool awaits a result, else
|
||||
/// success. Null (no tools) shows no indicator.
|
||||
@@ -1193,8 +1233,8 @@ class _EditRunCard extends StatelessWidget {
|
||||
final count = edits.length;
|
||||
return ClideCollapserCard(
|
||||
label: ClideSettings.i18n.string(context, 'conversation.cluster.edits', namespace: 'builtin.claude', placeholder: 'Edits'),
|
||||
collapsedSummary: _summarizeActivity(edits.last),
|
||||
counter: count == 1 ? '1 edit' : '$count edits',
|
||||
collapsedSummary: _summarizeActivity(context, edits.last),
|
||||
counter: _editsCounter(context, count),
|
||||
status: _runStatus(edits, resultByToolUseId),
|
||||
children: [
|
||||
for (final item in edits)
|
||||
@@ -1216,22 +1256,25 @@ class _EditRunCard extends StatelessWidget {
|
||||
}
|
||||
|
||||
/// One-line summary of a folded item for the collapsed ticker.
|
||||
String _summarizeActivity(ConversationItem item) {
|
||||
String _summarizeActivity(BuildContext context, ConversationItem item) {
|
||||
String label(String key, String fallback) => ClideSettings.i18n.string(context, key, namespace: 'builtin.claude', placeholder: fallback);
|
||||
switch (item) {
|
||||
case AssistantToolUse(:final name, :final input):
|
||||
final raw = input['command'] ?? input['file_path'] ?? input['path'] ?? input['pattern'] ?? input['url'];
|
||||
final detail = raw is String ? raw.split('\n').first.trim() : '';
|
||||
final clipped = detail.length > 72 ? '${detail.substring(0, 72)}…' : detail;
|
||||
return clipped.isEmpty ? name : '$name $clipped';
|
||||
final toolName = _toolNameLabel(context, name);
|
||||
return clipped.isEmpty ? toolName : '$toolName $clipped';
|
||||
case ToolResultMessage(:final isError):
|
||||
return isError ? '↳ result · error' : '↳ result';
|
||||
final result = label('conversation.label.result', 'result');
|
||||
return isError ? '↳ $result · ${label('conversation.label.error', 'error')}' : '↳ $result';
|
||||
case AssistantThinkingMessage():
|
||||
return 'thinking…';
|
||||
return '${label('conversation.label.thinking', 'thinking')}…';
|
||||
case UserMessage(:final text):
|
||||
return text;
|
||||
case AssistantTextMessage(:final text):
|
||||
return text;
|
||||
case ImageMessage(:final path):
|
||||
return 'image $path';
|
||||
return '${label('conversation.label.image', 'image')} $path';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,17 +90,22 @@ class _RunningIndicatorState extends State<RunningIndicator> with SingleTickerPr
|
||||
label: ClideSettings.i18n.string(context, 'running.semantics', namespace: 'builtin.claude', placeholder: 'Claude is running'),
|
||||
child: ExcludeSemantics(
|
||||
child: reduced
|
||||
? ClideText('${_verbs.first}…', color: claudeAccent, fontSize: clideFontMeta)
|
||||
? ClideText('${_verb(context, _verbs.first)}…', color: claudeAccent, fontSize: clideFontMeta)
|
||||
: AnimatedBuilder(
|
||||
animation: _c,
|
||||
builder: (ctx, _) {
|
||||
final elapsed = _c.value * _periodSeconds;
|
||||
final dots = '.' * (elapsed.floor() % 4);
|
||||
final word = _verbs[(elapsed ~/ _secondsPerWord) % _verbs.length];
|
||||
return ClideText('$word$dots', color: claudeAccent, fontSize: clideFontMeta);
|
||||
return ClideText('${_verb(ctx, word)}$dots', color: claudeAccent, fontSize: clideFontMeta);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Localize a verb through the catalog; the English word doubles as the key
|
||||
/// suffix and the fallback, so a missing translation degrades to English.
|
||||
String _verb(BuildContext context, String word) =>
|
||||
ClideSettings.i18n.string(context, 'running.verb.${word.toLowerCase()}', namespace: 'builtin.claude', placeholder: word);
|
||||
}
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ description: >-
|
||||
subsystem handlers (pane, files, editor, git, pql), and the
|
||||
extension framework.
|
||||
publish_to: none
|
||||
version: 2.8.0
|
||||
version: 2.8.1
|
||||
repository: https://github.com/postmeridiem/clide
|
||||
# Short user-facing tagline (the welcome subtitle, web meta
|
||||
# description, etc.). Baked into lib/src/build_info.g.dart by
|
||||
|
||||
Reference in New Issue
Block a user