Skip to content

Slint 的翻译基础设施让你的应用程序能够支持不同语言。

前置条件

安装 slint-tr-extractor 工具以从 .slint 文件中提取可翻译字符串:

Terminal window

bash
cargo install slint-tr-extractor

你可以在两种方式之间选择:使用 gettext 进行运行时翻译,或将翻译直接打包进可执行文件,以便在没有 gettext 或不实用的平台上使用。

要翻译你的应用程序,请按照以下步骤操作:

  1. 识别所有需要翻译的用户可见字符串,并使用 @tr() 宏对其进行标注。
  2. 运行 slint-tr-extractor 工具提取已标注的字符串,以生成 .pot 文件。
  3. 使用第三方工具将字符串翻译成每种目标语言的 .po 文件。
  4. (仅适用于运行时 gettext 翻译) 使用 gettext 的 msgfmt.po 文件转换为 .mo 文件。
  5. (仅适用于打包翻译) 在构建过程中配置打包,将翻译嵌入到你的应用程序中。
  6. 使用 Slint 的 API 根据用户的语言环境选择适当的翻译。

此时,所有标记为需要翻译的字符串都将自动以所选语言呈现。

标注可翻译字符串

.slint 文件中使用 @tr 宏来标记需要翻译的字符串。 该宏支持格式化和复数形式,并可以包含上下文信息。

第一个参数必须是一个普通字符串字面量,后面是参数:

基本示例

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

格式化

@tr 宏会将标记为翻译的字符串中的每个 {} 占位符替换为相应的参数。 还可以使用 {0}{1} 等重新排序参数。即使原始字符串没有使用有序占位符,译者也可以使用有序占位符。

可以通过在字符串中用相同字符前缀来包含字面字符 {}。 例如,用 &#123;&#123;{ 字符进行转义,用 &#125;&#125;} 字符进行转义。

复数

当涉及可变数量元素的文本翻译需要根据单个元素还是多个元素进行不同时,应使用复数格式。

给定 count 和一个表示某事物计数的表达式,使用 |% 符号构成复数形式,如下所示:

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

在格式字符串中使用 {n} 访问 % 后面的表达式。

slint
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} points" % score, name);}

上下文

通过使用 "..." => 语法向 @tr(...) 宏添加上下文,对源文本相同但上下文含义不同的字符串的翻译进行消歧。

使用上下文向译者提供额外的上下文信息,确保翻译准确且符合上下文。

上下文必须是普通字符串字面量,在 .pot 文件中显示为 msgctx。如果未指定,上下文默认为所在组件的名称。

