diff --git a/Cargo.toml b/Cargo.toml index 0b2ccc0..ae674a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "dcli" version = "0.0.3" authors = ["PrivateRookie <996514515@qq.com>"] edition = "2018" -description = "MySQL 数据库连接管理工具" +description = "MySQL 数据库连接管理工具 | MySQL connection manage tool" license-file = "LICENSE" readme = "README.md" diff --git a/README.md b/README.md index 3e2d9df..b0a442c 100644 --- a/README.md +++ b/README.md @@ -165,6 +165,12 @@ AsciiFull AsciiMd Utf8Full Utf8HBorderOnly 但 dcli 属于早期阶段,所以很多功能仍然不完整,如有问题请开 ISSUE。 +### 设置语言 + +默认情况下 dcli 会尝试读取本地语言设置,自动设置语言. 如果这不和预期, 可以试用 + +`dcli style lang` 命令设置语言. 目前支持 `zh-CN` 和 `en-US` 两种语言. + ### 其他命令 dcli 使用 structopt 构建命令工具,当你有疑问时可以运行 `dcli help <子命令>` 查看帮助信息。 diff --git a/src/cli/mod.rs b/src/cli/mod.rs index b097f1d..8e864ad 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -1,5 +1,6 @@ +use crate::fl; use crate::{ - config::{Config, Profile, SslMode, TableStyle}, + config::{Config, Lang, Profile, SslMode, TableStyle}, mysql::connect, utils::read_file, }; @@ -7,7 +8,6 @@ use anyhow::{anyhow, Context, Result}; use bigdecimal::BigDecimal; use chrono::{DateTime, Utc}; use comfy_table::*; -use crate::fl; use sqlx::{ mysql::MySqlRow, types::time::Date, types::time::Time, Column, Row, TypeInfo, Value, ValueRef, }; @@ -163,6 +163,13 @@ pub enum StyleCmd { )] style: TableStyle, }, + #[cfg_attr(feature = "zh-CN", doc = "设置语言")] + #[cfg_attr(feature = "en-US", doc = "set language")] + Lang { + #[cfg_attr(feature = "zh-CN", doc = "语言, 可选 en-US, zh-CN")] + #[cfg_attr(feature = "en-US", doc = "lang, options: en-US, zh-CN")] + name: Option, + }, } impl DCliCommand { @@ -174,6 +181,10 @@ impl DCliCommand { config.table_style = style.clone(); config.save()?; } + StyleCmd::Lang { name } => { + config.lang = name.clone(); + config.save()?; + } }; Ok(()) } diff --git a/src/config.rs b/src/config.rs index 60e92f9..5d85ef1 100644 --- a/src/config.rs +++ b/src/config.rs @@ -20,6 +20,46 @@ use crate::fl; pub struct Config { pub profiles: HashMap, pub table_style: TableStyle, + pub lang: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum Lang { + #[serde(rename = "en-US")] + EnUS, + #[serde(rename = "zh-CN")] + ZhCN, +} + +impl Default for Lang { + fn default() -> Self { + Lang::EnUS + } +} + +impl FromStr for Lang { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let lower = s.to_ascii_lowercase(); + if lower.starts_with("en-us") { + return Ok(Lang::EnUS); + } else if lower.starts_with("zh-cn") { + return Ok(Lang::ZhCN); + } else { + Err(anyhow!(fl!("invalid-value", val = s)))? + } + } +} + +impl ToString for Lang { + fn to_string(&self) -> String { + match self { + Lang::EnUS => "en-US", + Lang::ZhCN => "zh-CN", + } + .to_string() + } } #[derive(Debug, Clone, Serialize, Deserialize, StructOpt)] diff --git a/src/main.rs b/src/main.rs index 98f7705..fe11a2b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use std::sync::Mutex; +use std::sync::{Arc, Mutex}; use anyhow::Result; use cli::DCliCommand; @@ -26,14 +26,13 @@ pub mod config; pub mod mysql; pub mod utils; -pub static LOADER: Lazy> = Lazy::new(|| { +pub static LOADER: Lazy>> = Lazy::new(|| { let translations = Translations {}; - let language_loader: FluentLanguageLoader = fluent_language_loader!(); let requested_languages = DesktopLanguageRequester::requested_languages(); let _result = i18n_embed::select(&language_loader, &translations, &requested_languages); language_loader.set_use_isolating(false); - Mutex::new(language_loader) + Arc::new(Mutex::new(language_loader)) }); #[macro_export] @@ -52,6 +51,9 @@ async fn main() -> Result<()> { let cmd = DCliCommand::from_args(); // init_log(); let mut config = Config::load()?; + if let Some(lang) = &config.lang { + utils::reset_loader(lang) + } cmd.run(&mut config).await?; Ok(()) } diff --git a/src/utils.rs b/src/utils.rs index fff4446..3d00c93 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,5 +1,9 @@ -use crate::fl; +use crate::{config::Lang, fl, Translations}; use anyhow::{Context, Result}; +use i18n_embed::{ + fluent::{fluent_language_loader, FluentLanguageLoader}, + unic_langid::LanguageIdentifier, +}; use std::io::Read; pub fn read_file(path: &str) -> Result { @@ -10,3 +14,15 @@ pub fn read_file(path: &str) -> Result { .with_context(|| fl!("read-file-failed", file = path))?; Ok(content) } + +pub fn reset_loader(lang: &Lang) { + let lang = match lang { + Lang::ZhCN => lang.to_string().parse::().unwrap(), + Lang::EnUS => lang.to_string().parse::().unwrap(), + }; + let translations = Translations {}; + let language_loader: FluentLanguageLoader = fluent_language_loader!(); + let _result = i18n_embed::select(&language_loader, &translations, &vec![lang]); + language_loader.set_use_isolating(false); + *crate::LOADER.lock().unwrap() = language_loader +}