feat(i18n): localize ViewModel-built strings via ambient Loc accessor
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,7 @@ using ClaudeDo.Data;
|
||||
using ClaudeDo.Data.Models;
|
||||
using ClaudeDo.Data.Repositories;
|
||||
using ClaudeDo.Ui.Helpers;
|
||||
using ClaudeDo.Ui.Localization;
|
||||
using ClaudeDo.Ui.Services;
|
||||
using ClaudeDo.Ui.Services.Interfaces;
|
||||
using ClaudeDo.Ui.ViewModels.Modals;
|
||||
@@ -99,13 +100,14 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
|
||||
[NotifyCanExecuteChangedFor(nameof(DequeueCommand))]
|
||||
[NotifyCanExecuteChangedFor(nameof(ResetAndRetryCommand))]
|
||||
[NotifyCanExecuteChangedFor(nameof(ContinueCommand))]
|
||||
private string _agentStatusLabel = "Idle";
|
||||
public bool IsIdle => AgentStatusLabel == "Idle";
|
||||
public bool IsQueued => AgentStatusLabel == "Queued";
|
||||
public bool IsRunning => AgentStatusLabel == "Running";
|
||||
public bool IsDone => AgentStatusLabel == "Done";
|
||||
public bool IsFailed => AgentStatusLabel == "Failed";
|
||||
public bool IsCancelled => AgentStatusLabel == "Cancelled";
|
||||
private string _agentState = "idle";
|
||||
public string AgentStatusLabel => Loc.T($"vm.agentStatus.{AgentState}");
|
||||
public bool IsIdle => AgentState == "idle";
|
||||
public bool IsQueued => AgentState == "queued";
|
||||
public bool IsRunning => AgentState == "running";
|
||||
public bool IsDone => AgentState == "done";
|
||||
public bool IsFailed => AgentState == "failed";
|
||||
public bool IsCancelled => AgentState == "cancelled";
|
||||
|
||||
// Recovery actions: Continue (resume session) for Failed/Cancelled.
|
||||
public bool ShowContinue => IsFailed || IsCancelled;
|
||||
@@ -116,8 +118,9 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
|
||||
[NotifyCanExecuteChangedFor(nameof(ContinueCommand))]
|
||||
private string? _latestRunSessionId;
|
||||
|
||||
partial void OnAgentStatusLabelChanged(string value)
|
||||
partial void OnAgentStateChanged(string value)
|
||||
{
|
||||
OnPropertyChanged(nameof(AgentStatusLabel));
|
||||
OnPropertyChanged(nameof(IsIdle));
|
||||
OnPropertyChanged(nameof(IsQueued));
|
||||
OnPropertyChanged(nameof(IsRunning));
|
||||
@@ -127,6 +130,8 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
|
||||
OnPropertyChanged(nameof(ShowContinue));
|
||||
OnPropertyChanged(nameof(ShowResetAndRetry));
|
||||
OnPropertyChanged(nameof(IsAgentSectionEnabled));
|
||||
OnPropertyChanged(nameof(EffectiveModelLabel));
|
||||
OnPropertyChanged(nameof(EffectiveAgentLabel));
|
||||
}
|
||||
[ObservableProperty] private string? _model;
|
||||
|
||||
@@ -139,6 +144,12 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
|
||||
[ObservableProperty] private string _effectiveSystemPromptHint = "";
|
||||
[ObservableProperty] private string _effectiveAgentHint = "";
|
||||
|
||||
public string EffectiveModelLabel => Loc.T("vm.details.effectiveIfInherited", EffectiveModelHint);
|
||||
public string EffectiveAgentLabel => Loc.T("vm.details.effectiveIfInherited", EffectiveAgentHint);
|
||||
|
||||
partial void OnEffectiveModelHintChanged(string value) => OnPropertyChanged(nameof(EffectiveModelLabel));
|
||||
partial void OnEffectiveAgentHintChanged(string value) => OnPropertyChanged(nameof(EffectiveAgentLabel));
|
||||
|
||||
public System.Collections.ObjectModel.ObservableCollection<string> TaskModelOptions { get; } = new(
|
||||
new[] { ModelRegistry.TaskInheritSentinel }.Concat(ModelRegistry.Aliases));
|
||||
|
||||
@@ -223,6 +234,26 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
|
||||
// Set by the view so DeleteTaskCommand can show an error message
|
||||
public Func<string, System.Threading.Tasks.Task>? ShowErrorAsync { get; set; }
|
||||
|
||||
private static string StatusToStateKey(ClaudeDo.Data.Models.TaskStatus status) => status switch
|
||||
{
|
||||
ClaudeDo.Data.Models.TaskStatus.Queued => "queued",
|
||||
ClaudeDo.Data.Models.TaskStatus.Running => "running",
|
||||
ClaudeDo.Data.Models.TaskStatus.WaitingForReview => "running",
|
||||
ClaudeDo.Data.Models.TaskStatus.Done => "done",
|
||||
ClaudeDo.Data.Models.TaskStatus.Failed => "failed",
|
||||
ClaudeDo.Data.Models.TaskStatus.Cancelled => "cancelled",
|
||||
_ => "idle",
|
||||
};
|
||||
|
||||
private static string FinishedStatusToStateKey(string status) => status switch
|
||||
{
|
||||
"done" => "done",
|
||||
"failed" => "failed",
|
||||
"cancelled" => "cancelled",
|
||||
"waiting_for_review" => "running",
|
||||
_ => status.ToLowerInvariant(),
|
||||
};
|
||||
|
||||
private async System.Threading.Tasks.Task RefreshStatusAsync(string taskId)
|
||||
{
|
||||
try
|
||||
@@ -233,7 +264,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
|
||||
.FirstOrDefaultAsync(t => t.Id == taskId);
|
||||
if (entity is null || Task?.Id != taskId) return;
|
||||
|
||||
AgentStatusLabel = entity.Status.ToString();
|
||||
AgentState = StatusToStateKey(entity.Status);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
@@ -245,6 +276,12 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
|
||||
_services = services;
|
||||
_notesApi = notesApi;
|
||||
Notes = new NotesEditorViewModel(_notesApi);
|
||||
Loc.LanguageChanged += (_, _) =>
|
||||
{
|
||||
OnPropertyChanged(nameof(AgentStatusLabel));
|
||||
OnPropertyChanged(nameof(EffectiveModelLabel));
|
||||
OnPropertyChanged(nameof(EffectiveAgentLabel));
|
||||
};
|
||||
|
||||
// Subscribe once; filter by current task id inside the handler
|
||||
_worker.TaskMessageEvent += OnTaskMessage;
|
||||
@@ -264,7 +301,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
|
||||
// If the task row's live status changes (e.g. TaskStarted/Finished), mirror it.
|
||||
_worker.TaskStartedEvent += (slot, taskId, startedAt) =>
|
||||
{
|
||||
if (Task?.Id == taskId) AgentStatusLabel = "Running";
|
||||
if (Task?.Id == taskId) AgentState = "running";
|
||||
};
|
||||
_worker.TaskFinishedEvent += (slot, taskId, status, finishedAt) =>
|
||||
{
|
||||
@@ -275,7 +312,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
|
||||
Kind = LogKind.Done,
|
||||
Text = $"── {status.ToUpperInvariant()} · {finishedAt.ToLocalTime():HH:mm:ss} ──",
|
||||
});
|
||||
AgentStatusLabel = status;
|
||||
AgentState = FinishedStatusToStateKey(status);
|
||||
// Re-query to pick up worktree created during the run.
|
||||
_ = RefreshWorktreeAsync(taskId);
|
||||
};
|
||||
@@ -473,7 +510,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
|
||||
WorktreePath = null;
|
||||
WorktreeStateLabel = null;
|
||||
BranchLine = null;
|
||||
AgentStatusLabel = "Idle";
|
||||
AgentState = "idle";
|
||||
LatestRunSessionId = null;
|
||||
_suppressAgentSave = true;
|
||||
try
|
||||
@@ -519,7 +556,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
|
||||
WorktreeBaseCommit = entity.Worktree?.BaseCommit;
|
||||
WorktreeStateLabel = entity.Worktree?.State.ToString();
|
||||
BranchLine = entity.Worktree is { } w ? $"{w.BranchName} \u2190 main" : null;
|
||||
AgentStatusLabel = entity.Status.ToString();
|
||||
AgentState = StatusToStateKey(entity.Status);
|
||||
await LoadAgentSettingsAsync(entity, ct);
|
||||
ct.ThrowIfCancellationRequested();
|
||||
|
||||
@@ -730,7 +767,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
|
||||
WorktreeBaseCommit = entity.Worktree?.BaseCommit;
|
||||
WorktreeStateLabel = entity.Worktree?.State.ToString();
|
||||
BranchLine = entity.Worktree is { } w ? $"{w.BranchName} ← main" : null;
|
||||
AgentStatusLabel = entity.Status.ToString();
|
||||
AgentState = StatusToStateKey(entity.Status);
|
||||
if (Task is { } row && entity.Worktree?.DiffStat is { } stat)
|
||||
row.DiffStat = stat;
|
||||
}
|
||||
@@ -808,7 +845,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
|
||||
? ClaudeDo.Data.Models.TaskStatus.Done
|
||||
: ClaudeDo.Data.Models.TaskStatus.Idle;
|
||||
Task.Status = entity.Status;
|
||||
AgentStatusLabel = entity.Status.ToString();
|
||||
AgentState = StatusToStateKey(entity.Status);
|
||||
await repo.UpdateAsync(entity);
|
||||
}
|
||||
|
||||
@@ -922,7 +959,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
|
||||
try
|
||||
{
|
||||
await _worker.SetTaskStatusAsync(Task.Id, ClaudeDo.Data.Models.TaskStatus.Queued);
|
||||
AgentStatusLabel = "Queued";
|
||||
AgentState = "queued";
|
||||
}
|
||||
catch { /* offline */ }
|
||||
}
|
||||
@@ -938,7 +975,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
|
||||
try
|
||||
{
|
||||
await _worker.SetTaskStatusAsync(Task.Id, ClaudeDo.Data.Models.TaskStatus.Idle);
|
||||
AgentStatusLabel = "Idle";
|
||||
AgentState = "idle";
|
||||
}
|
||||
catch { /* offline */ }
|
||||
}
|
||||
@@ -973,7 +1010,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
|
||||
try
|
||||
{
|
||||
await _worker.SetTaskStatusAsync(Task.Id, ClaudeDo.Data.Models.TaskStatus.Queued);
|
||||
AgentStatusLabel = "Queued";
|
||||
AgentState = "queued";
|
||||
}
|
||||
catch { /* offline */ }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user