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 and LocalizationService |
Lizerium.Localization.Generator |
Incremental source generator for Generated.Localization.Localization |
Lizerium.Localization.Analyzer |
Analyzer and CodeFix provider for missing localization keys |
Lizerium.Localization.GUI |
Standalone WPF translation editor |
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);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.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.csproj