#gettext #translation #localization

include-po

将信息目录(PO文件)转换为Rust模块

1 个不稳定版本

新版本 0.1.0 2024年8月14日

#129国际化(i18n)

Download history 120/week @ 2024-08-11

120 每月下载量
easy-imgui-filechooser 中使用

MIT 许可证

30KB
709

include-po

一个crate,用于将gettext信息目录(PO文件)直接包含到您的Rust程序中,作为可编译的Rust模块。

tr crate一起使用。

如果您想使用不同的翻译引擎,只需提交一个问题或pull request,我会尽力而为。

阅读文档以获取详细信息。


lib.rs:

这个crate包含解析PO文件(gettext信息目录)并在Rust中使用它们的函数。

主要用途

推荐的使用方法是使用它来构建一个包含翻译的Rust模块。

首先将您的PO文件构建到项目根目录下的locales目录中。

然后在这个crate中将其作为[build-dependencies],并将tr作为一个常规依赖项:在您的Cargo.toml

[dev-dependencies]
include-po = "0.1"

[dependencies]
tr = { version = "0.1.10", default-features = false }

编写一个build.rs脚本

fn main() {
    let output_dir = std::env::var("OUT_DIR").unwrap();
    let out = std::path::PathBuf::from(&output_dir).join("locale/translators.rs");
    include_po::generate_locales_from_dir("locales", out).unwrap();
}

并在您的main.rslib.rs

include!(concat!(env!("OUT_DIR"), "/locale/translators.rs"));

这就对了!现在您可以通过调用translators::set_locale("es");来切换到西班牙语!

如果您正在编写一个lib crate,按照惯例,您应该在根命名空间中有一个公共函数

fn set_locale(locale: &str) {
    translators::set_locale(locale);
}

这样您就可以链式调用多个可翻译库的locale。

其他函数

如果您喜欢自己进行翻译,您也可以使用这个crate来解析PO文件并获取消息。但请注意,目前消息将不会被转义,即一个"将是一个'\n'等等。

为什么是PO而不是MO?

大多数基于gettext的解决方案都从MO文件中读取信息目录,而不是从PO中。一个MO文件是一个编译后的信息目录。原始gettext使用MO文件的原因是为了优化启动时间:当gettext库想要使用一个MO时,它只需定位文件,打开它并对其进行内存映射。它所做的解析非常少,因为一切都是为了从该内存映射中使用而设计的。它甚至包含一个预计算的哈希表!

在Rust中,我觉得没有必要将MO文件与可执行文件分开分发。有些人尝试使用include_bytes!,然后将二进制数据解析到BTreeMap中……但这最初就违背了MO存在的目的。

如果你打算将消息目录嵌入到可执行文件中,你不妨将其完全作为代码包含:消息目录再次是内存映射的(就像大多数可执行代码一样),并且运行时无需解析。但如果你打算在构建时解析目录并将其转换为Rust,为什么读MO而不是更简单且节省编译步骤的PO呢?

但是,关于哈希表,你可能想知道……好吧,目前这个crate正在为每个源PO文件构建一个巨大的match字符串。这似乎足够好了,但如果需要,我们可以透明地将其升级到一个更聪明的算法。我的希望是,编译器生成的代码会比这个crate的需求更快地变得更好。

依赖项

~1.1–1.8MB
~37K SLoC