55from PIL import Image
66import webbrowser
77import logging
8+ from tkinter import messagebox
89import os
910import sys
1011
@@ -101,43 +102,48 @@ def check_updates_silently(self):
101102 threading .Thread (target = self ._run_update_check , daemon = True ).start ()
102103
103104 def _run_update_check (self , show_no_update = False ):
104- checker = UpdateChecker ()
105- has_update , version , data = checker .check_for_updates ()
105+ try :
106+ checker = UpdateChecker ()
107+ has_update , version , data = checker .check_for_updates ()
106108
107- if has_update :
108- self .after (0 , lambda : self .show_update_dialog (checker ))
109- elif show_no_update :
110- self .after (0 , lambda : ctk .filedialog .showinfo ("Check for Updates" , f"You are up to date! ({ __version__ } )" ))
109+ if has_update :
110+ self .after (0 , lambda : self .show_update_dialog (checker ))
111+ elif show_no_update :
112+ self .after (0 , lambda : messagebox .showinfo ("Check for Updates" , f"You are up to date! ({ __version__ } )" ))
113+ except Exception as e :
114+ logger .error (f"Update check failed: { e } " )
115+ if show_no_update :
116+ self .after (0 , lambda err = str (e ): messagebox .showerror (i18n .get ("update_check_failed" ), f"{ i18n .get ('could_not_check' )} \n { err } " ))
111117
112118 def show_update_dialog (self , checker ):
113119 dialog = ctk .CTkToplevel (self )
114120 dialog .title ("Update Available 🚀" )
115121 dialog .geometry ("500x400" )
116122 dialog .transient (self )
117123
118- ctk .CTkLabel (dialog , text = "A new version of SwitchCraft is available!" , font = ctk .CTkFont (size = 16 , weight = "bold" )).pack (pady = 10 )
124+ ctk .CTkLabel (dialog , text = i18n . get ( "update_available" ) , font = ctk .CTkFont (size = 16 , weight = "bold" )).pack (pady = 10 )
119125
120126 info_frame = ctk .CTkFrame (dialog )
121127 info_frame .pack (fill = "both" , expand = True , padx = 20 , pady = 10 )
122128
123- ctk .CTkLabel (info_frame , text = f"Current Version : { checker .current_version } " ).pack (anchor = "w" , padx = 10 , pady = 2 )
124- ctk .CTkLabel (info_frame , text = f"New Version : { checker .latest_version } " , text_color = "green" ).pack (anchor = "w" , padx = 10 , pady = 2 )
129+ ctk .CTkLabel (info_frame , text = f"{ i18n . get ( 'current_version' ) } : { checker .current_version } " ).pack (anchor = "w" , padx = 10 , pady = 2 )
130+ ctk .CTkLabel (info_frame , text = f"{ i18n . get ( 'new_version' ) } : { checker .latest_version } " , text_color = "green" ).pack (anchor = "w" , padx = 10 , pady = 2 )
125131
126132 date_str = checker .release_date .split ("T" )[0 ] if checker .release_date else "Unknown"
127- ctk .CTkLabel (info_frame , text = f"Released : { date_str } " ).pack (anchor = "w" , padx = 10 , pady = 2 )
133+ ctk .CTkLabel (info_frame , text = f"{ i18n . get ( 'released' ) } : { date_str } " ).pack (anchor = "w" , padx = 10 , pady = 2 )
128134
129- ctk .CTkLabel (dialog , text = "Changelog :" , font = ctk .CTkFont (weight = "bold" )).pack (anchor = "w" , padx = 20 )
135+ ctk .CTkLabel (dialog , text = f" { i18n . get ( 'changelog' ) } :" , font = ctk .CTkFont (weight = "bold" )).pack (anchor = "w" , padx = 20 )
130136 textbox = ctk .CTkTextbox (dialog , height = 100 )
131137 textbox .pack (fill = "x" , padx = 20 , pady = 5 )
132- textbox .insert ("0.0" , checker .release_notes or "No changelog provided." )
138+ textbox .insert ("0.0" , checker .release_notes or i18n . get ( "no_changelog" ) )
133139 textbox .configure (state = "disabled" )
134140
135141 btn_frame = ctk .CTkFrame (dialog , fg_color = "transparent" )
136142 btn_frame .pack (fill = "x" , padx = 20 , pady = 20 )
137143
138144 download_url = checker .get_download_url ()
139- ctk .CTkButton (btn_frame , text = "Download Update" , command = lambda : webbrowser .open (download_url )).pack (side = "left" , padx = 5 )
140- ctk .CTkButton (btn_frame , text = "Skip" , fg_color = "gray" , command = dialog .destroy ).pack (side = "right" , padx = 5 )
145+ ctk .CTkButton (btn_frame , text = i18n . get ( "download_update" ) , command = lambda : webbrowser .open (download_url )).pack (side = "left" , padx = 5 )
146+ ctk .CTkButton (btn_frame , text = i18n . get ( "skip" ) , fg_color = "gray" , command = dialog .destroy ).pack (side = "right" , padx = 5 )
141147
142148
143149 # --- Analyzer Tab ---
@@ -337,7 +343,7 @@ def show_results(self, info, winget_url, brute_force_data=None, nested_data=None
337343 # Brute Force Output Log
338344 if brute_force_data :
339345 self .add_separator ()
340- lbl = ctk .CTkLabel (self .result_frame , text = "Automated Analysis Output" , font = ctk .CTkFont (weight = "bold" ))
346+ lbl = ctk .CTkLabel (self .result_frame , text = i18n . get ( "automated_output" ) , font = ctk .CTkFont (weight = "bold" ))
341347 lbl .pack (pady = 5 )
342348
343349 log_box = ctk .CTkTextbox (self .result_frame , height = 150 , fg_color = "black" , text_color = "#00FF00" , font = ("Consolas" , 11 ))
@@ -346,7 +352,7 @@ def show_results(self, info, winget_url, brute_force_data=None, nested_data=None
346352 log_box .pack (fill = "x" , pady = 5 )
347353
348354 if "MSI Wrapper" in info .installer_type :
349- ctk .CTkLabel (self .result_frame , text = "💡 Detected MSI Wrapper! Standard MSI switches may work." , text_color = "cyan" , font = ctk .CTkFont (weight = "bold" )).pack (pady = 5 )
355+ ctk .CTkLabel (self .result_frame , text = i18n . get ( "msi_wrapper_tip" ) , text_color = "cyan" , font = ctk .CTkFont (weight = "bold" )).pack (pady = 5 )
350356
351357 # Winget
352358 self .add_separator ()
@@ -361,9 +367,103 @@ def show_results(self, info, winget_url, brute_force_data=None, nested_data=None
361367 command = lambda : webbrowser .open (winget_url ))
362368 link_btn .pack (pady = 5 , padx = 10 , fill = "x" )
363369 else :
364- w_lbl = ctk .CTkLabel (winget_panel , text = "Winget: No match found / No properties detected" , text_color = "gray" )
370+ w_lbl = ctk .CTkLabel (winget_panel , text = i18n . get ( "winget_no_match" ) , text_color = "gray" )
365371 w_lbl .pack (pady = 5 )
366372
373+ # Parameter List - Show all found parameters with explanations
374+ all_params = []
375+ if info .install_switches :
376+ all_params .extend (info .install_switches )
377+ if info .uninstall_switches :
378+ all_params .extend (info .uninstall_switches )
379+
380+ if all_params :
381+ self .show_all_parameters (all_params )
382+
383+ def show_all_parameters (self , params ):
384+ """Display all found parameters with explanations."""
385+ self .add_separator ()
386+
387+ # Header
388+ header_frame = ctk .CTkFrame (self .result_frame , fg_color = ("#E8F5E9" , "#1B5E20" ), corner_radius = 8 )
389+ header_frame .pack (fill = "x" , pady = 10 , padx = 5 )
390+
391+ ctk .CTkLabel (
392+ header_frame ,
393+ text = f"📋 { i18n .get ('found_params' )} " ,
394+ font = ctk .CTkFont (size = 14 , weight = "bold" ),
395+ text_color = ("black" , "white" )
396+ ).pack (pady = 8 )
397+
398+ # Separate known and unknown params
399+ known_params = []
400+ unknown_params = []
401+
402+ for param in params :
403+ explanation = i18n .get_param_explanation (param )
404+ if explanation :
405+ known_params .append ((param , explanation ))
406+ else :
407+ unknown_params .append (param )
408+
409+ # Known parameters with explanations
410+ if known_params :
411+ known_frame = ctk .CTkFrame (self .result_frame , fg_color = ("gray90" , "gray25" ), corner_radius = 5 )
412+ known_frame .pack (fill = "x" , pady = 5 , padx = 10 )
413+
414+ ctk .CTkLabel (
415+ known_frame ,
416+ text = f"✓ { i18n .get ('known_params' )} " ,
417+ font = ctk .CTkFont (size = 12 , weight = "bold" ),
418+ text_color = "green"
419+ ).pack (anchor = "w" , padx = 10 , pady = 5 )
420+
421+ for param , explanation in known_params :
422+ param_row = ctk .CTkFrame (known_frame , fg_color = "transparent" )
423+ param_row .pack (fill = "x" , padx = 10 , pady = 2 )
424+
425+ # Parameter name (monospace, colored)
426+ ctk .CTkLabel (
427+ param_row ,
428+ text = param ,
429+ font = ("Consolas" , 12 ),
430+ text_color = ("#0066CC" , "#66B3FF" ),
431+ width = 180 ,
432+ anchor = "w"
433+ ).pack (side = "left" )
434+
435+ # Explanation
436+ ctk .CTkLabel (
437+ param_row ,
438+ text = f"→ { explanation } " ,
439+ text_color = ("gray40" , "gray70" ),
440+ anchor = "w"
441+ ).pack (side = "left" , fill = "x" , expand = True )
442+
443+ # Padding at bottom of known params
444+ ctk .CTkLabel (known_frame , text = "" , height = 5 ).pack ()
445+
446+ # Unknown parameters
447+ if unknown_params :
448+ unknown_frame = ctk .CTkFrame (self .result_frame , fg_color = ("gray95" , "gray30" ), corner_radius = 5 )
449+ unknown_frame .pack (fill = "x" , pady = 5 , padx = 10 )
450+
451+ ctk .CTkLabel (
452+ unknown_frame ,
453+ text = f"? { i18n .get ('unknown_params' )} " ,
454+ font = ctk .CTkFont (size = 12 , weight = "bold" ),
455+ text_color = "orange"
456+ ).pack (anchor = "w" , padx = 10 , pady = 5 )
457+
458+ unknown_text = " " .join (unknown_params )
459+ ctk .CTkLabel (
460+ unknown_frame ,
461+ text = unknown_text ,
462+ font = ("Consolas" , 11 ),
463+ text_color = ("gray50" , "gray60" ),
464+ wraplength = 400
465+ ).pack (anchor = "w" , padx = 10 , pady = (0 , 8 ))
466+
367467 def show_nested_executables (self , nested_data , parent_info ):
368468 """Display nested executables found inside an extracted archive."""
369469
@@ -609,7 +709,7 @@ def setup_settings_tab(self):
609709 # Update Check
610710 frame_upd = ctk .CTkFrame (self .tab_settings )
611711 frame_upd .pack (fill = "x" , padx = 10 , pady = 10 )
612- ctk .CTkButton (frame_upd , text = "Check for Updates" , command = lambda : self ._run_update_check (show_no_update = True )).pack (pady = 10 )
712+ ctk .CTkButton (frame_upd , text = i18n . get ( "check_updates" ) , command = lambda : self ._run_update_check (show_no_update = True )).pack (pady = 10 )
613713
614714 # About
615715 frame_about = ctk .CTkFrame (self .tab_settings , fg_color = "transparent" )
@@ -624,7 +724,7 @@ def setup_settings_tab(self):
624724 link .pack (pady = 5 )
625725
626726 # Footer
627- ctk .CTkLabel (self .tab_settings , text = "Brought to you by FaserF" , text_color = "gray" ).pack (side = "bottom" , pady = 10 )
727+ ctk .CTkLabel (self .tab_settings , text = i18n . get ( "brought_by" ) , text_color = "gray" ).pack (side = "bottom" , pady = 10 )
628728
629729 def change_theme (self , value ):
630730 if value == i18n .get ("settings_light" ): ctk .set_appearance_mode ("Light" )
0 commit comments