Skip to content

Commit 84eb0f7

Browse files
committed
Add auto-territory attribute to i18n!
1 parent 403e6f7 commit 84eb0f7

File tree

4 files changed

+52
-2
lines changed

4 files changed

+52
-2
lines changed

crates/macro/src/lib.rs

+30-1
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
use quote::quote;
22
use rust_i18n_support::{is_debug, load_locales};
33
use std::collections::HashMap;
4-
use syn::{parse_macro_input, Expr, Ident, LitStr, Token};
4+
use syn::{parse_macro_input, Expr, Ident, LitBool, LitStr, Token};
55

66
struct Args {
77
locales_path: String,
88
fallback: Option<String>,
99
extend: Option<Expr>,
10+
auto_territory: bool,
1011
}
1112

1213
impl Args {
@@ -30,6 +31,9 @@ impl Args {
3031
let val = input.parse::<Expr>()?;
3132
self.extend = Some(val);
3233
}
34+
"auto_territory" => {
35+
self.auto_territory = input.parse::<LitBool>()?.value();
36+
}
3337
_ => {}
3438
}
3539

@@ -56,6 +60,9 @@ impl syn::parse::Parse for Args {
5660
/// # fn v3() {
5761
/// i18n!("locales", fallback = "en");
5862
/// # }
63+
/// # fn v4() {
64+
/// i18n!("locales", fallback = "en", auto_territory = true);
65+
/// # }
5966
/// ```
6067
///
6168
/// Ref: https://docs.rs/syn/latest/syn/parse/index.html
@@ -66,6 +73,7 @@ impl syn::parse::Parse for Args {
6673
locales_path: String::from("locales"),
6774
fallback: None,
6875
extend: None,
76+
auto_territory: false,
6977
};
7078

7179
if lookahead.peek(LitStr) {
@@ -88,6 +96,10 @@ impl syn::parse::Parse for Args {
8896
///
8997
/// Attribute `fallback` for set the fallback locale, if present `t` macro will use it as the fallback locale.
9098
///
99+
/// Attribute `auto_territory` for set the auto territory flag,
100+
/// if true `t` macro will auto fallback to the language territory of the locale when missing,
101+
/// like: `zh-SG` => `zh`, if `zh` still missing, then fallback to the `fallback` locale.
102+
///
91103
/// ```no_run
92104
/// # use rust_i18n::i18n;
93105
/// # fn v1() {
@@ -99,6 +111,9 @@ impl syn::parse::Parse for Args {
99111
/// # fn v3() {
100112
/// i18n!("locales", fallback = "en");
101113
/// # }
114+
/// # fn v4() {
115+
/// i18n!("locales", fallback = "en", auto_territory = true);
116+
/// # }
102117
/// ```
103118
#[proc_macro]
104119
pub fn i18n(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
@@ -155,6 +170,12 @@ fn generate_code(
155170
}
156171
};
157172

173+
let auto_territory = if args.auto_territory {
174+
quote! { true }
175+
} else {
176+
quote! { false }
177+
};
178+
158179
let extend_code = if let Some(extend) = args.extend {
159180
quote! {
160181
let backend = backend.extend(#extend);
@@ -180,6 +201,7 @@ fn generate_code(
180201
});
181202

182203
static _RUST_I18N_FALLBACK_LOCALE: Option<&'static str> = #fallback;
204+
static _RUST_I18N_AUTO_TERRITORY: bool = #auto_territory;
183205

184206
/// Get I18n text by locale and key
185207
#[inline]
@@ -189,6 +211,13 @@ fn generate_code(
189211
return value.to_string();
190212
}
191213

214+
if _RUST_I18N_AUTO_TERRITORY {
215+
if let Some(fallback) = rust_i18n::language_territory(locale) {
216+
if let Some(value) = _RUST_I18N_BACKEND.translate(fallback, key) {
217+
return value.to_string();
218+
}
219+
}
220+
}
192221

193222
if let Some(fallback) = _RUST_I18N_FALLBACK_LOCALE {
194223
if let Some(value) = _RUST_I18N_BACKEND.translate(fallback, key) {

src/lib.rs

+5
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ pub fn locale() -> String {
2121
CURRENT_LOCALE.read().unwrap().to_string()
2222
}
2323

24+
/// Get language territory from locale
25+
pub fn language_territory(locale: &str) -> Option<&str> {
26+
locale.split_once(&['-', '_']).map(|(a, _)| a)
27+
}
28+
2429
/// Get I18n text
2530
///
2631
/// ```no_run

tests/integration_tests.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,18 @@ mod tests {
6868
rust_i18n::i18n!(fallback = "foo");
6969
}
7070

71+
mod test4 {
72+
rust_i18n::i18n!("./tests/locales", fallback = "en", auto_territory = true);
73+
74+
#[test]
75+
fn test_auto_territory() {
76+
assert_eq!(
77+
crate::tests::test2::_rust_i18n_translate("zh-SG", "hello"),
78+
"Bar - 你好世界!"
79+
);
80+
}
81+
}
82+
7183
#[test]
7284
fn check_test_environment() {
7385
assert_eq!(
@@ -98,7 +110,7 @@ mod tests {
98110
fn test_available_locales() {
99111
assert_eq!(
100112
rust_i18n::available_locales!(),
101-
&["en", "ja", "pt", "zh-CN"]
113+
&["en", "ja", "pt", "zh", "zh-CN"]
102114
);
103115
}
104116

tests/locales/zh.yml

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
hello: Bar - 你好世界!
2+
messages:
3+
hello: 你好,%{name}!
4+
other: 你收到了 %{count} 条新消息。

0 commit comments

Comments
 (0)