2 个版本
| 0.6.1 | 2024年6月28日 |
|---|---|
| 0.6.0 | 2024年6月18日 |
#64 in 国际化(i18n)
26KB
109 行
crate typed-i18n
将语言文件和枚举转换为类型安全的国际化系统。
基本用法
Yaml 语言文件:(也支持 json 和 lrc,更多见下文)
hello_world:
en: Hello World
de: Hallo Welt
hello_you:
en: Hello %{name}
代码
#[derive(Copy, Clone, TypedI18N)]
#[typed_i18n(filename = "example.yaml")]
#[typed_i18n(builder = "mixed_str", prefix = "str_")]
enum Language { En, De }
生成的代码
impl Language {
fn str_hello_world(self) -> &'static str;
fn str_hello_you(self, name: &str) -> String;
}
用法
fn print_hello(language: Language, name: Option<&str>){
if let Some(name) = name {
println!("{}", language.str_hello_you(name));
} else {
println!("{}", language.str_hello_world());
}
}
也支持全局存储的语言,详见下文 global。
更多构建器
不同的生成器会添加不同的代码
#[typed_i18n(builder = "static_str", prefix = "sta_")]
#[typed_i18n(builder = "String")]
生成的代码
impl Language {
fn sta_hello_world(self) -> &'static str;
// The static_str builder skips all parameterized messages
fn hello_world(self) -> String;
fn hello_you(self, name: &str) -> String;
}
其他输出类型
也支持字符串之外的类型
#in addition to the messages above
hello_with_icon:
en: Hello %{name}*{icon}
#[typed_i18n(builder = "HtmlBuilder", input = "Html", prefix = "html_")]
生成的代码
impl Language {
fn html_hello_world(self) -> <HtmlBuilder as Builder>::Output;
fn html_hello_you(self, name: &str) -> <HtmlBuilder as Builder>::Output;
fn html_hello_with_icon<T1: Into<Html>>(
self,
name: &str,
icon: T1,
) -> <HtmlBuilder as Builder>::Output;
}
请参见 示例,其中包含 HtmlBuilder 用于 yew::Html 实现的示例。
输入
字段
filename:翻译文件的路径,相对于 crate 根目录(必需)。separator:用于合并树路径,默认:_。global:用于全局存储的语言,详见下文 global,默认:不使用。
示例
#[typed_i18n(filename= "example.yaml",separator= "_")]
消息可以提供如下:
- yaml(如上例所示)
- json
- lrc
json
{"hello_world": {"en": "Hello World"}}
yaml 和 json 文件可能有一个 _version: 2 条目,以与其他国际化工具兼容。(其他数字是错误,省略它是可以的。)
如果 yaml 和 json 文件有一个更深的树,则使用分隔符将段连接成一个函数名。
示例
hello:
world:
en: Hello World
you:
en: Hello %{name}
使用分隔符 _,它将产生与上述示例相同的名称。这可能有助于您组织消息。
由于名称是函数名,因此不允许使用 . 作为分隔符,但您可以使用 ·(U+00B7)。
lrc
; lines starting with `;` or `/` will be skipped
#hello_world
en Hello World
输出
字段
builder:实现Builder的项目的名称,或一个特殊值。prefix:此构建器生成的所有函数的前缀,默认:空字符串。str_conversion:如何转换 str 参数,默认ref。input:输入类型(对于已类型化输入),默认:无输入。input_conversion:如何将参数转换为输入类型,默认:into。
builder
必须是特殊值或实现了 Builder 的类型。
所有没有输入类型的构建器都将跳过所有针对该类型的消息。
以下所有构建器都是内置的。对于这些,不得设置 input。始终可用
static_str:所有不带参数的消息的返回类型为&'static str。所有其他都将被跳过。mixed_str:所有不带参数的消息的返回类型为&'static str,所有其他将具有返回类型String。StringCow<'static, str>_:函数将泛型化构建器类型。这有时并不有用,例如,当在函数的结果上调用.into()或.as_ref()时。
除了 static_str 和 _ 外,都需要 alloc 功能(默认启用)以及 String 或 Cow 在作用域内。
有关自定义类型构建器的信息,请参阅上面的示例和在 示例目录 中的示例。
prefix
此 builder 的所有函数都将由前缀和消息名称组成。
使用相同的前缀或重叠的名称会导致具有相同名称的函数,从而引起编译错误。这不会由 derive 宏检查。
str_conversion
所有字符串(普通)%{param} 参数的转换
ref(默认):fn str_hello_you(self, name: &str) -> String。as_ref:fn str_hello_you<S1: AsRef<str>>(self, name: S1) -> String。
input
类型化 *{param} 参数的输入类型。
所有没有 input 的构建器将静默地跳过所有具有类型化参数的消息。
使用 _ 创建输入类型的泛型函数。可能会导致与泛型构建器类型相同的问题。
input_conversion
如何转换输入类型
value:输入类型作为参数:fn html_hello_with_icon(self, name: &str, icon: Input) -> <HtmlBuilder as BuilderFromValue>::Outputinto(默认):可以转换为输入类型的任何东西:fn html_hello_with_icon<T1: Into<Input>>(self, name: &str, icon: T1) -> <HtmlBuilder as BuilderFromValue>::Outputref:输入类型的引用:fn html_hello_with_icon(self, name: &str, icon: &Input) -> <HtmlBuilder as BuilderFromRef>::Outputas_ref:可以转换为输入类型引用的任何东西:fn html_hello_with_icon<T1: AsRef<Input>>(self, name: &str, icon: T1) -> <HtmlBuilder as BuilderFromRef>::Output
对于 value 和 into 来说,构建器必须也实现 BuilderFromValue。
对于 ref 和 as_ref 来说,构建器必须也实现 BuilderFromRef。
语言
枚举值可以被注解为
name:消息文件中语言的名称,默认为snake_case中的值名称。fallback:一个由空格和/或逗号分隔的语言名称列表,它定义了在消息缺失时应使用哪种语言。默认:按列表顺序的所有语言(不一定按数字顺序)。default:用于 全局 存储。只能有一个语言是默认的。
示例
#[derive(Copy, Clone, TypedI18N)]
#[typed_i18n(filename = "example.yaml")]
#[typed_i18n(builder = "mixed_str", prefix = "str_")]
enum Language {
De,
#[typed_i18n(name = "en")]
English,
#[typed_i18n(fallback = "en, de")]
EnAu,
}
全局
可以生成全局语言存储。
代码
#[derive(Copy, Clone, TypedI18N)]
#[typed_i18n(filename = "example.yaml", global = "atomic")]
#[typed_i18n(builder = "static_str")]
enum Language { En, #[typed_i18n(default = "true")] De }
生成的代码
impl Language {
fn global() -> Self;
fn set_global(self);
}
示例用法
// de is the default
assert_eq!(Language::global().hello_world(), "Hallo Welt");
Language::En.set_global();
assert_eq!(Language::global().hello_world(), "Hello world");
默认语言(要么标记为如此,参见上面的示例,要么是第一个)最初存储为全局语言。
目前 atomic 是唯一的实现,它使用 AtomicU8 来存储语言。转换不依赖于枚举的表示。在超过 256 种语言的情况下使用 AtomicUsize。
特性
alloc,默认启用:为String和Cow<'static, str>提供Builder实现,也支持mixed_str。
库始终为no_std。
依赖项
~3.5–4.5MB
~91K SLoC