From wpf-dev-pack
Localizes WPF applications using resource files, x:Uid, BAML, and culture settings for multi-language support and right-to-left layouts.
npx claudepluginhub christian289/dotnet-with-claudecode --plugin wpf-dev-packThis skill uses the workspace's default tool permissions.
Implementing multi-language support in WPF applications.
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
Implementing multi-language support in WPF applications.
Localization Approaches
├── Resource Files (.resx)
│ ├── Simple string lookup
│ └── Strongly-typed access
├── BAML Localization
│ ├── x:Uid attributes
│ └── LocBaml tool
└── Runtime Features
├── FlowDirection (RTL support)
├── Culture-aware formatting
└── Dynamic language switching
Project Structure:
├── Properties/
│ └── Resources.resx (default/fallback)
├── Resources/
│ ├── Strings.resx (default English)
│ ├── Strings.ko-KR.resx (Korean)
│ ├── Strings.ja-JP.resx (Japanese)
│ └── Strings.de-DE.resx (German)
Strings.resx (English - default):
<data name="AppTitle" xml:space="preserve">
<value>My Application</value>
</data>
<data name="WelcomeMessage" xml:space="preserve">
<value>Welcome, {0}!</value>
</data>
<data name="SaveButton" xml:space="preserve">
<value>Save</value>
</data>
<data name="CancelButton" xml:space="preserve">
<value>Cancel</value>
</data>
Strings.ko-KR.resx (Korean):
<data name="AppTitle" xml:space="preserve">
<value>My Application (Korean translation)</value>
</data>
<data name="WelcomeMessage" xml:space="preserve">
<value>Welcome, {0}! (Korean translation)</value>
</data>
<data name="SaveButton" xml:space="preserve">
<value>Save (Korean translation)</value>
</data>
<data name="CancelButton" xml:space="preserve">
<value>Cancel (Korean translation)</value>
</data>
<Window xmlns:p="clr-namespace:MyApp.Resources">
<Window.Title>
<Binding Source="{x:Static p:Strings.AppTitle}"/>
</Window.Title>
<StackPanel>
<TextBlock Text="{x:Static p:Strings.WelcomeMessage}"/>
<Button Content="{x:Static p:Strings.SaveButton}"/>
<Button Content="{x:Static p:Strings.CancelButton}"/>
</StackPanel>
</Window>
using MyApp.Resources;
// Direct access
var title = Strings.AppTitle;
// Formatted string
var welcome = string.Format(Strings.WelcomeMessage, userName);
// Access by key (for dynamic keys)
var value = Strings.ResourceManager.GetString("SaveButton");
namespace MyApp;
using System.Globalization;
using System.Threading;
using System.Windows;
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
// Set culture from user settings or system
var cultureName = GetSavedCulture() ?? CultureInfo.CurrentCulture.Name;
SetCulture(cultureName);
}
public static void SetCulture(string cultureName)
{
var culture = new CultureInfo(cultureName);
// Set for current thread
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
// Set for new threads (.NET 4.6+)
CultureInfo.DefaultThreadCurrentCulture = culture;
CultureInfo.DefaultThreadCurrentUICulture = culture;
}
private string? GetSavedCulture()
{
return Properties.Settings.Default.Culture;
}
}
namespace MyApp.Services;
using System.Globalization;
using System.Threading;
using System.Windows;
public sealed class LocalizationService
{
public event EventHandler? CultureChanged;
public CultureInfo CurrentCulture => Thread.CurrentThread.CurrentUICulture;
public void ChangeCulture(string cultureName)
{
var culture = new CultureInfo(cultureName);
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
CultureInfo.DefaultThreadCurrentCulture = culture;
CultureInfo.DefaultThreadCurrentUICulture = culture;
// Save preference
Properties.Settings.Default.Culture = cultureName;
Properties.Settings.Default.Save();
// Notify subscribers
CultureChanged?.Invoke(this, EventArgs.Empty);
// Restart required for full XAML update
RestartApplication();
}
private void RestartApplication()
{
var result = MessageBox.Show(
"Application needs to restart to apply language change. Restart now?",
"Language Changed",
MessageBoxButton.YesNo);
if (result == MessageBoxResult.Yes)
{
System.Diagnostics.Process.Start(Application.ResourceAssembly.Location);
Application.Current.Shutdown();
}
}
}
| Skill | Description |
|---|---|
/localizing-wpf-with-baml | BAML localization with x:Uid and LocBaml tool |
/implementing-wpf-rtl-support | RTL layout support for Arabic, Hebrew |
/formatting-culture-aware-data | Date, number, currency formatting + converters |
<ComboBox x:Name="LanguageSelector"
SelectionChanged="LanguageSelector_SelectionChanged">
<ComboBoxItem Tag="en-US" Content="English"/>
<ComboBoxItem Tag="ko-KR" Content="Korean"/>
<ComboBoxItem Tag="ja-JP" Content="Japanese"/>
<ComboBoxItem Tag="de-DE" Content="German"/>
</ComboBox>
private void LanguageSelector_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (LanguageSelector.SelectedItem is ComboBoxItem item)
{
var cultureName = item.Tag?.ToString();
if (!string.IsNullOrEmpty(cultureName))
{
_localizationService.ChangeCulture(cultureName);
}
}
}