You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 10:17:02