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
。String
Cow<'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>::Output
into
(默认):可以转换为输入类型的任何东西:fn html_hello_with_icon<T1: Into<Input>>(self, name: &str, icon: T1) -> <HtmlBuilder as BuilderFromValue>::Output
ref
:输入类型的引用:fn html_hello_with_icon(self, name: &str, icon: &Input) -> <HtmlBuilder as BuilderFromRef>::Output
as_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