Skip to main content

Localizing using ResX

Localization is a crucial step in delivering a great user experience for a global audience. In .NET, the ResXResourceReader and ResXResourceWriter classes are used to read and write resources in an XML-based format (.resx). This guide will walk you through the process of localizing an Avalonia application using ResX files.

Add ResX files to the project

Before localizing, you need to include ResX files for each language you want to support. This guide uses three ResX files, one for each of the following cultures:

  • Resources.fil-PH.resx (Filipino)
  • Resources.ja-JP.resx (Japanese)
  • Resources.resx (Default language, usually English)

Each ResX file will contain translated text that corresponds to the keys used in the application.

In this example, we added new files to a new folder called Lang. Since .NET generator creates namespaces depending on folder structure, it might be different for you.

caution

If you add the files into the Assets folder make sure to switch Build Action to Embedded resource, otherwise the code generation may fail.

Set the culture

To use a specific language in the application, you need to set the current culture. This can be done in the App.axaml.cs file. The following example sets the culture to Filipino (fil-PH):

App.xaml.cs
public partial class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}

public override void OnFrameworkInitializationCompleted()
{
Lang.Resources.Culture = new CultureInfo("fil-PH");
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new MainWindow
{
DataContext = new MainWindowViewModel(),
};
}

base.OnFrameworkInitializationCompleted();
}
}

Replace "fil-PH" with the appropriate culture code as required.

Use localized text in the view

To use the localized text in a view, you can refer to the resources statically in XAML:

<TextBlock Text="{x:Static lang:Resources.GreetingText}"/>

In the above example, GreetingText is the key that corresponds to a string in the ResX file. The {x:Static} markup extension is used to reference a static property that's been defined in a .NET class, which, in this case, is the resources file (lang:Resources.GreetingText).

That's it! You've now successfully localized your Avalonia application using ResX. By setting the culture to a different locale, you can display the user interface in the selected language, thereby creating an application that supports multiple languages and caters to a global audience.

caution

For the localized properties to be available from XAML, the code generated from the resource file must be publicly accessible. By default, the Resources class is generated by ResXFileCodeGenerator and is internal. Make sure to change the custom tool to PublicResXFileCodeGenerator. The relevant part of the csproj should look like this:

<ItemGroup>
<EmbeddedResource Update="Resources.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>

<ItemGroup>
<Compile Update="Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>

NB: also note that only the default resource file (Resources.resx) should generate code.

Runtime language switching

You can change the culture at runtime to allow users to switch languages without restarting the application:

public void SwitchLanguage(string cultureCode)
{
Lang.Resources.Culture = new CultureInfo(cultureCode);
// Raise PropertyChanged for all localized properties
// or reload the view to pick up new strings
}

Note that x:Static bindings do not automatically update when the culture changes. Because x:Static resolves its value once at load time, the UI will not reflect the new language until the view is refreshed. To work around this, consider one of the following approaches:

  • Reload the view or window. Close and re-create the window (or user control) so that all x:Static references are re-evaluated against the new culture.
  • Use a localization service with INotifyPropertyChanged. Create a service class that exposes localized strings as properties and raises PropertyChanged when the culture changes. Bind to these properties instead of using x:Static.

Right-to-left (RTL) support

Avalonia supports right-to-left layouts through the FlowDirection property. Setting FlowDirection to RightToLeft mirrors the layout of child controls, which is essential for languages such as Arabic, Hebrew, and Persian.

<Window FlowDirection="RightToLeft">
<!-- All child controls mirror their layout -->
</Window>

You can also set FlowDirection dynamically based on the current culture:

var culture = new CultureInfo("ar-SA");
if (culture.TextInfo.IsRightToLeft)
{
mainWindow.FlowDirection = FlowDirection.RightToLeft;
}

The following controls respect FlowDirection and will adjust their layout accordingly:

  • StackPanel (reverses the order of horizontal items)
  • Grid (mirrors column ordering)
  • DockPanel (swaps left and right docking)
  • TextBlock (adjusts text alignment)

Culture-aware formatting

When using StringFormat in data bindings, the formatting follows the current thread culture. For example, currency formatting adapts to the active culture:

<TextBlock Text="{Binding Price, StringFormat='{}{0:C}'}" />

This will display the Price value using the currency symbol and format of the current culture. To control which culture is used for formatting, set Thread.CurrentThread.CurrentCulture early in your application startup:

Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE");

With de-DE, a price of 1234.56 would display as 1.234,56 € instead of $1,234.56.

Platform considerations

Avalonia's localization features work consistently across all supported platforms:

FeatureWindowsmacOSLinuxMobile
ResX localizationFullFullFullFull
FlowDirectionFullFullFullFull
System locale detectionCultureInfo.CurrentCultureSameSameSame

See also