LiveResx.Avalonia 2.0.0

dotnet add package LiveResx.Avalonia --version 2.0.0
                    
NuGet\Install-Package LiveResx.Avalonia -Version 2.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="LiveResx.Avalonia" Version="2.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="LiveResx.Avalonia" Version="2.0.0" />
                    
Directory.Packages.props
<PackageReference Include="LiveResx.Avalonia" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add LiveResx.Avalonia --version 2.0.0
                    
#r "nuget: LiveResx.Avalonia, 2.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package LiveResx.Avalonia@2.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=LiveResx.Avalonia&version=2.0.0
                    
Install as a Cake Addin
#tool nuget:?package=LiveResx.Avalonia&version=2.0.0
                    
Install as a Cake Tool

LiveResx.Avalonia

CI License: MIT

A lightweight localization library for Avalonia with runtime language switching, strongly-typed translations, and zero ViewModel boilerplate.

Unlike traditional .resx localization approaches, LiveResx.Avalonia keeps using standard .resx files while providing automatic UI updates when the application's culture changes.

Why?

Avalonia currently does not provide a built-in localization solution comparable to WPF's dynamic resource system for .resx files.

Typical approaches usually involve one or more of the following:

  • restarting or recreating windows after a language change,
  • exposing every localized string through a ViewModel,
  • injecting localization services everywhere,
  • manually raising PropertyChanged notifications,
  • relying on reflection-based localization frameworks.

LiveResx.Avalonia aims to provide a small, strongly-typed alternative that feels natural to Avalonia applications while keeping .resx files as the single source of truth.

🚀 Getting Started

📋 Prerequisites

  • Avalonia 11.3 or later
  • Standard .resx resources with PublicResXFileCodeGenerator or InternalResXFileCodeGenerator

💡 Note: Use 1.x.x with Avalonia >= 11.3.0 and < 12.0.0, and 2.x.x with Avalonia >= 12.0.0.


📦 Installation

dotnet add package LiveResx.Avalonia

Or via the Package Manager Console:

Install-Package LiveResx.Avalonia

1️⃣ Create a resource file

Add a .resx file (e.g., Resources.resx) with the entries you want to localize:

Name Value
Greeting Hello, World!

Set the Custom Tool property to PublicResXFileCodeGenerator (or InternalResXFileCodeGenerator for internal types).


2️⃣ Declare the XAML namespace

In your Window or UserControl, add the markup extension namespace:

xmlns:loc="clr-namespace:LiveResx.Avalonia"

3️⃣ Use translations in XAML

<TextBlock Text="{loc:Translate {x:Static loc:DynamicResources.Greeting}}" />

💡 Tip: Every DynamicResources.* property is strongly typed and appears in IntelliSense after the source generator runs.


4️⃣ Switch culture at runtime

using System.Globalization;
using LiveResx.Avalonia;

// Switch to German
DynamicLocalization.Instance.SwitchLocale(new CultureInfo("de"));

// Switch back to English
DynamicLocalization.Instance.SwitchLocale(new CultureInfo("en"));

// Read the current locale
CultureInfo current = DynamicLocalization.Instance.Locale;

All controls using {loc:Translate ...} update automatically — no configuration, base class, or service registration required.

5️⃣ Rx integration

If your project references System.Reactive or ReactiveUI, three extension methods are emitted automatically:

// Observe translation value changes
IObservable<string> text = DynamicResources.Greeting.ToObservable();

// Observe locale switches
IObservable<CultureInfo> locale = DynamicLocalization.Instance.ObservableLocale();

// Observe custom resource value changes
IObservable<string> flag = DynamicLocalization.Instance
    .GetResource<string>("CountryFlag").ToObservable();

All emit the current value immediately on subscribe, then on each subsequent change.

6️⃣ Custom typed resources

For culture-aware values defined in code rather than .resx, see the Advanced Usage section.

Features

  • ✅ Uses standard .resx resource files
  • ✅ Runtime language switching
  • ✅ Automatic UI updates
  • ✅ Strongly-typed translations generated at compile time
  • ✅ IntelliSense and compile-time checking
  • ✅ No localization service injection
  • ✅ No ViewModel properties for localized strings
  • ✅ No INotifyPropertyChanged boilerplate in application code
  • ✅ ToObservable() / ObservableLocale() extensions — when System.Reactive or ReactiveUI is referenced
  • ✅ ILocalizedResource<T> — define a class and the source generator auto-creates a DynamicResources.* property, registers it, and wires up culture switching
  • ✅ LocalizedResource<T> — culture-aware typed values with Invariant or ParentChain fallback
  • ✅ RegisterResource<T>() / GetResource<T>() / TryGetResource<T>() — runtime custom resource registration

