From dcc64cdeae4a825f12a69edc8348e8b149b1f16e Mon Sep 17 00:00:00 2001 From: RustDesk <71636191+rustdesk@users.noreply.github.com> Date: Mon, 22 Jun 2026 14:47:12 +0800 Subject: [PATCH] cjk (#15379) --- src/lang.rs | 74 ++++++++++++++++++++++++++++++++++++++++----- src/ui_interface.rs | 2 ++ 2 files changed, 69 insertions(+), 7 deletions(-) diff --git a/src/lang.rs b/src/lang.rs index 6302c2aed..077c6232a 100644 --- a/src/lang.rs +++ b/src/lang.rs @@ -103,15 +103,29 @@ pub const LANGS: &[(&str, &str)] = &[ ("gu", "ગુજરાતી"), ]; -#[cfg(not(any(target_os = "android", target_os = "ios")))] -pub fn translate(name: String) -> String { - let locale = sys_locale::get_locale().unwrap_or_default(); - translate_locale(name, &locale) +pub(crate) fn cjk_ui_unavailable() -> bool { + cfg!(all( + target_os = "linux", + target_arch = "aarch64", + feature = "flutter" + )) } -pub fn translate_locale(name: String, locale: &str) -> String { +pub(crate) fn is_cjk_lang(lang_or_locale: &str) -> bool { + let lang = lang_or_locale + .split(|c| c == '-' || c == '_') + .next() + .unwrap_or_default() + .to_lowercase(); + matches!(lang.as_str(), "zh" | "ja" | "ko") +} + +fn resolve_lang(saved_lang: &str, locale: &str, cjk_fallback: bool) -> String { let locale = locale.to_lowercase(); - let mut lang = hbb_common::config::LocalConfig::get_option("lang").to_lowercase(); + let mut lang = saved_lang.to_lowercase(); + if cjk_fallback && is_cjk_lang(&lang) { + return "en".to_owned(); + } if lang.is_empty() { // zh_CN on Linux, zh-Hans-CN on mac, zh_CN_#Hans on Android if locale.starts_with("zh") { @@ -131,7 +145,25 @@ pub fn translate_locale(name: String, locale: &str) -> String { .unwrap_or_default() .to_owned(); } - let lang = lang.to_lowercase(); + if cjk_fallback && is_cjk_lang(&lang) { + "en".to_owned() + } else { + lang + } +} + +#[cfg(not(any(target_os = "android", target_os = "ios")))] +pub fn translate(name: String) -> String { + let locale = sys_locale::get_locale().unwrap_or_default(); + translate_locale(name, &locale) +} + +pub fn translate_locale(name: String, locale: &str) -> String { + let lang = resolve_lang( + &hbb_common::config::LocalConfig::get_option("lang"), + locale, + cjk_ui_unavailable(), + ); let m = match lang.as_str() { "fr" => fr::T.deref(), "zh-cn" => cn::T.deref(), @@ -275,4 +307,32 @@ mod test { ("{} times {4} makes {8}".to_string(), Some("2".to_string())) ); } + + #[test] + fn test_resolve_lang_forces_english_for_saved_cjk_when_target_disables_cjk() { + use super::resolve_lang as f; + + assert_eq!(f("zh-cn", "en-US", true), "en"); + assert_eq!(f("zh-tw", "en-US", true), "en"); + assert_eq!(f("ja", "en-US", true), "en"); + assert_eq!(f("ko", "en-US", true), "en"); + } + + #[test] + fn test_resolve_lang_forces_english_for_cjk_locale_when_target_disables_cjk() { + use super::resolve_lang as f; + + assert_eq!(f("", "zh_CN", true), "en"); + assert_eq!(f("", "ja-JP", true), "en"); + assert_eq!(f("", "ko_KR", true), "en"); + } + + #[test] + fn test_resolve_lang_preserves_cjk_when_target_allows_cjk() { + use super::resolve_lang as f; + + assert_eq!(f("zh-cn", "en-US", false), "zh-cn"); + assert_eq!(f("", "zh_TW", false), "zh-tw"); + assert_eq!(f("", "ja-JP", false), "ja"); + } } diff --git a/src/ui_interface.rs b/src/ui_interface.rs index 650972f72..e01595ef7 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -902,8 +902,10 @@ pub fn get_async_job_status() -> String { #[inline] pub fn get_langs() -> String { use serde_json::json; + let hide_cjk = crate::lang::cjk_ui_unavailable(); let mut x: Vec<(&str, String)> = crate::lang::LANGS .iter() + .filter(|a| !hide_cjk || !crate::lang::is_cjk_lang(a.0)) .map(|a| (a.0, format!("{} ({})", a.1, a.0))) .collect(); x.sort_by(|a, b| a.0.cmp(b.0));