feat(i18n): localize installer with language picker and config write-through

- Init Localizer at app startup (before self-update prompt) and assign to TrExtension.Localizer
- Register ILocalizer in DI; inject into WizardViewModel and SettingsViewModel
- WizardViewModel: SelectedLanguage ComboBox binding with OnSelectedLanguageChanged -> SetLanguage + InstallContext.Language
- WizardWindow.xaml: DockPanel wraps step chips + language ComboBox (right-aligned)
- Localize all installer XAML: WizardWindow, WelcomePage, PathsPage, ServicePage, UiSettingsPage, InstallPage, SettingsWindow, SelfUpdatePromptWindow
- Localize page Title properties and WizardViewModel.NextButtonText via TrExtension.Localizer
- Persist chosen Language in WriteConfigStep and SettingsViewModel.Save into ui.config.json
- Append installer section to en.json (nav, welcome, paths, service, uiSettings, install, settings, selfUpdate)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
mika kuns
2026-06-03 12:55:08 +02:00
parent 2fbf054a57
commit 364a037cb3
19 changed files with 210 additions and 83 deletions

View File

@@ -2,6 +2,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ClaudeDo.Installer.Pages.ServicePage"
xmlns:loc="clr-namespace:ClaudeDo.Installer.Localization"
d:DataContext="{d:DesignInstance local:ServicePageViewModel}"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@@ -9,37 +10,37 @@
<ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel MaxWidth="520">
<TextBlock Text="Worker" FontSize="18" FontWeight="SemiBold" Margin="0,0,0,4"/>
<TextBlock Text="Configure the ClaudeDo background worker."
<TextBlock Text="{loc:Tr installer.service.title}" FontSize="18" FontWeight="SemiBold" Margin="0,0,0,4"/>
<TextBlock Text="{loc:Tr installer.service.subtitle}"
Foreground="{StaticResource TextSecondaryBrush}" Margin="0,0,0,20"
TextWrapping="Wrap"/>
<Label Content="SignalR Port"/>
<Label Content="{loc:Tr installer.service.signalRPort}"/>
<TextBox Text="{Binding SignalRPort, UpdateSourceTrigger=PropertyChanged}" Margin="0,0,0,12"/>
<Label Content="Queue Backstop Interval (ms)"/>
<Label Content="{loc:Tr installer.service.queueBackstopInterval}"/>
<TextBox Text="{Binding QueueBackstopIntervalMs, UpdateSourceTrigger=PropertyChanged}" Margin="0,0,0,12"/>
<Label Content="Claude CLI Path"/>
<Label Content="{loc:Tr installer.service.claudeCliPath}"/>
<Grid Margin="0,0,0,12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" Text="{Binding ClaudeBin, UpdateSourceTrigger=PropertyChanged}"/>
<Button Grid.Column="1" Content="Browse..." Command="{Binding BrowseClaudeCommand}"
<Button Grid.Column="1" Content="{loc:Tr installer.nav.browse}" Command="{Binding BrowseClaudeCommand}"
Margin="8,0,0,0"/>
</Grid>
<Separator Margin="0,4,0,12"/>
<TextBlock Text="The worker runs as you (the logged-in user) via a per-user logon task, so it can use your Claude CLI authentication."
<TextBlock Text="{loc:Tr installer.service.autostartHint}"
Foreground="{StaticResource TextDimBrush}" FontSize="11" Margin="0,0,0,12"
TextWrapping="Wrap"/>
<CheckBox Content="Start worker automatically at logon" IsChecked="{Binding AutoStart}" Margin="0,0,0,12"/>
<CheckBox Content="{loc:Tr installer.service.autostart}" IsChecked="{Binding AutoStart}" Margin="0,0,0,12"/>
<Label Content="Restart Delay (ms)"/>
<Label Content="{loc:Tr installer.service.restartDelay}"/>
<TextBox Text="{Binding RestartDelayMs, UpdateSourceTrigger=PropertyChanged}" Margin="0,0,0,12"/>
<TextBlock Text="{Binding ValidationError}" Foreground="{StaticResource ErrorBrush}" FontSize="11"