Note
This project is part of the Lizerium ecosystem and belongs to the following project:
If you're looking for related engineering and support tools, start there.
Lizerium.Localization.Toolkit is a .NET localization workflow for projects that store translations in .resx files. It combines runtime loading, a Roslyn source generator, analyzer diagnostics, Visual Studio code fixes, and a standalone WPF editor.
The main package is designed for application projects:
<PackageReference Include="Lizerium.Localization.Toolkit" Version="1.0.0" />It brings the runtime package and registers the generator/analyzer from the NuGet package under analyzers/dotnet/cs.
| Package | Purpose |
|---|---|
Lizerium.Localization.Toolkit |
All-in-one package for applications: runtime, generator, analyzer, and code fix |
Lizerium.Localization.Core |
Runtime .resx reader/writer, LocalizationService, and WPF XAML {loc:Loc} |
Lizerium.Localization.Generator |
Incremental source generator for Generated.Localization.Localization |
Lizerium.Localization.Analyzer |
Analyzer and CodeFix provider for missing localization keys |
Lizerium.Localization.Ai.Analyzer |
AI CodeFix for C# string and interpolated string localization |
Lizerium.Localization.GUI |
Standalone WPF translation editor |
Lizerium.Localization.Xaml.Vsix |
Visual Studio XAML light bulb for WPF text localization |
Use separate packages only when you need a custom package layout:
<PackageReference Include="Lizerium.Localization.Core" Version="1.0.0" />
<PackageReference Include="Lizerium.Localization.Generator" Version="1.0.0"
OutputItemType="Analyzer"
ReferenceOutputAssembly="false"
PrivateAssets="all" />
<PackageReference Include="Lizerium.Localization.Analyzer" Version="1.0.0"
OutputItemType="Analyzer"
ReferenceOutputAssembly="false"
PrivateAssets="all" />Create localization files:
Resources/
Localization/
Strings.en.resx
Strings.ru.resx
Add them to your project:
<ItemGroup>
<AdditionalFiles Include="Resources\Localization\*.resx" />
<Content Include="Resources\Localization\*.resx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>AdditionalFiles feeds the generator and analyzer. Content copies the .resx files next to the application so the runtime service can load them.
Configure the service once during startup:
using Lizerium.Localization.Core;
LocalizationService.Instance.Configure(
Path.Combine(AppContext.BaseDirectory, "Resources", "Localization"));
LocalizationService.Instance.ChangeLanguage("en");Use the generated API:
using L = Generated.Localization.Localization;
var title = L.MainWindow.Title();
var message = L.MainWindow.Log.DirectoryCorrect(AppContext.BaseDirectory);For WPF XAML, add the localization namespace:
xmlns:loc="clr-namespace:Lizerium.Localization.Core;assembly=Lizerium.Localization.Core"Then use RESX keys directly in markup:
<Button Content="{loc:Loc MainWindow_Button_English}" />
<TextBlock Text="{loc:Loc MainWindow_Title}" />Keys are split by _ and become nested classes and methods.
| RESX key | Generated API |
|---|---|
MainWindow_Title |
Localization.MainWindow.Title() |
FactionView_Tooltip_Highlight |
Localization.FactionView.Tooltip.Highlight() |
Settings_Log_FileCreated_Format |
Localization.Settings.Log.FileCreated(arg0) |
Use _Format for values with placeholders:
<data name="MainWindow_Log_DirectoryCorrect_Format" xml:space="preserve">
<value>Directory is correct: {0}</value>
</data>The generator reports:
| ID | Meaning |
|---|---|
LOC001 |
A key exists in one language but is missing in another |
LOC002 |
Placeholder counts differ between languages |
The analyzer reports:
| ID | Meaning |
|---|---|
LOC100 |
Code calls a localization method but the matching .resx key does not exist |
You can write the generated call first:
using L = Generated.Localization.Localization;
check.ToolTip = L.FactionView.TooltipHighlight();Then use:
Ctrl + . -> Create localization key
For calls without parameters, the code fix adds:
<data name="FactionView_TooltipHighlight" xml:space="preserve">
<value>TODO</value>
</data>For calls with parameters:
var text = L.MainWindow.TestParam.CreateValue(path, "param2", 5);the code fix adds:
<data name="MainWindow_TestParam_CreateValue_Format" xml:space="preserve">
<value>TODO {0} {1} {2}</value>
</data>Rebuild the project after adding keys so the generator can refresh the strongly typed API.
Lizerium.Localization.Ai.Analyzer offers:
Ctrl + . -> Create localization key (AI)
on ordinary C# strings and interpolated strings:
var title = "Hello World";
var details = $"Log directory: {AppContext.BaseDirectory} | {5}";Interpolated strings are stored as RESX format values such as Log directory: {0} | {1} and replaced with generated calls that pass the original expressions as arguments.
The NuGet analyzer reads AI server settings from environment variables:
LIZERIUM_OLLAMA_URL
LIZERIUM_OLLAMA_MODEL
LIZERIUM_OLLAMA_GENERATE_ENDPOINT
LIZERIUM_LIBRETRANSLATE_URL
LIZERIUM_AI_TIMEOUT_SECONDS
For direct use of the AI NuGet package, configure AiLocalizationOptions and pass it to AILocalizationService.
Lizerium.Localization.Core.XamlLocalizationService provides reusable conversion logic for tools and editor extensions:
var xaml = new XamlLocalizationService();
xaml.LocalizeText(
"MainWindow.xaml",
"English",
"MainWindow_Button_English",
"Resources/Localization");It replaces values such as Content="English" with Content="{loc:Loc MainWindow_Button_English}", adds xmlns:loc when needed, and writes the key to Strings.en.resx and Strings.ru.resx.
For Visual Studio 2022, the Lizerium.Localization.Xaml.Vsix project provides the editor light bulb. After installing the generated VSIX, place the caret inside a XAML literal or select any UI text and choose:
Create XAML localization key
The VSIX writes diagnostics to %TEMP%/Lizerium.Localization.Xaml.Vsix.log.
Lizerium.Localization.GUI is a standalone WPF editor for translation files. It can open a project folder, find .resx files, compare en and ru, highlight missing translations, detect placeholder mismatches, edit values inline, and save changes.
Publish it as a desktop application:
dotnet publish src\Lizerium.Localization.GUI\Lizerium.Localization.GUI.csproj -c Release -r win-x64 --self-contained false -o artifacts\guiYou can also register it in Visual Studio through Tools -> External Tools...:
Title: Lizerium Localization
Command: path\to\Lizerium.Localization.GUI.exe
Arguments: $(ProjectDir)
Create local packages:
dotnet pack src\Lizerium.Localization.Core\Lizerium.Localization.Core.csproj -c Release -o artifacts\nuget
dotnet pack src\Lizerium.Localization.Generator\Lizerium.Localization.Generator.csproj -c Release -o artifacts\nuget
dotnet pack src\Lizerium.Localization.Analyzer\Lizerium.Localization.Analyzer.csproj -c Release -o artifacts\nuget
dotnet pack src\Lizerium.Localization.Toolkit\Lizerium.Localization.Toolkit.csproj -c Release -o artifacts\nuget
dotnet pack src\Lizerium.Localization.GUI\Lizerium.Localization.GUI.csproj -c Release -o artifacts\nugetInstall from the local feed:
dotnet nuget add source .\artifacts\nuget -n LizeriumLocal
dotnet add path\to\YourProject.csproj package Lizerium.Localization.Toolkit --version 1.0.0 --source .\artifacts\nugetIf you repack the same version while testing, clear the local NuGet cache:
dotnet nuget locals global-packages --clearSee samples/WpfSampleApp for a minimal WPF project with .resx files, generated API usage, runtime initialization, and language switching.
dotnet build samples\WpfSampleApp\WpfSampleApp.csproj
dotnet run --project samples\WpfSampleApp\WpfSampleApp.csprojThe docs/ folder contains both repository markdown docs and a static GitHub Pages site with English/Russian landing pages, JSON-LD metadata, sitemap.xml, and robots.txt.
Entry points:
docs/index.htmldocs/ru/index.html