国际化与翻译
Slint 的翻译基础设施让你的应用能够支持多种语言。
你可以选择使用 gettext 的运行时翻译,或者在 gettext 不可用或不切实际的平台上,将翻译直接捆绑到可执行文件中。
要翻译你的应用,请按以下步骤操作:
- 找出所有需要翻译的用户可见字符串,并用
@tr()宏标注它们。 - 运行
slint-tr-extractor工具提取已标注的字符串,生成.pot文件。 - 使用第三方工具将字符串翻译为每种目标语言的
.po文件。 - (仅用于运行时
gettext翻译) 使用 gettext 的msgfmt将.po文件转换为.mo文件。 - (仅用于捆绑翻译) 在构建过程中配置捆绑,将翻译嵌入到你的应用中。
- 使用 Slint 的 API 根据用户的 locale 选择合适的翻译。
此时,所有标记为翻译的字符串都会自动以所选语言渲染。
标注可翻译字符串
Section titled “标注可翻译字符串”在 .slint 文件中使用 @tr 宏将字符串标记为可翻译。
该宏支持格式化和复数形式,并且可以包含上下文信息。
第一个参数必须是纯字符串字面量,其后是各个参数:
export component Example { property <string> name; Text { text: @tr("Hello, {}", name); }}格式字符串中的每个 {} 占位符都会按顺序替换为对应的参数。
占位符可以指定一个从零开始的位置,如 {0} 或 {1},以显式选择某个参数。
在一个格式字符串中不能混用位置占位符和非位置占位符。
即使源字符串没有使用位置占位符,翻译也可以使用它们。
通过将 { 或 } 加倍,即写成 {{ 或 }},来写出字面量。
未终止的占位符、未转义的 { 或 },或者占位符多于参数,都是错误。
复数形式根据计数在两个格式字符串之间选择。
其写法是在两个字符串字面量之间加 |,并在计数表达式前加 %:
@tr("I have {n} item" | "I have {n} items" % count)| 的两侧都必须是纯字符串字面量,计数表达式会被转换为 int。
{n} 占位符指代计数,只在复数形式中有效。
其他占位符仍然指代计数之后的参数:
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);}上下文用于区分源文本相同但含义不同的字符串。
其写法是在格式字符串之前写一个纯字符串字面量,后跟 =>:
export component MenuItem { property <string> name: @tr("Default Name"); // context: `MenuItem` property <string> tooltip: @tr("ToolTip" => "ToolTip for {}", name); // context: `ToolTip`}如果没有提供上下文,则默认为外层组件的名称。
如果你不希望组件名称成为默认上下文,请向 slint-tr-extractor 传递 --no-default-translation-context 标志。同样的选项也需要传递给 Slint 编译器:
使用构建脚本时,用
slint_build::CompilerConfiguration::with_default_translation_context(slint_build::DefaultTranslationContext::None)
。使用 slint-interpreter crate 时,用
slint_interpreter::Compiler::set_default_translation_context(slint_interpreter::DefaultTranslationContext::None)
。
提取可翻译字符串
Section titled “提取可翻译字符串”使用 slint-tr-extractor 生成一个包含所有已标记为翻译的字符串的 .pot 文件:
find -name \*.slint | xargs slint-tr-extractor -o MY_PROJECT.pot这会创建一个名为 MY_PROJECT.pot 的文件。将 “MY_PROJECT” 替换为你的实际项目名称。
要了解项目名称如何影响翻译的查找,请阅读下面的章节。
通过从 .pot 文件创建 .po 文件来开始一个新的翻译。两种文件格式完全相同。
你可以手动复制文件,或者使用类似 Gettext 的 msginit 这样的工具来创建一个新的 .po 文件。
.po 文件包含目标语言的字符串。
.po 和 .pot 文件是纯文本文件,你可以用文本编辑器编辑它们。我们建议
使用专门的翻译工具来处理它们,例如以下几种:
使用 Gettext 的运行时翻译
Section titled “使用 Gettext 的运行时翻译”Slint 可以使用 Gettext 库在运行时加载翻译。
Gettext 期望翻译文件(称为消息目录)按以下目录层级组织:
Directorydir_name/
Directorylocale/ 例如
fr、en、de等DirectoryLC_MESSAGES/
- domain_name.mo
-
dir_name:你可以自由选择的基础目录。 -
locale:给定目标语言对应的用户 locale 名称,例如法语用fr,德语用de。locale 通常是使用操作系统设置的环境变量来确定的。
-
domain_name:根据你使用 Slint 时所搭配的编程语言来选择。
将 .po 文件转换为 .mo 文件
Section titled “将 .po 文件转换为 .mo 文件”将人类可读的 .po 文件转换为便于机器处理的 .mo 文件,后者是一种二进制表示,
代码读取起来更高效。
使用 Gettext 的 msgfmt 命令行工具将 .po 文件转换为 .mo
文件:
msgfmt translation.po -o translation.mo选择并加载翻译
Section titled “选择并加载翻译”首先,在 features 部分启用 slint crate 的 gettext feature,以访问翻译 API
并激活运行时翻译支持。
接下来,使用 slint::init_translations! 宏指定 .mo 文件的基础位置。
这就是上一节方案中的 dir_name。Slint 期望 .mo 文件位于
相应的子目录中,并且它们的文件名——domain_name——必须与
你的 Cargo.toml 中的包名匹配。这通常与 crate 名称相同。
例如:
slint::init_translations!(concat!(env!("CARGO_MANIFEST_DIR"), "/lang/"));例如,如果你的 Cargo.toml 包含以下几行,且用户的 locale 是 fr:
[package]name = "gallery"使用这些设置,Slint 会在 lang/fr/LC_MESSAGES/gallery.mo 中查找 gallery.mo。
首先,在编译 Slint 时启用 SLINT_FEATURE_GETTEXT cmake 选项,以访问
翻译 API 并激活运行时翻译支持。
在使用 cmake 的 C++ 应用中,domain_name 就是 CMake 目标名称。
接下来,使用标准 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()然后你就可以设置 locale 和文本域
#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 //...}例如,如果你使用上述代码,且用户的 locale 是 fr,
Slint 会在 lang/fr/LC_MESSAGES/ 目录中查找 my_application.mo。
捆绑翻译将翻译后的字符串直接嵌入到你的应用二进制文件中。
这种方法非常适合 WASM 或微控制器等 gettext 不可用的平台。
通过向 Slint 编译器提供翻译路径来配置翻译捆绑。 翻译文件应按以下层级组织:
path/<lang>/LC_MESSAGES/<domain>.po使用 slint_build::CompilerConfiguration 的 with_bundled_translations() 函数在
build.rs 中设置捆绑:
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 名称。
在 CMake 中设置 SLINT_BUNDLE_TRANSLATIONS 属性:
set_property(TARGET my_application PROPERTY SLINT_BUNDLE_TRANSLATIONS "${CMAKE_CURRENT_SOURCE_DIR}/lang")<domain> 就是 cmake 目标名称。
如果你为 Slint 启用了 std feature,翻译语言会根据 locale 检测:
如果某个捆绑语言与所选 locale 匹配,就会使用该语言。
使用 slint-viewer 预览翻译
Section titled “使用 slint-viewer 预览翻译”确保在构建 slint-viewer 时启用了 gettext feature。
使用 --translation-domain 和 --translation-dir 命令行选项加载翻译以进行预览。
选择小数分隔符
Section titled “选择小数分隔符”float 和 string 之间的转换使用 locale 的小数分隔符,
例如德语 locale 中的逗号(,)。
转换规则参见 数字与字符串之间的转换。
从 Platform.decimal-separator 读取当前使用的分隔符。
它默认是点(.)。
在捆绑翻译时,每种语言的小数分隔符在编译时确定,
并与应用一起捆绑:
选择某种翻译也会选择其小数分隔符。
当启用 gettext feature 时,小数分隔符由系统 locale 决定。
© 2026 SixtyFPS GmbH