|
@@ -0,0 +1,153 @@
|
|
|
+import os
|
|
|
+import sys
|
|
|
+import re
|
|
|
+
|
|
|
+from typing import List, Tuple, Dict
|
|
|
+
|
|
|
+FileList = List[str]
|
|
|
+FlatList = Dict[str, Tuple[str]]
|
|
|
+
|
|
|
+
|
|
|
+class RunError(Exception):
|
|
|
+ def __init__(self, message="RunError: run as module is not allowed."):
|
|
|
+ self.message = message
|
|
|
+
|
|
|
+
|
|
|
+class ArgError(Exception):
|
|
|
+ def __init__(self, message="ArgError: just 6 arg is allowed."):
|
|
|
+ self.message = message
|
|
|
+
|
|
|
+
|
|
|
+if __name__ != '__main__':
|
|
|
+ raise RunError()
|
|
|
+
|
|
|
+argv = sys.argv
|
|
|
+if len(argv) < 6:
|
|
|
+ print(f"{len(argv)}")
|
|
|
+ raise ArgError()
|
|
|
+
|
|
|
+output_dir = argv[1]
|
|
|
+export_h = argv[2]
|
|
|
+export = argv[3]
|
|
|
+translation = argv[4]
|
|
|
+input_dir = argv[5:]
|
|
|
+translation_output = os.path.join(output_dir, "tr")
|
|
|
+base_tr_file = os.path.join(translation, "base.py")
|
|
|
+
|
|
|
+try:
|
|
|
+ os.makedirs(output_dir)
|
|
|
+except OSError:
|
|
|
+ ...
|
|
|
+
|
|
|
+try:
|
|
|
+ os.makedirs(translation_output)
|
|
|
+except OSError:
|
|
|
+ ...
|
|
|
+
|
|
|
+base_tr = {}
|
|
|
+if os.path.exists(base_tr_file):
|
|
|
+ with open(base_tr_file, "r", encoding="utf-8") as f:
|
|
|
+ code = f.read()
|
|
|
+ exec(code, base_tr, base_tr)
|
|
|
+
|
|
|
+
|
|
|
+def getFileFromPath(paths: List[str], file_type_: str) -> FileList:
|
|
|
+ tmp: FileList = []
|
|
|
+ for path in paths:
|
|
|
+ for file_path, dir_names, file_names in os.walk(path):
|
|
|
+ for names in file_names:
|
|
|
+ file_type = os.path.splitext(names)[-1]
|
|
|
+ if file_type == file_type_:
|
|
|
+ tmp.append(os.path.join(file_path, names))
|
|
|
+ return tmp
|
|
|
+
|
|
|
+
|
|
|
+file_list: FileList = getFileFromPath(input_dir, '.c')
|
|
|
+pattern = re.compile(r'HT_getText\(([\S]+),[\s]*(\"[^\"]*\")\)')
|
|
|
+flat_list: FlatList = {}
|
|
|
+for file in file_list:
|
|
|
+ with open(file, "r", encoding="utf-8") as f:
|
|
|
+ data = f.readline()
|
|
|
+ while data:
|
|
|
+ result: List[str] = pattern.findall(data)
|
|
|
+ for i in result:
|
|
|
+ if i[0] in flat_list and flat_list[i[0]][0] != "": # 若果是空字串则可以覆盖
|
|
|
+ continue
|
|
|
+
|
|
|
+ if i[0] not in flat_list:
|
|
|
+ tmp = i[1]
|
|
|
+ if tmp == "\"<base-tr>\"":
|
|
|
+ tmp = f"\"{base_tr.get(i[0], None)}\""
|
|
|
+ default_ = tmp.replace('\n', '\\n').replace('\r', '')
|
|
|
+ flat_list[i[0]] = (default_,) # 生成一个数组
|
|
|
+ data = f.readline()
|
|
|
+
|
|
|
+with open(os.path.join(output_dir, f"_ht.c"), "w", encoding="utf-8") as fc:
|
|
|
+ with open(os.path.join(output_dir, f"_ht.h"), "w", encoding="utf-8") as fh:
|
|
|
+ head = f'''/*
|
|
|
+ * File: _ht.c/_ht.c
|
|
|
+ * The file is automatically generated by Huan-GetText
|
|
|
+ * Encoding: utf-8
|
|
|
+ */'''
|
|
|
+ fc.write(head + '\n\n')
|
|
|
+ fh.write(head + '\n\n')
|
|
|
+
|
|
|
+ fh.write(f"#include \"{export_h}.h\"\n")
|
|
|
+ fc.write(f"#include \"_ht.h\"\n")
|
|
|
+ fh.write("#define HT_getText(name, ...) (HT_TEXT_ ## name)\n")
|
|
|
+ fh.write(f"{export} int HT_initGetText(char *lang);\n")
|
|
|
+ fc.write("#undef HT_getText\n")
|
|
|
+
|
|
|
+ for i in flat_list:
|
|
|
+ fc.write(f"{export} const char *HT_TEXT_{i} = {flat_list[i][0]};\n")
|
|
|
+ fh.write(f"{export} const char *HT_TEXT_{i};\n")
|
|
|
+
|
|
|
+ fc.write('''\n
|
|
|
+/* define initGetText */
|
|
|
+/* need dlfcn or dlfcn-win32 */
|
|
|
+
|
|
|
+#include "dlfcn.h"
|
|
|
+#include "stdlib.h"
|
|
|
+static void *handle = NULL;
|
|
|
+
|
|
|
+static void destructExit(void) {
|
|
|
+ dlclose(handle);
|
|
|
+}
|
|
|
+
|
|
|
+int HT_initGetText(char *lang) {
|
|
|
+ if (lang == NULL || handle != NULL)
|
|
|
+ return 2;
|
|
|
+
|
|
|
+ handle = dlopen(lang, RTLD_NOW);
|
|
|
+ if (handle == NULL)
|
|
|
+ return 1;
|
|
|
+ atexit(destructExit);
|
|
|
+ char **tmp;\n\n''')
|
|
|
+
|
|
|
+ for i in flat_list:
|
|
|
+ fc.write(f''' tmp = dlsym(handle, "HT__TEXT_{i}");\n''')
|
|
|
+ fc.write(f''' if (tmp != NULL) HT_TEXT_{i} = *tmp;\n\n''')
|
|
|
+
|
|
|
+ fc.write(' return 0;\n}\n')
|
|
|
+
|
|
|
+for i in flat_list:
|
|
|
+ print(f"TEXT: {i}")
|
|
|
+
|
|
|
+translation_list: FileList = getFileFromPath([translation], '.py')
|
|
|
+for t in translation_list:
|
|
|
+ name = os.path.splitext(os.path.split(t)[-1])[0]
|
|
|
+ if name == 'base':
|
|
|
+ continue
|
|
|
+
|
|
|
+ print(f"tr: {name}")
|
|
|
+ with open(t, "r", encoding="utf-8") as f:
|
|
|
+ code = f.read()
|
|
|
+ var = {}
|
|
|
+ for i in flat_list:
|
|
|
+ var[i] = flat_list[i][0][1:-2] # [1:-2] 去除引号
|
|
|
+ exec(code, var, var)
|
|
|
+ with open(os.path.join(translation_output, f"{name}.c"), "w", encoding="utf-8") as fc:
|
|
|
+ fc.write(f"#include \"{export_h}.h\"\n")
|
|
|
+ for i in flat_list: # 根据 flat_list 生成变量
|
|
|
+ res = var[i].replace('\n', '\\n').replace('\r', '')
|
|
|
+ fc.write(f"{export} const char *const HT__TEXT_{i} = \"{res}\";\n")
|