Translations

Slint’s translation infrastructure makes your application available in different languages.

Overview

Install the slint-tr-extractor tool to extract translatable strings from .slint files:

cargo install slint-tr-extractor

Complete the following steps to translate your application:

  1. Identify all user visible strings that need translation and annotate them with the @tr() macro.

  2. Extract annotated strings by running the slint-tr-extractor tool and generate .pot files.

  3. Use a third-party tool to translate the strings into a target language, as .po files.

  4. Use gettext’s msgfmt tool to convert .po files into run-time loadable .mo files.

  5. Use Slint’s API to select and load .mo files at run-time, based on the user’s locale settings.

At this point, all strings marked for translation are automatically rendered in the target language.

Annotating Translatable Strings

Use the @tr macro in .slint files to mark that a string for translation. This macro takes care of both the translation and the formatting by replacing {} placeholders.

The first argument must be a plain string literal, followed by the arguments:

export component Example {
    property <string> name;
    Text {
        text: @tr("Hello, {}", name);
    }
}

Formatting

The @tr macro replaces each {} placeholder in the string marked for translation with the corresponding argument. It’s also possible to re-order the arguments using {0}, {1}, and so on. Translators can use ordered placeholders even if the original string did not.

You can include the literal characters { and } in a string by preceding them with the same character. For example, escaping the { character with {{ and the } character with }}.

Plurals

Use plural formatting when the translation of text involving a variable number of elements should change depending on whether there is a single element or multiple.

Given count and an expression that represents the count of something, form the plural with the | and % symbols like so:

@tr("I have {n} item" | "I have {n} items" % count).

Use {n} in the format string to access the expression after the %.

export component Example inherits Text {
    in property <int> score;
    in property <int> name;
    text: @tr("Hello {0}, you have one point" | "Hello {0}, you have {n} point" % score, name);
}

Context

Disambiguate translations for strings with the same source text but different contextual meanings by adding a context to the @tr(...) macro using the "..." => syntax.

Use the context to provide additional context information to translators, ensuring accurate and contextually appropriate translations.

The context must be a plain string literal and it appears as msgctx in the .pot files. If not specified, the context defaults to the name of the surrounding component.

export component MenuItem {
    property <string> name : @tr("Default Name"); // Default: `MenuItem` will be the context.
    property <string> tooltip : @tr("ToolTip" => "ToolTip for {}", name); // Specified: The context will be `ToolTip`.
}

Extract Translatable Strings

Use the slint-tr-extractor tool to generate a .pot file from .slint files. You can run it like so:

find -name \*.slint | xargs slint-tr-extractor -o MY_PROJECT.pot

This creates a file called MY_PROJECT.pot. Replace “MY_PROJECT” with your actual project name. To learn how the project name affects the lookup of translations, read the sections below.

.pot files are Gettext template files.

Translate the Strings

Start a new translation by creating a .po file from a .pot file. Both file formats are identical. You can either copy the file manually or use a tool like Gettext’s msginit to start a new .po file.

The .po file contains the strings in a target language.

.po and .pot files are plain text files that you can edit with a text editor. We recommend using a dedicated translation tool for working with them, such as the following:

Convert .po Files to .mo Files

Convert the human readable .po files into machine-friendly .mo files, which are a binary representation that is more efficient to read by code.

Use Gettext’s msgfmt command line tool to convert .po files to .mo files:

msgfmt translation.po -o translation.mo

Select and Load .mo Files at Run-Time

Slint uses the Gettext library to load translations at run-time. Gettext expects translation files - called message catalogs - in following directory hierarchy:

dir_name/locale/LC_MESSAGES/domain_name.mo
  • dir_name: the base directory that you can choose freely.

  • locale: The name of the user’s locale for a given target language, such as fr for French, or de for German.

    The locale is typically determined using environment variables that your operating system sets.

  • domain_name: Selected based on the programming language you’re using Slint with.

Read the Gettext documentation for more information.

Select and Load Translations with Rust

First, enable the gettext feature of the slint crate in the features section to gain access to the translations API and activate run-time translation support.

Next, use the slint::init_translations! macro to specify the base location of your .mo files. This is the dir_name in the scheme of the previous section. Slint expects the .mo files to be in the corresponding sub-directories and their file name - domain_name - must match the package name in your Cargo.toml. This is often the same as the crate name.

For example:

slint::init_translations!(concat!(env!("CARGO_MANIFEST_DIR"), "/lang/"));

For example, if your Cargo.toml contains the following lines and the user’s locale is fr:

[package]
name = "gallery"

With these settings, Slint looks for gallery.mo in the lang/fr/LC_MESSAGES/gallery.mo.

Select and Load Translations with C++

First, enable the SLINT_FEATURE_GETTEXT cmake option when compiling Slint to gain access to the translations API and activate run-time translation support.

In C++ applications using cmake, the domain_name is the CMake target name.

Next, bind the text domain to a path using the standard gettext library.

To do so, add this in your CMakeLists.txt file:

find_package(Intl)
if(Intl_FOUND)
    target_compile_definitions(my_application PRIVATE HAVE_GETTEXT SRC_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
    target_link_libraries(my_application PRIVATE Intl::Intl)
endif()

You can then setup the locale and the text domain

#ifdef HAVE_GETTEXT
#    include <locale>
#    include <libintl.h>
#endif

int main()
{
#ifdef HAVE_GETTEXT
    bindtextdomain("my_application", SRC_DIR "/lang/");
    std::locale::global(std::locale(""));
#endif
   //...
}

For example, if you’re using the above and the user’s locale is fr, Slint looks for my_application.mo in the lang/fr/LC_MESSAGES/ directory.

Previewing Translations with slint-viewer

Use slint-viewer to preview translations when previewing .slint files:

cargo install slint-viewer
  1. Enable the gettext feature when compiling slint-viewer.

  2. Use the --translation-domain and translation-dir command line options to load translations and display them based on the current locale.