From a4c537541ec01cf3ff2ff61450ba7af030b2738b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 12 Apr 2026 19:11:16 +0800 Subject: [PATCH] chore(deps): update rust crate rust-i18n to v4 (#6784) * chore(deps): update rust crate rust-i18n to v4 * fix: migrate rust-i18n to v4 with Cow-first zero-copy approach - Adapt to v4 breaking changes: available_locales!() returns Vec> - Cache locales in LazyLock>> to avoid repeated Vec alloc + sort - Propagate Cow<'static, str> through resolve/current/system_language APIs - Fix t! macro args branch: into_owned() + Cow::Owned for type correctness - Eliminate double resolve in sync_locale (skip redundant set_locale indirection) - Replace .to_string() with .into_owned() / Cow passthrough in updater.rs --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Tunglies <77394545+Tunglies@users.noreply.github.com> --- Cargo.lock | 15 ++++----- crates/clash-verge-i18n/Cargo.toml | 2 +- crates/clash-verge-i18n/src/lib.rs | 49 +++++++++++++++--------------- src-tauri/src/core/updater.rs | 6 ++-- 4 files changed, 35 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d418d1c4f..3d9b64803 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6261,12 +6261,11 @@ dependencies = [ [[package]] name = "rust-i18n" -version = "3.1.5" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda2551fdfaf6cc5ee283adc15e157047b92ae6535cf80f6d4962d05717dc332" +checksum = "21031bf5e6f2c0ae745d831791c403608e99a8bd3776c7e5e5535acd70c3b7ba" dependencies = [ "globwalk", - "once_cell", "regex", "rust-i18n-macro", "rust-i18n-support", @@ -6275,12 +6274,11 @@ dependencies = [ [[package]] name = "rust-i18n-macro" -version = "3.1.5" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22baf7d7f56656d23ebe24f6bb57a5d40d2bce2a5f1c503e692b5b2fa450f965" +checksum = "51fe5295763b358606f7ca26a564e20f4469775a57ec1f09431249a33849ff52" dependencies = [ "glob", - "once_cell", "proc-macro2", "quote", "rust-i18n-support", @@ -6292,9 +6290,9 @@ dependencies = [ [[package]] name = "rust-i18n-support" -version = "3.1.5" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "940ed4f52bba4c0152056d771e563b7133ad9607d4384af016a134b58d758f19" +checksum = "69bcc115c8eea2803aa3d85362e339776f4988a0349f2f475af572e497443f6f" dependencies = [ "arc-swap", "base62", @@ -6302,7 +6300,6 @@ dependencies = [ "itertools 0.11.0", "lazy_static", "normpath", - "once_cell", "proc-macro2", "regex", "serde", diff --git a/crates/clash-verge-i18n/Cargo.toml b/crates/clash-verge-i18n/Cargo.toml index 1823e18c8..c6bf7e7f5 100644 --- a/crates/clash-verge-i18n/Cargo.toml +++ b/crates/clash-verge-i18n/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2024" [dependencies] -rust-i18n = "3.1.5" +rust-i18n = "4.0.0" sys-locale = "0.3.2" [lints] diff --git a/crates/clash-verge-i18n/src/lib.rs b/crates/clash-verge-i18n/src/lib.rs index f837f0f8c..04b04fdfb 100644 --- a/crates/clash-verge-i18n/src/lib.rs +++ b/crates/clash-verge-i18n/src/lib.rs @@ -1,8 +1,12 @@ use rust_i18n::i18n; +use std::borrow::Cow; +use std::sync::LazyLock; const DEFAULT_LANGUAGE: &str = "zh"; i18n!("locales", fallback = "zh"); +static SUPPORTED_LOCALES: LazyLock>> = LazyLock::new(|| rust_i18n::available_locales!()); + #[inline] fn locale_alias(locale: &str) -> Option<&'static str> { match locale { @@ -14,54 +18,51 @@ fn locale_alias(locale: &str) -> Option<&'static str> { } #[inline] -fn resolve_supported_language(language: &str) -> Option<&'static str> { +fn resolve_supported_language(language: &str) -> Option> { if language.is_empty() { return None; } let normalized = language.to_lowercase().replace('_', "-"); let segments: Vec<&str> = normalized.split('-').collect(); - let supported = rust_i18n::available_locales!(); for i in (1..=segments.len()).rev() { let prefix = segments[..i].join("-"); if let Some(alias) = locale_alias(&prefix) - && let Some(&found) = supported.iter().find(|&&l| l.eq_ignore_ascii_case(alias)) + && let Some(found) = SUPPORTED_LOCALES.iter().find(|l| l.eq_ignore_ascii_case(alias)) { - return Some(found); + return Some(found.clone()); } - if let Some(&found) = supported.iter().find(|&&l| l.eq_ignore_ascii_case(&prefix)) { - return Some(found); + if let Some(found) = SUPPORTED_LOCALES.iter().find(|l| l.eq_ignore_ascii_case(&prefix)) { + return Some(found.clone()); } } None } #[inline] -fn current_language(language: Option<&str>) -> &str { +fn current_language(language: Option<&str>) -> Cow<'static, str> { language - .as_ref() .filter(|lang| !lang.is_empty()) - .and_then(|lang| resolve_supported_language(lang)) + .and_then(resolve_supported_language) .unwrap_or_else(system_language) } #[inline] -pub fn system_language() -> &'static str { +pub fn system_language() -> Cow<'static, str> { sys_locale::get_locale() .as_deref() .and_then(resolve_supported_language) - .unwrap_or(DEFAULT_LANGUAGE) + .unwrap_or(Cow::Borrowed(DEFAULT_LANGUAGE)) } #[inline] pub fn sync_locale(language: Option<&str>) { - let language = current_language(language); - set_locale(language); + rust_i18n::set_locale(¤t_language(language)); } #[inline] pub fn set_locale(language: &str) { - let lang = resolve_supported_language(language).unwrap_or(DEFAULT_LANGUAGE); - rust_i18n::set_locale(lang); + let lang = resolve_supported_language(language).unwrap_or(Cow::Borrowed(DEFAULT_LANGUAGE)); + rust_i18n::set_locale(&lang); } #[inline] @@ -76,11 +77,11 @@ macro_rules! t { }; ($key:expr, $($arg_name:ident = $arg_value:expr),*) => { { - let mut _text = $crate::translate(&$key); + let mut _text = $crate::translate(&$key).into_owned(); $( _text = _text.replace(&format!("{{{}}}", stringify!($arg_name)), &$arg_value); )* - _text + ::std::borrow::Cow::<'static, str>::Owned(_text) } }; } @@ -91,13 +92,13 @@ mod test { #[test] fn test_resolve_supported_language() { - assert_eq!(resolve_supported_language("en"), Some("en")); - assert_eq!(resolve_supported_language("en-US"), Some("en")); - assert_eq!(resolve_supported_language("zh"), Some("zh")); - assert_eq!(resolve_supported_language("zh-CN"), Some("zh")); - assert_eq!(resolve_supported_language("zh-Hant"), Some("zhtw")); - assert_eq!(resolve_supported_language("jp"), Some("jp")); - assert_eq!(resolve_supported_language("ja-JP"), Some("jp")); + assert_eq!(resolve_supported_language("en").as_deref(), Some("en")); + assert_eq!(resolve_supported_language("en-US").as_deref(), Some("en")); + assert_eq!(resolve_supported_language("zh").as_deref(), Some("zh")); + assert_eq!(resolve_supported_language("zh-CN").as_deref(), Some("zh")); + assert_eq!(resolve_supported_language("zh-Hant").as_deref(), Some("zhtw")); + assert_eq!(resolve_supported_language("jp").as_deref(), Some("jp")); + assert_eq!(resolve_supported_language("ja-JP").as_deref(), Some("jp")); assert_eq!(resolve_supported_language("fr"), None); } } diff --git a/src-tauri/src/core/updater.rs b/src-tauri/src/core/updater.rs index aa39e1ab2..81da3cc8f 100644 --- a/src-tauri/src/core/updater.rs +++ b/src-tauri/src/core/updater.rs @@ -294,10 +294,10 @@ impl SilentUpdater { async fn ask_user_to_install(app_handle: &tauri::AppHandle, version: &str) -> bool { use tauri_plugin_dialog::{DialogExt as _, MessageDialogButtons, MessageDialogKind}; - let title = clash_verge_i18n::t!("notifications.updateReady.title").to_string(); + let title = clash_verge_i18n::t!("notifications.updateReady.title"); let body = clash_verge_i18n::t!("notifications.updateReady.body").replace("{version}", version); - let install_now = clash_verge_i18n::t!("notifications.updateReady.installNow").to_string(); - let later = clash_verge_i18n::t!("notifications.updateReady.later").to_string(); + let install_now = clash_verge_i18n::t!("notifications.updateReady.installNow").into_owned(); + let later = clash_verge_i18n::t!("notifications.updateReady.later").into_owned(); let (tx, rx) = tokio::sync::oneshot::channel();