完善i18n,增加csv管理多语言

This commit is contained in:
李运家 2024-09-26 15:35:59 +08:00
parent af201086a7
commit f7dca5ba30
8 changed files with 65 additions and 69 deletions

22
Cargo.lock generated
View File

@ -407,6 +407,27 @@ dependencies = [
"typenum",
]
[[package]]
name = "csv"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe"
dependencies = [
"csv-core",
"itoa",
"ryu",
"serde",
]
[[package]]
name = "csv-core"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70"
dependencies = [
"memchr",
]
[[package]]
name = "darling"
version = "0.20.10"
@ -969,6 +990,7 @@ dependencies = [
name = "i18n"
version = "0.1.0"
dependencies = [
"csv",
"lazy_static",
"tracing",
]

View File

@ -53,3 +53,4 @@ syn = "2.0.77"
quote = "1.0.37"
hyper = "1.4.1"
tower = "0.5.1"
csv = "1.3.0"

14
i18n.csv Normal file
View File

@ -0,0 +1,14 @@
id,en-US,zh-CN
SERVER_INTERNAL_ERROR,Internal server error,系统内部错误
HELLO,hello {},你好 {}
ACCOUNT_DISABLED,account is disabled,账户已禁用
ACCOUNT_NO_PERMISSION,account has no permission,账户无权限
INCORRECT_USERNAME_OR_PASSWORD,incorrect username or password,用户名或密码错误
INVALID_TOKEN,invalid token,无效令牌
VALIDATE_FEEDBACK_CONTENT_REQUIRED,feedback content is required,反馈内容不能为空
VALIDATE_ACCOUNT_NAME_REQUIRED,username is required,"用户名称不能为空"
VALIDATE_ACCOUNT_PASSWORD_REQUIRED,password is required,密码不能为空
VALIDATE_ACCOUNT_ID_TOKEN_REQUIRED,ID Token is required,用户ID Token不能为空
VALIDATE_ACCOUNT_LANG_TAG_REQUIRED,lang tag is required,用户语言标识不能为空
VALIDATE_PAGEABLE_PAGE_REQUIRED,invalid page number,页码无效
VALIDATE_PAGEABLE_PAGE_SIZE_REQUIRED,invalid quantity per page,每页数量无效
1 id en-US zh-CN
2 SERVER_INTERNAL_ERROR Internal server error 系统内部错误
3 HELLO hello {} 你好 {}
4 ACCOUNT_DISABLED account is disabled 账户已禁用
5 ACCOUNT_NO_PERMISSION account has no permission 账户无权限
6 INCORRECT_USERNAME_OR_PASSWORD incorrect username or password 用户名或密码错误
7 INVALID_TOKEN invalid token 无效令牌
8 VALIDATE_FEEDBACK_CONTENT_REQUIRED feedback content is required 反馈内容不能为空
9 VALIDATE_ACCOUNT_NAME_REQUIRED username is required 用户名称不能为空
10 VALIDATE_ACCOUNT_PASSWORD_REQUIRED password is required 密码不能为空
11 VALIDATE_ACCOUNT_ID_TOKEN_REQUIRED ID Token is required 用户ID Token不能为空
12 VALIDATE_ACCOUNT_LANG_TAG_REQUIRED lang tag is required 用户语言标识不能为空
13 VALIDATE_PAGEABLE_PAGE_REQUIRED invalid page number 页码无效
14 VALIDATE_PAGEABLE_PAGE_SIZE_REQUIRED invalid quantity per page 每页数量无效

View File

@ -6,3 +6,4 @@ edition = "2021"
[dependencies]
lazy_static = { workspace = true }
tracing = { workspace = true }
csv = { workspace = true }

View File

@ -1,31 +0,0 @@
use std::collections::HashMap;
use lazy_static::lazy_static;
use crate::message_ids::{
SERVER_INTERNAL_ERROR, ACCOUNT_DISABLED, ACCOUNT_NO_PERMISSION, HELLO, INCORRECT_USERNAME_OR_PASSWORD, INVALID_TOKEN, VALIDATE_ACCOUNT_ID_TOKEN_REQUIRED, VALIDATE_ACCOUNT_LANG_TAG_REQUIRED, VALIDATE_ACCOUNT_NAME_REQUIRED, VALIDATE_ACCOUNT_PASSWORD_REQUIRED, VALIDATE_FEEDBACK_CONTENT_REQUIRED, VALIDATE_PAGEABLE_PAGE_REQUIRED, VALIDATE_PAGEABLE_PAGE_SIZE_REQUIRED
};
pub const LANGUAGE_ID: &str = "en-US";
lazy_static! {
pub static ref MESSAGE: HashMap<&'static str, &'static str> = {
let mut map = HashMap::new();
map.insert(SERVER_INTERNAL_ERROR, "Internal server error");
map.insert(HELLO, "hello {}");
map.insert(ACCOUNT_DISABLED, "account is disabled");
map.insert(ACCOUNT_NO_PERMISSION, "account has no permission");
map.insert(INCORRECT_USERNAME_OR_PASSWORD,"incorrect username or password");
map.insert(INVALID_TOKEN, "invalid token");
map.insert(VALIDATE_FEEDBACK_CONTENT_REQUIRED, "feedback content is required");
map.insert(VALIDATE_ACCOUNT_NAME_REQUIRED, "username is required");
map.insert(VALIDATE_ACCOUNT_PASSWORD_REQUIRED, "password is required");
map.insert(VALIDATE_ACCOUNT_ID_TOKEN_REQUIRED, "ID Token is required");
map.insert(VALIDATE_ACCOUNT_LANG_TAG_REQUIRED, "lang tag is required");
map.insert(VALIDATE_PAGEABLE_PAGE_REQUIRED, "invalid page number");
map.insert(VALIDATE_PAGEABLE_PAGE_SIZE_REQUIRED, "invalid quantity per page");
map
};
}

View File

@ -3,15 +3,35 @@ extern crate self as i18n;
use std::{collections::HashMap, sync::OnceLock};
pub mod message_ids;
pub mod en_us;
pub mod zh_cn;
const I18N_FILE: &str = "i18n.csv";
static I18N: OnceLock<HashMap<&'static str, HashMap<&'static str, &'static str>>> = OnceLock::new();
fn init_i18n() -> HashMap<&'static str, HashMap<&'static str, &'static str>> {
let mut i18n_map = HashMap::new();
i18n_map.insert(en_us::LANGUAGE_ID, en_us::MESSAGE.clone());
i18n_map.insert(zh_cn::LANGUAGE_ID, zh_cn::MESSAGE.clone());
let mut i18n_id_map = HashMap::new();
let mut rdr = csv::Reader::from_path(I18N_FILE).expect("读取多语言文件失败");
let headers = rdr.headers().expect("解析多语言文件失败");
let header_length = headers.len();
for i in 1..header_length {
let lang_id = headers.get(i).unwrap();
i18n_id_map.insert(i, lang_id.to_string());
}
for result in rdr.deserialize() {
let record: Vec<String> = result.expect("解析多语言文件失败");
let column_length = record.len();
let message_id: &'static str = Box::leak(Box::new(record[0].clone()));
for i in 1..column_length {
let lang_id: &'static str = Box::leak(Box::new(i18n_id_map.get(&i).unwrap().clone()));
let message: &'static str = Box::leak(Box::new(record[i].clone()));
i18n_map
.entry(lang_id)
.or_insert_with(HashMap::new)
.insert(message_id, message);
}
}
tracing::info!("多语言文件解析完成:{:?}", i18n_map);
i18n_map
}

