Skip to content

Commit

Permalink
Add metadata supports to in18n!
Browse files Browse the repository at this point in the history
  • Loading branch information
varphone committed Jan 28, 2024
1 parent 2a9e8cf commit 8762c15
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 2 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ members = [
"crates/macro",
"examples/app-egui",
"examples/app-load-path",
"examples/app-metadata",
"examples/app-minify-key",
"examples/foo",
]
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ i18n!("locales",
);
// Now, if the message length exceeds 64, the `t!` macro will automatically generate
// a 12-byte short hashed key with a "T." prefix for it, if not, it will use the original.
// Configuration using the `[package.metadata.i18n]` section in `Cargo.toml`,
// Useful for the `cargo i18n` command line tool.
i18n!(metadata = true);
```

Or you can import by use directly:
Expand Down
59 changes: 57 additions & 2 deletions crates/macro/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use quote::quote;
use rust_i18n_support::{
is_debug, load_locales, DEFAULT_MINIFY_KEY, DEFAULT_MINIFY_KEY_LEN, DEFAULT_MINIFY_KEY_PREFIX,
DEFAULT_MINIFY_KEY_THRESH,
is_debug, load_locales, I18nConfig, DEFAULT_MINIFY_KEY, DEFAULT_MINIFY_KEY_LEN,
DEFAULT_MINIFY_KEY_PREFIX, DEFAULT_MINIFY_KEY_THRESH,
};
use std::collections::HashMap;
use syn::{parse_macro_input, Expr, Ident, LitBool, LitStr, Token};
Expand All @@ -11,8 +11,10 @@ mod tr;

struct Args {
locales_path: String,
default_locale: Option<String>,
fallback: Option<Vec<String>>,
extend: Option<Expr>,
metadata: bool,
minify_key: bool,
minify_key_len: usize,
minify_key_prefix: String,
Expand Down Expand Up @@ -54,6 +56,30 @@ impl Args {
Ok(())
}

fn consume_metadata(&mut self, input: syn::parse::ParseStream) -> syn::parse::Result<()> {
let lit_bool = input.parse::<LitBool>()?;
self.metadata = lit_bool.value;
// Load the config from Cargo.toml. This can be overridden by subsequent options.
if self.metadata {
// CARGO_MANIFEST_DIR is current build directory
let cargo_dir = std::env::var("CARGO_MANIFEST_DIR")
.map_err(|_| input.error("The CARGO_MANIFEST_DIR is required fo `metadata`"))?;
let current_dir = std::path::PathBuf::from(cargo_dir);
let cfg = I18nConfig::load(&current_dir)
.map_err(|_| input.error("Failed to load config from Cargo.toml for `metadata`"))?;
self.locales_path = cfg.load_path;
self.default_locale = Some(cfg.default_locale.clone());
if !cfg.fallback.is_empty() {
self.fallback = Some(cfg.fallback);
}
self.minify_key = cfg.minify_key;
self.minify_key_len = cfg.minify_key_len;
self.minify_key_prefix = cfg.minify_key_prefix;
self.minify_key_thresh = cfg.minify_key_thresh;
}
Ok(())
}

fn consume_minify_key(&mut self, input: syn::parse::ParseStream) -> syn::parse::Result<()> {
let lit_bool = input.parse::<LitBool>()?;
self.minify_key = lit_bool.value;
Expand Down Expand Up @@ -96,6 +122,9 @@ impl Args {
let val = input.parse::<Expr>()?;
self.extend = Some(val);
}
"metadata" => {
self.consume_metadata(input)?;
}
"minify_key" => {
self.consume_minify_key(input)?;
}
Expand Down Expand Up @@ -137,6 +166,16 @@ impl syn::parse::Parse for Args {
/// # fn v4() {
/// i18n!("locales", fallback = ["en", "es"]);
/// # }
/// # fn v5() {
/// i18n!("locales", fallback = ["en", "es"],
/// minify_key = true,
/// minify_key_len = 12,
/// minify_key_prefix = "T.",
/// minify_key_thresh = 64);
/// # }
/// # fn v6() {
/// i18n!(metadata = true);
/// # }
/// ```
///
/// Ref: https://docs.rs/syn/latest/syn/parse/index.html
Expand All @@ -145,8 +184,10 @@ impl syn::parse::Parse for Args {

let mut result = Self {
locales_path: String::from("locales"),
default_locale: None,
fallback: None,
extend: None,
metadata: false,
minify_key: DEFAULT_MINIFY_KEY,
minify_key_len: DEFAULT_MINIFY_KEY_LEN,
minify_key_prefix: DEFAULT_MINIFY_KEY_PREFIX.to_owned(),
Expand Down Expand Up @@ -175,6 +216,7 @@ impl syn::parse::Parse for Args {
///
/// - `fallback` for set the fallback locale, if present [`t!`](macro.t.html) macro will use it as the fallback locale.
/// - `backend` for set the backend, if present [`t!`](macro.t.html) macro will use it as the backend.
/// - `metadata` to enable/disable loading of the [package.metadata.i18n] config from Cargo.toml, default: `false`.
/// - `minify_key` for enable/disable minify key, default: [`DEFAULT_MINIFY_KEY`](constant.DEFAULT_MINIFY_KEY.html).
/// - `minify_key_len` for set the minify key length, default: [`DEFAULT_MINIFY_KEY_LEN`](constant.DEFAULT_MINIFY_KEY_LEN.html),
/// * The range of available values is from `0` to `24`.
Expand Down Expand Up @@ -203,6 +245,9 @@ impl syn::parse::Parse for Args {
/// minify_key_prefix = "T.",
/// minify_key_thresh = 64);
/// # }
/// # fn v6() {
/// i18n!(metadata = true);
/// # }
/// ```
#[proc_macro]
pub fn i18n(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
Expand Down Expand Up @@ -249,6 +294,14 @@ fn generate_code(
});
});

let default_locale = if let Some(default_locale) = args.default_locale {
quote! {
rust_i18n::set_locale(#default_locale);
}
} else {
quote! {}
};

let fallback = if let Some(fallback) = args.fallback {
quote! {
Some(&[#(#fallback),*])
Expand Down Expand Up @@ -285,6 +338,8 @@ fn generate_code(
#(#all_translations)*
#extend_code

#default_locale

Box::new(backend)
});

Expand Down
18 changes: 18 additions & 0 deletions examples/app-metadata/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
edition = "2021"
name = "app-metadata"
version = "0.1.0"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
rust-i18n = { path = "../.." }

[package.metadata.i18n]
available-locales = ["en", "zh"]
default-locale = "zh"
load-path = "locales"
minify-key = true
minify-key-len = 12
minify-key-prefix = "T."
minify-key-thresh = 4
23 changes: 23 additions & 0 deletions examples/app-metadata/locales/v2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
_version: 2

T.1LokVzuiIrh1:
en: "Hello, world!"
zh: "你好,世界!"
T.53pFZEJAcwid:
en: ABCDEF
zh: 甲乙丙丁戊己
T.6zJ2nRuJ42Z5:
en: ABCDE
zh: 甲乙丙丁戊
a:
en: A
zh:
ab:
en: AB
zh: 甲乙
abc:
en: ABC
zh: 甲乙丙
abcd:
en: ABCD
zh: 甲乙丙丁
24 changes: 24 additions & 0 deletions examples/app-metadata/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use rust_i18n::t;

rust_i18n::i18n!(metadata = true);

fn main() {
let locales = rust_i18n::available_locales!();
println!("Available locales: {:?}", locales);
println!();

assert_eq!(t!("a"), "甲");
assert_eq!(t!("ab"), "甲乙");
assert_eq!(t!("abc"), "甲乙丙");
assert_eq!(t!("abcd"), "甲乙丙丁");
assert_eq!(t!("abcde"), "甲乙丙丁戊");
assert_eq!(t!("abcdef"), "甲乙丙丁戊己");
assert_eq!(t!("Hello, world!"), "你好,世界!");
assert_eq!(t!("a", locale = "en"), "A");
assert_eq!(t!("ab", locale = "en"), "AB");
assert_eq!(t!("abc", locale = "en"), "ABC");
assert_eq!(t!("abcd", locale = "en"), "ABCD");
assert_eq!(t!("abcde", locale = "en"), "ABCDE");
assert_eq!(t!("abcdef", locale = "en"), "ABCDEF");
assert_eq!(t!("Hello, world!", locale = "en"), "Hello, world!");
}
4 changes: 4 additions & 0 deletions tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ mod tests {
}
}

mod test5 {
rust_i18n::i18n!(metadata = true);
}

#[test]
fn check_test_environment() {
assert_eq!(
Expand Down

0 comments on commit 8762c15

Please sign in to comment.