Skip to content

Localization and Translation in the Nexus Mods app

This page describes how to work with 'languages' in the App.

For the research info, see 07: Localization and Internationalisation

In the Nexus Mods app we use the industry standard Resource (.resx) files for porting the App to different languages and cultures.

You can find them in Resources folder for any project that contains UI elements.

NexusMods.App.UI
└── Resources
   ├── Language.de.resx // Autobahn (German)
   ├── Language.it.resx // Pizza (Italian)
   ├── Language.pl.resx // Pierogi (Polish)
   └── Language.resx    // Bri'ish innit

We create a .resx file in every project for the base language, and additional .resx files for any additional language you want to support.

Creating and Editing .resx files requires a supported IDE such as Rider or Visual Studio

Adding Languages to a Project

  • Create a folder called Resources, if it does not already exist.
  • Create a Resource file (right click folder, Add -> Resources), name it Language.resx.
Resources/Language.resx

Doubleclicking this file in a supported IDE will bring you to the Resource Editor, which will allow you to edit the resources file.

Adding a New Language to the Project

This should be supported as a button in your IDE.

In Rider it is top left of 'Localization Manager', above the project listing.

If your IDE does not support this out of the box, create a Resource file using the naming convention:

Language.{culture}.resx
For the culture, use the two letter ISO 639 language code, e.g. de (German).

Full localized cultures are also supported, so de-de (German, Germany) are supported.

Fixing Languages for Avalonia

For elements which may be referenced from the UI (Avalonia's .axaml files), an additional step is required.

When you create a Resource file from Within Rider, it will be set to internal by default. This is okay for code, but is not okay for XAML; as XAML needs those elements public.

To make these elements public, open the project's .csproj file; find the .resx file and change ResXFileCodeGenerator to PublicResXFileCodeGenerator such that you will see:

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

You will then need to perform an action that would trigger a rebuild of Language.Designer.cs.

This could be temporarily adding or renaming a key. These files are (unfortunately), not autogenerated as part of MSBuild (.NET build system).

How language is changed

The current locale for the app is set during startup, based on user configuration.

Runtime changes of the locale will not be immediately reflected in the UI, as most references are static.

Users will need to restart the App for the language change to fully take effect.

Overriding the Language at Boot Time

You can change the locale in AppConfig.json file.

"LauncherSettings": {
  "LocaleOverride": ""
}

For example, you can set "LocaleOverride": "de" for your App to display in German. This file is copied to upon build.

Switching a Language

Language can be switched at runtime with the following code:

Thread.CurrentThread.CurrentUICulture = new CultureInfo(/* locale */);

Where locale is a string representing the locale, e.g. it for Italian.

We run this code at startup.

This will not update the UI. Users will need to be asked to restart the App for the language change to take effect.

Using Localized Text

Tells you how to use localized text in the App.

Reference Text from C#

Basic Referencing

You can reference strings via the Language static class.

var text = Language.MyGames

In some cases your language may default to English.

This can happen if the code is ran before the locale is set at startup; this should not however be a common occurrence.

Formatted Text

In some cases, you might have to use string.Format to inject parameters into the text:

// Language.Hello is "Hello {0}"
string.Format(Language.Hello, user)

Reference from AXAML

In AXAML, you can reference localized string using static compile safe binding as follows:

<TextBlock Text="{x:Static resources:Language.SearchBox__Search}"/>

If formatting is required, please do so in the code behind.

Reference from XAML (stylesheets)

Avalonia .axaml themes cannot reference localised resources.

The theme files are loaded before the language can be set at startup; and there is currently no way to manually trigger a refresh. So the default english strings will; be used.

If you run into this problem, set the strings inside your .axaml.cs views. This might lead to some loss of convenience from styled elements use, but ensures compile time safety.