View File

@ -1,31 +0,0 @@
use std::collections::HashMap;
use lazy_static::lazy_static;
use crate::message_ids::{
SERVER_INTERNAL_ERROR, ACCOUNT_DISABLED, ACCOUNT_NO_PERMISSION, HELLO, INCORRECT_USERNAME_OR_PASSWORD, INVALID_TOKEN, VALIDATE_ACCOUNT_ID_TOKEN_REQUIRED, VALIDATE_ACCOUNT_LANG_TAG_REQUIRED, VALIDATE_ACCOUNT_NAME_REQUIRED, VALIDATE_ACCOUNT_PASSWORD_REQUIRED, VALIDATE_FEEDBACK_CONTENT_REQUIRED, VALIDATE_PAGEABLE_PAGE_REQUIRED, VALIDATE_PAGEABLE_PAGE_SIZE_REQUIRED
};
pub const LANGUAGE_ID: &str = "zh-CN";
lazy_static! {
pub static ref MESSAGE: HashMap<&'static str, &'static str> = {
let mut map = HashMap::new();
map.insert(SERVER_INTERNAL_ERROR, "系统内部错误");
map.insert(HELLO, "你好 {}");
map.insert(ACCOUNT_DISABLED, "账户已禁用");
map.insert(ACCOUNT_NO_PERMISSION, "账户无权限");
map.insert(INCORRECT_USERNAME_OR_PASSWORD, "用户名或密码错误");
map.insert(INVALID_TOKEN, "无效令牌");
map.insert(VALIDATE_FEEDBACK_CONTENT_REQUIRED, "反馈内容不能为空");
map.insert(VALIDATE_ACCOUNT_NAME_REQUIRED, "用户名称不能为空");
map.insert(VALIDATE_ACCOUNT_PASSWORD_REQUIRED, "密码不能为空");
map.insert(VALIDATE_ACCOUNT_ID_TOKEN_REQUIRED, "用户ID Token不能为空");
map.insert(VALIDATE_ACCOUNT_LANG_TAG_REQUIRED, "用户语言标识不能为空");
map.insert(VALIDATE_PAGEABLE_PAGE_REQUIRED, "页码无效");
map.insert(VALIDATE_PAGEABLE_PAGE_SIZE_REQUIRED, "每页数量无效");
map
};
}

View File

@ -2,7 +2,7 @@ use tokio_cron_scheduler::{Job, JobSchedulerError};
pub fn get_task(name: String, cron: String) -> Result<Job, JobSchedulerError> {
tracing::info!("添加定时任务: {}", name);
Job::new_async(cron.as_str(), |_uuid, _l| {
Job::new_async(cron.as_str(), move |_uuid, _l| {
Box::pin(async move {
tracing::info!("定时任务执行中");
})