How it works

LiveResx.Avalonia consists of three parts:

  • Runtime library – manages translations and language switching.
  • Source generator – discovers .resx resources and generates strongly-typed translation objects.
  • Markup extension – connects generated translations to Avalonia bindings.

Internally, every generated translation is represented by a small observable object. When the culture changes, the library updates all registered translations, causing Avalonia bindings to refresh automatically.

Advanced Usage

Source-generated custom resources (ILocalizedResource<T>)

When you need a culture-switchable resource that is defined in application code rather than a .resx file — for example, paths to flag images, enum values, or configuration objects — implement ILocalizedResource<T> on a class.

The source generator automatically discovers the class, creates a LocalizedResource<T> field, registers it with DynamicLocalization, and exposes it as a property on DynamicResources.

1. Define the resource
using System.Collections.Generic;
using System.Globalization;
using LiveResx.Avalonia;

internal sealed class CountryFlags : ILocalizedResource<string>
{
    public IReadOnlyDictionary<CultureInfo, string> Values { get; } =
        new Dictionary<CultureInfo, string>
        {
            [CultureInfo.InvariantCulture] = "/Assets/default.svg",
            [new CultureInfo("en")]          = "/Assets/uk.svg",
            [new CultureInfo("de")]          = "/Assets/de.svg",
        }.AsReadOnly();
}
2. Use it in XAML
<Image Source="{Binding Value, Source={x:Static loc:DynamicResources.CountryFlags}}" />

Note: DynamicResources.CountryFlags returns a LocalizedResource<string> instance. Binding to Value ensures the image source updates automatically when DynamicLocalization.SwitchLocale is called, because LocalizedResource<T>.Value raises PropertyChanged.

3. Imperative usage
// Read the current value (snapshot of the active culture)
string currentFlag = DynamicResources.CountryFlags.Value;

// Switch locale — all bindings and .Value accessors update automatically
DynamicLocalization.Instance.SwitchLocale(new CultureInfo("de"));
4. Reactive extensions

When System.Reactive or ReactiveUI is referenced, you can observe value changes:

IObservable<string> flag = DynamicResources.CountryFlags.ToObservable();

The observable emits the current value immediately on subscribe, then on each culture switch.


Manual custom resources (LocalizedResource<T>)

If you prefer to create and manage resource instances in code instead of using the source generator:

// Create a culture-aware resource with a fallback strategy
var flag = new LocalizedResource<string>(
    "CountryFlag",
    new Dictionary<CultureInfo, string>
    {
        [CultureInfo.InvariantCulture] = "/Assets/default.svg",
        [new CultureInfo("en")] = "/Assets/uk.svg",
        [new CultureInfo("de")] = "/Assets/de.svg"
    },
    FallbackBehavior.Invariant);

// Register it — it will refresh automatically on SwitchLocale
DynamicLocalization.Instance.RegisterResource(flag);

// Retrieve and use
string currentFlag = DynamicLocalization.Instance.GetResource<string>("CountryFlag").Value;

// Safe retrieval when unsure about type
if (DynamicLocalization.Instance.TryGetResource<string>("CountryFlag", out var resource))
{
    // Use resource.Value
}

This is useful when the resource values are computed at runtime, loaded from a database, or when you need multiple instances of the same type.

Both approaches support ToObservable<T>() when System.Reactive or ReactiveUI is referenced.


Composite format strings (TranslateFormatExtension)

For localized strings that contain placeholders (e.g. "Hello, {0}!"), use TranslateFormat to bind the format template and arguments separately:

<TextBlock>
  <TextBlock.Text>
    <loc:TranslateFormat Template="{x:Static loc:DynamicResources.WelcomeMessage}">
      <Binding Path="UserName" />
    </loc:TranslateFormat>
  </TextBlock.Text>
</TextBlock>

The UI is automatically updated when either the bound value (UserName) changes or the localized template is refreshed due to a culture change.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.0 414 7/21/2026
2.0.0-rc1 112 7/21/2026
1.1.2 166 7/20/2026
1.1.1 133 7/14/2026
1.1.0 112 7/14/2026
1.0.3 123 7/13/2026
1.0.2 112 7/13/2026
1.0.1 115 7/13/2026
1.0.0 120 7/12/2026
0.1.0 115 7/11/2026