|
|
|
|
|
import uuid |
|
import hashlib |
|
import time |
|
import aiohttp |
|
import time |
|
|
|
from .common import CommonTranslator, InvalidServerResponse, MissingAPIKeyException |
|
from .keys import YOUDAO_APP_KEY, YOUDAO_SECRET_KEY |
|
|
|
def sha256_encode(signStr): |
|
hash_algorithm = hashlib.sha256() |
|
hash_algorithm.update(signStr.encode('utf-8')) |
|
return hash_algorithm.hexdigest() |
|
|
|
class YoudaoTranslator(CommonTranslator): |
|
_LANGUAGE_CODE_MAP = { |
|
'CHS': 'zh-CHS', |
|
'JPN': "ja", |
|
'ENG': 'en', |
|
'KOR': 'ko', |
|
'VIN': 'vi', |
|
'CSY': 'cs', |
|
'NLD': 'nl', |
|
'FRA': 'fr', |
|
'DEU': 'de', |
|
'HUN': 'hu', |
|
'ITA': 'it', |
|
'PLK': 'pl', |
|
'PTB': 'pt', |
|
'ROM': 'ro', |
|
'RUS': 'ru', |
|
'ESP': 'es', |
|
'TRK': 'tr', |
|
'THA': 'th', |
|
'IND': 'id' |
|
} |
|
_API_URL = 'https://openapi.youdao.com/api' |
|
|
|
def __init__(self): |
|
super().__init__() |
|
if not YOUDAO_APP_KEY or not YOUDAO_SECRET_KEY: |
|
raise MissingAPIKeyException('Please set the YOUDAO_APP_KEY and YOUDAO_SECRET_KEY environment variables before using the youdao translator.') |
|
|
|
async def _translate(self, from_lang, to_lang, queries): |
|
data = {} |
|
query_text = '\n'.join(queries) |
|
data['from'] = from_lang |
|
data['to'] = to_lang |
|
data['signType'] = 'v3' |
|
curtime = str(int(time.time())) |
|
data['curtime'] = curtime |
|
salt = str(uuid.uuid1()) |
|
signStr = YOUDAO_APP_KEY + self._truncate(query_text) + salt + curtime + YOUDAO_SECRET_KEY |
|
sign = sha256_encode(signStr) |
|
data['appKey'] = YOUDAO_APP_KEY |
|
data['q'] = query_text |
|
data['salt'] = salt |
|
data['sign'] = sign |
|
|
|
|
|
result = await self._do_request(data) |
|
result_list = [] |
|
if "translation" not in result: |
|
raise InvalidServerResponse(f'Youdao returned invalid response: {result}\nAre the API keys set correctly?') |
|
for ret in result["translation"]: |
|
result_list.extend(ret.split('\n')) |
|
return result_list |
|
|
|
def _truncate(self, q): |
|
if q is None: |
|
return None |
|
size = len(q) |
|
return q if size <= 20 else q[0:10] + str(size) + q[size - 10:size] |
|
|
|
async def _do_request(self, data): |
|
headers = {'Content-Type': 'application/x-www-form-urlencoded'} |
|
async with aiohttp.ClientSession() as session: |
|
async with session.post(self._API_URL, data=data, headers=headers) as resp: |
|
return await resp.json() |
|
|