|
|
@@ -0,0 +1,251 @@
|
|
|
+'''
|
|
|
+Author: deng.yinping deng.yinping@muchinfo.cn
|
|
|
+Date: 2024-12-06 10:22:52
|
|
|
+LastEditors: deng.yinping deng.yinping@muchinfo.cn
|
|
|
+LastEditTime: 2024-12-06 14:01:17
|
|
|
+FilePath: \MTP20_WEB_GLOBAL_i18n_Tool\common.py
|
|
|
+Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
|
|
+'''
|
|
|
+import json
|
|
|
+import pandas as pd
|
|
|
+from openpyxl import load_workbook
|
|
|
+from openpyxl.styles import PatternFill
|
|
|
+import os
|
|
|
+
|
|
|
+
|
|
|
+class CommonUti:
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def read_from_json(file_path):
|
|
|
+ # 从JSON文件中读取内容
|
|
|
+ with open(file_path, 'r', encoding='utf-8') as file:
|
|
|
+ data = json.load(file)
|
|
|
+
|
|
|
+ return data
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def get_leaf_paths(data, path="", result=None):
|
|
|
+ # 递归函数,遍历所有终节点并将全路径和值存入字典
|
|
|
+ # 不需要翻译的Key
|
|
|
+ ignore_data = ['app.name', 'mine.setting.chinese',
|
|
|
+ 'mine.setting.english', 'mine.setting.enth']
|
|
|
+ if result is None:
|
|
|
+ result = {}
|
|
|
+
|
|
|
+ if isinstance(data, dict):
|
|
|
+ # 如果是字典,继续遍历字典中的每个键
|
|
|
+ for key, value in data.items():
|
|
|
+ current_path = f"{path}.{key}" if path else key
|
|
|
+ CommonUti.get_leaf_paths(value, current_path, result)
|
|
|
+ elif isinstance(data, list):
|
|
|
+ # 如果是列表,遍历每个元素
|
|
|
+ for index, item in enumerate(data):
|
|
|
+ current_path = f"{path}[{index}]"
|
|
|
+ CommonUti.get_leaf_paths(item, current_path, result)
|
|
|
+ else:
|
|
|
+ # 如果是终节点,将当前路径和值保存到字典中
|
|
|
+ if path not in ignore_data:
|
|
|
+ result[path] = data
|
|
|
+
|
|
|
+ return result
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def generate_dict_from_json(file_path):
|
|
|
+ data = CommonUti.read_from_json(file_path)
|
|
|
+ # 生成全路径的字典
|
|
|
+ leaf_paths_dict = CommonUti.get_leaf_paths(data)
|
|
|
+ return leaf_paths_dict
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def generate_excle_by_oem(oem, output_folder, zh_data, en_data, th_data, tw_data):
|
|
|
+ df = pd.DataFrame.from_dict(zh_data, orient='index', columns=['zh-CN'])
|
|
|
+
|
|
|
+ # 将 其它 的值合并到 DataFrame 中
|
|
|
+ df['en-US'] = df.index.map(en_data).fillna('')
|
|
|
+ df['th-TH'] = df.index.map(th_data).fillna('')
|
|
|
+ df['zh-TW'] = df.index.map(tw_data).fillna('')
|
|
|
+
|
|
|
+ # 重置索引,以便将索引变为一列
|
|
|
+ df.reset_index(inplace=True)
|
|
|
+ df.rename(columns={'index': 'Key'}, inplace=True) # 将索引列重命名为 'Key'
|
|
|
+
|
|
|
+ # 导出到 Excel 文件
|
|
|
+ output_file = output_folder + '/excels/' + oem + '.xlsx'
|
|
|
+ df.to_excel(output_file, index=False)
|
|
|
+
|
|
|
+ # 使用 openpyxl 设置列宽
|
|
|
+ wb = load_workbook(output_file)
|
|
|
+ ws = wb.active
|
|
|
+
|
|
|
+ # 指定列宽
|
|
|
+ ws.column_dimensions['A'].width = 60 # 设置第一列宽度
|
|
|
+ ws.column_dimensions['B'].width = 50 # 设置第二列宽度
|
|
|
+ ws.column_dimensions['C'].width = 50 # 设置第三列宽度
|
|
|
+ ws.column_dimensions['D'].width = 50 # 设置第四列宽度
|
|
|
+ ws.column_dimensions['E'].width = 50 # 设置第五列宽度
|
|
|
+
|
|
|
+ # 保存更改
|
|
|
+ wb.save(output_file)
|
|
|
+
|
|
|
+ print("字典已成功输出到 " + output_file)
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def update_excel_by_inc(oem, output_folder, inc_name):
|
|
|
+ ''' 增量更新,在生成excel里标注新增的key为黄色 '''
|
|
|
+ # 读取输出的Excel文件, 格式:key(A) zh-CN(B) en-US(C) th-TH(C) zh-TW(D)
|
|
|
+ inc_file = output_folder + "/excels/" + inc_name + ".xlsx"
|
|
|
+ if not os.path.exists(inc_file):
|
|
|
+ return
|
|
|
+
|
|
|
+ df = pd.read_excel(inc_file)
|
|
|
+ # 将 A 列和 C 列转换为zh-CN字典
|
|
|
+ old_dic = dict(zip(df.iloc[:, 0], df.iloc[:, 1]))
|
|
|
+
|
|
|
+ new_file = output_folder + "/excels/" + oem + ".xlsx"
|
|
|
+ wb = load_workbook(new_file)
|
|
|
+ sheet = wb.active
|
|
|
+
|
|
|
+ # 定义黄色填充样式
|
|
|
+ yellow_fill = PatternFill(
|
|
|
+ start_color="FFFF00", end_color="FFFF00", fill_type="solid")
|
|
|
+
|
|
|
+ # 遍历第一列
|
|
|
+ for row in sheet.iter_rows(min_row=2, max_row=sheet.max_row, min_col=1, max_col=1):
|
|
|
+ cell = row[0]
|
|
|
+ if cell.value not in old_dic:
|
|
|
+ cell.fill = yellow_fill
|
|
|
+
|
|
|
+ # 保存文件
|
|
|
+ update_file = output_folder + "/excels/" + oem + "_inc.xlsx"
|
|
|
+ wb.save(update_file) # 保存为新文件,避免覆盖原文件
|
|
|
+
|
|
|
+ print("增量字典已成功输出到 " + update_file)
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def generate_excle(oem, output_folder, json_folder, oem_json_folder):
|
|
|
+ # 据JSON生成excel文件
|
|
|
+ zh_data = CommonUti.read_data_from_json(
|
|
|
+ oem, json_folder, oem_json_folder, 'zh-CN')
|
|
|
+ en_data = CommonUti.read_data_from_json(
|
|
|
+ oem, json_folder, oem_json_folder, 'en-US')
|
|
|
+ th_data = CommonUti.read_data_from_json(
|
|
|
+ oem, json_folder, oem_json_folder, 'th-TH')
|
|
|
+ tw_data = CommonUti.read_data_from_json(
|
|
|
+ oem, json_folder, oem_json_folder, 'zh-TW')
|
|
|
+
|
|
|
+ CommonUti.generate_excle_by_oem(
|
|
|
+ oem, output_folder, zh_data, en_data, th_data, tw_data)
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def read_data_from_json(oem, json_folder, oem_json_folder, lang):
|
|
|
+ common_file = json_folder + lang + '.json'
|
|
|
+ common_data = CommonUti.generate_dict_from_json(common_file)
|
|
|
+
|
|
|
+ # 处理OEM数据
|
|
|
+ oem_file = oem_json_folder + oem + '/locales/extras/' + lang + '.json'
|
|
|
+ if os.path.exists(oem_file):
|
|
|
+ oem_data = CommonUti.generate_dict_from_json(oem_file)
|
|
|
+
|
|
|
+ if oem_data:
|
|
|
+ for key, value in oem_data.items():
|
|
|
+ # 更新通用字典的oem个性化值(有则更新,无则添加)
|
|
|
+ common_data[key] = value
|
|
|
+
|
|
|
+ return common_data
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def read_from_excel(oem, output_folder):
|
|
|
+ # 读取输出的Excel文件, 格式:key(A) zh-CN(B) en-US(C) th-TH(C) zh-TW(D)
|
|
|
+ excel_filename = output_folder + "/excels/" + oem + ".xlsx"
|
|
|
+ df = pd.read_excel(excel_filename)
|
|
|
+
|
|
|
+ # 将 A 列和 C 列转换为zh-CN字典
|
|
|
+ dict_cn = dict(zip(df.iloc[:, 0], df.iloc[:, 1]))
|
|
|
+
|
|
|
+ # 将 A 列和 C 列转换为en-US字典
|
|
|
+ dict_en = dict(zip(df.iloc[:, 0], df.iloc[:, 2]))
|
|
|
+
|
|
|
+ # 将 A 列和 D 列转换为th-TH字典
|
|
|
+ dict_th = dict(zip(df.iloc[:, 0], df.iloc[:, 3]))
|
|
|
+
|
|
|
+ # 将 A 列和 E 列转换为zh-TW字典
|
|
|
+ dict_tw = dict(zip(df.iloc[:, 0], df.iloc[:, 4]))
|
|
|
+
|
|
|
+ return dict_cn, dict_en, dict_th, dict_tw
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def modify_json_values(data, modify_func, path="", extra_data=None, exclude_data=None):
|
|
|
+ if isinstance(data, dict): # 如果是字典类型,遍历键值对
|
|
|
+ for key, value in data.items():
|
|
|
+ new_path = f"{path}.{key}" if path else key # 更新路径
|
|
|
+ if isinstance(value, (dict, list)): # 如果值是字典或列表,递归调用
|
|
|
+ CommonUti.modify_json_values(value, modify_func,
|
|
|
+ new_path, extra_data, exclude_data)
|
|
|
+ else:
|
|
|
+ # 对终节点进行修改,传递完整路径和辅助字典
|
|
|
+ data[key] = modify_func(
|
|
|
+ value, new_path, extra_data, exclude_data)
|
|
|
+ elif isinstance(data, list): # 如果是列表类型,遍历列表中的每个元素
|
|
|
+ for index, item in enumerate(data):
|
|
|
+ new_path = f"{path}[{index}]" # 更新路径为列表的索引
|
|
|
+ if isinstance(item, (dict, list)):
|
|
|
+ CommonUti.modify_json_values(item, modify_func,
|
|
|
+ new_path, extra_data, exclude_data)
|
|
|
+ else:
|
|
|
+ # 修改列表中的值,并传递完整路径
|
|
|
+ data[index] = modify_func(item, new_path, extra_data)
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def modify_func(value, path, extra_data, exclude_data):
|
|
|
+ # 修改函数,基于额外字典的内容修改值
|
|
|
+ if extra_data and path in extra_data:
|
|
|
+ # exclude_data 为空 或是path不在exclude_data
|
|
|
+ if (exclude_data is None) or (exclude_data and path not in exclude_data):
|
|
|
+ new_value = extra_data[path].replace('\r\n', '\n')
|
|
|
+ return new_value.replace('\n', '\r\n') # 从 extra_data 中取出新值
|
|
|
+
|
|
|
+ return value # 如果路径不在 extra_data 中,保持原值
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def save_to_json(path, data):
|
|
|
+ # 创建目录(如果不存在)
|
|
|
+ directory = os.path.dirname(path) # 获取文件路径的目录部分
|
|
|
+ if not os.path.exists(directory):
|
|
|
+ os.makedirs(directory) # 创建目录
|
|
|
+
|
|
|
+ # 将修改后的字典保存为 .json 文件
|
|
|
+ with open(path, 'w', encoding='utf-8') as json_file:
|
|
|
+ json.dump(data, json_file, ensure_ascii=False, indent=4)
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def generate_json(oem, excel_dic, lang, output_folder, json_folder, oem_json_folder):
|
|
|
+ # OEM的Lang文件
|
|
|
+ oem_input = oem_json_folder + oem + '/locales/extras/' + lang + '.json'
|
|
|
+ # OEM输出文件地址
|
|
|
+ oem_output = output_folder + '/jsons/' + oem + '/' + lang + '.json'
|
|
|
+ oem_dic = None
|
|
|
+ if os.path.exists(oem_input):
|
|
|
+ # 读取OEM的JSON文件
|
|
|
+ oem_data = CommonUti.read_from_json(oem_input)
|
|
|
+ # 更新 common_data
|
|
|
+ CommonUti.modify_json_values(
|
|
|
+ oem_data, CommonUti.modify_func, extra_data=excel_dic)
|
|
|
+ # 另存为OEM的json文件
|
|
|
+ CommonUti.save_to_json(oem_output, oem_data)
|
|
|
+ print("%s %s json save success" % (oem, lang))
|
|
|
+
|
|
|
+ # 通用JSON:oem中存在的Key,则不更新common的值
|
|
|
+ oem_dic = CommonUti.generate_dict_from_json(oem_input)
|
|
|
+
|
|
|
+ # 通用的Lang文件
|
|
|
+ common_input = json_folder + lang + '.json'
|
|
|
+ # 输出文件地址
|
|
|
+ common_output = output_folder + '/jsons/' + lang + '.json'
|
|
|
+ # 读取JSON文件
|
|
|
+ common_data = CommonUti.read_from_json(common_input)
|
|
|
+ # 更新 common_data
|
|
|
+ CommonUti.modify_json_values(common_data, CommonUti.modify_func,
|
|
|
+ extra_data=excel_dic, exclude_data=oem_dic)
|
|
|
+ # 另存为json文件
|
|
|
+ CommonUti.save_to_json(common_output, common_data)
|
|
|
+ print("%s json save success" % lang)
|