slint
export component MenuItem {    property <string> name : @tr("Default Name"); // 默认:上下文将为 `MenuItem`。    property <string> tooltip : @tr("ToolTip" => "ToolTip for {}", name); // 指定:上下文将为 `ToolTip`。}

如果你不希望组件名称成为默认上下文,请向 slint-tr-extractor 传递 --no-default-translation-context 标志。需要向 Slint 编译器传递相同的选项:

在使用 CMake 时,在你的 CMake target 上设置 SLINT_NO_DEFAULT_TRANSLATION_CONTEXT target 属性。

在使用构建脚本时,使用 slint_build::CompilerConfiguration::set_default_translation_context(slint_build::DefaultTranslationContext::None)

在使用 slint-interpreter crate 时,使用 slint_interpreter::Compiler::set_default_translation_context(slint_interpreter::DefaultTranslationContext::None)

提取可翻译字符串

使用 slint-tr-extractor 生成包含所有标记为翻译字符串的 .pot 文件:

Terminal window

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

这会创建一个名为 MY_PROJECT.pot 的文件。将 "MY_PROJECT" 替换为你实际的项目名称。 要了解项目名称如何影响翻译查找,请阅读以下章节。

提示

.pot 文件是 Gettext 模板文件。

翻译字符串

通过从 .pot 文件创建 .po 文件来开始新的翻译。两种文件格式完全相同。 你可以手动复制文件,也可以使用 Gettext 的 msginit 等工具来启动新的 .po 文件。

.po 文件包含目标语言中的字符串。

.po.pot 文件是纯文本文件,你可以使用文本编辑器进行编辑。我们建议使用专门的翻译工具来处理它们,例如以下工具:

使用 Gettext 进行运行时翻译

Slint 可以使用 Gettext 库在运行时加载翻译。

Gettext 期望翻译文件——称为消息目录——位于以下目录层次结构中:

  • Directorydir_name/

    • Directorylocale/ 例如 frende
      • DirectoryLC_MESSAGES/
        • domain_name.mo
  • dir_name:你可以自由选择的基础目录。

  • locale:给定目标语言的用户语言环境名称,例如法语为 fr,德语为 de

    语言环境通常使用操作系统设置的环境变量来确定。

  • domain_name:根据你使用的 Slint 编程语言选择。

提示

请阅读 Gettext 文档 获取更多信息。

.po 文件转换为 .mo 文件

将人类可读的 .po 文件转换为机器友好的 .mo 文件,后者是代码读取效率更高的二进制表示。

使用 Gettextmsgfmt 命令行工具将 .po 文件转换为 .mo 文件:

Terminal window

bash
msgfmt translation.po -o translation.mo

选择并加载翻译

首先,在编译 Slint 时启用 SLINT_FEATURE_GETTEXT cmake 选项,以使用翻译 API 并激活运行时翻译支持。

在使用 cmake 的 C++ 应用程序中,domain_name 是 CMake target 的名称。

接下来,使用标准 gettext 库将文本域绑定到路径。

为此,请在你的 CMakeLists.txt 文件中添加以下内容:

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()

cmake

然后你可以设置语言环境和文本域

c++
#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   //...}

例如,如果你使用上面的代码并且用户的语言环境是 fr,则 Slint 会在 lang/fr/LC_MESSAGES/ 目录中查找 my_application.mo

首先,在 slint crate 的 features 部分启用 gettext 功能,以使用翻译 API 并激活运行时翻译支持。

接下来,使用 slint::init_translations! 宏指定 .mo 文件的基础位置。 这就是上一节方案中的 dir_name。Slint 期望 .mo 文件位于相应的子目录中,并且它们的文件名——domain_name——必须与你的 Cargo.toml 中的包名称匹配。这通常与 crate 名称相同。

例如:

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

例如,如果你的 Cargo.toml 包含以下行,并且用户的语言环境是 fr

toml
[package]name = "gallery"

在这些设置下,Slint 会在 lang/fr/LC_MESSAGES/gallery.mo 中查找 gallery.mo

打包翻译

打包翻译将翻译后的字符串直接嵌入到应用程序二进制文件中。 此方法非常适合像 WASM 或微控制器这样没有 gettext 的平台。

通过提供翻译路径来配置 Slint 编译器以打包翻译。 翻译文件应按以下层次结构组织:

path/<lang>/LC_MESSAGES/<domain>.po

plaintext

打包

在 CMake 中设置 SLINT_BUNDLE_TRANSLATIONS 属性:

set_property(TARGET my_application PROPERTY SLINT_BUNDLE_TRANSLATIONS "${CMAKE_CURRENT_SOURCE_DIR}/lang")

cmake

<domain> 是 cmake target 的名称。

使用 slint_build::CompilerConfigurationwith_bundled_translations() 函数在 build.rs 中设置打包:

rust
let config = slint_build::CompilerConfiguration::new()    .with_bundled_translations("path/to/translations");slint_build::compile_with_config("path/to/main-ui.slint", config).unwrap();

<domain> 是 crate 名称。

选择翻译

如果在 Slint 中启用了 std 功能,则会根据语言环境检测翻译语言: 如果某个打包的语言与所选语言环境匹配,则会使用它。

使用 slint::select_bundled_translation 函数在运行时更改翻译。

使用 slint::select_bundled_translation 函数在运行时更改翻译。

使用 slint.init_translations() 函数在运行时更改翻译。

使用 slint-viewer 预览翻译

确保在构建 slint-viewer 时启用了 gettext 功能。 使用 --translation-domain--translation-dir 命令行选项加载翻译以进行预览。

基于 MIT 协议发布