diff --git a/Changelog b/Changelog index a6ee910..e420496 100644 --- a/Changelog +++ b/Changelog @@ -2,7 +2,13 @@ Changelog for LXTools installer ## [Unreleased] - - + - replace pack with grid + + ### Added +18-06-2025 + +- Added language support for German + ### Added 14-06-2025 diff --git a/locale/de/LC_MESSAGES/lxtoolsinstaller.mo b/locale/de/LC_MESSAGES/lxtoolsinstaller.mo new file mode 100644 index 0000000..27eb7b9 Binary files /dev/null and b/locale/de/LC_MESSAGES/lxtoolsinstaller.mo differ diff --git a/lx-icons/128/Lunix_Tools.png b/lx-icons/128/Lunix_Tools.png new file mode 100644 index 0000000..e5bcb10 Binary files /dev/null and b/lx-icons/128/Lunix_Tools.png differ diff --git a/lx-icons/128/wg_vpn-stop.png b/lx-icons/128/wg_vpn-stop.png index 7698de3..1412b72 100644 Binary files a/lx-icons/128/wg_vpn-stop.png and b/lx-icons/128/wg_vpn-stop.png differ diff --git a/lx-icons/256/Lunix_Tools.png b/lx-icons/256/Lunix_Tools.png new file mode 100644 index 0000000..10f93a9 Binary files /dev/null and b/lx-icons/256/Lunix_Tools.png differ diff --git a/lx-icons/256/wg_vpn-stop.png b/lx-icons/256/wg_vpn-stop.png index 535d948..a7f6cdf 100644 Binary files a/lx-icons/256/wg_vpn-stop.png and b/lx-icons/256/wg_vpn-stop.png differ diff --git a/lx-icons/32/Lunix_Tools.png b/lx-icons/32/Lunix_Tools.png new file mode 100644 index 0000000..6e7ca0c Binary files /dev/null and b/lx-icons/32/Lunix_Tools.png differ diff --git a/lx-icons/32/wg_vpn-stop.png b/lx-icons/32/wg_vpn-stop.png index a972a98..8c164a4 100644 Binary files a/lx-icons/32/wg_vpn-stop.png and b/lx-icons/32/wg_vpn-stop.png differ diff --git a/lx-icons/48/Lunix_Tools.png b/lx-icons/48/Lunix_Tools.png new file mode 100644 index 0000000..8582456 Binary files /dev/null and b/lx-icons/48/Lunix_Tools.png differ diff --git a/lx-icons/48/wg_vpn-stop.png b/lx-icons/48/wg_vpn-stop.png index fb9fee6..bfb490d 100644 Binary files a/lx-icons/48/wg_vpn-stop.png and b/lx-icons/48/wg_vpn-stop.png differ diff --git a/lx-icons/64/Lunix_Tools.png b/lx-icons/64/Lunix_Tools.png new file mode 100644 index 0000000..7e62161 Binary files /dev/null and b/lx-icons/64/Lunix_Tools.png differ diff --git a/lx-icons/64/wg_vpn-stop.png b/lx-icons/64/wg_vpn-stop.png index 353e2e4..e6052c1 100644 Binary files a/lx-icons/64/wg_vpn-stop.png and b/lx-icons/64/wg_vpn-stop.png differ diff --git a/lxtools_installer.py b/lxtools_installer.py index 77735e9..1f33198 100755 --- a/lxtools_installer.py +++ b/lxtools_installer.py @@ -10,6 +10,7 @@ import zipfile from manager import ( OSDetector, Theme, + LocaleStrings, LXToolsAppConfig, System, Image, @@ -19,9 +20,6 @@ from manager import ( from network import NetworkChecker from message import MessageDialog -# Initialize translations -_ = LXToolsAppConfig.setup_translations() - class InstallationManager: def __init__( @@ -38,10 +36,12 @@ class InstallationManager: """Install or update project""" project_info = self.app_manager.get_project_info(project_key) if not project_info: - raise Exception(_(f"Unknown project: {project_key}")) + raise Exception(f"{LocaleStrings.MSG["unknow_project"]}{project_key}") - self.update_progress(_(f"Starting installation of {project_info['name']}...")) - self.log(_(f"=== Installing {project_info['name']} ===")) + self.update_progress( + f"{LocaleStrings.MSGI["start_install"]}{project_info['name']}..." + ) + self.log(f"=== {LocaleStrings.MSGI["install"]}{project_info['name']} ===") try: # Create installation script @@ -51,17 +51,19 @@ class InstallationManager: self._execute_install_script(script_content) self.update_progress( - _(f"{project_info['name']} installation completed successfully!") + f"{project_info["name"]}{LocaleStrings.MSGI["install_success"]}" + ) + self.log( + f"=== {project_info["name"]}{LocaleStrings.MSGI["install_success"]} ===" ) - self.log(_(f"=== {project_info['name']} installed successfully ===")) # Set success icon self.update_icon("success") except Exception as e: - self.log(_(f"ERROR: Installation failed: {e}")) + self.log(f"ERROR: {LocaleStrings.MSGI["install_failed"]}{e}") self.update_icon("error") - raise Exception(_(f"Installation failed: {e}")) + raise Exception(f"{LocaleStrings.MSGI["install_failed"]}{e}") def _create_install_script(self, project_key): """Create installation script based on project""" @@ -70,7 +72,7 @@ class InstallationManager: elif project_key == "logviewer": return self._create_logviewer_install_script() else: - raise Exception(_(f"Unknown project: {project_key}")) + raise Exception(f"{LocaleStrings.MSGI["unknow_project"]}{project_key}") def _create_wirepy_install_script(self): """Create Wire-Py installation script""" @@ -299,7 +301,7 @@ echo "LogViewer installation completed!" # Make script executable os.chmod(script_file.name, 0o755) - self.log(_(f"Created install script: {script_file.name}")) + self.log(f"{LocaleStrings.MSGI["install_create"]}{script_file.name}") # Execute with pkexec result = subprocess.run( @@ -319,12 +321,14 @@ echo "LogViewer installation completed!" os.unlink(script_file.name) if result.returncode != 0: - raise Exception(_(f"Installation script failed: {result.stderr}")) + raise Exception( + f"{LocaleStrings.MSGI["install_script_failed"]}{result.stderr}" + ) except subprocess.TimeoutExpired: - raise Exception(_("Installation timed out")) + raise Exception(LocaleStrings.MSGI["install_timeout"]) except subprocess.CalledProcessError as e: - raise Exception(_(f"Installation script failed: {e}")) + raise Exception(f"{LocaleStrings.MSGI["install_script_failed"]}{e}") def update_progress(self, message): if self.progress_callback: @@ -349,13 +353,17 @@ class UninstallationManager: """Uninstall project""" project_info = self.app_manager.get_project_info(project_key) if not project_info: - raise Exception(f"Unknown project: {project_key}") + raise Exception(f"{LocaleStrings.MSGO["unknow_project"]}{project_key}") if not self.app_manager.is_installed(project_key): - raise Exception(_(f"{project_info['name']} is not installed.")) + raise Exception( + f"{project_info["name"]}{LocaleStrings.MSGO["not_installed"]}" + ) - self.update_progress(_(f"Uninstalling {project_info['name']}...")) - self.log(_(f"=== Uninstalling {project_info['name']} ===")) + self.update_progress( + f"{LocaleStrings.MSGU["uninstall"]}{project_info['name']}..." + ) + self.log(f"=== {LocaleStrings.MSGU["uninstall"]}{project_info['name']} ===") try: # Create uninstallation script @@ -364,12 +372,16 @@ class UninstallationManager: # Execute uninstallation self._execute_uninstall_script(script_content) - self.update_progress(_(f"{project_info['name']} uninstalled successfully!")) - self.log(_(f"=== {project_info['name']} uninstalled successfully ===")) + self.update_progress( + f"{project_info['name']}{LocaleStrings.MSGU["uninstall_success"]}" + ) + self.log( + f"=== {project_info['name']}{LocaleStrings.MSGU["uninstall_success"]} ===" + ) except Exception as e: - self.log(_(f"ERROR: Uninstallation failed: {e}")) - raise Exception(_(f"Uninstallation failed: {e}")) + self.log(f"ERROR: {LocaleStrings.MSGU['uninstall_failed']}{e}") + raise Exception(f"{LocaleStrings.MSGU["uninstall_failed"]}{e}") def _create_uninstall_script(self, project_key): """Create uninstallation script based on project""" @@ -378,7 +390,7 @@ class UninstallationManager: elif project_key == "logviewer": return self._create_logviewer_uninstall_script() else: - raise Exception(_(f"Unknown project: {project_key}")) + raise Exception(f"{LocaleStrings.MSGO["unknow_project"]}{project_key}") def _create_wirepy_uninstall_script(self): """Create Wire-Py uninstallation script""" @@ -513,7 +525,7 @@ echo "LogViewer uninstallation completed!" # Make script executable os.chmod(script_file.name, 0o755) - self.log(_(f"Created uninstall script: {script_file.name}")) + self.log(f"{LocaleStrings.MSGU["uninstall_create"]}{script_file.name}") # Execute with pkexec result = subprocess.run( @@ -533,12 +545,14 @@ echo "LogViewer uninstallation completed!" os.unlink(script_file.name) if result.returncode != 0: - raise Exception(_(f"Uninstallation script failed: {result.stderr}")) + raise Exception( + f"{LocaleStrings.MSGU["uninstall_script_failed"]}{result.stderr}" + ) except subprocess.TimeoutExpired: - raise Exception(_("Uninstallation timed out")) + raise Exception(LocaleStrings.MSGU["uninstall_timeout"]) except subprocess.CalledProcessError as e: - raise Exception(_(f"Uninstallation script failed: {e}")) + raise Exception(f"{LocaleStrings.MSGU["uninstall_script_failed"]}{e}") def update_progress(self, message): if self.progress_callback: @@ -555,13 +569,13 @@ class DownloadManager: """Download and extract ZIP file""" try: if progress_callback: - progress_callback(_(f"Downloading from {url}...")) + progress_callback(f"{LocaleStrings.MSGO["download_from"]}{url}...") with tempfile.NamedTemporaryFile(suffix=".zip", delete=False) as tmp_file: urllib.request.urlretrieve(url, tmp_file.name) if progress_callback: - progress_callback(_("Extracting files...")) + progress_callback(LocaleStrings.MSGO["extract_files"]) with zipfile.ZipFile(tmp_file.name, "r") as zip_ref: zip_ref.extractall(extract_to) @@ -571,7 +585,7 @@ class DownloadManager: except Exception as e: if progress_callback: - progress_callback(_(f"Download failed: {str(e)}")) + progress_callback(f"{LocaleStrings.MSGO["download_failed"]}{e}") return False @@ -694,7 +708,7 @@ class LXToolsGUI: tk.Label( text_frame, - text=f"v {LXToolsAppConfig.VERSION} • Linux App Installer", + text=f"v {LXToolsAppConfig.VERSION} • {LocaleStrings.MSGO["head_string3"]}", font=("Helvetica", 9), fg="#bdc3c7", bg="#2c3e50", @@ -706,7 +720,7 @@ class LXToolsGUI: tk.Label( right_side, - text=f"System: {self.detected_os}", + text=f"{LocaleStrings.MSGO["head_string2"]}{self.detected_os}", font=("Helvetica", 11), fg="#ecf0f1", bg="#2c3e50", @@ -729,23 +743,29 @@ class LXToolsGUI: def check_ready_status(self): """Check if system is ready for installation""" - # Prüfungen: + # Checks: internet_ok = NetworkChecker.check_internet_connection() repo_ok = NetworkChecker.check_repository_access() if internet_ok and repo_ok: - self.update_header_status(_("Ready for installation"), "#1abc9c") # Green + self.update_header_status(LocaleStrings.MSGO["ready"], "#1abc9c") # Green elif not internet_ok: - self.update_header_status(_("No internet connection"), "#e74c3c") # Red + self.update_header_status( + LocaleStrings.MSGO["no_internet"], "#e74c3c" + ) # Red elif not repo_ok: - self.update_header_status(_("Repository unavailable"), "#f39c12") # Orange + self.update_header_status( + LocaleStrings.MSGO["repo_unavailable"], "#f39c12" + ) # Orange else: - self.update_header_status(_("System checking..."), "#3498db") # Blue + self.update_header_status( + LocaleStrings.MSGO["system_check"], "#3498db" + ) # Blue def _create_projects_tab(self): """Create projects tab with project cards""" projects_frame = ttk.Frame(self.notebook) - self.notebook.add(projects_frame, text=_("Applications")) + self.notebook.add(projects_frame, text=LocaleStrings.MSGO["applications"]) # Scrollable frame canvas = tk.Canvas(projects_frame, bg=self.colors["bg"]) @@ -842,7 +862,7 @@ class LXToolsGUI: # Status label status_label = tk.Label( status_frame, - text="❓ Checking...", + text=f"❓ {LocaleStrings.MSGC["checking"]}", font=("Helvetica", 10), bg=self.colors["card_bg"], fg="#95a5a6", @@ -853,7 +873,7 @@ class LXToolsGUI: # Version label version_label = tk.Label( status_frame, - text="Version: Checking...", + text=LocaleStrings.MSGC["version_check"], font=("Helvetica", 9), bg=self.colors["card_bg"], fg="#95a5a6", @@ -936,12 +956,12 @@ class LXToolsGUI: self._update_frame_children_bg(new_content, self.colors["selected_bg"]) project_info = self.app_manager.get_project_info(project_key) - self.log_message(f"Selected project: {project_info['name']}") + self.log_message(f"{LocaleStrings.MSGL["selected_app"]}{project_info["name"]}") def _create_log_tab(self): """Create log tab""" log_frame = ttk.Frame(self.notebook) - self.notebook.add(log_frame, text=_("Installation Log")) + self.notebook.add(log_frame, text=LocaleStrings.MSGL["log_name"]) # Log text with scrollbar log_container = tk.Frame(log_frame) @@ -971,7 +991,7 @@ class LXToolsGUI: # Clear log button clear_log_btn = ttk.Button( - log_controls, text=_("Clear Log"), command=self.clear_log + log_controls, text=LocaleStrings.MSGB["clear_log"], command=self.clear_log ) clear_log_btn.pack(side="right") @@ -979,14 +999,18 @@ class LXToolsGUI: self.log_message( f"=== {LXToolsAppConfig.APP_NAME} v {LXToolsAppConfig.VERSION} ===" ) - self.log_message(_(f"Working directory: {LXToolsAppConfig.WORK_DIR}")) - self.log_message(_(f"Icons directory: {LXToolsAppConfig.ICONS_DIR}")) - self.log_message(_(f"Detected OS: {self.detected_os}")) - self.log_message(_("Ready for installation...")) + self.log_message(f"{LocaleStrings.MSGL["work_dir"]}{LXToolsAppConfig.WORK_DIR}") + self.log_message( + f"{LocaleStrings.MSGL["icons_dir"]}{LXToolsAppConfig.ICONS_DIR}" + ) + self.log_message(f"{LocaleStrings.MSGL["detected_os"]}{self.detected_os}") + self.log_message(f"{LocaleStrings.MSGO["ready"]}...") def _create_progress_section(self): """Create progress section with download icon""" - progress_frame = ttk.LabelFrame(self.root, text=_("Progress"), padding=10) + progress_frame = ttk.LabelFrame( + self.root, text=LocaleStrings.MSGO["progress"], padding=10 + ) progress_frame.pack(fill="x", padx=15, pady=10) # Container for Icon and Progress @@ -1000,7 +1024,7 @@ class LXToolsGUI: # Progress Text (right, expandable) self.progress_label = tk.Label( progress_container, - text=_("Ready for installation..."), + text=f"{LocaleStrings.MSGO["ready"]}...", font=("Helvetica", 10), fg="blue", anchor="w", @@ -1044,7 +1068,7 @@ class LXToolsGUI: # Create buttons install_btn = ttk.Button( button_frame, - text=_("Install/Update"), + text=LocaleStrings.MSGB["install"], command=self.install_selected, style="Install.TButton", padding=8, @@ -1053,7 +1077,7 @@ class LXToolsGUI: uninstall_btn = ttk.Button( button_frame, - text=_("Uninstall"), + text=LocaleStrings.MSGB["uninstall"], command=self.uninstall_selected, style="Uninstall.TButton", padding=8, @@ -1062,7 +1086,7 @@ class LXToolsGUI: refresh_btn = ttk.Button( button_frame, - text=_("Refresh Status"), + text=LocaleStrings.MSGB["refresh"], command=self.refresh_status, style="Refresh.TButton", padding=8, @@ -1111,23 +1135,24 @@ class LXToolsGUI: def refresh_status(self): """Refresh application status and version information""" - self.update_progress(_("Refreshing status and checking versions...")) + self.update_progress(LocaleStrings.MSGI["refresh_and_check"]) self._reset_download_icon() - self.log_message(_("=== Refreshing Status ===")) + self.log_message(f"=== {LocaleStrings.MSGB["refresh"]} ===") self.root.focus_set() for project_key, project_info in self.app_manager.get_all_projects().items(): status_label = self.status_labels[project_key] version_label = self.version_labels[project_key] - self.log_message(_(f"Checking {project_info['name']}...")) + self.log_message(f"{LocaleStrings.MSGC["checking"]} {project_info['name']}") if self.app_manager.is_installed(project_key): installed_version = self.app_manager.get_installed_version(project_key) status_label.config( - text=_(f"✅ Installed ({installed_version})"), fg="green" + text=f"✅ {LocaleStrings.MSGI["installed"]}({installed_version})", + fg="green", ) self.log_message( - _(f"{project_info['name']}: Installed {installed_version}") + f"{project_info['name']}: {LocaleStrings.MSGI["installed"]}({installed_version})" ) # Get latest version from API @@ -1136,87 +1161,88 @@ class LXToolsGUI: if latest_version != "Unknown": if installed_version != f"v. {latest_version}": version_label.config( - text=_( - f"Latest: v. {latest_version} (Update available)" - ), + text=f"{LocaleStrings.MSGC["latest"]}(v. {latest_version}) {LocaleStrings.MSGC["update_available"]}", fg="orange", ) self.log_message( - _( - f"{project_info['name']}: Update available v. {latest_version}" - ) + f"{project_info['name']}: {LocaleStrings.MSGC["update_available"]}(v. {latest_version})" ) + else: version_label.config( - text=f"Latest: v. {latest_version} (Up to date)", + text=f"{LocaleStrings.MSGC["latest"]}: (v. {latest_version}) {LocaleStrings.MSGC["up_to_date"]}", fg="green", ) - self.log_message(f"{project_info['name']}: Up to date") + self.log_message( + f"{project_info['name']}: {LocaleStrings.MSGC["up_to_date"]}", + ) else: - version_label.config(text="Latest: Unknown", fg="gray") + version_label.config( + text=LocaleStrings.MSGC["latest_unknown"], fg="gray" + ) self.log_message( - f"{project_info['name']}: Could not check latest version" + f"{project_info['name']}: {LocaleStrings.MSGC["could_not_check"]}" ) except Exception as e: - version_label.config(text="Latest: Check failed", fg="gray") + version_label.config( + text=LocaleStrings.MSGC["check_last_failed"], fg="gray" + ) self.log_message( - f"{project_info['name']}: Version check failed: {e}" + f"{project_info['name']}: {LocaleStrings.MSGC["version_check_failed"]}: {e}" ) else: - status_label.config(text="❌ Not installed", fg="red") - self.log_message(_(f"{project_info['name']}: Not installed")) + status_label.config( + text=f"❌ {LocaleStrings.MSGC["not_installed"]}", fg="red" + ) + self.log_message( + f"{project_info['name']}: {LocaleStrings.MSGC["not_installed"]}" + ) # Still show latest available version try: latest_version = self.app_manager.get_latest_version(project_key) if latest_version != "Unknown": version_label.config( - text=_(f"Available: v {latest_version}"), fg="blue" + text=f"{project_info['name']} {LocaleStrings.MSGC["available"]}: v {latest_version}", + fg="blue", ) + self.log_message( - _(f"{project_info['name']}: Available v {latest_version}") + f"{project_info['name']} {LocaleStrings.MSGC["available"]}: v {latest_version}" ) else: - version_label.config(text=_("Available: Unknown"), fg="gray") + version_label.config( + text=LocaleStrings.MSGC["available_unknown"], fg="gray" + ) except Exception as e: - version_label.config(text=_("Available: Check failed"), fg="gray") + version_label.config( + text=LocaleStrings.MSGC["available_check_unknown"], fg="gray" + ) self.log_message( - _(f"{project_info['name']}: Version check failed: {e}") + f" {project_info['name']}: {LocaleStrings.MSGC["version_check_failed"]}: {e}" ) - self.update_progress(_("Status refresh completed.")) - self.log_message(_("=== Status refresh completed ===")) + self.update_progress(LocaleStrings.MSGO["refresh2"]) + self.log_message(f"=== {LocaleStrings.MSGO["refresh2"]} ===") self.check_ready_status() def install_selected(self): """Handle install button click""" if not self.selected_project: - MessageDialog("error", _("Please select a project to install.")) + MessageDialog("error", LocaleStrings.MSGM["please_select"]) self.root.focus_set() return # Check internet connection if not NetworkChecker.check_internet_connection(): self.update_download_icon("error") - MessageDialog( - "error", - _( - "Network Error", - "No internet connection available.\nPlease check your network connection.", - ), - ) + MessageDialog("error", LocaleStrings.MSGM["network_error"]) self.root.focus_set() return if not NetworkChecker.check_repository_access(): self.update_download_icon("error") - MessageDialog( - "error", - _( - "Repository Error", - "Cannot access repository.\nPlease try again later.", - ), - ) + MessageDialog("error", LocaleStrings.MSGM["repo_error"]) self.root.focus_set() return @@ -1230,12 +1256,13 @@ class LXToolsGUI: self.update_download_icon("success") MessageDialog( "info", - _(f"{project_info['name']} has been successfully installed/updated."), + f"{project_info["name"]} {LocaleStrings.MSGM["has_success_update"]}", ) + self.refresh_status() except Exception as e: self.update_download_icon("error") - MessageDialog("error", _(f"{e}")) + MessageDialog("error", f"{e}") self.root.focus_set() @@ -1243,14 +1270,16 @@ class LXToolsGUI: """Handle uninstall button click""" if not self.selected_project: - MessageDialog("error", _("Please select a project to uninstall.")) + MessageDialog("error", LocaleStrings.MSGM["please_select_uninstall"]) self.root.focus_set() return project_info = self.app_manager.get_project_info(self.selected_project) if not self.app_manager.is_installed(self.selected_project): - MessageDialog("error", _(f"{project_info['name']} is not installed.")) + MessageDialog( + "error", f"{project_info["name"]} {LocaleStrings.MSGO["not_installed"]}" + ) self.root.focus_set() return @@ -1258,14 +1287,13 @@ class LXToolsGUI: self.uninstallation_manager.uninstall_project(self.selected_project) MessageDialog( "info", - _( - f"{project_info['name']} has been successfully uninstalled.", - ), + f"{project_info["name"]} {LocaleStrings.MSGU["uninstall_success"]}", ) + self.refresh_status() self.root.focus_set() except Exception as e: - MessageDialog("error", _(f"Uninstallation failed: {e}")) + MessageDialog("error", f"{LocaleStrings.MSGU["uninstall_failed"]}: {e}") self.root.focus_set() def update_progress(self, message): @@ -1273,7 +1301,7 @@ class LXToolsGUI: if self.progress_label: self.progress_label.config(text=message) self.progress_label.update() - print(_(f"Progress: {message}")) + print(f"{LocaleStrings.MSGO["progress"]}: {message}") def log_message(self, message): """Add message to log""" @@ -1283,13 +1311,13 @@ class LXToolsGUI: self.log_text.insert(tk.END, log_entry) self.log_text.see(tk.END) self.log_text.update() - print(_(f"Log: {message}")) + print(f"Log: {message}") def clear_log(self): """Clear the log""" if self.log_text: self.log_text.delete(1.0, tk.END) - self.log_message(_("Log cleared")) + self.log_message(MSGL["log_cleared"]) def run(self): """Start the GUI application""" @@ -1300,21 +1328,19 @@ class LXToolsGUI: def main(): """Main function to start the application""" print(f"=== {LXToolsAppConfig.APP_NAME} v {LXToolsAppConfig.VERSION} ===") - print(_(f"Working directory: {os.getcwd()}")) + print(f"{LocaleStrings.MSGL["working_dir"]}{os.getcwd()}") try: # Create and run the GUI app = LXToolsGUI() - app.run() except KeyboardInterrupt: - print(_("\nApplication interrupted by user.")) + print(LocaleStrings.MSGL["user_interrupt"]) except Exception as e: - print(_(f"Fatal error: {e}")) + print(f"{LocaleStrings.MSGL["fatal_error"]}: {e}") try: - MessageDialog( - "error", _("Fatal Error", f"Application failed to start: {e}") - ) + MessageDialog("error", f"{LocaleStrings.MSGL['fatal_app_error']}: {e}") + except: pass diff --git a/manager.py b/manager.py index 472343b..c7bfdc9 100644 --- a/manager.py +++ b/manager.py @@ -1,7 +1,6 @@ import locale import gettext import tkinter as tk -from pathlib import Path from tkinter import ttk import os import subprocess @@ -10,10 +9,10 @@ from network import GiteaUpdate class LXToolsAppConfig: - VERSION = "1.1.4" - APP_NAME = "Lunix Tools Installer" + VERSION = "1.1.5" + APP_NAME = "lxtoolsinstaller" WINDOW_WIDTH = 450 - WINDOW_HEIGHT = 580 + WINDOW_HEIGHT = 740 # Working directory WORK_DIR = os.getcwd() @@ -21,7 +20,7 @@ class LXToolsAppConfig: THEMES_DIR = os.path.join(WORK_DIR, "TK-Themes") # Locale settings - LOCALE_DIR = Path("/usr/share/locale/") + LOCALE_DIR = "./locale/" # Download URLs WIREPY_URL = "https://git.ilunix.de/punix/Wire-Py/archive/main.zip" @@ -94,7 +93,7 @@ class LXToolsAppConfig: } @staticmethod - def setup_translations(): + def setup_translations() -> gettext.gettext: """Initialize translations and set the translation function""" try: locale.bindtextdomain( @@ -113,6 +112,117 @@ class LXToolsAppConfig: _ = LXToolsAppConfig.setup_translations() +class LocaleStrings: + + MSGI = { + "refresh_and_check": _("Refreshing status and checking versions..."), + "start_install": _("Starting installation of "), + "install": _("Installing "), + "install_success": _(" installation successfully!"), + "install_failed": _("Installation failed: "), + "install_create": _("Created install script: "), + "install_script_failed": _("Installation script failed: "), + "install_timeout": _("Installation timed out"), + "installed": _("Installed "), + } + + MSGU = { + "uninstall": _("Uninstalling "), + "uninstall_success": _(" uninstalled successfully!"), + "uninstall_failed": _("Uninstallation failed: "), + "uninstall_create": _("Created uninstall script: "), + "uninstall_script_failed": _("Uninstallation script failed: "), + "uninstall_timeout": _("Uninstallation timed out"), + } + # MSGO = Other messages + MSGO = { + "unknown_project": _("Unknown project: "), + "not_install": _(" is not installed."), + "download_from": _("Downloading from "), + "extract_files": _("Extracting files..."), + "download_failed": _("Download failed: "), + "head_string2": _("System: "), + "head_string3": _("Linux App Installer"), + "ready": _("Ready for installation"), + "no_internet": _("No internet connection"), + "repo_unavailable": _("Repository unavailable"), + "system_check": _("System checking..."), + "applications": _("Applications"), + "progress": _("Progress"), + "refresh2": _("Status refresh completed"), + } + + # MSGC = Strings on Cards + MSGC = { + "checking": _("Checking..."), + "version_check": _("Version: Checking..."), + "latest": _("Latest: "), + "update_available": _("Update available "), + "up_to_date": _("Up to date"), + "latest_unknown": _("Latest unknown"), + "could_not_check": _("Could not check latest version"), + "check_last_failed": _("Latest: Check failed"), + "version_check_failed": _("Version check failed"), + "not_installed": _("Not installed"), + "available": _("Available "), + "available_unknown": _("Available unknown"), + "available_ckeck_failed": _("Available: Check failed"), + } + + # MSGL = Strings on Logmessages + MSGL = { + "selected_app": _("Selected project: "), + "log_name": _("Installation Log"), + "work_dir": _("Working directory: "), + "icons_dir": _("Icons directory: "), + "detected_os": _("Detected OS: "), + "log_cleared": _("Log cleared"), + "working_dir": _("Working directory: "), + "user_interuppt": _("\nApplication interrupted by user."), + "fatal_error": _("Fatal error: "), + "fatal_app_error": _("Fatal Error Application failed to start: "), + } + + # MSGB = Strings on Buttons + MSGB = { + "clear_log": _("Clear Log"), + "install": _("Install/Update"), + "uninstall": _("Uninstall"), + "refresh": _("Refresh Status"), + } + + # MSGM = String on MessagDialogs + MSGM = { + "please_select": _("Please select a project to install."), + "network_error": _( + "No internet connection available.\nPlease check your network connection.", + ), + "repo_error": _( + "Cannot access repository.\nPlease try again later.", + ), + "has_success_update": _("has been successfully installed/updated."), + "please_select_uninstall": _("Please select a project to uninstall."), + } + + # MSGP = Others print strings + MSGP = { + "tk_install": _("Installing tkinter for )"), + "command_string": _("Command: "), + "tk_success": _("TKinter installation completed successfully!"), + "tk_failed": _("TKinter installation failed: "), + "tk_timeout": _("TKinter installation timed out"), + "tk_install_error": _("Error installing tkinter: "), + "tk_command_error": _("No tkinter installation command defined for "), + "fail_load_image": _("Failed to load image from "), + "logviewer_check": _("LogViewer installation check:"), + "symlink_exist": _(" Symlink exists: "), + "executable_exist": _(" Executable exists: "), + "is_executable": _(" Is executable: "), + "final_result": _(" Final result: "), + "get_version_error": _("Error getting version for "), + } + + class OSDetector: @staticmethod def detect_os(): @@ -148,8 +258,8 @@ class OSDetector: if detected_os in LXToolsAppConfig.TKINTER_INSTALL_COMMANDS: commands = LXToolsAppConfig.TKINTER_INSTALL_COMMANDS[detected_os] - print(f"Installing tkinter for {detected_os}...") - print(_(f"Command: {' '.join(commands)}")) + print(f"{LocaleStrings.MSGP["tk_install"]}{detected_os}...") + print(f"{LocaleStrings.MSGP["command_string"]}{' '.join(commands)}") try: # Use pkexec for privilege escalation @@ -159,20 +269,20 @@ class OSDetector: ) if result.returncode == 0: - print(_("TKinter installation completed successfully!")) + print(f"{LocaleStrings.MSGP["tk_succcess"]}") return True else: - print(_(f"TKinter installation failed: {result.stderr}")) + print(f"{LocaleStrings.MSGP["tk_failed"]}{result.stderr}") return False except subprocess.TimeoutExpired: - print(_("TKinter installation timed out")) + print(LocaleStrings.MSGP["tk_timeout"]) return False except Exception as e: - print(_(f"Error installing tkinter: {e}")) + print(f"{LocaleStrings.MSGP['tk_install_error']}{str(e)}") return False else: - print(_(f"No tkinter installation command defined for {detected_os}")) + print(f"{LocaleStrings.MSGP["tk_command_error"]}{detected_os}") return False @@ -307,7 +417,7 @@ class Image: self.images[image_key] = photo return photo except tk.TclError as e: - print(_(f"Failed to load image from {path}: {e}")) + print(f"{LocaleStrings.MSGP["fail_load_image"]}{path}: {e}") continue # Return None if no image found @@ -356,11 +466,11 @@ class AppManager: ) # Debug logging - print(_("LogViewer installation check:")) - print(_(f" Symlink exists: {symlink_exists}")) - print(_(f" Executable exists: {executable_exists}")) - print(_(f" Is executable: {executable_is_executable}")) - print(_(f" Final result: {is_installed}")) + print(LocaleStrings.MSGP["logviewer_check"]) + print(f"{LocaleStrings.MSGP["symlink_exist"]}{symlink_exists}") + print(f"{LocaleStrings.MSGP["executable_exist"]}{executable_exists}") + print(f"{LocaleStrings.MSGP["is_executable"]}{executable_is_executable}") + print(f"{LocaleStrings.MSGP["final_result"]}{is_installed}") return is_installed @@ -385,7 +495,7 @@ class AppManager: return version return "Unknown" except Exception as e: - print(_(f"Error getting version for {project_key}: {e}")) + print(f"{LocaleStrings.MSGP["get_version_error"]}{project_key}: {e}") return "Unknown" def get_latest_version(self, project_key):