Localize ~40 remaining hardcoded English strings (toasts, canvas, webchat, download dialog). Both en-US and zh-CN now have 163 resource keys, fully in sync. - Add LocalizationHelper.SetLanguageOverride() for unpackaged app locale testing - Add docs/LOCALIZATION.md contributor guide - File issue #61 calling for community translations Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
3.8 KiB
Localization Guide
OpenClaw Tray uses WinUI .resw resource files for localization. Windows automatically selects the correct language based on the OS locale — no user configuration needed.
Currently Supported Languages
| Language | Locale | Resource File |
|---|---|---|
| English (US) | en-us |
Strings/en-us/Resources.resw |
| Chinese (Simplified) | zh-cn |
Strings/zh-cn/Resources.resw |
Adding a New Language
-
Copy the English resource file as your starting point:
src/OpenClaw.Tray.WinUI/Strings/en-us/Resources.resw -
Create a new folder for your locale under
Strings/:src/OpenClaw.Tray.WinUI/Strings/<locale>/Resources.reswUse the standard BCP-47 locale tag in lowercase (e.g.,
de-de,fr-fr,ja-jp,ko-kr,pt-br,es-es). -
Translate the
<value>elements — do not change thenameattributes. Each entry looks like:<data name="SettingsSaveButton.Content" xml:space="preserve"> <value>Save</value> <!-- ← translate this --> </data> -
Keep format placeholders intact. Some strings use
{0},{1}, etc. These must remain in the translation:<data name="Menu_SessionsFormat" xml:space="preserve"> <value>Sessions ({0})</value> <!-- {0} = session count --> </data> -
Do not translate resource key names (the
nameattribute). Only translate<value>content. -
Submit a pull request with just your new
Resources.reswfile. No code changes are needed — the build system automatically discovers new locale folders.
How It Works
XAML strings (automatic)
Elements with x:Uid attributes are automatically matched to resource keys:
<Button x:Uid="SettingsSaveButton" Content="Save" />
Maps to resource key SettingsSaveButton.Content.
C# runtime strings (via LocalizationHelper)
Code uses LocalizationHelper.GetString("key") to load strings at runtime:
Title = LocalizationHelper.GetString("WindowTitle_Settings");
Language selection
Windows picks the language automatically based on the user's OS display language. No in-app language picker is needed.
Testing a Language Locally
To test a specific locale without changing your Windows language:
- Open
src/OpenClaw.Tray.WinUI/App.xaml.cs - Add this line at the top of the
App()constructor, beforeInitializeComponent():LocalizationHelper.SetLanguageOverride("zh-CN"); - Build and run (
dotnet build src/OpenClaw.Tray.WinUI -r win-x64). Remove the line when done testing.
Note: This overrides
LocalizationHelper.GetString()calls (menus, toasts, dialogs, window titles). XAMLx:Uidbindings follow the OS display language. For full XAML localization testing, change your Windows display language in Settings → Time & Language.
Resource Key Naming Conventions
| Pattern | Used For | Example |
|---|---|---|
ComponentName.Property |
XAML x:Uid bindings |
SettingsSaveButton.Content |
WindowTitle_Name |
Window title bars | WindowTitle_Settings |
Toast_Name |
Toast notification text | Toast_NodePaired |
Menu_Name |
Tray menu items | Menu_Settings |
Status_Name |
Status display text | Status_Connected |
TimeAgo_Format |
Relative time strings | TimeAgo_MinutesFormat |
Validation
Both resource files must have the same set of keys. You can verify with:
$en = (Select-String -Path "src\OpenClaw.Tray.WinUI\Strings\en-us\Resources.resw" -Pattern '<data name="' | Measure-Object).Count
$new = (Select-String -Path "src\OpenClaw.Tray.WinUI\Strings\<locale>\Resources.resw" -Pattern '<data name="' | Measure-Object).Count
Write-Host "en-us: $en keys | <locale>: $new keys | Match: $($en -eq $new)"