如何在CustomTkinter中实现多语言界面切换(含命令行方式)
CustomTkinter应用多语言切换实现方案
针对你的两个需求,下面提供完整的实现方案,基于现有代码修改,支持英语、波兰语、乌克兰语全界面切换:
完整修改代码
import customtkinter import os from PIL import Image class App(customtkinter.CTk): def __init__(self): super().__init__() self.title("FinPulse") self.geometry("750x450") self.wm_resizable(False, False) self.iconbitmap(r'C:\Users\vladm\Desktop\FinPulseCode\images\logo1.ico') # 语言字典:统一管理所有界面文本,键为控件标识,值为对应语言的文本 self.language_dict = { "uk": { "kurs_button": "Курси", "swap_button": "Конвертер", "news_button": "Новини", "settings_button": "Налаштування", "appearance_mode_label": "Кольорова схема:", "appearance_options": ["Системи", "Світла", "Темна"], "scaling_label": "Масштаб:", "language_label": "Мова:", "language_options": ["Українська", "English", "Polski"] }, "en": { "kurs_button": "Rates", "swap_button": "Converter", "news_button": "News", "settings_button": "Settings", "appearance_mode_label": "Color scheme:", "appearance_options": ["System", "Light", "Dark"], "scaling_label": "Scaling:", "language_label": "Language:", "language_options": ["Ukrainian", "English", "Polski"] }, "pl": { "kurs_button": "Stawki", "swap_button": "Konwerter", "news_button": "Wiadomości", "settings_button": "Ustawienia", "appearance_mode_label": "Schemat kolorów:", "appearance_options": ["System", "Jasny", "Ciemny"], "scaling_label": "Skala:", "language_label": "Język:", "language_options": ["Ukraiński", "Angielski", "Polski"] } } self.current_language = "uk" # 默认语言为乌克兰语 # set grid layout 1x2 self.grid_rowconfigure(0, weight=1) self.grid_columnconfigure(1, weight=1) # load images with light and dark mode image image_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "images") self.logo_image = customtkinter.CTkImage(Image.open(os.path.join(image_path, "logo.png")), size=(40, 40)) self.kurs = customtkinter.CTkImage(light_image=Image.open(os.path.join(image_path, "kurs_dark.png")), dark_image=Image.open(os.path.join(image_path, "kurs_light.png")), size=(25, 25)) self.news = customtkinter.CTkImage(light_image=Image.open(os.path.join(image_path, "news_dark.png")), dark_image=Image.open(os.path.join(image_path, "news_light.png")), size=(25, 25)) self.swap = customtkinter.CTkImage(light_image=Image.open(os.path.join(image_path, "swap_dark.png")), dark_image=Image.open(os.path.join(image_path, "swap_light.png")), size=(25, 25)) self.settings = customtkinter.CTkImage(light_image=Image.open(os.path.join(image_path, "settings_dark.png")), dark_image=Image.open(os.path.join(image_path, "settings_light.png")), size=(25, 25)) # create navigation frame self.navigation_frame = customtkinter.CTkFrame(self, corner_radius=0) self.navigation_frame.grid(row=0, column=0, sticky="nsew") self.navigation_frame.grid_rowconfigure(4, weight=1) self.navigation_frame_label = customtkinter.CTkLabel(self.navigation_frame, text="", image=self.logo_image) self.navigation_frame_label.grid(row=0, column=0, padx=20, pady=20) # 导航按钮初始化(使用语言字典的默认文本) self.kurs_button = customtkinter.CTkButton(self.navigation_frame, corner_radius=0, height=40, border_spacing=10, text=self.language_dict[self.current_language]["kurs_button"], fg_color="transparent", text_color=("gray10", "gray90"), hover_color=("gray70", "gray30"), image=self.kurs, anchor="w", command=self.kurs_button_event) self.kurs_button.grid(row=1, column=0, sticky="ew") self.swap_button = customtkinter.CTkButton(self.navigation_frame, corner_radius=0, height=40, border_spacing=10, text=self.language_dict[self.current_language]["swap_button"], fg_color="transparent", text_color=("gray10", "gray90"), hover_color=("gray70", "gray30"), image=self.swap, anchor="w", command=self.swap_button_event) self.swap_button.grid(row=2, column=0, sticky="ew") self.news_button = customtkinter.CTkButton(self.navigation_frame, corner_radius=0, height=40, border_spacing=10, text=self.language_dict[self.current_language]["news_button"], fg_color="transparent", text_color=("gray10", "gray90"), hover_color=("gray70", "gray30"), image=self.news, anchor="w", command=self.news_button_event) self.news_button.grid(row=3, column=0, sticky="ew") self.settings_button = customtkinter.CTkButton(self.navigation_frame, corner_radius=0, height=40, border_spacing=10, text=self.language_dict[self.current_language]["settings_button"], fg_color="transparent", text_color=("gray10", "gray90"), hover_color=("gray70", "gray30"), image=self.settings, anchor="w", command=self.settings_button_event) self.settings_button.grid(row=4, column=0, sticky="s") # create kurs frame self.kurs_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color="transparent") # create swap frame self.swap_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color="transparent") # create news frame self.news_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color="transparent") # create settings frame self.settings_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color="transparent") self.settings_frame.grid_columnconfigure((0,1,2), weight=1) # 外观模式设置(使用语言字典默认文本) self.appearance_mode_label = customtkinter.CTkLabel(self.settings_frame, text=self.language_dict[self.current_language]["appearance_mode_label"], anchor="w") self.appearance_mode_label.grid(row=0, column=0, padx=20, pady=(10, 0)) self.settings_appearance_mode_menu = customtkinter.CTkOptionMenu(self.settings_frame, values=self.language_dict[self.current_language]["appearance_options"], command=self.change_appearance_mode_event) self.settings_appearance_mode_menu.grid(row=1, column=0, padx=(10, 10), pady=(0, 20)) # 缩放设置(使用语言字典默认文本) self.scaling_label = customtkinter.CTkLabel(self.settings_frame, text=self.language_dict[self.current_language]["scaling_label"], anchor="w") self.scaling_label.grid(row=0, column=1, padx=20, pady=(10, 0)) self.scaling_optionemenu = customtkinter.CTkOptionMenu(self.settings_frame, values=["100%", "110%", "120%", "130%", "140%", "150%"], command=self.change_scaling_event) self.scaling_optionemenu.grid(row=1, column=1, padx=(10, 10), pady=(0, 20)) # 语言选择控件(使用语言字典默认文本) self.language_label = customtkinter.CTkLabel(self.settings_frame, text=self.language_dict[self.current_language]["language_label"], anchor="w") self.language_label.grid(row=0, column=2, padx=20, pady=(10, 0)) self.language_optionmenu = customtkinter.CTkOptionMenu(self.settings_frame, values=self.language_dict[self.current_language]["language_options"], command=self.change_language_event) self.language_optionmenu.grid(row=1, column=2, padx=(10, 10), pady=(0, 20)) # 记录所有需要更新文本的控件,键为语言字典中的标识,值为控件对象 self.ui_elements = { "kurs_button": self.kurs_button, "swap_button": self.swap_button, "news_button": self.news_button, "settings_button": self.settings_button, "appearance_mode_label": self.appearance_mode_label, "scaling_label": self.scaling_label, "language_label": self.language_label } # select default frame self.select_frame_by_name("kurs") def select_frame_by_name(self, name): # set button color for selected button self.kurs_button.configure(fg_color=("gray75", "gray25") if name == "kurs" else "transparent") self.swap_button.configure(fg_color=("gray75", "gray25") if name == "swap" else "transparent") self.news_button.configure(fg_color=("gray75", "gray25") if name == "news" else "transparent") self.settings_button.configure(fg_color=("gray75", "gray25") if name == "settings" else "transparent") # show selected frame if name == "kurs": self.kurs_frame.grid(row=0, column=1, sticky="nsew") else: self.kurs_frame.grid_forget() if name == "swap": self.swap_frame.grid(row=0, column=1, sticky="nsew") else: self.swap_frame.grid_forget() if name == "news": self.news_frame.grid(row=0, column=1, sticky="nsew") else: self.news_frame.grid_forget() if name == "settings": self.settings_frame.grid(row=0, column=1, sticky="nsew") else: self.settings_frame.grid_forget() def kurs_button_event(self): self.select_frame_by_name("kurs") def swap_button_event(self): self.select_frame_by_name("swap") def news_button_event(self): self.select_frame_by_name("news") def settings_button_event(self): self.select_frame_by_name("settings") def change_appearance_mode_event(self, selected_value): # 根据当前语言获取对应的英文值(customtkinter只识别英文参数) lang = self.current_language option_index = self.language_dict[lang]["appearance_options"].index(selected_value) english_value = self.language_dict["en"]["appearance_options"][option_index] customtkinter.set_appearance_mode(english_value) def change_scaling_event(self, new_scaling: str): new_scaling_float = int(new_scaling.replace("%", "")) / 100 customtkinter.set_widget_scaling(new_scaling_float) def change_language_event(self, selected_option): # 根据选中的选项确定当前语言 lang_map = { "Українська": "uk", "English": "en", "Polski": "pl", "Ukrainian": "uk", "Angielski": "pl" } self.current_language = lang_map[selected_option] # 更新界面所有文本 self.update_ui_text() def update_ui_text(self): current_lang_data = self.language_dict[self.current_language] # 更新普通控件文本 for key, element in self.ui_elements.items(): element.configure(text=current_lang_data[key]) # 更新下拉菜单选项 self.settings_appearance_mode_menu.configure(values=current_lang_data["appearance_options"]) self.language_optionmenu.configure(values=current_lang_data["language_options"]) # 保持下拉菜单当前选中项的对应翻译 current_appearance = self.settings_appearance_mode_menu.get() old_lang = [k for k, v in self.language_dict.items() if current_appearance in v["appearance_options"]][0] old_index = self.language_dict[old_lang]["appearance_options"].index(current_appearance) self.settings_appearance_mode_menu.set(current_lang_data["appearance_options"][old_index]) current_lang = self.language_optionmenu.get() old_lang2 = [k for k, v in self.language_dict.items() if current_lang in v["language_options"]][0] old_index2 = self.language_dict[old_lang2]["language_options"].index(current_lang) self.language_optionmenu.set(current_lang_data["language_options"][old_index2]) if __name__ == "__main__": app = App() app.mainloop()
关键实现说明
1. 语言字典设计
用字典统一管理所有需要翻译的文本,每个语言对应独立的键值对集合,后续新增语言只需在字典中添加对应条目,无需修改控件初始化代码。
2. 控件文本动态绑定
初始化控件时直接从语言字典中读取默认语言的文本,同时将所有需更新的控件存入ui_elements字典,方便后续批量更新。
3. 语言切换逻辑
- 通过
change_language_event方法识别用户选中的语言,更新current_language变量 - 调用
update_ui_text方法遍历所有控件,替换为对应语言的文本,同时更新下拉菜单的选项列表,并保持当前选中项的一致性
4. 外观模式兼容
因为customtkinter.set_appearance_mode只接受英文参数,所以在切换外观模式时,需要根据当前语言的选项索引映射到英文值。
内容的提问来源于stack exchange,提问作者user23320140
相关产品推荐
相关产品推荐

