77//! events so the existing `useOnBroadcast` subscribers in the renderer
88//! fire unchanged.
99
10- use tauri:: menu:: {
11- Menu , MenuItemBuilder , PredefinedMenuItem , Submenu , SubmenuBuilder ,
12- } ;
10+ use tauri:: menu:: { Menu , MenuItemBuilder , PredefinedMenuItem , Submenu , SubmenuBuilder } ;
1311use tauri:: { AppHandle , Runtime } ;
1412
13+ use crate :: i18n:: { menu_labels, MenuLabels } ;
14+
1515// ---- menu item ids ---------------------------------------------------------
1616// Every custom item gets a stable id routed through the global
1717// `on_menu_event` handler in `lib.rs`.
@@ -30,24 +30,37 @@ pub const HOMEPAGE_URL: &str = "https://switchhosts.vercel.app/home/";
3030/// Build and install the application menu. Called once from
3131/// `lib.rs::run`'s setup hook.
3232pub fn install < R : Runtime > ( app : & AppHandle < R > ) -> Result < ( ) , tauri:: Error > {
33+ refresh ( app)
34+ }
35+
36+ /// Rebuild and reinstall the application menu after language changes.
37+ pub fn refresh < R : Runtime > ( app : & AppHandle < R > ) -> Result < ( ) , tauri:: Error > {
3338 let menu = build_menu ( app) ?;
3439 app. set_menu ( menu) ?;
3540 Ok ( ( ) )
3641}
3742
3843fn build_menu < R : Runtime > ( app : & AppHandle < R > ) -> Result < Menu < R > , tauri:: Error > {
39- let file_menu = build_file_menu ( app) ?;
40- let edit_menu = build_edit_menu ( app) ?;
41- let view_menu = build_view_menu ( app) ?;
42- let window_menu = build_window_menu ( app) ?;
43- let help_menu = build_help_menu ( app) ?;
44+ let labels = menu_labels ( app) ;
45+ let file_menu = build_file_menu ( app, & labels) ?;
46+ let edit_menu = build_edit_menu ( app, & labels) ?;
47+ let view_menu = build_view_menu ( app, & labels) ?;
48+ let window_menu = build_window_menu ( app, & labels) ?;
49+ let help_menu = build_help_menu ( app, & labels) ?;
4450
4551 #[ cfg( target_os = "macos" ) ]
4652 {
47- let app_menu = build_macos_app_menu ( app) ?;
53+ let app_menu = build_macos_app_menu ( app, & labels ) ?;
4854 Menu :: with_items (
4955 app,
50- & [ & app_menu, & file_menu, & edit_menu, & view_menu, & window_menu, & help_menu] ,
56+ & [
57+ & app_menu,
58+ & file_menu,
59+ & edit_menu,
60+ & view_menu,
61+ & window_menu,
62+ & help_menu,
63+ ] ,
5164 )
5265 }
5366 #[ cfg( not( target_os = "macos" ) ) ]
@@ -62,80 +75,96 @@ fn build_menu<R: Runtime>(app: &AppHandle<R>) -> Result<Menu<R>, tauri::Error> {
6275// ---- macOS app submenu (About, Hide, Quit) --------------------------------
6376
6477#[ cfg( target_os = "macos" ) ]
65- fn build_macos_app_menu < R : Runtime > ( app : & AppHandle < R > ) -> Result < Submenu < R > , tauri:: Error > {
66- let about = MenuItemBuilder :: with_id ( MENU_ID_ABOUT , "About SwitchHosts" ) . build ( app) ?;
78+ fn build_macos_app_menu < R : Runtime > (
79+ app : & AppHandle < R > ,
80+ labels : & MenuLabels ,
81+ ) -> Result < Submenu < R > , tauri:: Error > {
82+ let about = MenuItemBuilder :: with_id ( MENU_ID_ABOUT , labels. about_app ) . build ( app) ?;
83+ let services = PredefinedMenuItem :: services ( app, Some ( labels. services ) ) ?;
84+ let hide = PredefinedMenuItem :: hide ( app, Some ( labels. hide_app ) ) ?;
85+ let hide_others = PredefinedMenuItem :: hide_others ( app, Some ( labels. hide_others ) ) ?;
86+ let show_all = PredefinedMenuItem :: show_all ( app, Some ( labels. show_all ) ) ?;
87+ let quit = PredefinedMenuItem :: quit ( app, Some ( labels. quit_app ) ) ?;
88+
6789 SubmenuBuilder :: new ( app, "SwitchHosts" )
6890 . item ( & about)
6991 . separator ( )
70- . services ( )
92+ . item ( & services )
7193 . separator ( )
72- . hide ( )
73- . hide_others ( )
74- . show_all ( )
94+ . item ( & hide )
95+ . item ( & hide_others )
96+ . item ( & show_all )
7597 . separator ( )
76- . quit ( )
98+ . item ( & quit )
7799 . build ( )
78100}
79101
80102// ---- File ------------------------------------------------------------------
81103
82- fn build_file_menu < R : Runtime > ( app : & AppHandle < R > ) -> Result < Submenu < R > , tauri:: Error > {
83- let new_item = MenuItemBuilder :: with_id ( MENU_ID_NEW , "New" )
104+ fn build_file_menu < R : Runtime > (
105+ app : & AppHandle < R > ,
106+ labels : & MenuLabels ,
107+ ) -> Result < Submenu < R > , tauri:: Error > {
108+ let new_item = MenuItemBuilder :: with_id ( MENU_ID_NEW , labels. new )
84109 . accelerator ( "CmdOrCtrl+N" )
85110 . build ( app) ?;
86- let prefs = MenuItemBuilder :: with_id ( MENU_ID_PREFERENCES , "Preferences \u{2026} " )
111+ let prefs = MenuItemBuilder :: with_id ( MENU_ID_PREFERENCES , labels . preferences )
87112 . accelerator ( "CmdOrCtrl+," )
88113 . build ( app) ?;
89114
90- let mut builder = SubmenuBuilder :: new ( app, "File" ) ;
115+ let mut builder = SubmenuBuilder :: new ( app, labels . file ) ;
91116
92117 // On Windows/Linux put About at the top of File (Electron does this)
93118 #[ cfg( not( target_os = "macos" ) ) ]
94119 {
95- let about = MenuItemBuilder :: with_id ( MENU_ID_ABOUT , "About SwitchHosts" ) . build ( app) ?;
120+ let about = MenuItemBuilder :: with_id ( MENU_ID_ABOUT , labels . about_app ) . build ( app) ?;
96121 builder = builder. item ( & about) . separator ( ) ;
97122 }
98123
99- builder = builder
100- . item ( & new_item)
101- . separator ( )
102- . item ( & prefs) ;
124+ builder = builder. item ( & new_item) . separator ( ) . item ( & prefs) ;
103125
104126 #[ cfg( not( target_os = "macos" ) ) ]
105127 {
106- builder = builder
107- . separator ( )
108- . item ( & PredefinedMenuItem :: quit ( app, None ) ?) ;
128+ let quit = PredefinedMenuItem :: quit ( app, Some ( labels. quit ) ) ?;
129+ builder = builder. separator ( ) . item ( & quit) ;
109130 }
110131
111132 #[ cfg( target_os = "macos" ) ]
112133 {
113- builder = builder
114- . separator ( )
115- . item ( & PredefinedMenuItem :: close_window ( app, None ) ?) ;
134+ let close_window = PredefinedMenuItem :: close_window ( app, Some ( labels. close_window ) ) ?;
135+ builder = builder. separator ( ) . item ( & close_window) ;
116136 }
117137
118138 builder. build ( )
119139}
120140
121141// ---- Edit ------------------------------------------------------------------
122142
123- fn build_edit_menu < R : Runtime > ( app : & AppHandle < R > ) -> Result < Submenu < R > , tauri:: Error > {
124- let comment = MenuItemBuilder :: with_id ( MENU_ID_COMMENT , "Comment / Uncomment" )
143+ fn build_edit_menu < R : Runtime > (
144+ app : & AppHandle < R > ,
145+ labels : & MenuLabels ,
146+ ) -> Result < Submenu < R > , tauri:: Error > {
147+ let comment = MenuItemBuilder :: with_id ( MENU_ID_COMMENT , labels. comment_uncomment )
125148 . accelerator ( "CmdOrCtrl+/" )
126149 . build ( app) ?;
127- let find = MenuItemBuilder :: with_id ( MENU_ID_FIND , "Find \u{2026} " )
150+ let find = MenuItemBuilder :: with_id ( MENU_ID_FIND , labels . find )
128151 . accelerator ( "CmdOrCtrl+F" )
129152 . build ( app) ?;
130-
131- SubmenuBuilder :: new ( app, "Edit" )
132- . undo ( )
133- . redo ( )
153+ let undo = PredefinedMenuItem :: undo ( app, Some ( labels. undo ) ) ?;
154+ let redo = PredefinedMenuItem :: redo ( app, Some ( labels. redo ) ) ?;
155+ let cut = PredefinedMenuItem :: cut ( app, Some ( labels. cut ) ) ?;
156+ let copy = PredefinedMenuItem :: copy ( app, Some ( labels. copy ) ) ?;
157+ let paste = PredefinedMenuItem :: paste ( app, Some ( labels. paste ) ) ?;
158+ let select_all = PredefinedMenuItem :: select_all ( app, Some ( labels. select_all ) ) ?;
159+
160+ SubmenuBuilder :: new ( app, labels. edit )
161+ . item ( & undo)
162+ . item ( & redo)
134163 . separator ( )
135- . cut ( )
136- . copy ( )
137- . paste ( )
138- . select_all ( )
164+ . item ( & cut )
165+ . item ( & copy )
166+ . item ( & paste )
167+ . item ( & select_all )
139168 . separator ( )
140169 . item ( & comment)
141170 . item ( & find)
@@ -144,45 +173,53 @@ fn build_edit_menu<R: Runtime>(app: &AppHandle<R>) -> Result<Submenu<R>, tauri::
144173
145174// ---- View ------------------------------------------------------------------
146175
147- fn build_view_menu < R : Runtime > ( app : & AppHandle < R > ) -> Result < Submenu < R > , tauri:: Error > {
148- let builder = SubmenuBuilder :: new ( app, "View" ) ;
176+ fn build_view_menu < R : Runtime > (
177+ app : & AppHandle < R > ,
178+ labels : & MenuLabels ,
179+ ) -> Result < Submenu < R > , tauri:: Error > {
180+ let builder = SubmenuBuilder :: new ( app, labels. view ) ;
149181
150182 #[ cfg( target_os = "macos" ) ]
151- let builder = builder
152- . item ( & PredefinedMenuItem :: fullscreen ( app, None ) ? )
153- . separator ( ) ;
154-
155- builder
156- . item ( & PredefinedMenuItem :: minimize ( app, None ) ? )
157- . item ( & PredefinedMenuItem :: maximize ( app, None ) ? )
158- . build ( )
183+ let builder = {
184+ let fullscreen = PredefinedMenuItem :: fullscreen ( app, Some ( labels . fullscreen ) ) ? ;
185+ builder . item ( & fullscreen ) . separator ( )
186+ } ;
187+
188+ let minimize = PredefinedMenuItem :: minimize ( app, Some ( labels . minimize ) ) ? ;
189+ let maximize = PredefinedMenuItem :: maximize ( app, Some ( labels . maximize ) ) ? ;
190+ builder . item ( & minimize ) . item ( & maximize ) . build ( )
159191}
160192
161193// ---- Window ----------------------------------------------------------------
162194
163- fn build_window_menu < R : Runtime > ( app : & AppHandle < R > ) -> Result < Submenu < R > , tauri:: Error > {
164- let mut builder = SubmenuBuilder :: new ( app, "Window" ) ;
165- builder = builder. minimize ( ) . close_window ( ) ;
195+ fn build_window_menu < R : Runtime > (
196+ app : & AppHandle < R > ,
197+ labels : & MenuLabels ,
198+ ) -> Result < Submenu < R > , tauri:: Error > {
199+ let minimize = PredefinedMenuItem :: minimize ( app, Some ( labels. minimize ) ) ?;
200+ let close_window = PredefinedMenuItem :: close_window ( app, Some ( labels. close_window ) ) ?;
201+ let mut builder = SubmenuBuilder :: new ( app, labels. window ) ;
202+ builder = builder. item ( & minimize) . item ( & close_window) ;
166203
167204 #[ cfg( target_os = "macos" ) ]
168205 {
169- builder = builder
170- . separator ( )
171- . item ( & PredefinedMenuItem :: maximize ( app, None ) ?) ;
206+ let maximize = PredefinedMenuItem :: maximize ( app, Some ( labels. maximize ) ) ?;
207+ builder = builder. separator ( ) . item ( & maximize) ;
172208 }
173209
174210 builder. build ( )
175211}
176212
177213// ---- Help ------------------------------------------------------------------
178214
179- fn build_help_menu < R : Runtime > ( app : & AppHandle < R > ) -> Result < Submenu < R > , tauri:: Error > {
180- let feedback = MenuItemBuilder :: with_id ( MENU_ID_FEEDBACK , "Feedback" )
181- . build ( app) ?;
182- let homepage = MenuItemBuilder :: with_id ( MENU_ID_HOMEPAGE , "Homepage" )
183- . build ( app) ?;
215+ fn build_help_menu < R : Runtime > (
216+ app : & AppHandle < R > ,
217+ labels : & MenuLabels ,
218+ ) -> Result < Submenu < R > , tauri:: Error > {
219+ let feedback = MenuItemBuilder :: with_id ( MENU_ID_FEEDBACK , labels. feedback ) . build ( app) ?;
220+ let homepage = MenuItemBuilder :: with_id ( MENU_ID_HOMEPAGE , labels. homepage ) . build ( app) ?;
184221
185- SubmenuBuilder :: new ( app, "Help" )
222+ SubmenuBuilder :: new ( app, labels . help )
186223 . item ( & feedback)
187224 . item ( & homepage)
188225 . build ( )
0 commit comments