2025-06-12 15:29:20 +08:00
|
|
|
|
#!/usr/bin/python3
|
|
|
|
|
|
import base64
|
|
|
|
|
|
import datetime
|
|
|
|
|
|
import hashlib
|
|
|
|
|
|
import hmac
|
|
|
|
|
|
import json
|
|
|
|
|
|
import os
|
|
|
|
|
|
import sys
|
|
|
|
|
|
import time
|
|
|
|
|
|
import urllib.parse
|
|
|
|
|
|
from typing import Dict
|
|
|
|
|
|
|
|
|
|
|
|
import requests
|
|
|
|
|
|
|
|
|
|
|
|
# 运行格式方式:python langAi.py youdao 备注:aliyun 阿里云 youdao 有道翻译
|
|
|
|
|
|
|
|
|
|
|
|
# 语言文件路径 /Users/mac/www/app-starlock/lan
|
2025-06-12 17:25:12 +08:00
|
|
|
|
path = "./lan2/"
|
2025-06-12 15:29:20 +08:00
|
|
|
|
# 原语言
|
|
|
|
|
|
SOURCE_LANG = 'lan_en'
|
|
|
|
|
|
|
|
|
|
|
|
# 过滤不翻译的语言
|
|
|
|
|
|
FILTER_LANG = ['lan_zh', 'lan_en', 'lan_keys']
|
|
|
|
|
|
|
|
|
|
|
|
# 阿里云语言映射
|
|
|
|
|
|
ALIYUN_LANG_MAP = {
|
|
|
|
|
|
'lan_zh': {
|
|
|
|
|
|
'name': '中文',
|
|
|
|
|
|
'code': 'zh'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_tw': {
|
|
|
|
|
|
'name': '繁体中文',
|
|
|
|
|
|
'code': 'zh-tw',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_en': {
|
|
|
|
|
|
'name': '英文',
|
|
|
|
|
|
'code': 'en',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_fr': {
|
|
|
|
|
|
'name': '法文',
|
|
|
|
|
|
'code': 'fr',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_ru': {
|
|
|
|
|
|
'name': '俄文',
|
|
|
|
|
|
'code': 'ru',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_de': {
|
|
|
|
|
|
'name': '德文',
|
|
|
|
|
|
'code': 'de',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_ja': {
|
|
|
|
|
|
'name': '日文',
|
|
|
|
|
|
'code': 'ja',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_ko': {
|
|
|
|
|
|
'name': '韩文',
|
|
|
|
|
|
'code': 'ko',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_it': {
|
|
|
|
|
|
'name': '意大利文',
|
|
|
|
|
|
'code': 'it',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_pt': {
|
|
|
|
|
|
'name': '葡萄牙文',
|
|
|
|
|
|
'code': 'pt',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_es': {
|
|
|
|
|
|
'name': '西班牙文',
|
|
|
|
|
|
'code': 'es',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_ar': {
|
|
|
|
|
|
'name': '阿拉伯文',
|
|
|
|
|
|
'code': 'ar',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_vi': {
|
|
|
|
|
|
'name': '越南文',
|
|
|
|
|
|
'code': 'vi',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_ms': {
|
|
|
|
|
|
'name': '马来文',
|
|
|
|
|
|
'code': 'ms',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_nl': {
|
|
|
|
|
|
'name': '荷兰文',
|
|
|
|
|
|
'code': 'nl',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_ro': {
|
|
|
|
|
|
'name': '罗马尼亚文',
|
|
|
|
|
|
'code': 'ro',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_lt': {
|
|
|
|
|
|
'name': '立陶宛文',
|
|
|
|
|
|
'code': 'lt',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_sv': {
|
|
|
|
|
|
'name': '瑞典文',
|
|
|
|
|
|
'code': 'sv',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_et': {
|
|
|
|
|
|
'name': '爱沙尼亚文',
|
|
|
|
|
|
'code': 'et',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_pl': {
|
|
|
|
|
|
'name': '波兰文',
|
|
|
|
|
|
'code': 'pl',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_sk': {
|
|
|
|
|
|
'name': '斯洛伐克文',
|
|
|
|
|
|
'code': 'sk',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_cs': {
|
|
|
|
|
|
'name': '捷克文',
|
|
|
|
|
|
'code': 'cs',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_el': {
|
|
|
|
|
|
'name': '希腊文',
|
|
|
|
|
|
'code': 'el',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_he': {
|
|
|
|
|
|
'name': '希伯来文',
|
|
|
|
|
|
'code': 'he',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_tr': {
|
|
|
|
|
|
'name': '土耳其文',
|
|
|
|
|
|
'code': 'tr',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_hu': {
|
|
|
|
|
|
'name': '匈牙利文',
|
|
|
|
|
|
'code': 'hu',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_bg': {
|
|
|
|
|
|
'name': '保加利亚文',
|
|
|
|
|
|
'code': 'bg',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_kk': {
|
|
|
|
|
|
'name': '哈萨克文',
|
|
|
|
|
|
'code': 'kk',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_bn': {
|
|
|
|
|
|
'name': '孟加拉文',
|
|
|
|
|
|
'code': 'bn',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_hr': {
|
|
|
|
|
|
'name': '克罗地亚文',
|
|
|
|
|
|
'code': 'hbs',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_th': {
|
|
|
|
|
|
'name': '泰文',
|
|
|
|
|
|
'code': 'th',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_id': {
|
|
|
|
|
|
'name': '印尼文',
|
|
|
|
|
|
'code': 'id',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_fi': {
|
|
|
|
|
|
'name': '芬兰文',
|
|
|
|
|
|
'code': 'fi',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_da': {
|
|
|
|
|
|
'name': '丹麦文',
|
|
|
|
|
|
'code': 'da',
|
|
|
|
|
|
},
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# 有道语言映射
|
|
|
|
|
|
YOUDAO_LANG_MAP = {
|
|
|
|
|
|
'lan_zh': {
|
|
|
|
|
|
'name': '中文',
|
|
|
|
|
|
'code': 'zh-CHS',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_tw': {
|
|
|
|
|
|
'name': '繁体中文(中国台湾)',
|
|
|
|
|
|
'code': 'zh-CHT',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_hk': {
|
|
|
|
|
|
'name': '繁体中文(中国香港)',
|
|
|
|
|
|
'code': 'yue',
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_en': {
|
|
|
|
|
|
'name': '英文',
|
|
|
|
|
|
'code': 'en'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_fr': {
|
|
|
|
|
|
'name': '法文',
|
|
|
|
|
|
'code': 'fr'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_ru': {
|
|
|
|
|
|
'name': '俄文',
|
|
|
|
|
|
'code': 'ru'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_de': {
|
|
|
|
|
|
'name': '德文',
|
|
|
|
|
|
'code': 'de'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_ja': {
|
|
|
|
|
|
'name': '日文',
|
|
|
|
|
|
'code': 'ja'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_ko': {
|
|
|
|
|
|
'name': '韩文',
|
|
|
|
|
|
'code': 'ko'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_it': {
|
|
|
|
|
|
'name': '意大利文',
|
|
|
|
|
|
'code': 'it'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_pt': {
|
|
|
|
|
|
'name': '葡萄牙文',
|
|
|
|
|
|
'code': 'pt'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_es': {
|
|
|
|
|
|
'name': '西班牙文',
|
|
|
|
|
|
'code': 'es'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_ar': {
|
|
|
|
|
|
'name': '阿拉伯文',
|
|
|
|
|
|
'code': 'ar'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_vi': {
|
|
|
|
|
|
'name': '越南文',
|
|
|
|
|
|
'code': 'vi'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_ms': {
|
|
|
|
|
|
'name': '马来文',
|
|
|
|
|
|
'code': 'ms'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_nl': {
|
|
|
|
|
|
'name': '荷兰文',
|
|
|
|
|
|
'code': 'nl'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_ro': {
|
|
|
|
|
|
'name': '罗马尼亚文',
|
|
|
|
|
|
'code': 'ro'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_lt': {
|
|
|
|
|
|
'name': '立陶宛文',
|
|
|
|
|
|
'code': 'lt'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_sv': {
|
|
|
|
|
|
'name': '瑞典文',
|
|
|
|
|
|
'code': 'sv'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_et': {
|
|
|
|
|
|
'name': '爱沙尼亚文',
|
|
|
|
|
|
'code': 'et'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_pl': {
|
|
|
|
|
|
'name': '波兰文',
|
|
|
|
|
|
'code': 'pl'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_sk': {
|
|
|
|
|
|
'name': '斯洛伐克文',
|
|
|
|
|
|
'code': 'sk'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_cs': {
|
|
|
|
|
|
'name': '捷克文',
|
|
|
|
|
|
'code': 'cs'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_el': {
|
|
|
|
|
|
'name': '希腊文',
|
|
|
|
|
|
'code': 'el'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_he': {
|
|
|
|
|
|
'name': '希伯来文',
|
|
|
|
|
|
'code': 'he'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_tr': {
|
|
|
|
|
|
'name': '土耳其文',
|
|
|
|
|
|
'code': 'tr'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_hu': {
|
|
|
|
|
|
'name': '匈牙利文',
|
|
|
|
|
|
'code': 'hu'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_bg': {
|
|
|
|
|
|
'name': '保加利亚文',
|
|
|
|
|
|
'code': 'bg'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_kk': {
|
|
|
|
|
|
'name': '哈萨克文',
|
|
|
|
|
|
'code': 'kk'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_bn': {
|
|
|
|
|
|
'name': '孟加拉文',
|
|
|
|
|
|
'code': 'bn'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_hr': {
|
|
|
|
|
|
'name': '克罗地亚文',
|
|
|
|
|
|
'code': 'hr'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_th': {
|
|
|
|
|
|
'name': '泰文',
|
|
|
|
|
|
'code': 'th'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_id': {
|
|
|
|
|
|
'name': '印尼文',
|
|
|
|
|
|
'code': 'id'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_fi': {
|
|
|
|
|
|
'name': '芬兰文',
|
|
|
|
|
|
'code': 'fi'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_da': {
|
|
|
|
|
|
'name': '丹麦文',
|
|
|
|
|
|
'code': 'da'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_uk': {
|
|
|
|
|
|
'name': '乌克兰文',
|
|
|
|
|
|
'code': 'uk'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_sr_cyrl': {
|
|
|
|
|
|
'name': '塞尔维亚语(西里尔文)',
|
|
|
|
|
|
'code': 'sr-Cyrl'
|
|
|
|
|
|
},
|
2025-06-12 17:25:12 +08:00
|
|
|
|
'lan_hy': {
|
|
|
|
|
|
'name': '亚美尼亚语',
|
|
|
|
|
|
'code': 'hy'
|
|
|
|
|
|
},
|
|
|
|
|
|
'lan_ka': {
|
|
|
|
|
|
'name': '格鲁吉亚语',
|
|
|
|
|
|
'code': 'ka'
|
|
|
|
|
|
},
|
2025-06-12 15:29:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# =============================== 以下为固定代码,非必要请勿修改 ===============================
|
|
|
|
|
|
|
|
|
|
|
|
# 阿里云配置
|
|
|
|
|
|
ALIYUN_CONFIG = {
|
|
|
|
|
|
'domain': 'mt.cn-hangzhou.aliyuncs.com/api/translate/web/ecommerce',
|
|
|
|
|
|
'accessKeyId': 'LTAI5tFke4yGaY94ondXkmHn',
|
|
|
|
|
|
'accessKeySecret': '08zPw8BoRqfqlKDTMX65k7gfeER33x',
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# 有道翻译配置
|
|
|
|
|
|
YOUDAO_CONFIG = {
|
|
|
|
|
|
'domain': 'https://openapi.youdao.com/api',
|
|
|
|
|
|
'appKey': '3e4923bad470f8d2',
|
|
|
|
|
|
'appSecret': '5thWwZ7D0RIzT0aquCF6NKmaiakAyhqr'
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CHANNELS = ['aliyun', 'youdao']
|
|
|
|
|
|
|
|
|
|
|
|
if len(sys.argv) < 2:
|
|
|
|
|
|
print('Usage: python langAi.py aliLang')
|
|
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
|
|
|
|
# 检测传入参数是否合法
|
|
|
|
|
|
if sys.argv[1] not in CHANNELS:
|
|
|
|
|
|
print('channel must be one of {}'.format(CHANNELS))
|
|
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 主函数
|
|
|
|
|
|
def main(channel):
|
|
|
|
|
|
en_path = path + SOURCE_LANG + ".json"
|
|
|
|
|
|
# 判断文件是否存在
|
|
|
|
|
|
if not os.path.exists(en_path):
|
|
|
|
|
|
print('文件不存在:', en_path)
|
|
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
|
|
|
|
# 读取文件内容
|
|
|
|
|
|
en_us_content = read_file(en_path)
|
|
|
|
|
|
|
|
|
|
|
|
# 把json转数组
|
|
|
|
|
|
en_us_data = json.loads(en_us_content)
|
|
|
|
|
|
|
|
|
|
|
|
# 语言列表 如果channel为aliyun赋值ALIYUN_LANG_MAP,否则赋值YOUDAO_LANG_MAP
|
|
|
|
|
|
lang_map = ALIYUN_LANG_MAP if channel == 'aliyun' else YOUDAO_LANG_MAP
|
|
|
|
|
|
|
|
|
|
|
|
# 遍历ALIYUN_LANG_MAP
|
|
|
|
|
|
for key in lang_map:
|
|
|
|
|
|
# 过滤掉不翻译的语言
|
|
|
|
|
|
if key in FILTER_LANG:
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
|
lang_path = path + key + ".json"
|
|
|
|
|
|
# 验证文件是否存在,如果不存在即创建
|
|
|
|
|
|
if not os.path.exists(lang_path):
|
|
|
|
|
|
create_file(lang_path)
|
|
|
|
|
|
|
|
|
|
|
|
data_content = read_file(lang_path)
|
|
|
|
|
|
if data_content.strip(): # Check if the file is not empty
|
|
|
|
|
|
datas = json.loads(data_content)
|
|
|
|
|
|
else:
|
|
|
|
|
|
datas = {}
|
|
|
|
|
|
|
|
|
|
|
|
total = len(en_us_data) # 总数
|
|
|
|
|
|
current = 0 # 当前数
|
|
|
|
|
|
|
|
|
|
|
|
for en_us_key in en_us_data:
|
|
|
|
|
|
current += 1
|
|
|
|
|
|
print('语言:%s-%s 正在翻译处理第%d/%d批数据' % (key,lang_map[key]['code'], current, total))
|
|
|
|
|
|
# 过滤已存在的key
|
|
|
|
|
|
if en_us_key in datas:
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
|
# 异常处理
|
|
|
|
|
|
try:
|
|
|
|
|
|
datas[en_us_key] = translation(channel, lang_map[SOURCE_LANG]['code'], lang_map[key]['code'],
|
|
|
|
|
|
en_us_data[en_us_key])
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
print('翻译异常:', e.args, 'key:', en_us_key, 'content:', en_us_data[en_us_key])
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
|
# 写入文件
|
|
|
|
|
|
with open(lang_path, 'w', encoding='utf-8') as file:
|
|
|
|
|
|
json.dump(datas, file, ensure_ascii=False, indent=4)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 翻译
|
|
|
|
|
|
def translation(channel, source_language, target_language, text):
|
|
|
|
|
|
translation_text = ''
|
|
|
|
|
|
if channel == 'aliyun':
|
|
|
|
|
|
translation_text = aliyun_translation(source_language, target_language, text)
|
|
|
|
|
|
elif channel == 'youdao':
|
|
|
|
|
|
translation_text = youdao_translation(source_language, target_language, text)
|
2025-06-12 17:25:12 +08:00
|
|
|
|
# 延迟2秒
|
|
|
|
|
|
time.sleep(2)
|
2025-06-12 15:29:20 +08:00
|
|
|
|
|
|
|
|
|
|
return translation_text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 有道翻译
|
|
|
|
|
|
def youdao_translation(source_language, target_language, text):
|
|
|
|
|
|
post_body = {
|
|
|
|
|
|
'q': text,
|
|
|
|
|
|
'from': source_language,
|
|
|
|
|
|
'to': target_language,
|
|
|
|
|
|
'appKey': YOUDAO_CONFIG['appKey'],
|
|
|
|
|
|
'salt': hashlib.md5(os.urandom(32)).hexdigest(), # 随机字符串,可使用UUID进行生产
|
|
|
|
|
|
'signType': 'v3',
|
|
|
|
|
|
'curtime': str(int(datetime.datetime.now().timestamp())),
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# 签名生成方法如下:
|
|
|
|
|
|
# signType=v3;
|
|
|
|
|
|
# sign=sha256(应用ID+input+salt+curtime+应用密钥);
|
|
|
|
|
|
# 其中,input的计算方式为:input=q前10个字符 + q长度 + q后10个字符(当q长度大于20)或 input=q字符串(当q长度小于等于20);
|
|
|
|
|
|
|
|
|
|
|
|
input_text = post_body['q']
|
|
|
|
|
|
if len(input_text) > 20:
|
|
|
|
|
|
input_text = input_text[:10] + str(len(input_text)) + input_text[-10:]
|
|
|
|
|
|
post_body['input'] = input_text
|
|
|
|
|
|
|
|
|
|
|
|
sign = hashlib.sha256((YOUDAO_CONFIG['appKey'] + input_text + post_body['salt'] + post_body['curtime'] +
|
|
|
|
|
|
YOUDAO_CONFIG['appSecret']).encode('utf-8')).hexdigest()
|
|
|
|
|
|
|
|
|
|
|
|
post_body['sign'] = sign
|
|
|
|
|
|
|
|
|
|
|
|
req = fetch_content(YOUDAO_CONFIG['domain'], 'POST', post_body)
|
2025-06-12 17:25:12 +08:00
|
|
|
|
req_json = json.loads(req)
|
|
|
|
|
|
try:
|
|
|
|
|
|
return req_json['translation'][0]
|
|
|
|
|
|
except KeyError as e:
|
|
|
|
|
|
print(f"[翻译异常][KeyError] 目标语言: {target_language}, key: {text}, API返回: {req_json}, 请求参数: {post_body}")
|
|
|
|
|
|
raise
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
print(f"[翻译异常][OtherError] 目标语言: {target_language}, key: {text}, API返回: {req_json}, 请求参数: {post_body}, 异常: {e}")
|
|
|
|
|
|
raise
|
2025-06-12 15:29:20 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 阿里云翻译
|
|
|
|
|
|
def aliyun_translation(source_language, target_language, text):
|
|
|
|
|
|
headers = {
|
|
|
|
|
|
'Version': '2018-10-12',
|
|
|
|
|
|
}
|
|
|
|
|
|
post_body = {
|
|
|
|
|
|
"FormatType": "text",
|
|
|
|
|
|
"SourceLanguage": source_language,
|
|
|
|
|
|
"TargetLanguage": target_language,
|
|
|
|
|
|
"SourceText": text,
|
|
|
|
|
|
"Ccene": "general",
|
|
|
|
|
|
'Action': 'TranslateGeneral',
|
|
|
|
|
|
}
|
|
|
|
|
|
req = aliyun_request(ALIYUN_CONFIG['domain'], {**post_body, **headers})
|
|
|
|
|
|
if req['Code'] == '200':
|
|
|
|
|
|
return req['Data']['Translated']
|
|
|
|
|
|
else:
|
|
|
|
|
|
raise Exception(req)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def aliyun_request(domain: str, params: Dict, security: bool = True,
|
|
|
|
|
|
method: str = 'POST') -> Dict:
|
|
|
|
|
|
# Add common parameters
|
|
|
|
|
|
api_params = {
|
|
|
|
|
|
"SignatureMethod": "HMAC-SHA1",
|
|
|
|
|
|
"SignatureNonce": hashlib.md5(os.urandom(32)).hexdigest(),
|
|
|
|
|
|
"SignatureVersion": "1.0",
|
|
|
|
|
|
"AccessKeyId": ALIYUN_CONFIG['accessKeyId'],
|
|
|
|
|
|
"Timestamp": datetime.datetime.utcnow().isoformat("T"),
|
|
|
|
|
|
"Format": "JSON",
|
|
|
|
|
|
}
|
|
|
|
|
|
api_params.update(params)
|
|
|
|
|
|
|
|
|
|
|
|
# Sort parameters by key
|
|
|
|
|
|
sorted_params = sorted(api_params.items(), key=lambda x: x[0])
|
|
|
|
|
|
|
|
|
|
|
|
sorted_query_string_tmp = ""
|
|
|
|
|
|
for key, value in sorted(sorted_params):
|
|
|
|
|
|
sorted_query_string_tmp += "&" + aliyun_encode(key) + "=" + aliyun_encode(value)
|
|
|
|
|
|
|
|
|
|
|
|
string_to_sign = "{}&%2F&{}".format(method, aliyun_encode(sorted_query_string_tmp[1:]))
|
|
|
|
|
|
|
|
|
|
|
|
# Calculate the signature
|
|
|
|
|
|
signature = base64.b64encode(
|
|
|
|
|
|
hmac.new((ALIYUN_CONFIG['accessKeySecret'] + "&").encode('utf-8'), string_to_sign.encode('utf-8'),
|
|
|
|
|
|
hashlib.sha1).digest()).decode(
|
|
|
|
|
|
'utf-8')
|
|
|
|
|
|
|
|
|
|
|
|
# Add the signature to the parameters
|
|
|
|
|
|
api_params['Signature'] = signature
|
|
|
|
|
|
|
|
|
|
|
|
# Send the request
|
|
|
|
|
|
url = ("https" if security else "http") + "://" + domain + "/"
|
|
|
|
|
|
if method == 'POST':
|
|
|
|
|
|
response = requests.post(url, data=api_params)
|
|
|
|
|
|
else:
|
|
|
|
|
|
response = requests.get(url, params=api_params)
|
|
|
|
|
|
return response.json()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 阿里云编码
|
|
|
|
|
|
def aliyun_encode(value):
|
|
|
|
|
|
res = urllib.parse.quote_plus(value)
|
|
|
|
|
|
res = res.replace("+", "%20")
|
|
|
|
|
|
res = res.replace("*", "%2A")
|
|
|
|
|
|
res = res.replace("%7E", "~")
|
|
|
|
|
|
return res
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def fetch_content(url, method, body):
|
|
|
|
|
|
headers = {"x-sdk-client": "python/2.0.0"}
|
|
|
|
|
|
|
|
|
|
|
|
if method == 'POST':
|
|
|
|
|
|
response = requests.post(url, data=body, headers=headers)
|
|
|
|
|
|
else:
|
|
|
|
|
|
response = requests.get(url, params=body, headers=headers)
|
|
|
|
|
|
|
|
|
|
|
|
if response.status_code != 200:
|
|
|
|
|
|
raise Exception(f"Request failed with status {response.status_code}")
|
|
|
|
|
|
|
|
|
|
|
|
return response.text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 创建文件
|
|
|
|
|
|
def create_file(file_path):
|
|
|
|
|
|
with open(file_path, 'w') as file:
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 读取文件内容
|
|
|
|
|
|
def read_file(file_path):
|
|
|
|
|
|
with open(file_path, 'r', encoding='utf-8') as file:
|
|
|
|
|
|
content = file.read()
|
|
|
|
|
|
return content
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# translation_text = youdao_translation('en', 'de', 'Your application <:name> has been approved.')
|
|
|
|
|
|
# print(translation_text)
|
|
|
|
|
|
main(sys.argv[1])
|