diff --git a/src/ClaudeDo.Installer/ClaudeDo.Installer.csproj b/src/ClaudeDo.Installer/ClaudeDo.Installer.csproj
index eb58cf3..ba65109 100644
--- a/src/ClaudeDo.Installer/ClaudeDo.Installer.csproj
+++ b/src/ClaudeDo.Installer/ClaudeDo.Installer.csproj
@@ -46,6 +46,9 @@
+
+
+
diff --git a/src/ClaudeDo.Installer/Core/ConfigModels.cs b/src/ClaudeDo.Installer/Core/ConfigModels.cs
index 3705931..462a035 100644
--- a/src/ClaudeDo.Installer/Core/ConfigModels.cs
+++ b/src/ClaudeDo.Installer/Core/ConfigModels.cs
@@ -77,6 +77,7 @@ public sealed class InstallerAppSettings
{
public string DbPath { get; set; } = "~/.todo-app/todo.db";
public string SignalRUrl { get; set; } = "http://127.0.0.1:47821/hub";
+ public string Language { get; set; } = "";
private static readonly JsonSerializerOptions ReadOpts = new()
{
diff --git a/src/ClaudeDo.Installer/Localization/LocalizedString.cs b/src/ClaudeDo.Installer/Localization/LocalizedString.cs
new file mode 100644
index 0000000..fe628a4
--- /dev/null
+++ b/src/ClaudeDo.Installer/Localization/LocalizedString.cs
@@ -0,0 +1,22 @@
+using System.ComponentModel;
+using ClaudeDo.Localization;
+
+namespace ClaudeDo.Installer.Localization;
+
+public sealed class LocalizedString : INotifyPropertyChanged
+{
+ private readonly ILocalizer _localizer;
+ private readonly string _key;
+
+ public LocalizedString(ILocalizer localizer, string key)
+ {
+ _localizer = localizer;
+ _key = key;
+ _localizer.LanguageChanged += (_, _) =>
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Value)));
+ }
+
+ public string Value => _localizer[_key];
+
+ public event PropertyChangedEventHandler? PropertyChanged;
+}
diff --git a/src/ClaudeDo.Installer/Localization/TrExtension.cs b/src/ClaudeDo.Installer/Localization/TrExtension.cs
new file mode 100644
index 0000000..6fb9459
--- /dev/null
+++ b/src/ClaudeDo.Installer/Localization/TrExtension.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Windows.Data;
+using System.Windows.Markup;
+using ClaudeDo.Localization;
+
+namespace ClaudeDo.Installer.Localization;
+
+public sealed class TrExtension : MarkupExtension
+{
+ public TrExtension() { }
+ public TrExtension(string key) => Key = key;
+
+ public string Key { get; set; } = "";
+
+ public static ILocalizer? Localizer { get; set; }
+
+ public override object ProvideValue(IServiceProvider serviceProvider)
+ {
+ var loc = Localizer ?? throw new InvalidOperationException("TrExtension.Localizer not initialized");
+ var binding = new Binding(nameof(LocalizedString.Value))
+ {
+ Source = new LocalizedString(loc, Key),
+ Mode = BindingMode.OneWay
+ };
+ return binding.ProvideValue(serviceProvider);
+ }
+}