diff --git a/Cargo.lock b/Cargo.lock index 19468c2..0b727dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -472,6 +472,17 @@ dependencies = [ "subtle", ] +[[package]] +name = "displaydoc" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + [[package]] name = "domain" version = "0.1.0" @@ -597,6 +608,50 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" +[[package]] +name = "fluent" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb74634707bebd0ce645a981148e8fb8c7bccd4c33c652aeffd28bf2f96d555a" +dependencies = [ + "fluent-bundle", + "unic-langid", +] + +[[package]] +name = "fluent-bundle" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe0a21ee80050c678013f82edf4b705fe2f26f1f9877593d13198612503f493" +dependencies = [ + "fluent-langneg", + "fluent-syntax", + "intl-memoizer", + "intl_pluralrules", + "rustc-hash", + "self_cell 0.10.3", + "smallvec", + "unic-langid", +] + +[[package]] +name = "fluent-langneg" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4ad0989667548f06ccd0e306ed56b61bd4d35458d54df5ec7587c0e8ed5e94" +dependencies = [ + "unic-langid", +] + +[[package]] +name = "fluent-syntax" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a530c4694a6a8d528794ee9bbd8ba0122e779629ac908d15ad5a7ae7763a33d" +dependencies = [ + "thiserror", +] + [[package]] name = "flume" version = "0.11.0" @@ -940,6 +995,15 @@ dependencies = [ "tracing", ] +[[package]] +name = "i18n" +version = "0.1.0" +dependencies = [ + "fluent", + "lazy_static", + "unic-langid", +] + [[package]] name = "iana-time-zone" version = "0.1.60" @@ -989,6 +1053,25 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "intl-memoizer" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe22e020fce238ae18a6d5d8c502ee76a52a6e880d99477657e6acc30ec57bda" +dependencies = [ + "type-map", + "unic-langid", +] + +[[package]] +name = "intl_pluralrules" +version = "7.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "078ea7b7c29a2b4df841a7f6ac8775ff6074020c6776d48491ce2268e068f972" +dependencies = [ + "unic-langid", +] + [[package]] name = "ipnet" version = "2.9.0" @@ -1742,6 +1825,12 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc_version" version = "0.4.0" @@ -1870,6 +1959,21 @@ dependencies = [ "libc", ] +[[package]] +name = "self_cell" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14e4d63b804dc0c7ec4a1e52bcb63f02c7ac94476755aa579edac21e01f915d" +dependencies = [ + "self_cell 1.0.4", +] + +[[package]] +name = "self_cell" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" + [[package]] name = "semver" version = "1.0.22" @@ -1946,6 +2050,7 @@ dependencies = [ "domain", "error-stack", "futures-executor", + "i18n", "lazy_static", "library", "moka", @@ -2437,6 +2542,15 @@ dependencies = [ "time-core", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -2691,6 +2805,15 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "type-map" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deb68604048ff8fa93347f02441e4487594adc20bb8a084f9e564d2b827a0a9f" +dependencies = [ + "rustc-hash", +] + [[package]] name = "typenum" version = "1.17.0" @@ -2708,6 +2831,24 @@ dependencies = [ "web-time", ] +[[package]] +name = "unic-langid" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23dd9d1e72a73b25e07123a80776aae3e7b0ec461ef94f9151eed6ec88005a44" +dependencies = [ + "unic-langid-impl", +] + +[[package]] +name = "unic-langid-impl" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a5422c1f65949306c99240b81de9f3f15929f5a8bfe05bb44b034cc8bf593e5" +dependencies = [ + "tinystr", +] + [[package]] name = "unicode-bidi" version = "0.3.15" diff --git a/Cargo.toml b/Cargo.toml index 3183dd9..a75cc90 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [workspace] -members = [".", "api", "domain","library", "service"] +members = [".", "api", "domain", "i18n","library", "service"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -42,4 +42,6 @@ futures-executor = "0.3" error-stack = "0.4" jsonwebtoken = "9.3.0" lazy_static = "1.4.0" -mimalloc = "0.1.42" \ No newline at end of file +mimalloc = "0.1.42" +fluent = "0.16.1" +unic-langid = "0.9.5" \ No newline at end of file diff --git a/i18n/Cargo.toml b/i18n/Cargo.toml new file mode 100644 index 0000000..2bbbc73 --- /dev/null +++ b/i18n/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "i18n" +version = "0.1.0" +edition = "2021" + +[dependencies] +fluent = { workspace = true } +unic-langid = { workspace = true, feature = ["unic-langid-macros", "macros"]} +lazy_static = { workspace = true } \ No newline at end of file diff --git a/i18n/src/en_us.rs b/i18n/src/en_us.rs new file mode 100644 index 0000000..b823508 --- /dev/null +++ b/i18n/src/en_us.rs @@ -0,0 +1,3 @@ +pub const MESSAGE: &str = r#" +hello = "hello {$name}" +"#; \ No newline at end of file diff --git a/i18n/src/lib.rs b/i18n/src/lib.rs new file mode 100644 index 0000000..0ba9225 --- /dev/null +++ b/i18n/src/lib.rs @@ -0,0 +1,35 @@ +use std::{cell::RefCell, collections::HashMap, sync::{Arc, Mutex, OnceLock, RwLock}}; + +use fluent::{FluentBundle, FluentResource}; + +use lazy_static::lazy_static; + +pub mod en_us; +pub mod zh_cn; + +// static I18N: OnceLock>>> = OnceLock::new(); + +lazy_static!{ + pub static ref I18N_MAP: RwLock>>> = { + init_i18n() + }; +} + +pub fn init_i18n() -> RwLock>>> { + // 英文资源初始化 + let langid_en_us = "en-US".parse().expect("初始化英文标识失败"); + let en_us_res = FluentResource::try_new(en_us::MESSAGE.to_string()).expect("初始化英文资源失败"); + let mut en_us_bundle = FluentBundle::new(vec![langid_en_us]); + en_us_bundle.add_resource(en_us_res).expect("添加英文资源失败"); + + // 简体中文资源初始化 + let langid_zh_cn = "en-US".parse().expect("初始化简体中文标识失败"); + let zh_cn_res = FluentResource::try_new(en_us::MESSAGE.to_string()).expect("初始化简体中文资源失败"); + let mut zj_cn_bundle = FluentBundle::new(vec![langid_zh_cn]); + zj_cn_bundle.add_resource(zh_cn_res).expect("添加简体中文资源失败"); + + let mut map = HashMap::new(); + map.insert("en-US", Arc::new(en_us_bundle)); + map.insert("zh-CN", Arc::new(zj_cn_bundle)); + RwLock::new(map) +} \ No newline at end of file diff --git a/i18n/src/zh_cn.rs b/i18n/src/zh_cn.rs new file mode 100644 index 0000000..5c047fe --- /dev/null +++ b/i18n/src/zh_cn.rs @@ -0,0 +1,3 @@ +pub const MESSAGE: &str = r#" +hello = "你好 {$name}" +"#; \ No newline at end of file diff --git a/service/Cargo.toml b/service/Cargo.toml index 98d4e99..34d6d83 100644 --- a/service/Cargo.toml +++ b/service/Cargo.toml @@ -16,4 +16,5 @@ moka = { workspace = true, features = ["future", "logging"] } lazy_static = { workspace = true } library = { path = "../library" } -domain = { path = "../domain" } \ No newline at end of file +domain = { path = "../domain" } +i18n = { path = "../i18n" } \ No newline at end of file