From da9a26e8179cd603c491c7de823ec05f0747b7f1 Mon Sep 17 00:00:00 2001 From: Cooper Harasyn Date: Wed, 26 Feb 2025 20:34:38 -0800 Subject: [PATCH] Update text on language change --- coilsnake/lang/en.json | 1 + coilsnake/lang/jp.json | 1 + coilsnake/ui/gui.py | 541 ++++++++++++++++++----------------------- 3 files changed, 242 insertions(+), 301 deletions(-) diff --git a/coilsnake/lang/en.json b/coilsnake/lang/en.json index e1b48e0..111ec6b 100644 --- a/coilsnake/lang/en.json +++ b/coilsnake/lang/en.json @@ -66,6 +66,7 @@ "help_text": "Help", "decomp_rom_new_proj": "Decompile a ROM to create a new project.", "comp_rom_new_proj": "Compile a project to create a new ROM.", + "rom": "ROM", "output_dir": "Output Directory", "base_rom": "Base ROM", "project": "Project", diff --git a/coilsnake/lang/jp.json b/coilsnake/lang/jp.json index 84aa073..956ec53 100644 --- a/coilsnake/lang/jp.json +++ b/coilsnake/lang/jp.json @@ -66,6 +66,7 @@ "help_text": "ヘルプ", "decomp_rom_new_proj": "ROMをデコンパイルして新しいプロジェクトを作成します。", "comp_rom_new_proj": "プロジェクトをコンパイルして新しいROMを作成します。", + "rom": "ROM", "output_dir": "出力ディレクトリ", "base_rom": "ベースROM", "project": "プロジェクト", diff --git a/coilsnake/ui/gui.py b/coilsnake/ui/gui.py index 2d03070..9ce0ef6 100644 --- a/coilsnake/ui/gui.py +++ b/coilsnake/ui/gui.py @@ -1,4 +1,6 @@ #! /usr/bin/env python +from typing import Callable + import sys import tkinter as tk import tkinter @@ -16,6 +18,7 @@ from tkinter.ttk import * import platform import json +from collections import defaultdict import os from PIL import ImageTk @@ -46,159 +49,52 @@ BUTTON_WIDTH = 15 LABEL_WIDTH = 20 -# Function to update GUI text based on the selected language -def update_texts(self, translations): - missing = "Missing localization string" - self.guistrings["coilsnake_name"] = Label(self.root, text=translations.get("coilsnake_name", missing)) - self.guistrings["enable_debug_mode"] = Label(self.root, text=translations.get("enable_debug_mode", missing)) - self.guistrings["disable_debug_mode"] = Label(self.root, text=translations.get("disable_debug_mode", missing)) - self.guistrings["ask_disable_debug"] = Label(self.root, text=translations.get("ask_disable_debug", missing)) - self.guistrings["ask_enable_debug"] = Label(self.root, text=translations.get("ask_enable_debug", missing)) - self.guistrings["ask_disable_debug_prompt"] = Label(self.root, text=translations.get("ask_disable_debug_prompt", missing)) - self.guistrings["ask_enable_debug_prompt"] = Label(self.root, text=translations.get("ask_enable_debug_prompt", missing)) - self.guistrings["coilsnake_is_running"] = Label(self.root, text=translations.get("coilsnake_is_running", missing)) - self.guistrings["advanced_users"] = Label(self.root, text=translations.get("advanced_users", missing)) - self.guistrings["select_emu_exe"] = Label(self.root, text=translations.get("select_emu_exe", missing)) - self.guistrings["select_an_emu"] = Label(self.root, text=translations.get("select_an_emu", missing)) - self.guistrings["coilsnake_use_emu"] = Label(self.root, text=translations.get("coilsnake_use_emu", missing)) - self.guistrings["emu_hint"] = Label(self.root, text=translations.get("emu_hint", missing)) - self.guistrings["ccscript_offset"] = Label(self.root, text=translations.get("ccscript_offset", missing)) - self.guistrings["which_ccscript_compile"] = Label(self.root, text=translations.get("which_ccscript_compile", missing)) - self.guistrings["default_F10000"] = Label(self.root, text=translations.get("default_F10000", missing)) - self.guistrings["know_what_youre_doing"] = Label(self.root, text=translations.get("know_what_youre_doing", missing)) - self.guistrings["error"] = Label(self.root, text=translations.get("error", missing)) - self.guistrings["cant_find_emu"] = Label(self.root, text=translations.get("cant_find_emu", missing)) - self.guistrings["cant_find_java"] = Label(self.root, text=translations.get("cant_find_java", missing)) - self.guistrings["cant_patch_rom"] = Label(self.root, text=translations.get("cant_patch_rom", missing)) - self.guistrings["invalid_format"] = Label(self.root, text=translations.get("invalid_format", missing)) - self.guistrings["name_exists"] = Label(self.root, text=translations.get("name_exists", missing)) - self.guistrings["cant_delete_prof"] = Label(self.root, text=translations.get("cant_delete_prof", missing)) - self.guistrings["not_a_valid_hex"] = Label(self.root, text=translations.get("not_a_valid_hex", missing)) - self.guistrings["config_java"] = Label(self.root, text=translations.get("config_java", missing)) - self.guistrings["java_following_loc"] = Label(self.root, text=translations.get("java_following_loc", missing)) - self.guistrings["select_yes"] = Label(self.root, text=translations.get("select_yes", missing)) - self.guistrings["select_no"] = Label(self.root, text=translations.get("select_no", missing)) - self.guistrings["select_the_java_exe"] = Label(self.root, text=translations.get("select_the_java_exe", missing)) - self.guistrings["java_for_coilsnake"] = Label(self.root, text=translations.get("java_for_coilsnake", missing)) - self.guistrings["on_windows_info"] = Label(self.root, text=translations.get("on_windows_info", missing)) - self.guistrings["are_you_sure"] = Label(self.root, text=translations.get("are_you_sure", missing)) - self.guistrings["ask_upgrade"] = Label(self.root, text=translations.get("ask_upgrade", missing)) - self.guistrings["ask_upgrade_2"] = Label(self.root, text=translations.get("ask_upgrade_2", missing)) - self.guistrings["backup_info"] = Label(self.root, text=translations.get("backup_info", missing)) - self.guistrings["ask_perm_overwrite"] = Label(self.root, text=translations.get("ask_perm_overwrite", missing)) - self.guistrings["ask_perm_overwrite_2"] = Label(self.root, text=translations.get("ask_perm_overwrite_2", missing)) - self.guistrings["ask_expand_rom"] = Label(self.root, text=translations.get("ask_expand_rom", missing)) - self.guistrings["attempt_compile"] = Label(self.root, text=translations.get("attempt_compile", missing)) - self.guistrings["attempt_compile_2"] = Label(self.root, text=translations.get("attempt_compile_2", missing)) - self.guistrings["attempt_compile_3"] = Label(self.root, text=translations.get("attempt_compile_3", missing)) - self.guistrings["ask_expand_base"] = Label(self.root, text=translations.get("ask_expand_base", missing)) - self.guistrings["ask_expand_base_2"] = Label(self.root, text=translations.get("ask_expand_base_2", missing)) - self.guistrings["start_comp"] = Label(self.root, text=translations.get("start_comp", missing)) - self.guistrings["decomp_script_prompt"] = Label(self.root, text=translations.get("decomp_script_prompt", missing)) - self.guistrings["decomp_script_prompt_2"] = Label(self.root, text=translations.get("decomp_script_prompt_2", missing)) - self.guistrings["decompile_text"] = Label(self.root, text=translations.get("decompile_text", missing)) - self.guistrings["compile_text"] = Label(self.root, text=translations.get("compile_text", missing)) - self.guistrings["upgrade"] = Label(self.root, text=translations.get("upgrade", missing)) - self.guistrings["decomp_script"] = Label(self.root, text=translations.get("decomp_script", missing)) - self.guistrings["apply_patch"] = Label(self.root, text=translations.get("apply_patch", missing)) - self.guistrings["create_patch"] = Label(self.root, text=translations.get("create_patch", missing)) - self.guistrings["about_coilsnake"] = Label(self.root, text=translations.get("about_coilsnake", missing)) - self.guistrings["eb_proj_edit"] = Label(self.root, text=translations.get("eb_proj_edit", missing)) - self.guistrings["expand_to_32"] = Label(self.root, text=translations.get("expand_to_32", missing)) - self.guistrings["expand_to_48"] = Label(self.root, text=translations.get("expand_to_48", missing)) - self.guistrings["add_header"] = Label(self.root, text=translations.get("add_header", missing)) - self.guistrings["remove_header"] = Label(self.root, text=translations.get("remove_header", missing)) - self.guistrings["tools"] = Label(self.root, text=translations.get("tools", missing)) - self.guistrings["config_emu"] = Label(self.root, text=translations.get("config_emu", missing)) - self.guistrings["config_ccscript"] = Label(self.root, text=translations.get("config_ccscript", missing)) - self.guistrings["settings"] = Label(self.root, text=translations.get("settings", missing)) - self.guistrings["coilsnake_site"] = Label(self.root, text=translations.get("coilsnake_site", missing)) - self.guistrings["help_text"] = Label(self.root, text=translations.get("help_text", missing)) - self.guistrings["decomp_rom_new_proj"] = Label(self.root, text=translations.get("decomp_rom_new_proj", missing)) - self.guistrings["comp_rom_new_proj"] = Label(self.root, text=translations.get("comp_rom_new_proj", missing)) - self.guistrings["output_dir"] = Label(self.root, text=translations.get("output_dir", missing)) - self.guistrings["base_rom"] = Label(self.root, text=translations.get("base_rom", missing)) - self.guistrings["project"] = Label(self.root, text=translations.get("project", missing)) - self.guistrings["output_rom"] = Label(self.root, text=translations.get("output_rom", missing)) - self.guistrings["upgrade_info"] = Label(self.root, text=translations.get("upgrade_info", missing)) - self.guistrings["clean_rom"] = Label(self.root, text=translations.get("clean_rom", missing)) - self.guistrings["decomp_rom_script"] = Label(self.root, text=translations.get("decomp_rom_script", missing)) - self.guistrings["apply_patch_info"] = Label(self.root, text=translations.get("apply_patch_info", missing)) - self.guistrings["patched_rom"] = Label(self.root, text=translations.get("patched_rom", missing)) - self.guistrings["patch_rom"] = Label(self.root, text=translations.get("patch_rom", missing)) - self.guistrings["patch"] = Label(self.root, text=translations.get("patch", missing)) - self.guistrings["header_ips_only"] = Label(self.root, text=translations.get("header_ips_only", missing)) - self.guistrings["create_ebp_info"] = Label(self.root, text=translations.get("create_ebp_info", missing)) - self.guistrings["modded_rom"] = Label(self.root, text=translations.get("modded_rom", missing)) - self.guistrings["author"] = Label(self.root, text=translations.get("author", missing)) - self.guistrings["desc"] = Label(self.root, text=translations.get("desc", missing)) - self.guistrings["title"] = Label(self.root, text=translations.get("title", missing)) - self.guistrings["ebp_patch"] = Label(self.root, text=translations.get("ebp_patch", missing)) - self.guistrings["input_ebp"] = Label(self.root, text=translations.get("input_ebp", missing)) - self.guistrings["ok"] = Label(self.root, text=translations.get("ok", missing)) - self.guistrings["profile"] = Label(self.root, text=translations.get("profile", missing)) - self.guistrings["new_prof_name"] = Label(self.root, text=translations.get("new_prof_name", missing)) - self.guistrings["specify_name"] = Label(self.root, text=translations.get("specify_name", missing)) - self.guistrings["save"] = Label(self.root, text=translations.get("save", missing)) - self.guistrings["delete"] = Label(self.root, text=translations.get("delete", missing)) - self.guistrings["new"] = Label(self.root, text=translations.get("new", missing)) - self.guistrings["browse"] = Label(self.root, text=translations.get("browse", missing)) - self.guistrings["run"] = Label(self.root, text=translations.get("run", missing)) - self.guistrings["open_text"] = Label(self.root, text=translations.get("open_text", missing)) - self.guistrings["edit"] = Label(self.root, text=translations.get("edit", missing)) - self.guistrings["yes"] = Label(self.root, text=translations.get("yes", missing)) - self.guistrings["no"] = Label(self.root, text=translations.get("no", missing)) - - self.guistrings["console_proj_already_updated"] = Label(self.root, text=translations.get("console_proj_already_updated", missing)) - self.guistrings["console_upgrading_version"] = Label(self.root, text=translations.get("console_upgrading_version", missing)) - self.guistrings["console_upgrading"] = Label(self.root, text=translations.get("console_upgrading", missing)) - self.guistrings["console_finished_upgrading"] = Label(self.root, text=translations.get("console_finished_upgrading", missing)) - self.guistrings["console_upgrading_in"] = Label(self.root, text=translations.get("console_upgrading_in", missing)) - self.guistrings["console_compiling_ccs"] = Label(self.root, text=translations.get("console_compiling_ccs", missing)) - self.guistrings["console_finished_ccs"] = Label(self.root, text=translations.get("console_finished_ccs", missing)) - self.guistrings["console_error_outout"] = Label(self.root, text=translations.get("console_error_outout", missing)) - self.guistrings["console_comp_proj"] = Label(self.root, text=translations.get("console_comp_proj", missing)) - self.guistrings["console_compiling"] = Label(self.root, text=translations.get("console_compiling", missing)) - self.guistrings["console_finished_comp"] = Label(self.root, text=translations.get("console_finished_comp", missing)) - self.guistrings["console_saving_rom"] = Label(self.root, text=translations.get("console_saving_rom", missing)) - self.guistrings["console_comp_to_finish"] = Label(self.root, text=translations.get("console_comp_to_finish", missing)) - self.guistrings["console_decomp_rom"] = Label(self.root, text=translations.get("console_decomp_rom", missing)) - self.guistrings["console_decompiling"] = Label(self.root, text=translations.get("console_decompiling", missing)) - self.guistrings["console_finish_decomp"] = Label(self.root, text=translations.get("console_finish_decomp", missing)) - self.guistrings["console_saving_proj"] = Label(self.root, text=translations.get("console_saving_proj", missing)) - self.guistrings["console_decomp_to"] = Label(self.root, text=translations.get("console_decomp_to", missing)) - self.guistrings["console_error_decomp_script"] = Label(self.root, text=translations.get("console_error_decomp_script", missing)) - self.guistrings["console_decomp_script"] = Label(self.root, text=translations.get("console_decomp_script", missing)) - self.guistrings["console_patching_rom"] = Label(self.root, text=translations.get("console_patching_rom", missing)) - self.guistrings["console_error_unknown_patch"] = Label(self.root, text=translations.get("console_error_unknown_patch", missing)) - self.guistrings["console_title_author"] = Label(self.root, text=translations.get("console_title_author", missing)) - self.guistrings["console_patched_to"] = Label(self.root, text=translations.get("console_patched_to", missing)) - self.guistrings["console_creating_ebp"] = Label(self.root, text=translations.get("console_creating_ebp", missing)) - self.guistrings["console_with_desc"] = Label(self.root, text=translations.get("console_with_desc", missing)) - self.guistrings["console_creating_ips"] = Label(self.root, text=translations.get("console_creating_ips", missing)) - self.guistrings["console_error_creating_patch"] = Label(self.root, text=translations.get("console_error_creating_patch", missing)) - self.guistrings["console_patch_success"] = Label(self.root, text=translations.get("console_patch_success", missing)) - self.guistrings["console_error_compatibility"] = Label(self.root, text=translations.get("console_error_compatibility", missing)) - self.guistrings["console_error_compatibility_2"] = Label(self.root, text=translations.get("console_error_compatibility_2", missing)) - self.guistrings["console_error_upgrade_before_op"] = Label(self.root, text=translations.get("console_error_upgrade_before_op", missing)) - self.guistrings["console_error_rom_type"] = Label(self.root, text=translations.get("console_error_rom_type", missing)) - # This updates the list of strings it refers to when it builds the UI. - # BUT, it doesn't modify everything after the UI has already built. - # We need to either figure out a way to update everything, close the whole window and open it again, - # or display a dialog box that tells the user "This won't take effect until you close and re-open CoilSnake" - # And if we go with the latter option, we'll need to make language one of the preferences that gets - # loaded when CoilSnake starts. Which we should do anyway tbh. --livvy - -# Function to load the selected language -def load_language(self, language): - file_path = LANGUAGE_FILES.get(language, None) - if file_path and os.path.exists(file_path): - with open(file_path, "r", encoding="utf-8") as file: - translations = json.load(file) - update_texts(self, translations) - - else: - print(f"Language file for {language} not found.") +class GuiStringManager: + _TRANSLATIONS_LANGUAGE_NOT_LOADED = defaultdict( lambda: "Translation not loaded" ) + + @staticmethod + def _json_to_translations(json_data): + missing = "Missing localization string" + return defaultdict(lambda: missing, json_data) + + @classmethod + def _load_language(cls, language): + file_path = LANGUAGE_FILES.get(language, None) + try: + with open(file_path, "r", encoding="utf-8") as file: + json_data = json.load(file) + return cls._json_to_translations(json_data) + except: + return None + + def __init__(self): + self.callbacks = set() + self.translations = self._TRANSLATIONS_LANGUAGE_NOT_LOADED + + def change_language(self, language): + translations = self._load_language(language) + if not translations: + log.error("Unable to load translation file for language '%s'", language) + return + self.translations = translations + for cb in self.callbacks: + cb() + + def get(self, string_name: str) -> str: + return self.translations[string_name] + + def register_callback(self, cb, invoke=True): + self.callbacks.add(cb) + if invoke: + cb() + + def register_widget(self, elem: Widget, string_name: str, invoke=True): + cb = lambda: elem.configure(text=self.get(string_name)) + self.register_callback(cb, invoke=invoke) + + def register_notebook_frame(self, notebook, frame, string_name, invoke=True): + cb = lambda: notebook.tab(frame, text=self.get(string_name)) + self.register_callback(cb, invoke=invoke) class CoilSnakeGui(object): def __init__(self): @@ -206,7 +102,7 @@ def __init__(self): self.preferences.load() self.components = [] self.progress_bar = None - self.guistrings = {} + self.guistrings = GuiStringManager() # Function to open the language selection window def open_language_window(self): @@ -232,7 +128,8 @@ def open_language_window(self): # Function to apply the selected language def apply_language(): - load_language(self, selected_language.get()) + language = selected_language.get() + self.guistrings.change_language(language) language_window.destroy() @@ -243,7 +140,6 @@ def apply_language(): # Cancel Button to close without applying changes cancel_button = tk.Button(language_window, text="Cancel", command=language_window.destroy) cancel_button.pack(pady=5) - def refresh_debug_logging(self): if self.preferences["debug mode"]: @@ -256,13 +152,13 @@ def refresh_debug_mode_command_label(self): self.pref_menu.entryconfig(5, label=self.get_debug_mode_command_label()) def get_debug_mode_command_label(self): - return self.guistrings["disable_debug_mode"].cget("text") if self.preferences["debug mode"] else self.guistrings["enable_debug_mode"].cget("text") + return self.guistrings.get("disable_debug_mode") if self.preferences["debug mode"] else self.guistrings.get("enable_debug_mode") def set_debug_mode(self): if self.preferences["debug mode"]: confirm = tkinter.messagebox.askquestion( - self.guistrings["ask_disable_debug"].cget("text"), - self.guistrings["ask_disable_debug_prompt"].cget("text"), + self.guistrings.get("ask_disable_debug"), + self.guistrings.get("ask_disable_debug_prompt"), icon="question" ) @@ -270,10 +166,10 @@ def set_debug_mode(self): self.preferences["debug mode"] = False else: confirm = tkinter.messagebox.askquestion( - self.guistrings["ask_enable_debug"].cget("text"), - self.guistrings["ask_enable_debug_prompt"].cget("text") - + self.guistrings["coilsnake_is_running"].cget("text") - + self.guistrings["advanced_users"].cget("text"), + self.guistrings.get("ask_enable_debug"), + self.guistrings.get("ask_enable_debug_prompt") + + self.guistrings.get("coilsnake_is_running") + + self.guistrings.get("advanced_users"), icon="question" ) @@ -287,25 +183,25 @@ def set_debug_mode(self): def set_emulator_exe(self): tkinter.messagebox.showinfo( - self.guistrings["select_emu_exe"].cget("text"), - self.guistrings["coilsnake_use_emu"].cget("text"), - self.guistrings["emu_hint"].cget("text") + self.guistrings.get("select_emu_exe"), + self.guistrings.get("coilsnake_use_emu"), + self.guistrings.get("emu_hint") ) emulator_exe = tkinter.filedialog.askopenfilename( parent=self.root, initialdir=os.path.expanduser("~"), - title=self.guistrings["select_an_emu"].cget("text")) + title=self.guistrings.get("select_an_emu")) if emulator_exe: self.preferences["emulator"] = emulator_exe self.preferences.save() def set_ccscript_offset(self): ccscript_offset_str = tkinter.simpledialog.askstring( - title=self.guistrings["ccscript_offset"].cget("text"), - prompt=(self.guistrings["which_ccscript_compile"].cget("text") - + self.guistrings["default_F10000"].cget("text") - + self.guistrings["know_what_youre_doing"].cget("text")), + title=self.guistrings.get("ccscript_offset"), + prompt=(self.guistrings.get("which_ccscript_compile") + + self.guistrings.get("default_F10000") + + self.guistrings.get("know_what_youre_doing")), initialvalue="{:x}".format(self.preferences.get_ccscript_offset()).upper()) if ccscript_offset_str: @@ -313,8 +209,8 @@ def set_ccscript_offset(self): ccscript_offset = int(ccscript_offset_str, 16) except: tkinter.messagebox.showerror(parent=self.root, - title=self.guistrings["error"].cget("text"), - message=self.guistrings["not_a_valid_hex"].cget("text").format(ccscript_offset_str)) + title=self.guistrings.get("error"), + message=self.guistrings.get("not_a_valid_hex").format(ccscript_offset_str)) return self.preferences.set_ccscript_offset(ccscript_offset) @@ -328,11 +224,11 @@ def set_java_exe(self): if system_java_exe: confirm = tkinter.messagebox.askquestion( - self.guistrings["config_java"].cget("text"), - self.guistrings["java_following_loc"].cget("text") + self.guistrings.get("config_java"), + self.guistrings.get("java_following_loc") + system_java_exe + "\n\n" - + self.guistrings["select_yes"].cget("text") - + self.guistrings["select_yes"].cget("text"), + + self.guistrings.get("select_yes") + + self.guistrings.get("select_yes"), icon="question" ) if confirm == "yes": @@ -341,14 +237,14 @@ def set_java_exe(self): return tkinter.messagebox.showinfo( - self.guistrings["select_the_java_exe"].cget("text"), - self.guistrings["java_for_coilsnake"].cget("text"), - self.guistrings["on_windows_info"].cget("text") + self.guistrings.get("select_the_java_exe"), + self.guistrings.get("java_for_coilsnake"), + self.guistrings.get("on_windows_info") ) java_exe = tkinter.filedialog.askopenfilename( parent=self.root, - title=self.guistrings["select_the_java_exe"].cget("text"), + title=self.guistrings.get("select_the_java_exe"), initialfile=(self.preferences["java"] or system_java_exe)) if java_exe: self.preferences["java"] = java_exe @@ -402,8 +298,8 @@ def run_rom(self, entry): rom_filename = entry.get() if not self.preferences["emulator"]: tkinter.messagebox.showerror(parent=self.root, - title=self.guistrings["error"].cget("text"), - message=self.guistrings["cant_find_emu"].cget("text")) + title=self.guistrings.get("error"), + message=self.guistrings.get("cant_find_emu")) elif rom_filename: Popen([self.preferences["emulator"], rom_filename]) @@ -416,8 +312,8 @@ def open_ebprojedit(self, entry=None): java_exe = self.get_java_exe() if not java_exe: tkinter.messagebox.showerror(parent=self.root, - title=self.guistrings["error"].cget("text"), - message=self.guistrings["cant_find_java"].cget("text")) + title=self.guistrings.get("error"), + message=self.guistrings.get("cant_find_java")) return command = [java_exe, "-jar", asset_path(["bin", "EbProjEdit.jar"])] @@ -434,9 +330,9 @@ def do_decompile(self, rom_entry, project_entry): if rom and project: if os.path.isdir(project): - confirm = tkinter.messagebox.askquestion(self.guistrings["are_you_sure"].cget("text"), - self.guistrings["ask_perm_overwrite"].cget("text") - + self.guistrings["ask_perm_overwrite_2"].cget("text"), + confirm = tkinter.messagebox.askquestion(self.guistrings.get("are_you_sure"), + self.guistrings.get("ask_perm_overwrite") + + self.guistrings.get("ask_perm_overwrite_2"), icon='warning') if confirm != "yes": return @@ -472,13 +368,13 @@ def do_compile(self, project_entry, base_rom_entry, rom_entry): base_rom_rom = Rom() base_rom_rom.from_file(base_rom) if base_rom_rom.type in ROM_TYPE_GROUP_EBM2 and len(base_rom_rom) == 0x300000: - confirm = tkinter.messagebox.askquestion(self.guistrings["ask_expand_rom"].cget("text"), - self.guistrings["attempt_compile"].cget("text"), - self.guistrings["attempt_compile_2"].cget("text"), - self.guistrings["attempt_compile_3"].cget("text"), + confirm = tkinter.messagebox.askquestion(self.guistrings.get("ask_expand_rom"), + self.guistrings.get("attempt_compile"), + self.guistrings.get("attempt_compile_2"), + self.guistrings.get("attempt_compile_3"), "\n\n", - self.guistrings["ask_expand_base"].cget("text"), - self.guistrings["ask_expand_base_2"].cget("text"), + self.guistrings.get("ask_expand_base"), + self.guistrings.get("ask_expand_base_2"), icon='warning') if confirm == "yes": base_rom_rom.expand(0x400000) @@ -491,7 +387,7 @@ def do_compile(self, project_entry, base_rom_entry, rom_entry): self.progress_bar.clear() - log.info(self.guistrings["start_comp"].cget("text")) + log.info(self.guistrings.get("start_comp")) thread = Thread(target=self._do_compile_help, args=(project, base_rom, rom)) thread.start() @@ -513,10 +409,10 @@ def do_upgrade(self, rom_entry, project_entry): project = project_entry.get() if rom and project: - confirm = tkinter.messagebox.askquestion(self.guistrings["are_you_sure"].cget("text"), - self.guistrings["ask_upgrade"].cget("text") - + self.guistrings["ask_upgrade_2"].cget("text") - + self.guistrings["backup_info"].cget("text"), + confirm = tkinter.messagebox.askquestion(self.guistrings.get("are_you_sure"), + self.guistrings.get("ask_upgrade") + + self.guistrings.get("ask_upgrade_2") + + self.guistrings.get("backup_info"), icon='warning') if confirm != "yes": return @@ -546,10 +442,10 @@ def do_decompile_script(self, rom_entry, project_entry): project = project_entry.get() if rom and project: - confirm = tkinter.messagebox.askquestion(self.guistrings["are_you_sure"].cget("text"), - self.guistrings["decomp_script_prompt"].cget("text"), - self.guistrings["decomp_script_prompt_2"].cget("text"), - + self.guistrings["backup_info"].cget("text"), + confirm = tkinter.messagebox.askquestion(self.guistrings.get("are_you_sure"), + self.guistrings.get("decomp_script_prompt"), + self.guistrings.get("decomp_script_prompt_2"), + + self.guistrings.get("backup_info"), icon='warning') if confirm != "yes": return @@ -624,7 +520,7 @@ def _do_create_patch_help(self, clean_rom, hacked_rom, patch_path, author, descr elif patch_path.endswith(".ips"): create_patch(clean_rom, hacked_rom, patch_path, "", "", "", progress_bar=self.progress_bar) else: - log.info(self.guistrings["cant_patch_rom"].cget("text")) + log.info(self.guistrings.get("cant_patch_rom")) return except Exception as inst: log.debug(format_exc()) @@ -639,8 +535,8 @@ def main(self): def create_gui(self): self.root = Tk() - load_language(self, "English") #replace this with [whatever is in Preferences when we put default language in the preferences stuff] - self.root.wm_title(self.guistrings["coilsnake_name"].cget("text") + information.VERSION) + self.guistrings.change_language("English") #replace this with [whatever is in Preferences when we put default language in the preferences stuff] + self.guistrings.register_callback(lambda: self.root.wm_title(self.guistrings.get("coilsnake_name") + information.VERSION)) if platform.system() == "Windows": self.root.tk.call("wm", "iconbitmap", self.root._w, asset_path(["images", "CoilSnake.ico"])) @@ -668,22 +564,28 @@ def create_gui(self): self.notebook = tkinter.ttk.Notebook(self.root) decompile_frame = self.create_decompile_frame(self.notebook) - self.notebook.add(decompile_frame, text=self.guistrings["decompile_text"].cget("text")) + self.notebook.add(decompile_frame) + self.guistrings.register_notebook_frame(self.notebook, decompile_frame, "decompile_text") compile_frame = self.create_compile_frame(self.notebook) - self.notebook.add(compile_frame, text=self.guistrings["compile_text"].cget("text")) + self.notebook.add(compile_frame) + self.guistrings.register_notebook_frame(self.notebook, compile_frame, "compile_text") upgrade_frame = self.create_upgrade_frame(self.notebook) - self.notebook.add(upgrade_frame, text=self.guistrings["upgrade"].cget("text")) + self.notebook.add(upgrade_frame) + self.guistrings.register_notebook_frame(self.notebook, upgrade_frame, "upgrade") decompile_script_frame = self.create_decompile_script_frame(self.notebook) - self.notebook.add(decompile_script_frame, text=self.guistrings["decomp_script"].cget("text")) + self.notebook.add(decompile_script_frame) + self.guistrings.register_notebook_frame(self.notebook, decompile_script_frame, "decomp_script") patcher_patch_frame = self.create_apply_patch_frame(self.notebook) - self.notebook.add(patcher_patch_frame, text=self.guistrings["apply_patch"].cget("text")) + self.notebook.add(patcher_patch_frame) + self.guistrings.register_notebook_frame(self.notebook, patcher_patch_frame, "apply_patch") patcher_create_frame = self.create_create_patch_frame(self.notebook) - self.notebook.add(patcher_create_frame, text=self.guistrings["create_patch"].cget("text")) + self.notebook.add(patcher_create_frame) + self.guistrings.register_notebook_frame(self.notebook, patcher_create_frame, "create_patch") self.notebook.pack(fill=X) self.notebook.select(self.preferences.get_default_tab()) @@ -775,6 +677,29 @@ def create_about_window(self): self.about_menu.protocol('WM_DELETE_WINDOW', self.about_menu.withdraw) + last_used_temporary_menu_index = 1 + def add_menu_item_and_get_index(self, menu: Menu, command=None, submenu=None) -> int: + templabel = f"MyTemp{self.last_used_temporary_menu_index}" + self.last_used_temporary_menu_index += 1 + if command: + menu.add_command(label=templabel, command=command) + elif submenu: + menu.add_cascade(label=templabel, menu=submenu) + item_index = menu.index(templabel) + return item_index + + def _add_translated_menu_item(self, menu: Menu, label_string_name: str, command=None, submenu=None): + index = self.add_menu_item_and_get_index(menu, command=command, submenu=submenu) + def translation_callback(): + menu.entryconfigure(index, label=self.guistrings.get(label_string_name)) + self.guistrings.register_callback(translation_callback) + + def add_translated_menu_command(self, menu: Menu, label_string_name: str, command: Callable[[], None]): + self._add_translated_menu_item(menu, label_string_name, command=command) + + def add_translated_menu_cascade(self, menu: Menu, label_string_name: str, submenu: Menu): + self._add_translated_menu_item(menu, label_string_name, submenu=submenu) + def create_menubar(self): menubar = Menu(self.root) @@ -788,40 +713,32 @@ def show_about_window(): if platform.system() == "Darwin": app_menu = Menu(menubar, name='apple') menubar.add_cascade(menu=app_menu) - app_menu.add_command(label=self.guistrings["about_coilsnake"].cget("text"), command=show_about_window) + self.add_translated_menu_command(app_menu, "about_coilsnake", show_about_window) # Tools pulldown menu tools_menu = Menu(menubar, tearoff=0) - tools_menu.add_command(label=self.guistrings["eb_proj_edit"].cget("text"), - command=self.open_ebprojedit) + self.add_translated_menu_command(tools_menu, "eb_proj_edit", self.open_ebprojedit) tools_menu.add_separator() - tools_menu.add_command(label=self.guistrings["expand_to_32"].cget("text"), - command=partial(gui_util.expand_rom, self.root)) - tools_menu.add_command(label=self.guistrings["expand_to_48"].cget("text"), - command=partial(gui_util.expand_rom_ex, self.root)) + self.add_translated_menu_command(tools_menu, "expand_to_32", partial(gui_util.expand_rom, self.root)) + self.add_translated_menu_command(tools_menu, "expand_to_48", partial(gui_util.expand_rom_ex, self.root)) tools_menu.add_separator() - tools_menu.add_command(label=self.guistrings["add_header"].cget("text"), - command=partial(gui_util.add_header_to_rom, self.root)) - tools_menu.add_command(label=self.guistrings["remove_header"].cget("text"), - command=partial(gui_util.strip_header_from_rom, self.root)) - menubar.add_cascade(label=self.guistrings["tools"].cget("text"), menu=tools_menu) + self.add_translated_menu_command(tools_menu, "add_header", partial(gui_util.add_header_to_rom, self.root)) + self.add_translated_menu_command(tools_menu, "remove_header", partial(gui_util.strip_header_from_rom, self.root)) + self.add_translated_menu_cascade(menubar, "tools", tools_menu) # Preferences pulldown menu self.pref_menu = Menu(menubar, tearoff=0) - self.pref_menu.add_command(label=self.guistrings["config_emu"].cget("text"), - command=self.set_emulator_exe) - self.pref_menu.add_command(label=self.guistrings["config_java"].cget("text"), - command=self.set_java_exe) + self.add_translated_menu_command(self.pref_menu, "config_emu", self.set_emulator_exe) + self.add_translated_menu_command(self.pref_menu, "config_java", self.set_java_exe) self.pref_menu.add_separator() - self.pref_menu.add_command(label=self.guistrings["config_ccscript"].cget("text"), - command=self.set_ccscript_offset) + self.add_translated_menu_command(self.pref_menu, "config_ccscript", self.set_ccscript_offset) self.pref_menu.add_separator() - self.pref_menu.add_command(label=self.get_debug_mode_command_label(), - command=self.set_debug_mode) + debug_mode_index = self.add_menu_item_and_get_index(self.pref_menu, command=self.set_debug_mode) + self.guistrings.register_callback(lambda: self.pref_menu.entryconfigure(debug_mode_index, label=self.get_debug_mode_command_label())) self.pref_menu.add_separator() self.pref_menu.add_command(label="Language", command=self.open_language_window) - menubar.add_cascade(label=self.guistrings["settings"].cget("text"), menu=self.pref_menu) + self.add_translated_menu_cascade(menubar, "settings", self.pref_menu) # Help menu help_menu = Menu(menubar, tearoff=0) @@ -830,11 +747,11 @@ def open_coilsnake_website(): webbrowser.open(information.WEBSITE, 2) if platform.system() != "Darwin": - help_menu.add_command(label=self.guistrings["about_coilsnake"].cget("text"), command=show_about_window) + self.add_translated_menu_command(help_menu, "about_coilsnake", show_about_window) - help_menu.add_command(label=self.guistrings["coilsnake_site"].cget("text"), command=open_coilsnake_website) + self.add_translated_menu_command(help_menu, "coilsnake_site", open_coilsnake_website) - menubar.add_cascade(label=self.guistrings["help_text"].cget("text"), menu=help_menu) + self.add_translated_menu_cascade(menubar, "help_text", help_menu) self.root.config(menu=menubar) @@ -842,15 +759,15 @@ def create_decompile_frame(self, notebook): self.decompile_fields = dict() decompile_frame = tkinter.ttk.Frame(notebook) - self.add_title_label_to_frame(text=self.guistrings["decomp_rom_new_proj"].cget("text"), frame=decompile_frame) + self.add_title_label_to_frame("decomp_rom_new_proj", frame=decompile_frame) profile_selector_init = self.add_profile_selector_to_frame(frame=decompile_frame, tab="decompile", fields=self.decompile_fields) - input_rom_entry = self.add_rom_fields_to_frame(name="ROM", frame=decompile_frame) + input_rom_entry = self.add_rom_fields_to_frame("rom", frame=decompile_frame) self.decompile_fields["rom"] = input_rom_entry - project_entry = self.add_project_fields_to_frame(name=self.guistrings["output_dir"].cget("text"), frame=decompile_frame) + project_entry = self.add_project_fields_to_frame("output_dir", frame=decompile_frame) self.decompile_fields["output_directory"] = project_entry profile_selector_init() @@ -858,8 +775,10 @@ def create_decompile_frame(self, notebook): def decompile_tmp(): self.do_decompile(input_rom_entry, project_entry) - decompile_button = Button(decompile_frame, text=self.guistrings["decompile_text"].cget("text"), command=decompile_tmp) + decompile_button = Button(decompile_frame, command=decompile_tmp) decompile_button.pack(fill=X, expand=1) + self.guistrings.register_widget(decompile_button, "decompile_text") + self.components.append(decompile_button) return decompile_frame @@ -868,17 +787,17 @@ def create_compile_frame(self, notebook): self.compile_fields = dict() compile_frame = tkinter.ttk.Frame(notebook) - self.add_title_label_to_frame(text=self.guistrings["comp_rom_new_proj"].cget("text"), frame=compile_frame) + self.add_title_label_to_frame("comp_rom_new_proj", frame=compile_frame) profile_selector_init = self.add_profile_selector_to_frame(frame=compile_frame, tab="compile", fields=self.compile_fields) - base_rom_entry = self.add_rom_fields_to_frame(name=self.guistrings["base_rom"].cget("text"), frame=compile_frame) + base_rom_entry = self.add_rom_fields_to_frame("base_rom", frame=compile_frame) self.compile_fields["base_rom"] = base_rom_entry - project_entry = self.add_project_fields_to_frame(name=self.guistrings["project"].cget("text"), frame=compile_frame) + project_entry = self.add_project_fields_to_frame("project", frame=compile_frame) self.compile_fields["project"] = project_entry - output_rom_entry = self.add_rom_fields_to_frame(name=self.guistrings["output_rom"].cget("text"), frame=compile_frame, save=True) + output_rom_entry = self.add_rom_fields_to_frame("output_rom", frame=compile_frame, save=True) self.compile_fields["output_rom"] = output_rom_entry profile_selector_init() @@ -886,19 +805,19 @@ def create_compile_frame(self, notebook): def compile_tmp(): self.do_compile(project_entry, base_rom_entry, output_rom_entry) - compile_button = Button(compile_frame, text=self.guistrings["compile_text"].cget("text"), command=compile_tmp) + compile_button = Button(compile_frame, command=compile_tmp) compile_button.pack(fill=X, expand=1) + self.guistrings.register_widget(compile_button, "compile_text") self.components.append(compile_button) return compile_frame def create_upgrade_frame(self, notebook): upgrade_frame = tkinter.ttk.Frame(notebook) - self.add_title_label_to_frame(text=self.guistrings["upgrade_info"].cget("text"), - frame=upgrade_frame) + self.add_title_label_to_frame("upgrade_info", frame=upgrade_frame) - rom_entry = self.add_rom_fields_to_frame(name=self.guistrings["clean_rom"].cget("text"), frame=upgrade_frame) - project_entry = self.add_project_fields_to_frame(name=self.guistrings["project"].cget("text"), frame=upgrade_frame) + rom_entry = self.add_rom_fields_to_frame("clean_rom", frame=upgrade_frame) + project_entry = self.add_project_fields_to_frame("project", frame=upgrade_frame) def upgrade_tmp(): self.preferences["default upgrade rom"] = rom_entry.get() @@ -906,8 +825,9 @@ def upgrade_tmp(): self.preferences.save() self.do_upgrade(rom_entry, project_entry) - self.upgrade_button = Button(upgrade_frame, text=self.guistrings["upgrade"].cget("text"), command=upgrade_tmp) + self.upgrade_button = Button(upgrade_frame, command=upgrade_tmp) self.upgrade_button.pack(fill=X, expand=1) + self.guistrings.register_widget(self.upgrade_button, "upgrade") self.components.append(self.upgrade_button) if self.preferences["default upgrade rom"]: @@ -922,11 +842,10 @@ def upgrade_tmp(): def create_decompile_script_frame(self, notebook): decompile_script_frame = tkinter.ttk.Frame(notebook) - self.add_title_label_to_frame(text=self.guistrings["decomp_rom_script"].cget("text"), - frame=decompile_script_frame) + self.add_title_label_to_frame("decomp_rom_script", frame=decompile_script_frame) - input_rom_entry = self.add_rom_fields_to_frame(name="ROM", frame=decompile_script_frame) - project_entry = self.add_project_fields_to_frame(name=self.guistrings["project"].cget("text"), frame=decompile_script_frame) + input_rom_entry = self.add_rom_fields_to_frame("rom", frame=decompile_script_frame) + project_entry = self.add_project_fields_to_frame("project", frame=decompile_script_frame) def decompile_script_tmp(): self.preferences["default decompile script rom"] = input_rom_entry.get() @@ -934,8 +853,9 @@ def decompile_script_tmp(): self.preferences.save() self.do_decompile_script(input_rom_entry, project_entry) - button = Button(decompile_script_frame, text=self.guistrings["decomp_script"].cget("text"), command=decompile_script_tmp) + button = Button(decompile_script_frame, command=decompile_script_tmp) button.pack(fill=X, expand=1) + self.guistrings.register_widget(button, "decomp_script") self.components.append(button) if self.preferences["default decompile script rom"]: @@ -950,13 +870,13 @@ def decompile_script_tmp(): def create_apply_patch_frame(self, notebook): patcher_patch_frame = tkinter.ttk.Frame(notebook) - self.add_title_label_to_frame(self.guistrings["apply_patch_info"].cget("text"), patcher_patch_frame) + self.add_title_label_to_frame("apply_patch_info", frame=patcher_patch_frame) - clean_rom_entry = self.add_rom_fields_to_frame(name=self.guistrings["clean_rom"].cget("text"), frame=patcher_patch_frame, padding_buttons=0) - patched_rom_entry = self.add_rom_fields_to_frame(name=self.guistrings["patched_rom"].cget("text"), frame=patcher_patch_frame, save=True, + clean_rom_entry = self.add_rom_fields_to_frame("clean_rom", frame=patcher_patch_frame, padding_buttons=0) + patched_rom_entry = self.add_rom_fields_to_frame("patched_rom", frame=patcher_patch_frame, save=True, padding_buttons=0) - patch_entry = self.add_patch_fields_to_frame(name=self.guistrings["patch"].cget("text"), frame=patcher_patch_frame) - headered_var = self.add_headered_field_to_frame(name=self.guistrings["header_ips_only"].cget("text"), frame=patcher_patch_frame) + patch_entry = self.add_patch_fields_to_frame("patch", frame=patcher_patch_frame) + headered_var = self.add_headered_field_to_frame("header_ips_only", frame=patcher_patch_frame) def patch_rom_tmp(): self.preferences["default clean rom"] = clean_rom_entry.get() @@ -965,8 +885,9 @@ def patch_rom_tmp(): self.preferences.save() self.do_patch_rom(clean_rom_entry, patched_rom_entry, patch_entry, headered_var) - button = Button(patcher_patch_frame, text=self.guistrings["patch_rom"].cget("text"), command=patch_rom_tmp) + button = Button(patcher_patch_frame, command=patch_rom_tmp) button.pack(fill=X, expand=1) + self.guistrings.register_widget(button, "patch_rom") self.components.append(button) if self.preferences["default clean rom"]: @@ -983,12 +904,11 @@ def patch_rom_tmp(): def create_create_patch_frame(self, notebook): patcher_create_frame = tkinter.ttk.Frame(notebook) - self.add_title_label_to_frame(self.guistrings["create_patch"].cget("text"), patcher_create_frame) + self.add_title_label_to_frame("create_patch", patcher_create_frame) - clean_rom_entry = self.add_rom_fields_to_frame(name=self.guistrings["clean_rom"].cget("text"), frame=patcher_create_frame, padding_buttons=0) - hacked_rom_entry = self.add_rom_fields_to_frame(name=self.guistrings["modded_rom"].cget("text"), frame=patcher_create_frame, - padding_buttons=0) - patch_entry = self.add_patch_fields_to_frame(name=self.guistrings["patch"].cget("text"), frame=patcher_create_frame, save=True) + clean_rom_entry = self.add_rom_fields_to_frame("clean_rom", frame=patcher_create_frame, padding_buttons=0) + hacked_rom_entry = self.add_rom_fields_to_frame("modded_rom", frame=patcher_create_frame, padding_buttons=0) + patch_entry = self.add_patch_fields_to_frame("patch", frame=patcher_create_frame, save=True) def create_patch_tmp(author, description, title): self.preferences["default clean rom"] = clean_rom_entry.get() @@ -1003,29 +923,29 @@ def create_patch_do_first(): elif patch_entry.get().endswith(".ips"): create_patch_tmp("", "", "") else: - exc = Exception(self.guistrings["invalid_format"].cget("text")) + exc = Exception(self.guistrings.get("invalid_format")) log.error(exc) def popup_ebp_patch_info(self, notebook): if self.preferences["default author"] is None: - self.preferences["default author"] = self.guistrings["author"].cget("text") + self.preferences["default author"] = self.gui_string_manager.get("author") author = self.preferences["default author"] if self.preferences["default description"] is None: - self.preferences["default description"] = self.guistrings["desc"].cget("text") + self.preferences["default description"] = self.gui_string_manager.get("desc") description = self.preferences["default description"] if self.preferences["default title"] is None: - self.preferences["default title"] = self.guistrings["title"].cget("text") + self.preferences["default title"] = self.gui_string_manager.get("title") title = self.preferences["default title"] top = self.top = Toplevel(notebook) - top.wm_title(self.guistrings["ebp_patch"].cget("text")) - l = Label(top,text=self.guistrings["input_ebp"].cget("text")) + top.wm_title(self.gui_string_manager.get("ebp_patch")) + l = Label(top,text=self.gui_string_manager.get("input_ebp")) l.pack() auth = Entry(top) auth.delete(0,) @@ -1050,11 +970,12 @@ def cleanup(): self.top.destroy() create_patch_tmp(author, description, title) - self.b=Button(top,text=self.guistrings["ok"].cget("text"),command=cleanup) + self.b=Button(top,text=self.gui_string_manager.get("ok"),command=cleanup) self.b.pack() - button = Button(patcher_create_frame, text=self.guistrings["create_patch"].cget("text"), command=create_patch_do_first) + button = Button(patcher_create_frame, command=create_patch_do_first) button.pack(fill=X, expand=1) + self.guistrings.register_widget(button, "create_patch") self.components.append(button) if self.preferences["default clean rom"]: @@ -1070,13 +991,17 @@ def cleanup(): return patcher_create_frame - def add_title_label_to_frame(self, text, frame): - Label(frame, text=text, justify=CENTER).pack(fill=BOTH, expand=1) + def add_title_label_to_frame(self, text_string_name, frame): + label = Label(frame, justify=CENTER) + label.pack(fill=BOTH, expand=1) + self.guistrings.register_widget(label, text_string_name) def add_profile_selector_to_frame(self, frame, tab, fields): profile_frame = tkinter.ttk.Frame(frame) - Label(profile_frame, text=self.guistrings["profile"].cget("text"), width=LABEL_WIDTH).pack(side=LEFT) + label = Label(profile_frame, width=LABEL_WIDTH) + label.pack(side=LEFT) + self.guistrings.register_widget(label, "profile") def tmp_select(profile_name): for field_id in fields: @@ -1103,12 +1028,12 @@ def tmp_reload_options(selected_profile_name=None): tmp_select(selected_profile_name) def tmp_new(): - profile_name = tkinter.simpledialog.askstring(self.guistrings["new_prof_name"].cget("text"), self.guistrings["specify_name"].cget("text")) + profile_name = tkinter.simpledialog.askstring(self.guistrings.get("new_prof_name"), self.guistrings.get("specify_name")) if profile_name: profile_name = profile_name.strip() if self.preferences.has_profile(tab, profile_name): tkinter.messagebox.showerror(parent=self.root, - title=self.guistrings["error"].cget("text"), + title=self.guistrings.get("error"), message="A profile with that name already exists.") return @@ -1125,23 +1050,26 @@ def tmp_save(): def tmp_delete(): if self.preferences.count_profiles(tab) <= 1: tkinter.messagebox.showerror(parent=self.root, - title=self.guistrings["error"].cget("text"), - message=self.guistrings["cant_delete_prof"].cget("text")) + title=self.guistrings.get("error"), + message=self.guistrings.get("cant_delete_prof")) else: self.preferences.delete_profile(tab, profile_var.get()) tmp_reload_options() self.preferences.save() - button = Button(profile_frame, text=self.guistrings["save"].cget("text"), width=BUTTON_WIDTH, command=tmp_save) + button = Button(profile_frame, width=BUTTON_WIDTH, command=tmp_save) button.pack(side=LEFT) + self.guistrings.register_widget(button, "save") self.components.append(button) - button = Button(profile_frame, text=self.guistrings["delete"].cget("text"), width=BUTTON_WIDTH, command=tmp_delete) + button = Button(profile_frame, width=BUTTON_WIDTH, command=tmp_delete) button.pack(side=LEFT) + self.guistrings.register_widget(button, "delete") self.components.append(button) - button = Button(profile_frame, text=self.guistrings["new"].cget("text"), width=BUTTON_WIDTH, command=tmp_new) + button = Button(profile_frame, width=BUTTON_WIDTH, command=tmp_new) button.pack(side=LEFT) + self.guistrings.register_widget(button, "new") self.components.append(button) profile_frame.pack(fill=X, expand=1) @@ -1151,10 +1079,12 @@ def tmp_reload_options_and_select_default(): return tmp_reload_options_and_select_default - def add_rom_fields_to_frame(self, name, frame, save=False, padding_buttons=1): + def add_rom_fields_to_frame(self, text_string_name, frame, save=False, padding_buttons=1): rom_frame = tkinter.ttk.Frame(frame) - Label(rom_frame, text="{}:".format(name), width=LABEL_WIDTH, justify=RIGHT).pack(side=LEFT) + label = Label(rom_frame, width=LABEL_WIDTH, justify=RIGHT) + label.pack(side=LEFT) + self.guistrings.register_callback(lambda: label.configure(text="{}:".format(self.guistrings.get(text_string_name)))) rom_entry = Entry(rom_frame) rom_entry.pack(side=LEFT, fill=BOTH, expand=1, padx=1) self.components.append(rom_entry) @@ -1165,15 +1095,17 @@ def browse_tmp(): def run_tmp(): self.run_rom(rom_entry) - button = Button(rom_frame, text=self.guistrings["browse"].cget("text"), command=browse_tmp, width=BUTTON_WIDTH) + button = Button(rom_frame, command=browse_tmp, width=BUTTON_WIDTH) button.pack(side=LEFT) + self.guistrings.register_widget(button, "browse") self.components.append(button) - button = Button(rom_frame, text=self.guistrings["run"].cget("text"), command=run_tmp, width=BUTTON_WIDTH) + button = Button(rom_frame, command=run_tmp, width=BUTTON_WIDTH) button.pack(side=LEFT) + self.guistrings.register_widget(button, "run") self.components.append(button) - for i in range(padding_buttons): + for _ in range(padding_buttons): button = Button(rom_frame, text="", width=BUTTON_WIDTH, state=DISABLED, takefocus=False) button.pack(side=LEFT) button.lower() @@ -1182,10 +1114,12 @@ def run_tmp(): return rom_entry - def add_project_fields_to_frame(self, name, frame): + def add_project_fields_to_frame(self, text_string_name, frame): project_frame = tkinter.ttk.Frame(frame) - Label(project_frame, text="{}:".format(name), width=LABEL_WIDTH, justify=RIGHT).pack(side=LEFT) + label = Label(project_frame, width=LABEL_WIDTH, justify=RIGHT) + label.pack(side=LEFT) + self.guistrings.register_callback(lambda: label.configure(text="{}:".format(self.guistrings.get(text_string_name)))) project_entry = Entry(project_frame) project_entry.pack(side=LEFT, fill=BOTH, expand=1, padx=1) self.components.append(project_entry) @@ -1199,28 +1133,31 @@ def open_tmp(): def edit_tmp(): self.open_ebprojedit(project_entry) - button = Button(project_frame, text=self.guistrings["browse"].cget("text"), command=browse_tmp, width=BUTTON_WIDTH) + button = Button(project_frame, command=browse_tmp, width=BUTTON_WIDTH) button.pack(side=LEFT) + self.guistrings.register_widget(button, "browse") self.components.append(button) - button = Button(project_frame, text=self.guistrings["open_text"].cget("text"), command=open_tmp, width=BUTTON_WIDTH) + button = Button(project_frame, command=open_tmp, width=BUTTON_WIDTH) button.pack(side=LEFT) + self.guistrings.register_widget(button, "open_text") self.components.append(button) - button = Button(project_frame, text=self.guistrings["edit"].cget("text"), command=edit_tmp, width=BUTTON_WIDTH) + button = Button(project_frame, command=edit_tmp, width=BUTTON_WIDTH) button.pack(side=LEFT) + self.guistrings.register_widget(button, "edit") self.components.append(button) project_frame.pack(fill=X, expand=1) return project_entry - def add_patch_fields_to_frame(self, name, frame, save=False): + def add_patch_fields_to_frame(self, text_string_name, frame, save=False): patch_frame = tkinter.ttk.Frame(frame) - Label( - patch_frame, text="{}:".format(name), width=LABEL_WIDTH, justify=RIGHT - ).pack(side=LEFT) + label = Label(patch_frame, width=LABEL_WIDTH, justify=RIGHT) + label.pack(side=LEFT) + self.guistrings.register_callback(lambda: label.configure(text="{}:".format(self.guistrings.get(text_string_name)))) patch_entry = Entry(patch_frame) patch_entry.pack(side=LEFT, fill=BOTH, expand=1, padx=1) self.components.append(patch_entry) @@ -1228,8 +1165,9 @@ def add_patch_fields_to_frame(self, name, frame, save=False): def browse_tmp(): browse_for_patch(self.root, patch_entry, save) - button = Button(patch_frame, text=self.guistrings["browse"].cget("text"), command=browse_tmp, width=BUTTON_WIDTH) + button = Button(patch_frame, command=browse_tmp, width=BUTTON_WIDTH) button.pack(side=LEFT) + self.guistrings.register_widget(button, "browse") self.components.append(button) button = Button(patch_frame, text="", width=BUTTON_WIDTH, state=DISABLED, takefocus=False) @@ -1240,14 +1178,15 @@ def browse_tmp(): return patch_entry - def add_headered_field_to_frame(self, name, frame): + def add_headered_field_to_frame(self, text_string_name, frame): patch_frame = tkinter.ttk.Frame(frame) headered_var = BooleanVar() - headered_check = Checkbutton(patch_frame, text=name, variable=headered_var) + headered_check = Checkbutton(patch_frame, variable=headered_var) headered_check.pack( side=LEFT, fill=BOTH, expand=1 ) + self.guistrings.register_widget(headered_check, text_string_name) self.components.append(headered_check) patch_frame.pack(fill=BOTH, expand=1)