319 lines
9.7 KiB
Python
319 lines
9.7 KiB
Python
|
|
#coding: utf-8
|
|||
|
|
|
|||
|
|
import os
|
|||
|
|
import sys
|
|||
|
|
import json
|
|||
|
|
import re
|
|||
|
|
import time
|
|||
|
|
import random
|
|||
|
|
import json
|
|||
|
|
from hashlib import md5
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
from googletrans import Translator
|
|||
|
|
except ImportError:
|
|||
|
|
print("未安装 googletrans==4.0.0-rc1,正在安装...")
|
|||
|
|
os.system('btpip install googletrans==4.0.0-rc1')
|
|||
|
|
from googletrans import Translator
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
import requests
|
|||
|
|
except ImportError:
|
|||
|
|
print("未安装 requests,正在安装...")
|
|||
|
|
os.system('btpip install requests')
|
|||
|
|
import requests
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
# 解决 Windows 下编码问题,强制使用 utf-8 编码
|
|||
|
|
if sys.platform == "win32":
|
|||
|
|
sys.stdout.reconfigure(encoding='utf-8')
|
|||
|
|
|
|||
|
|
# 百度翻译
|
|||
|
|
class baidu_translate:
|
|||
|
|
endpoint = 'http://api.fanyi.baidu.com'
|
|||
|
|
path = '/api/trans/vip/translate'
|
|||
|
|
url = endpoint + path
|
|||
|
|
appid = ''
|
|||
|
|
appkey = ''
|
|||
|
|
# todo
|
|||
|
|
# from_lang = 'zh'
|
|||
|
|
from_lang = 'en'
|
|||
|
|
|
|||
|
|
def make_md5(self,s, encoding='utf-8'):
|
|||
|
|
'''
|
|||
|
|
@name 生成md5
|
|||
|
|
@param s 字符串
|
|||
|
|
@param encoding 编码
|
|||
|
|
@return string
|
|||
|
|
'''
|
|||
|
|
return md5(s.encode(encoding)).hexdigest()
|
|||
|
|
|
|||
|
|
|
|||
|
|
def translate(self, query, to_lang='en'):
|
|||
|
|
'''
|
|||
|
|
@name 调用百度翻译API
|
|||
|
|
@param query 原文
|
|||
|
|
@param to_lang 目标语言
|
|||
|
|
@return dict
|
|||
|
|
'''
|
|||
|
|
salt = random.randint(32768, 65536)
|
|||
|
|
sign = self.make_md5(self.appid + query + str(salt) + self.appkey)
|
|||
|
|
|
|||
|
|
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
|
|||
|
|
|
|||
|
|
payload = {'appid': self.appid, 'q': query, 'from': self.from_lang, 'to': to_lang, 'salt': salt, 'sign': sign}
|
|||
|
|
|
|||
|
|
r = requests.post(self.url, params=payload, headers=headers)
|
|||
|
|
result = r.json()
|
|||
|
|
return result
|
|||
|
|
|
|||
|
|
|
|||
|
|
def google(self,text,dest,src):
|
|||
|
|
'''
|
|||
|
|
@name 调用googletrans API
|
|||
|
|
@param text 原文
|
|||
|
|
@param dest 目标语言
|
|||
|
|
@param src 源语言
|
|||
|
|
@return string
|
|||
|
|
'''
|
|||
|
|
print('原文:',text,'目标语言:',dest)
|
|||
|
|
translater = Translator()
|
|||
|
|
result = translater.translate(text, dest, src)
|
|||
|
|
return result.text
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
class Lang:
|
|||
|
|
client_extension = [".json",".js",".ts",".html",".css",".sh",".vue"] # 前端文件后缀
|
|||
|
|
server_extension = [".py"] # 后端文件后缀
|
|||
|
|
server_path = ['class', 'class_v2', 'plugin', 'mod'] # 后端代码 目录
|
|||
|
|
# client_path = "../YakPanel"
|
|||
|
|
exec_path = os.getcwd() # 语言包目录
|
|||
|
|
panel_path = os.path.dirname(os.path.dirname(exec_path)) # 项目目录
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
def get_files(self, path, mark='client'):
|
|||
|
|
'''
|
|||
|
|
@name 获取指定目录下的文件列表
|
|||
|
|
@param path 目录
|
|||
|
|
@param mark 标记 区分前端与后端 前端 'client' 后端 'server'
|
|||
|
|
@return list
|
|||
|
|
'''
|
|||
|
|
files = []
|
|||
|
|
for root, dirs, file in os.walk(path):
|
|||
|
|
for f in file:
|
|||
|
|
if root.find('node_modules') != -1:
|
|||
|
|
continue
|
|||
|
|
if mark == 'client':
|
|||
|
|
for ext in self.client_extension:
|
|||
|
|
if f.endswith(ext):
|
|||
|
|
files.append(os.path.join(root, f))
|
|||
|
|
else:
|
|||
|
|
for ext in self.server_extension:
|
|||
|
|
if f.endswith(ext):
|
|||
|
|
files.append(os.path.join(root, f))
|
|||
|
|
return files
|
|||
|
|
|
|||
|
|
def read_file(self,filename):
|
|||
|
|
'''
|
|||
|
|
@name 读取文件
|
|||
|
|
@param filename 文件名
|
|||
|
|
@return any
|
|||
|
|
'''
|
|||
|
|
with open(filename, "r",encoding="utf-8") as file:
|
|||
|
|
fbody = file.read()
|
|||
|
|
return fbody
|
|||
|
|
|
|||
|
|
def write_file(self,filename, body):
|
|||
|
|
'''
|
|||
|
|
@name 写入文件
|
|||
|
|
@param filename 文件名
|
|||
|
|
@param body 内容
|
|||
|
|
'''
|
|||
|
|
with open(filename, "w",encoding="utf-8") as file:
|
|||
|
|
file.write(body)
|
|||
|
|
|
|||
|
|
def get_lang(self, body):
|
|||
|
|
'''
|
|||
|
|
@name 解析文件中要翻译的文本
|
|||
|
|
@param body 文件内容
|
|||
|
|
@return list
|
|||
|
|
'''
|
|||
|
|
|
|||
|
|
lang_list = []
|
|||
|
|
# 匹配单引号 双引号
|
|||
|
|
pattern = r"public\.lang\([\"'](.+?)[\"']"
|
|||
|
|
for line in body.split("\n"):
|
|||
|
|
if "public.lang(" in line:
|
|||
|
|
# lang = re.findall(r"public\.lang\(\'(.+?)\'", line)
|
|||
|
|
lang = re.findall(pattern, line)
|
|||
|
|
|
|||
|
|
if lang:
|
|||
|
|
lang_list.extend(lang)
|
|||
|
|
return lang_list
|
|||
|
|
|
|||
|
|
def get_all_lang_dict(self,to_lang='en'):
|
|||
|
|
'''
|
|||
|
|
@name 取已经翻译过的结果集
|
|||
|
|
@param to_lang 目标语言
|
|||
|
|
@return dict
|
|||
|
|
'''
|
|||
|
|
|
|||
|
|
filename = os.path.join(self.exec_path,'all',to_lang + '.json')
|
|||
|
|
if not os.path.exists(filename):
|
|||
|
|
return {}
|
|||
|
|
body = self.read_file(filename)
|
|||
|
|
try:
|
|||
|
|
return json.loads(body)
|
|||
|
|
except:
|
|||
|
|
return {}
|
|||
|
|
|
|||
|
|
def save_all_lang_dict(self,langs,to_lang='en'):
|
|||
|
|
'''
|
|||
|
|
@name 保存翻译结果集
|
|||
|
|
@param langs dict
|
|||
|
|
@param to_lang 目标语言
|
|||
|
|
'''
|
|||
|
|
save_path = os.path.join(self.exec_path,'all')
|
|||
|
|
filename = os.path.join(save_path,to_lang + '.json')
|
|||
|
|
if not os.path.exists(save_path):
|
|||
|
|
os.makedirs(save_path)
|
|||
|
|
|
|||
|
|
self.write_file(filename,json.dumps(langs,indent=4,ensure_ascii=False))
|
|||
|
|
|
|||
|
|
# todo 改源语言为英文
|
|||
|
|
def translate(self, langs,to_lang='en',name='server',to_lang_google='en'):
|
|||
|
|
'''
|
|||
|
|
@name 翻译
|
|||
|
|
@param langs list
|
|||
|
|
@param to_lang 目标语言
|
|||
|
|
@param name 保存文件名
|
|||
|
|
'''
|
|||
|
|
baidu = baidu_translate()
|
|||
|
|
to_lang_dict = {}
|
|||
|
|
all_lang_dict = self.get_all_lang_dict(to_lang)
|
|||
|
|
for lang in langs:
|
|||
|
|
print('----- lang')
|
|||
|
|
print(lang)
|
|||
|
|
md5 = baidu.make_md5(lang)
|
|||
|
|
# if to_lang == 'zh':
|
|||
|
|
if to_lang == 'en':
|
|||
|
|
to_lang_dict[md5] = lang
|
|||
|
|
continue
|
|||
|
|
|
|||
|
|
# 先从已经翻译过的结果集中取
|
|||
|
|
if md5 in all_lang_dict:
|
|||
|
|
to_lang_dict[md5] = all_lang_dict[md5]
|
|||
|
|
continue
|
|||
|
|
|
|||
|
|
# 调用googletrans API
|
|||
|
|
trans_result = {}
|
|||
|
|
try:
|
|||
|
|
# trans_result['dst'] = baidu.google(lang,to_lang_google,'zh-cn')
|
|||
|
|
trans_result['dst'] = baidu.google(lang,to_lang_google,'en')
|
|||
|
|
except Exception as e:
|
|||
|
|
print('Error:',e)
|
|||
|
|
continue
|
|||
|
|
|
|||
|
|
to_lang_dict[md5] = trans_result['dst']
|
|||
|
|
|
|||
|
|
all_lang_dict[md5] = trans_result['dst']
|
|||
|
|
time.sleep(0.1)
|
|||
|
|
|
|||
|
|
# 保存翻译结果集
|
|||
|
|
self.save_all_lang_dict(all_lang_dict,to_lang)
|
|||
|
|
|
|||
|
|
# 保存翻译结果到语言文件
|
|||
|
|
save_path = os.path.join(self.exec_path,to_lang)
|
|||
|
|
if not os.path.exists(save_path):
|
|||
|
|
os.makedirs(save_path)
|
|||
|
|
filename = os.path.join(save_path,name+'.json')
|
|||
|
|
|
|||
|
|
self.write_file(filename,json.dumps(to_lang_dict,indent=4,ensure_ascii=False))
|
|||
|
|
|
|||
|
|
|
|||
|
|
def get_settings(self):
|
|||
|
|
'''
|
|||
|
|
@name 获取配置文件
|
|||
|
|
@return list
|
|||
|
|
'''
|
|||
|
|
default = [{
|
|||
|
|
"name": "en",
|
|||
|
|
"google": "en",
|
|||
|
|
"title": "English",
|
|||
|
|
"cn": "英语"
|
|||
|
|
}]
|
|||
|
|
filename = os.path.join(self.exec_path,'settings.json')
|
|||
|
|
if not os.path.exists(filename):
|
|||
|
|
return default
|
|||
|
|
body = self.read_file(filename)
|
|||
|
|
try:
|
|||
|
|
return json.loads(body)['languages']
|
|||
|
|
except:
|
|||
|
|
return default
|
|||
|
|
|
|||
|
|
|
|||
|
|
def start(self):
|
|||
|
|
'''
|
|||
|
|
@name 开始翻译
|
|||
|
|
'''
|
|||
|
|
|
|||
|
|
# 获取需要翻译的文件列表(后端)
|
|||
|
|
server_files = []
|
|||
|
|
for directory in self.server_path:
|
|||
|
|
directory_path = os.path.join(self.panel_path, directory)
|
|||
|
|
files = self.get_files(directory_path, 'server')
|
|||
|
|
server_files.extend(files)
|
|||
|
|
print(files)
|
|||
|
|
# return
|
|||
|
|
# server_files = self.get_files(os.path.join(self.exec_path,self.server_path))
|
|||
|
|
|
|||
|
|
# 解析文件中需要翻译的文本
|
|||
|
|
langs = []
|
|||
|
|
for file in server_files:
|
|||
|
|
body = self.read_file(file)
|
|||
|
|
langs.extend(self.get_lang(body))
|
|||
|
|
|
|||
|
|
# 获取配置文件中的语言
|
|||
|
|
config_langs = self.get_settings()
|
|||
|
|
for lang in config_langs:
|
|||
|
|
# 翻译
|
|||
|
|
print('正在翻译:',lang['cn'],'=>',lang['name'],'=>',lang['title'],'...')
|
|||
|
|
self.translate(langs,lang['name'],'server',lang['google'])
|
|||
|
|
|
|||
|
|
#-----------------------------------------------------------------------------------------
|
|||
|
|
# # 获取需要翻译的文件列表(前端)
|
|||
|
|
# client_files = self.get_files(self.client_path)
|
|||
|
|
# # 解析文件中需要翻译的文本
|
|||
|
|
# langs = []
|
|||
|
|
# for file in client_files:
|
|||
|
|
# print('解析文件:',file)
|
|||
|
|
# body = self.read_file(file)
|
|||
|
|
# langs.extend(self.get_lang(body))
|
|||
|
|
|
|||
|
|
# for lang in config_langs:
|
|||
|
|
# # 翻译
|
|||
|
|
# print('正在翻译:',lang['cn'],'=>',lang['name'],'=>',lang['title'],'...')
|
|||
|
|
# self.translate(langs,lang['name'],'client',lang['google'])
|
|||
|
|
|
|||
|
|
print('翻译完成!')
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
if __name__ == "__main__":
|
|||
|
|
# PS: 在项目目录/YakPanel/languages/lang.py 中运行此脚本
|
|||
|
|
# 需要先安装 googletrans==4.0.0-rc1 和 requests
|
|||
|
|
# 设置代理(如果你已在本机开启了系统代理,可以注释下面两行代码,否则将其设置为你的HTTP代理地址)
|
|||
|
|
os.environ["http_proxy"] = "http://192.168.168.162:7890"
|
|||
|
|
os.environ["https_proxy"] = "http://192.168.168.162:7890"
|
|||
|
|
|
|||
|
|
# 开始翻译
|
|||
|
|
lang = Lang()
|
|||
|
|
lang.start()
|
|||
|
|
|
|||
|
|
|