diff --git a/Cargo.lock b/Cargo.lock index e6269f032e915d..d335c128dd2019 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5232,9 +5232,14 @@ dependencies = [ name = "i18n" version = "0.1.0" dependencies = [ + "anyhow", "assets", + "gpui", "rust-i18n", + "schemars", + "serde", "serde_yaml 0.9.34+deprecated", + "settings", "util", ] diff --git a/assets/locales/en.yml b/assets/locales/en.yml index 321cb2f94db37c..e9c6566a824a77 100644 --- a/assets/locales/en.yml +++ b/assets/locales/en.yml @@ -6,3 +6,20 @@ Themes…: "Themes…" Sign in: "Sign In" Sign Out: "Sign Out" Toggle User Menu: "Toggle User Menu" +File: "File" +Edit: "Edit" +New: "New" +New Window: "New Window" +Open…: "Open…" +Open Recent...: "Open Recent..." +Add Folder to Project…: "Add Folder to Project…" +Save: "Save" +Save As…: "Save As…" +Save All: "Save All" +Close Editor: "Close Editor" +Close Window: "Close Window" +Undo: "Undo" +Redo: "Redo" +Cut: "Cut" +Copy: "Copy" +Paste: "Paste" diff --git a/assets/locales/zh-CN.yml b/assets/locales/zh-CN.yml index 9ec853c1547a08..6b52957409b33d 100644 --- a/assets/locales/zh-CN.yml +++ b/assets/locales/zh-CN.yml @@ -6,3 +6,20 @@ Themes…: 主题… Sign in: 登录 Sign Out: 登出 Toggle User Menu: 切换用户菜单 +File: 文件 +Edit: 编辑 +New: 新建 +New Window: "新建窗口" +Open…: 打开… +Open Recent...: 打开最近… +Add Folder to Project…: 添加文件夹到项目… +Save: "保存" +Save As…: "另存为…" +Save All: "全部保存" +Close Editor: "关闭编辑器" +Close Window: "关闭窗口" +Undo: "撤销" +Redo: "重做" +Cut: "剪切" +Copy: "复制" +Paste: "粘贴" diff --git a/crates/gpui/src/platform/mac/platform.rs b/crates/gpui/src/platform/mac/platform.rs index 81aacb336947c9..a8415080eb0ea9 100644 --- a/crates/gpui/src/platform/mac/platform.rs +++ b/crates/gpui/src/platform/mac/platform.rs @@ -207,7 +207,7 @@ impl MacPlatform { for menu_config in menus { let menu = NSMenu::new(nil).autorelease(); - menu.setTitle_(ns_string(menu_config.name)); + menu.setTitle_(ns_string(&menu_config.name)); menu.setDelegate_(delegate); for item_config in menu_config.items { @@ -311,7 +311,7 @@ impl MacPlatform { item = NSMenuItem::alloc(nil) .initWithTitle_action_keyEquivalent_( - ns_string(name), + ns_string(&name), selector, ns_string(key_to_native(&keystroke.key).as_ref()), ) @@ -342,7 +342,7 @@ impl MacPlatform { } else { item = NSMenuItem::alloc(nil) .initWithTitle_action_keyEquivalent_( - ns_string(name), + ns_string(&name), selector, ns_string(""), ) @@ -362,7 +362,7 @@ impl MacPlatform { submenu.addItem_(Self::create_menu_item(item, delegate, actions, keymap)); } item.setSubmenu_(submenu); - item.setTitle_(ns_string(name)); + item.setTitle_(ns_string(&name)); item } } diff --git a/crates/i18n/Cargo.toml b/crates/i18n/Cargo.toml index 237c3026e7a5af..79c88c9aa34a7a 100644 --- a/crates/i18n/Cargo.toml +++ b/crates/i18n/Cargo.toml @@ -10,7 +10,13 @@ license = "GPL-3.0-or-later" workspace = true [dependencies] +anyhow.workspace = true assets.workspace = true rust-i18n.workspace = true -serde_yaml = "0.9" util.workspace = true +gpui.workspace = true +settings.workspace = true +serde.workspace = true +schemars.workspace = true + +serde_yaml = "0.9" diff --git a/crates/i18n/src/lib.rs b/crates/i18n/src/lib.rs index ec2b5839c10af1..e6d2bebc927d66 100644 --- a/crates/i18n/src/lib.rs +++ b/crates/i18n/src/lib.rs @@ -1,6 +1,12 @@ +use ::settings::Settings; +use ::settings::SettingsStore; +use gpui::AppContext; +use settings::I18nSettings; use std::collections::HashMap; use util::ResultExt; +mod settings; + rust_i18n::i18n!(fallback = "en"); type Translations = HashMap>; @@ -23,12 +29,10 @@ impl Backend { .to_string_lossy() .to_string(); - dbg!(f.clone()); if let Some(asset) = assets::Assets::get(&f) { if let Some(data) = serde_yaml::from_slice::>(&asset.data).log_err() { - dbg!("install trs", locale.clone()); trs.insert(locale, data); } } @@ -62,5 +66,20 @@ macro_rules! init { }; } +pub fn init(cx: &mut AppContext) { + settings::I18nSettings::register(cx); + + let previus_locale = I18nSettings::get_global(cx).locale.clone(); + cx.observe_global::(move |cx| { + let locale = I18nSettings::get_global(cx).locale.clone(); + if previus_locale != locale { + dbg!("locale changed to {}", locale); + // TODO: Dispatch Notification to tell use to restart Zed to apply new locale + } + }) + .detach(); +} + +pub use rust_i18n::available_locales; pub use rust_i18n::set_locale; pub use rust_i18n::t; diff --git a/crates/i18n/src/settings.rs b/crates/i18n/src/settings.rs new file mode 100644 index 00000000000000..d04c9b8ca2d219 --- /dev/null +++ b/crates/i18n/src/settings.rs @@ -0,0 +1,53 @@ +use anyhow::Result; +use gpui::AppContext; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use settings::SettingsSources; + +#[derive(Clone)] +pub struct I18nSettings { + /// Set the UI language, default is "en". + pub locale: String, +} + +impl I18nSettings { + /// Switches to the locale and reloads the translations. + pub fn switch_locale(&mut self, locale: &str, _cx: &mut AppContext) -> Option { + let mut new_locale = None; + + if crate::available_locales!().iter().any(|l| *l == locale) { + self.locale = locale.to_string(); + new_locale = Some(locale.to_string()); + } + + new_locale + } +} +/// Settings for rendering text in UI and text buffers. +#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)] +pub struct I18nSettingsContent { + /// The default font size for text in the UI. + #[serde(default)] + pub locale: Option, +} + +impl settings::Settings for I18nSettings { + const KEY: Option<&'static str> = None; + + type FileContent = I18nSettingsContent; + + fn load(sources: SettingsSources, cx: &mut AppContext) -> Result { + let defaults = sources.default; + let mut this = Self { + locale: defaults.locale.clone().unwrap(), + }; + + for value in sources.user.into_iter().chain(sources.release_channel) { + if let Some(locale) = &value.locale { + this.locale = locale.to_string(); + } + } + + Ok(this) + } +} diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 6852f5643e7984..cff4022b2f9891 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -132,7 +132,7 @@ fn init_ui(app_state: Arc, cx: &mut AppContext) -> Result<()> { SystemAppearance::init(cx); load_embedded_fonts(cx); - + i18n::init(cx); theme::init(theme::LoadThemes::All(Box::new(Assets)), cx); app_state.languages.set_theme(cx.theme().clone()); command_palette::init(cx); diff --git a/crates/zed/src/zed/app_menus.rs b/crates/zed/src/zed/app_menus.rs index af0fa58bd87240..fa20754c82e074 100644 --- a/crates/zed/src/zed/app_menus.rs +++ b/crates/zed/src/zed/app_menus.rs @@ -36,10 +36,10 @@ pub fn app_menus() -> Vec> { Menu { name: t!("File"), items: vec![ - MenuItem::action("New", workspace::NewFile), - MenuItem::action("New Window", workspace::NewWindow), + MenuItem::action(t!("New"), workspace::NewFile), + MenuItem::action(t!("New Window"), workspace::NewWindow), MenuItem::separator(), - MenuItem::action("Open…", workspace::Open), + MenuItem::action(t!("Open…"), workspace::Open), MenuItem::action( t!("Open Recent..."), recent_projects::OpenRecent { @@ -47,10 +47,10 @@ pub fn app_menus() -> Vec> { }, ), MenuItem::separator(), - MenuItem::action("Add Folder to Project…", workspace::AddFolderToProject), - MenuItem::action("Save", workspace::Save { save_intent: None }), - MenuItem::action("Save As…", workspace::SaveAs), - MenuItem::action("Save All", workspace::SaveAll { save_intent: None }), + MenuItem::action(t!("Add Folder to Project…"), workspace::AddFolderToProject), + MenuItem::action(t!("Save"), workspace::Save { save_intent: None }), + MenuItem::action(t!("Save As…"), workspace::SaveAs), + MenuItem::action(t!("Save All"), workspace::SaveAll { save_intent: None }), MenuItem::action( t!("Close Editor"), workspace::CloseActiveItem { save_intent: None },