-
Notifications
You must be signed in to change notification settings - Fork 156
/
Copy pathi18n.rs
131 lines (114 loc) · 3.38 KB
/
i18n.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use fluent::{FluentArgs, FluentBundle, FluentResource};
use strum_macros::{AsRefStr, Display, EnumIter, EnumString};
use unic_langid::LanguageIdentifier;
// ------ I18n ------
pub struct I18n {
lang: Lang,
ftl_bundle: FluentBundle<FluentResource>,
}
impl I18n {
pub fn new(lang: Lang) -> Self {
Self {
lang,
ftl_bundle: lang.create_ftl_bundle(),
}
}
pub const fn lang(&self) -> &Lang {
&self.lang
}
pub fn set_lang(&mut self, lang: Lang) -> &Self {
self.lang = lang;
self.ftl_bundle = lang.create_ftl_bundle();
self
}
pub fn translate(&self, key: impl AsRef<str>, args: Option<&FluentArgs>) -> String {
let mmessage = self
.ftl_bundle
.get_message(key.as_ref())
.expect("get fluent message");
let pattern = mmessage.value.expect("get value for fluent message");
self.ftl_bundle
.format_pattern(pattern, args, &mut vec![])
.to_string()
}
}
// ------ Lang ------
#[derive(Debug, Copy, Clone, Display, EnumIter, EnumString, AsRefStr, Eq, PartialEq)]
pub enum Lang {
#[strum(serialize = "en-US")]
EnUS,
#[strum(serialize = "de-DE")]
DeDE,
}
impl Lang {
pub fn label(self) -> &'static str {
match self {
Self::EnUS => "English (US)",
Self::DeDE => "Deutsch (Deutschland)",
}
}
pub fn ftl_messages(self) -> &'static str {
macro_rules! include_ftl_messages {
( $lang_id:literal ) => {
include_str!(concat!("../ftl_messages/", $lang_id, ".ftl"))
};
}
match self {
Self::EnUS => include_ftl_messages!("en-US"),
Self::DeDE => include_ftl_messages!("de-DE"),
}
}
pub fn to_language_identifier(self) -> LanguageIdentifier {
self.as_ref()
.parse()
.expect("parse Lang to LanguageIdentifier")
}
pub fn create_ftl_bundle(self) -> FluentBundle<FluentResource> {
let ftl_resource =
FluentResource::try_new(self.ftl_messages().to_owned()).expect("parse FTL messages");
let mut bundle = FluentBundle::new(&[self.to_language_identifier()]);
bundle.add_resource(ftl_resource).expect("add FTL resource");
bundle
}
}
// ------ create_t ------
/// Convenience macro to improve readability of `view`s with many translations.
///
/// # Example
///
///```rust,no_run
/// fn view(model: &Model) -> Node<Msg> {
/// let args_male_sg = fluent_args![
/// "userName" => "Stephan",
/// "userGender" => "male",
/// ];
///
/// create_t!(model.i18n);
/// div![
/// p![t!("hello-world")],
/// p![t!("hello-user", args_male_sg)],
/// ]
/// }
///```
#[macro_export]
macro_rules! create_t {
( $i18n:expr ) => {
// This replaces $d with $ in the inner macro.
seed::with_dollar_sign! {
($d:tt) => {
macro_rules! t {
{ $d key:expr } => {
{
$i18n.translate($d key, None)
}
};
{ $d key:expr, $d args:expr } => {
{
$i18n.translate($d key, Some(&$d args))
}
};
}
}
}
};
}