-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
340 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
import tkinter as tk | ||
from tkinter import ttk | ||
from functools import partial | ||
import sv_ttk | ||
|
||
|
||
def show_message(title="Title", details="Description", *, parent=None, icon=None): | ||
return popup( | ||
parent, | ||
title, | ||
details, | ||
icon, | ||
buttons=[("Yes", None, "default")], | ||
) | ||
|
||
|
||
def ask_ok_cancel(title="Title", details="Description", *, parent=None, icon=None): | ||
return popup( | ||
parent, | ||
title, | ||
details, | ||
icon, | ||
buttons=[("Yes", True, "accent"), ("Cancel", None)], | ||
) | ||
|
||
|
||
def ask_yes_no(title="Title", details="Description", *, parent=None, icon=None): | ||
return popup( | ||
parent, | ||
title, | ||
details, | ||
icon, | ||
buttons=[("Yes", True, "accent"), ("No", False)], | ||
) | ||
|
||
|
||
def ask_yes_no_cancel(title="Title", details="Description", *, parent=None, icon=None): | ||
return popup( | ||
parent, | ||
title, | ||
details, | ||
icon, | ||
buttons=[("Yes", True, "accent"), ("No", False), ("Cancel", None)], | ||
) | ||
|
||
|
||
def ask_retry_cancel(title="Title", details="Description", *, parent=None, icon=None): | ||
return popup( | ||
parent, | ||
title, | ||
details, | ||
icon, | ||
buttons=[("重试", True, "accent"), ("Cancel", None)], | ||
) | ||
|
||
|
||
def ask_allow_block(title="Title", details="Description", *, parent=None, icon=None): | ||
return popup( | ||
parent, | ||
title, | ||
details, | ||
icon, | ||
buttons=[("运行", True, "accent"), ("禁止", False)], | ||
) | ||
|
||
|
||
def popup(parent, title, details, icon, *, buttons): | ||
dialog = tk.Toplevel() | ||
|
||
result = None | ||
|
||
big_frame = ttk.Frame(dialog) | ||
big_frame.pack(fill="both", expand=True) | ||
big_frame.columnconfigure(0, weight=1) | ||
big_frame.rowconfigure(0, weight=1) | ||
|
||
info_frame = ttk.Frame(big_frame, padding=(10, 12), style="Dialog_info.TFrame") | ||
info_frame.grid(row=0, column=0, sticky="nsew") | ||
info_frame.columnconfigure(1, weight=1) | ||
info_frame.rowconfigure(1, weight=1) | ||
|
||
try: | ||
color = big_frame.tk.call("set", "themeColors::dialogInfoBg") | ||
except tk.TclError: | ||
color = big_frame.tk.call("ttk::style", "lookup", "TFrame", "-background") | ||
|
||
icon_label = ttk.Label(info_frame, image=icon, anchor="nw", background=color) | ||
if icon is not None: | ||
icon_label.grid( | ||
row=0, column=0, sticky="nsew", padx=(12, 0), pady=10, rowspan=2 | ||
) | ||
|
||
title_label = ttk.Label( | ||
info_frame, text=title, anchor="nw", font=("", 24, "bold"), background=color | ||
) | ||
title_label.grid(row=0, column=1, sticky="nsew", padx=(12, 17), pady=(10, 8)) | ||
|
||
detail_label = ttk.Label(info_frame, text=details, font=("", 15), anchor="nw", background=color) | ||
detail_label.grid(row=1, column=1, sticky="nsew", padx=(12, 17), pady=(5, 10)) | ||
|
||
button_frame = ttk.Frame( | ||
big_frame, padding=(22, 22, 12, 22), style="Dialog_buttons.TFrame" | ||
) | ||
button_frame.grid(row=2, column=0, sticky="nsew") | ||
|
||
def on_button(value): | ||
nonlocal result | ||
result = value | ||
dialog.destroy() | ||
|
||
for index, button_value in enumerate(buttons): | ||
style = None | ||
state = None | ||
default = False | ||
sticky = "nes" if len(buttons) == 1 else "nsew" | ||
|
||
if len(button_value) > 2: | ||
if button_value[2] == "accent": | ||
style = "Accent.TButton" | ||
default = True | ||
elif button_value[2] == "disabled": | ||
state = "disabled" | ||
elif button_value[2] == "default": | ||
default = True | ||
|
||
button = ttk.Button( | ||
button_frame, | ||
text=button_value[0], | ||
width=18, | ||
command=partial(on_button, button_value[1]), | ||
style=style, | ||
state=state, | ||
) | ||
if default: | ||
button.bind("<Return>", button["command"]) | ||
button.focus() | ||
|
||
button.grid(row=0, column=index, sticky=sticky, padx=(0, 10)) | ||
|
||
button_frame.columnconfigure(index, weight=1) | ||
|
||
dialog.overrideredirect(True) | ||
dialog.update() | ||
|
||
dialog_width = dialog.winfo_width() | ||
dialog_height = dialog.winfo_height() | ||
|
||
if parent is None: | ||
parent_width = dialog.winfo_screenwidth() | ||
parent_height = dialog.winfo_screenheight() | ||
parent_x = 0 | ||
parent_y = 0 | ||
else: | ||
parent_width = parent.winfo_width() | ||
parent_height = parent.winfo_height() | ||
parent_x = parent.winfo_x() | ||
parent_y = parent.winfo_y() | ||
|
||
x_coord = int(parent_width / 2 + parent_x - dialog_width / 2) + 250 | ||
y_coord = int(parent_height / 2 + parent_y - dialog_height / 2) + 50 | ||
|
||
dialog.geometry("+{}+{}".format(x_coord, y_coord)) | ||
dialog.minsize(600, 300) | ||
|
||
dialog.transient(parent) | ||
dialog.grab_set() | ||
|
||
dialog.wait_window() | ||
return result | ||
|
||
|
||
if __name__ == "__main__": | ||
window = tk.Tk() | ||
|
||
sv_ttk.use_light_theme() | ||
|
||
window.geometry("600x600") | ||
window.mainloop() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
import ctypes | ||
import json | ||
import os | ||
import re | ||
import sys | ||
import sv_ttk | ||
import dialogs | ||
from random import choices | ||
from tkinter import filedialog, StringVar, Tk | ||
from tkinter.ttk import * | ||
|
||
# 匹配的前缀 | ||
prefixes = [ | ||
"tooltip", "displayName", "Text.yellow", "Text.of", "Text.white", | ||
"Text.green", "Text.gray", "Text.gold", "Text.darkPurple", | ||
"Text.blue", "Text.darkGreen", "Text.aqua", "Text.red" | ||
] | ||
|
||
# 定义存储键值对的字典 | ||
translation_dict = {} | ||
|
||
|
||
def browseJson(): | ||
json_var.set( | ||
filedialog.askopenfilename(filetypes=(('选择回填需要的json', "*.json"),), initialdir=os.path.abspath(os.path.dirname(__file__)))) | ||
|
||
def browseKubeJS(): | ||
kubejs_var.set( | ||
filedialog.askdirectory(title='选择处理 KubeJS 的文件夹', initialdir=os.path.abspath(os.path.dirname(__file__)))) | ||
|
||
|
||
def on_sv_ttk_theme_select(event): | ||
if sv_ttk_theme_entry.get() == "亮色": | ||
sv_ttk.use_light_theme() | ||
else: | ||
sv_ttk.use_dark_theme() | ||
|
||
def on_mode_select(event): | ||
if mode_entry.get() == "回填": | ||
return mode_entry.set("回填") | ||
|
||
|
||
def gui(): | ||
saveButton.grid_forget() | ||
r = 0 | ||
json_lb.grid(row=r, column=0, pady=5, padx=20, sticky='nsew') | ||
json_entry.grid(row=r, column=1, pady=5, sticky='nsew') | ||
jsonButton.grid(row=r, column=2, pady=5, padx=30, sticky='nsew') | ||
r += 1 | ||
kubejs_lb.grid(row=r, column=0, pady=5, padx=20, sticky='nsew') | ||
kubejs_entry.grid(row=r, column=1, pady=5, sticky='nsew') | ||
kubeJSButton.grid(row=r, column=2, pady=5, padx=30, sticky='nsew') | ||
r += 1 | ||
mode_lb.grid(row=r, column=0, pady=5, padx=20, sticky='nsew') | ||
mode_entry.current(0) | ||
mode_entry.grid(row=r, column=1, pady=5, padx=30, sticky='nsew') | ||
r += 1 | ||
sv_ttk_theme_lb.grid(row=r, column=0, pady=5, padx=20, sticky='nsew') | ||
sv_ttk_theme_entry.current(0) | ||
sv_ttk_theme_entry.grid(row=r, column=1, pady=5, padx=30, sticky='nsew') | ||
r += 1 | ||
saveButton.grid(row=r, column=2, pady=5, padx=30, sticky='nsew') | ||
|
||
# 让列和行自适应 | ||
for i in range(3): # 列数 | ||
root.columnconfigure(i, weight=1) | ||
|
||
for i in range(r + 1): # 行数 | ||
root.rowconfigure(i, weight=1) | ||
|
||
|
||
def replace_keys_in_js(json_file, folder_path): | ||
with open(json_file, 'r', encoding='utf-8') as json_file: | ||
translation_dict = json.load(json_file) | ||
|
||
# 遍历文件夹里的所有.js文件 | ||
for root, dirs, files in os.walk(folder_path): | ||
for filename in files: | ||
if filename.endswith(".js"): | ||
file_path = os.path.join(root, filename) | ||
with open(file_path, 'r', encoding='utf-8') as file: | ||
js_content = file.read() | ||
|
||
# 遍历翻译字典,将匹配的键替换为对应的值 | ||
for key, value in translation_dict.items(): | ||
js_content = js_content.replace(f'{key}', f'\'{value}\'') | ||
|
||
# 写回原始文件 | ||
with open(file_path, 'w', encoding='utf-8') as file: | ||
file.write(js_content) | ||
dialogs.show_message('KubeJS翻译工具', 'KubeJS翻译工具回填翻译成功') | ||
|
||
def runFromGui(): | ||
if len(kubejs_var.get()) == 0 and mode_entry.get() == "提取": | ||
dialogs.show_message("错误", "你需要选一个文件夹。") | ||
elif mode_entry.get() == "提取": | ||
# 遍历文件夹里的所有.js文件 | ||
for root, dirs, files in os.walk(kubejs_var.get()): | ||
for filename in files: | ||
if filename.endswith(".js"): | ||
file_path = os.path.join(root, filename) | ||
with open(file_path, 'r', encoding='utf-8') as file: | ||
js_content = file.read() | ||
|
||
# 使用正则表达式匹配前缀并提取内容 | ||
for prefix in prefixes: | ||
pattern = re.compile(rf'{prefix}\s*\([\'"]([^\'"]+)[\'"]\)') | ||
matches = pattern.findall(js_content) | ||
for match in matches: | ||
# 生成随机键 | ||
random_key = 'kubejs.key.' + ''.join(choices("abcdefghijklmnopqrstuvwxyz", k=5)) | ||
# 替换匹配的内容为随机键 | ||
js_content = js_content.replace(f'{prefix}(\'{match}\')', f'{prefix}({random_key})') | ||
# 添加到翻译字典中 | ||
translation_dict[random_key] = match | ||
# 写回原始文件 | ||
with open(file_path, 'w', encoding='utf-8') as file: | ||
file.write(js_content) | ||
|
||
# 保存提取出的内容为en_us.json文件 | ||
with open("en_us.json", 'w', encoding='utf-8') as json_file: | ||
json.dump(translation_dict, json_file, indent=2, ensure_ascii=False) | ||
dialogs.show_message('KubeJS翻译工具', | ||
f'KubeJS翻译工具提取翻译成功\njson已保存在当前程序所在的文件夹中\n注意,本工具提取不全,请人工检查未提取内容') | ||
elif mode_entry.get() == "回填": | ||
replace_keys_in_js(json_var.get(), kubejs_var.get()) | ||
|
||
root = Tk() | ||
if sys.platform == "win32": | ||
try: | ||
# >= Windows 8.1 | ||
ScaleFactor = ctypes.windll.shcore.SetProcessDpiAwareness(2) | ||
except: | ||
# <= Windows 8.0 | ||
ScaleFactor = ctypes.windll.user32.SetProcessDPIAware(0) | ||
|
||
root.title("KubeJS翻译工具 1.0") | ||
root.iconbitmap(bitmap="icon.ico") | ||
kubejs_var, json_var = StringVar(), StringVar() | ||
kubejs_entry = Entry(root, textvariable=kubejs_var) | ||
json_entry = Entry(root, textvariable=json_var) | ||
kubejs_lb = Label(root, text="选择处理 KubeJS 的文件夹", font=10) | ||
json_lb = Label(root, text="选择回填需要的json", font=10) | ||
kubeJSButton = Button(root, text="选择", command=browseKubeJS) | ||
jsonButton = Button(root, text="选择", command=browseJson) | ||
mode_lb = Label(root, text="工作模式", font=10) | ||
mode_list = ["提取", "回填"] | ||
mode_entry = Combobox(root, state="readonly", values=mode_list) | ||
mode_entry.bind("<<ComboboxSelected>>", on_mode_select) | ||
sv_ttk.use_light_theme() | ||
sv_ttk_theme_lb = Label(root, text="工具窗口颜色设置", font=10) | ||
sv_ttk_theme_list = ["亮色", "暗色"] | ||
sv_ttk_theme_entry = Combobox(root, state="readonly", values=sv_ttk_theme_list) | ||
sv_ttk_theme_entry.bind("<<ComboboxSelected>>", on_sv_ttk_theme_select) | ||
saveButton = Button(root, text="生成", command=runFromGui) | ||
gui() | ||
root.update_idletasks() | ||
x = (root.winfo_screenwidth() // 2) - (root.winfo_width() // 2) + 250 | ||
y = (root.winfo_screenheight() // 2) - (root.winfo_height() // 2) | ||
root.geometry('{}x{}+{}+{}'.format(700, 300, x, y)) | ||
|
||
root.mainloop() |