Skip to content

Commit

Permalink
Merge pull request #20 from longbridgeapp/feat/available_locales
Browse files Browse the repository at this point in the history
Add available_locales method
  • Loading branch information
huacnlee authored Jan 4, 2023
2 parents 0017479 + 06fe5ea commit 9d4f3e6
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 26 deletions.
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ license = "MIT"
name = "rust-i18n"
readme = "README.md"
repository = "https://github.com/longbridgeapp/rust-i18n"
version = "1.0.1"
version = "1.1.0"

[dependencies]
anyhow = {version = "1", optional = true}
clap = {version = "2.32", optional = true}
itertools = {version = "0.10.3", optional = true}
once_cell = "1.10.0"
quote = {version = "1", optional = true}
rust-i18n-extract = {path = "./crates/extract", version = ">=1.0", optional = true}
rust-i18n-macro = {path = "./crates/macro", version = ">=0.4"}
rust-i18n-extract = {path = "./crates/extract", version = ">=1.1", optional = true}
rust-i18n-macro = {path = "./crates/macro", version = ">=1.1"}
serde = "1"
serde_derive = "1"
toml = "0.5.8"
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ rust_i18n::i18n!("locales");

fn main() {
println!("{}", t!("hello"));

// Use `available_locales` method to get all available locales.
println!("{:?}", available_locales());
}
```

Expand Down
4 changes: 2 additions & 2 deletions crates/extract/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ license = "MIT"
name = "rust-i18n-extract"
readme = "../../README.md"
repository = "https://github.com/longbridgeapp/rust-i18n"
version = "1.0.0"
version = "1.1.0"

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

Expand All @@ -15,7 +15,7 @@ ignore = "0.4"
proc-macro2 = {version = "1", features = ["span-locations"]}
quote = "1"
regex = "1"
rust-i18n-support = {path = "../support", version = ">= 0.3"}
rust-i18n-support = {path = "../support", version = ">= 1.1"}
serde = "1"
serde_json = "1"
serde_yaml = "0.8"
Expand Down
4 changes: 2 additions & 2 deletions crates/extract/src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub fn generate<'a, P: AsRef<Path>>(
let output_path = output.as_ref().display().to_string();

let ignore_file = |fname: &str| fname.ends_with(&filename);
let old_translations = load_locales(&output_path, ignore_file);
let data = load_locales(&output_path, ignore_file);

let mut new_values: HashMap<String, String> = HashMap::new();

Expand All @@ -31,7 +31,7 @@ pub fn generate<'a, P: AsRef<Path>>(
}
}

if old_translations.get(&key).is_some() {
if data.translations.get(&key).is_some() {
continue;
}

Expand Down
2 changes: 1 addition & 1 deletion crates/macro/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ license = "MIT"
name = "rust-i18n-macro"
readme = "../../README.md"
repository = "https://github.com/longbridgeapp/rust-i18n"
version = "0.4.0"
version = "1.1.0"

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

Expand Down
43 changes: 34 additions & 9 deletions crates/macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,43 +34,68 @@ pub fn i18n(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let current_dir = std::path::PathBuf::from(cargo_dir);
let locales_path = current_dir.join(option.locales_path);

let translations = load_locales(&locales_path.display().to_string(), |_| false);
let code = generate_code(translations);
let data = load_locales(&locales_path.display().to_string(), |_| false);
let code = generate_code(data.translations, data.locales);

if is_debug() {
println!("{}", code.to_string());
// panic!("Debug mode, show codegen.");
}

code.into()
}

fn generate_code(translations: HashMap<String, String>) -> proc_macro2::TokenStream {
let mut locales = Vec::<proc_macro2::TokenStream>::new();
fn generate_code(
translations: HashMap<String, String>,
locales: Vec<String>,
) -> proc_macro2::TokenStream {
let mut all_translations = Vec::<proc_macro2::TokenStream>::new();
let mut all_locales = Vec::<proc_macro2::TokenStream>::new();
// For keep locales unique
let mut locale_names = HashMap::<String, String>::new();

translations.iter().for_each(|(k, v)| {
let k = k.to_string();
let v = v.to_string();

locales.push(quote! {
all_translations.push(quote! {
#k => #v,
});
});

locales.iter().for_each(|l| {
if locale_names.contains_key(l) {
return;
}

locale_names.insert(l.to_string(), l.to_string());
all_locales.push(quote! {
#l,
});
});

// result
quote! {
static LOCALES: once_cell::sync::Lazy<std::collections::HashMap<&'static str, &'static str>> = once_cell::sync::Lazy::new(|| rust_i18n::map! [
#(#locales)*
static ALL_TRANSLATIONS: once_cell::sync::Lazy<std::collections::HashMap<&'static str, &'static str>> = once_cell::sync::Lazy::new(|| rust_i18n::map! [
#(#all_translations)*
"" => ""
]);

static AVAILABLE_LOCALES: &[&'static str] = &[
#(#all_locales)*
];

/// Get I18n text by locale and key
pub fn translate(locale: &str, key: &str) -> String {
let key = format!("{}.{}", locale, key);
match LOCALES.get(key.as_str()) {
match ALL_TRANSLATIONS.get(key.as_str()) {
Some(value) => value.to_string(),
None => key.to_string(),
}
}

/// Return all available locales, for example: `&["en", "zh-CN"]`
pub fn available_locales() -> &'static [&'static str] {
AVAILABLE_LOCALES
}
}
}
2 changes: 1 addition & 1 deletion crates/support/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ license = "MIT"
name = "rust-i18n-support"
readme = "../../README.md"
repository = "https://github.com/longbridgeapp/rust-i18n"
version = "1.0.0"
version = "1.1.0"

[dependencies]
glob = "0.3"
Expand Down
21 changes: 14 additions & 7 deletions crates/support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,18 @@ pub fn merge_value(a: &mut Value, b: &Value) {
}
}

pub struct LocaleData {
pub translations: HashMap<String, String>,
pub locales: Vec<String>,
}

// Load locales into flatten key, value HashMap
pub fn load_locales<F: Fn(&str) -> bool>(
locales_path: &str,
ignore_if: F,
) -> HashMap<String, String> {
pub fn load_locales<F: Fn(&str) -> bool>(locales_path: &str, ignore_if: F) -> LocaleData {
let mut translations: Translations = HashMap::new();
let mut data = LocaleData {
translations: HashMap::new(),
locales: Vec::new(),
};

let path_pattern = format!("{}/**/*.yml", locales_path);

Expand All @@ -55,6 +61,8 @@ pub fn load_locales<F: Fn(&str) -> bool>(
.unwrap()
.to_string();

data.locales.push(locale.clone());

let file = File::open(entry).expect("Failed to open the YAML file");
let mut reader = std::io::BufReader::new(file);
let mut content = String::new();
Expand All @@ -76,13 +84,12 @@ pub fn load_locales<F: Fn(&str) -> bool>(
});
}

let mut locale_vars = HashMap::<String, String>::new();
translations.iter().for_each(|(locale, trs)| {
let new_vars = extract_vars(locale.as_str(), &trs);
locale_vars.extend(new_vars);
data.translations.extend(new_vars);
});

locale_vars
data
}

pub fn extract_vars(prefix: &str, trs: &Value) -> HashMap<String, String> {
Expand Down
12 changes: 11 additions & 1 deletion tests/intergartion_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,17 @@ mod tests {
use rust_i18n::t;

#[test]
fn test_foo_title() {
fn test_translate() {
assert_eq!(crate::translate("en", "hello"), "Bar - Hello, World!");
}

#[test]
fn test_available_locales() {
assert_eq!(crate::available_locales(), &["de", "en"]);
}

#[test]
fn it_foo_title() {
rust_i18n::set_locale("en");
assert_eq!(foo::t("hello"), "Foo - Hello, World!");
}
Expand Down

0 comments on commit 9d4f3e6

Please sign in to comment.