You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
894 lines
34 KiB
894 lines
34 KiB
|
4 years ago
|
var tjs = (function (exports, bluemd5) {
|
||
|
|
'use strict';
|
||
|
|
|
||
|
|
bluemd5 = bluemd5 && bluemd5.hasOwnProperty('default') ? bluemd5['default'] : bluemd5;
|
||
|
|
|
||
|
|
/*! *****************************************************************************
|
||
|
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
|
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||
|
|
this file except in compliance with the License. You may obtain a copy of the
|
||
|
|
License at http://www.apache.org/licenses/LICENSE-2.0
|
||
|
|
|
||
|
|
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||
|
|
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||
|
|
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||
|
|
MERCHANTABLITY OR NON-INFRINGEMENT.
|
||
|
|
|
||
|
|
See the Apache Version 2.0 License for specific language governing permissions
|
||
|
|
and limitations under the License.
|
||
|
|
***************************************************************************** */
|
||
|
|
|
||
|
|
function __awaiter(thisArg, _arguments, P, generator) {
|
||
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
|
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
function __generator(thisArg, body) {
|
||
|
|
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||
|
|
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||
|
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
||
|
|
function step(op) {
|
||
|
|
if (f) throw new TypeError("Generator is already executing.");
|
||
|
|
while (_) try {
|
||
|
|
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||
|
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
||
|
|
switch (op[0]) {
|
||
|
|
case 0: case 1: t = op; break;
|
||
|
|
case 4: _.label++; return { value: op[1], done: false };
|
||
|
|
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||
|
|
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||
|
|
default:
|
||
|
|
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||
|
|
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||
|
|
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||
|
|
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||
|
|
if (t[2]) _.ops.pop();
|
||
|
|
_.trys.pop(); continue;
|
||
|
|
}
|
||
|
|
op = body.call(thisArg, _);
|
||
|
|
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||
|
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 反转对象 */
|
||
|
|
function invert (obj) {
|
||
|
|
var result = {};
|
||
|
|
for (var key in obj) {
|
||
|
|
if (obj.hasOwnProperty(key)) {
|
||
|
|
result[obj[key]] = key;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
var root = 'https://fanyi.baidu.com';
|
||
|
|
/**
|
||
|
|
* 百度支持的语种到百度自定义的语种名的映射,去掉了文言文。
|
||
|
|
* @see http://api.fanyi.baidu.com/api/trans/product/apidoc#languageList
|
||
|
|
*/
|
||
|
|
var standard2custom = {
|
||
|
|
en: 'en',
|
||
|
|
th: 'th',
|
||
|
|
ru: 'ru',
|
||
|
|
pt: 'pt',
|
||
|
|
el: 'el',
|
||
|
|
nl: 'nl',
|
||
|
|
pl: 'pl',
|
||
|
|
bg: 'bul',
|
||
|
|
et: 'est',
|
||
|
|
da: 'dan',
|
||
|
|
fi: 'fin',
|
||
|
|
cs: 'cs',
|
||
|
|
ro: 'rom',
|
||
|
|
sl: 'slo',
|
||
|
|
sv: 'swe',
|
||
|
|
hu: 'hu',
|
||
|
|
de: 'de',
|
||
|
|
it: 'it',
|
||
|
|
'zh-CN': 'zh',
|
||
|
|
'zh-TW': 'cht',
|
||
|
|
// 'zh-HK': 'yue',
|
||
|
|
ja: 'jp',
|
||
|
|
ko: 'kor',
|
||
|
|
es: 'spa',
|
||
|
|
fr: 'fra',
|
||
|
|
ar: 'ara'
|
||
|
|
};
|
||
|
|
/** 百度自定义的语种名到标准语种名的映射 */
|
||
|
|
var custom2standard = invert(standard2custom);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 安全的获取一个变量上指定路径的值。
|
||
|
|
* TODO: 使用 noshjs 代替
|
||
|
|
*/
|
||
|
|
function getValue (obj, pathArray, defaultValue) {
|
||
|
|
if (obj == null)
|
||
|
|
return defaultValue;
|
||
|
|
if (typeof pathArray === 'string') {
|
||
|
|
pathArray = [pathArray];
|
||
|
|
}
|
||
|
|
var value = obj;
|
||
|
|
for (var i = 0; i < pathArray.length; i += 1) {
|
||
|
|
var key = pathArray[i];
|
||
|
|
value = value[key];
|
||
|
|
if (value == null) {
|
||
|
|
return defaultValue;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return value;
|
||
|
|
}
|
||
|
|
|
||
|
|
function getError (code, msg) {
|
||
|
|
var e = new Error(msg);
|
||
|
|
e.code = code;
|
||
|
|
return e;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 将对象转换成查询字符串
|
||
|
|
* TODO: 使用 noshjs 中的方法
|
||
|
|
*/
|
||
|
|
function qs(obj) {
|
||
|
|
if (!obj)
|
||
|
|
return '';
|
||
|
|
var r = [];
|
||
|
|
var _loop_1 = function (key) {
|
||
|
|
var v = [].concat(obj[key]);
|
||
|
|
r.push.apply(r, v.map(function (valStr) { return key + "=" + encodeURIComponent(valStr); }));
|
||
|
|
};
|
||
|
|
for (var key in obj) {
|
||
|
|
_loop_1(key);
|
||
|
|
}
|
||
|
|
return r.join('&');
|
||
|
|
}
|
||
|
|
function request (options) {
|
||
|
|
var xhr = new XMLHttpRequest();
|
||
|
|
var urlObj = new URL(options.url);
|
||
|
|
urlObj.search += (urlObj.search ? '&' : '?') + qs(options.query);
|
||
|
|
var _a = options.method, method = _a === void 0 ? 'get' : _a;
|
||
|
|
xhr.open(method, urlObj.toString());
|
||
|
|
xhr.timeout = options.timeout || 5000;
|
||
|
|
var body;
|
||
|
|
if (method === 'post') {
|
||
|
|
switch (options.type) {
|
||
|
|
case 'form':
|
||
|
|
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
|
||
|
|
body = qs(options.body);
|
||
|
|
break;
|
||
|
|
case 'json':
|
||
|
|
default:
|
||
|
|
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
|
||
|
|
body = JSON.stringify(options.body);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
var headers = options.headers;
|
||
|
|
if (headers) {
|
||
|
|
for (var header in headers) {
|
||
|
|
xhr.setRequestHeader(header, headers[header]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
xhr.responseType = options.responseType || 'json';
|
||
|
|
return new Promise(function (resolve, reject) {
|
||
|
|
xhr.onload = function () {
|
||
|
|
// 如果 responseType 设为 json 但服务器返回的数据无法解析成 json,
|
||
|
|
// 则 response 是 null,其他无法解析的情况也是同理。
|
||
|
|
// 另外,responseText 只能在 responseType 是 '' 或 'text' 访问。
|
||
|
|
if (xhr.status !== 200 || xhr.response === null) {
|
||
|
|
reject(getError("API_SERVER_ERROR" /* API_SERVER_ERROR */));
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
resolve(xhr.response);
|
||
|
|
};
|
||
|
|
xhr.ontimeout = function () {
|
||
|
|
reject(getError("NETWORK_TIMEOUT" /* NETWORK_TIMEOUT */, '查询超时'));
|
||
|
|
};
|
||
|
|
xhr.onerror = function () {
|
||
|
|
reject(getError("NETWORK_ERROR" /* NETWORK_ERROR */, '网络错误'));
|
||
|
|
};
|
||
|
|
xhr.send(body);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
// tslint:disable
|
||
|
|
var C = null;
|
||
|
|
/**
|
||
|
|
* 从百度网页翻译中复制过来的计算签名的代码
|
||
|
|
* @param text 要查询的文本
|
||
|
|
* @param seed 从 ./seed.ts 获取到的 seed
|
||
|
|
*/
|
||
|
|
function sign (text, seed) {
|
||
|
|
var o = text.length;
|
||
|
|
o > 30 &&
|
||
|
|
(text =
|
||
|
|
'' +
|
||
|
|
text.substr(0, 10) +
|
||
|
|
text.substr(Math.floor(o / 2) - 5, 10) +
|
||
|
|
text.substr(-10, 10));
|
||
|
|
var t = null !== C ? C : (C = seed || '') || '';
|
||
|
|
for (var e = t.split('.'), h = Number(e[0]) || 0, i = Number(e[1]) || 0, d = [], f = 0, g = 0; g < text.length; g++) {
|
||
|
|
var m = text.charCodeAt(g);
|
||
|
|
128 > m
|
||
|
|
? (d[f++] = m)
|
||
|
|
: (2048 > m
|
||
|
|
? (d[f++] = (m >> 6) | 192)
|
||
|
|
: (55296 === (64512 & m) &&
|
||
|
|
g + 1 < text.length &&
|
||
|
|
56320 === (64512 & text.charCodeAt(g + 1))
|
||
|
|
? ((m =
|
||
|
|
65536 + ((1023 & m) << 10) + (1023 & text.charCodeAt(++g))),
|
||
|
|
(d[f++] = (m >> 18) | 240),
|
||
|
|
(d[f++] = ((m >> 12) & 63) | 128))
|
||
|
|
: (d[f++] = (m >> 12) | 224),
|
||
|
|
(d[f++] = ((m >> 6) & 63) | 128)),
|
||
|
|
(d[f++] = (63 & m) | 128));
|
||
|
|
}
|
||
|
|
for (var S = h, u = '+-a^+6', l = '+-3^+b+-f', s = 0; s < d.length; s++)
|
||
|
|
(S += d[s]), (S = a(S, u));
|
||
|
|
return ((S = a(S, l)),
|
||
|
|
(S ^= i),
|
||
|
|
0 > S && (S = (2147483647 & S) + 2147483648),
|
||
|
|
(S %= 1e6),
|
||
|
|
S.toString() + '.' + (S ^ h));
|
||
|
|
}
|
||
|
|
function a(r, o) {
|
||
|
|
for (var t = 0; t < o.length - 2; t += 3) {
|
||
|
|
var a = o.charAt(t + 2);
|
||
|
|
(a = a >= 'a' ? a.charCodeAt(0) - 87 : Number(a)),
|
||
|
|
(a = '+' === o.charAt(t + 1) ? r >>> a : r << a),
|
||
|
|
(r = '+' === o.charAt(t) ? (r + a) & 4294967295 : r ^ a);
|
||
|
|
}
|
||
|
|
return r;
|
||
|
|
}
|
||
|
|
|
||
|
|
var seedReg = /window\.gtk\s=\s'([^']+)';/;
|
||
|
|
var tokenReg = /token:\s'([^']+)'/;
|
||
|
|
var headers = undefined;
|
||
|
|
function getSeed () {
|
||
|
|
return __awaiter(this, void 0, void 0, function () {
|
||
|
|
var html, seed, token;
|
||
|
|
return __generator(this, function (_a) {
|
||
|
|
switch (_a.label) {
|
||
|
|
case 0: return [4 /*yield*/, request({
|
||
|
|
url: 'https://fanyi.baidu.com',
|
||
|
|
headers: headers,
|
||
|
|
responseType: 'text'
|
||
|
|
})];
|
||
|
|
case 1:
|
||
|
|
html = _a.sent();
|
||
|
|
seed = html.match(seedReg);
|
||
|
|
if (seed) {
|
||
|
|
token = html.match(tokenReg);
|
||
|
|
if (token) {
|
||
|
|
return [2 /*return*/, {
|
||
|
|
seed: seed[1],
|
||
|
|
token: token[1]
|
||
|
|
}];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
// 如果不能正确解析出 seed 和 token,则视为服务器错误
|
||
|
|
throw getError("API_SERVER_ERROR" /* API_SERVER_ERROR */);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 获取查询百度网页翻译接口所需的 token 和 sign
|
||
|
|
* @param text 要查询的文本
|
||
|
|
*/
|
||
|
|
function sign$1 (text) {
|
||
|
|
return __awaiter(this, void 0, void 0, function () {
|
||
|
|
var _a, seed, token;
|
||
|
|
return __generator(this, function (_b) {
|
||
|
|
switch (_b.label) {
|
||
|
|
case 0: return [4 /*yield*/, getSeed()];
|
||
|
|
case 1:
|
||
|
|
_a = _b.sent(), seed = _a.seed, token = _a.token;
|
||
|
|
return [2 /*return*/, {
|
||
|
|
token: token,
|
||
|
|
sign: sign(text, seed)
|
||
|
|
}];
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
function detect (options) {
|
||
|
|
return __awaiter(this, void 0, void 0, function () {
|
||
|
|
var query, body, iso689lang;
|
||
|
|
return __generator(this, function (_a) {
|
||
|
|
switch (_a.label) {
|
||
|
|
case 0:
|
||
|
|
query = (typeof options === 'string' ? options : options.text).slice(0, 73);
|
||
|
|
return [4 /*yield*/, request({
|
||
|
|
method: 'post',
|
||
|
|
url: root + '/langdetect',
|
||
|
|
body: {
|
||
|
|
query: query
|
||
|
|
},
|
||
|
|
type: 'form'
|
||
|
|
})];
|
||
|
|
case 1:
|
||
|
|
body = _a.sent();
|
||
|
|
if (body.error === 0) {
|
||
|
|
iso689lang = custom2standard[body.lan];
|
||
|
|
if (iso689lang)
|
||
|
|
return [2 /*return*/, iso689lang];
|
||
|
|
}
|
||
|
|
throw getError("UNSUPPORTED_LANG" /* UNSUPPORTED_LANG */);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 生成百度语音地址
|
||
|
|
* @param text 要朗读的文本
|
||
|
|
* @param lang 文本的语种,使用百度自定义的语种名称
|
||
|
|
*/
|
||
|
|
function getAudioURI(text, lang) {
|
||
|
|
return (root +
|
||
|
|
("/gettts?lan=" + lang + "&text=" + encodeURIComponent(text) + "&spd=3&source=web"));
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* 获取指定文本的网络语音地址
|
||
|
|
*/
|
||
|
|
function audio (options) {
|
||
|
|
return __awaiter(this, void 0, void 0, function () {
|
||
|
|
var _a, text, _b, from, lang;
|
||
|
|
return __generator(this, function (_c) {
|
||
|
|
switch (_c.label) {
|
||
|
|
case 0:
|
||
|
|
_a = typeof options === 'string' ? { text: options } : options, text = _a.text, _b = _a.from, from = _b === void 0 ? undefined : _b;
|
||
|
|
if (!!from) return [3 /*break*/, 2];
|
||
|
|
return [4 /*yield*/, detect(text)];
|
||
|
|
case 1:
|
||
|
|
from = _c.sent();
|
||
|
|
_c.label = 2;
|
||
|
|
case 2:
|
||
|
|
if (from === 'en-GB') {
|
||
|
|
lang = 'uk';
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
lang = standard2custom[from];
|
||
|
|
if (!lang)
|
||
|
|
throw getError("UNSUPPORTED_LANG" /* UNSUPPORTED_LANG */);
|
||
|
|
}
|
||
|
|
return [2 /*return*/, getAudioURI(text, lang)];
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
var headers$1 = {
|
||
|
|
'X-Requested-With': 'XMLHttpRequest'
|
||
|
|
};
|
||
|
|
function translate (options) {
|
||
|
|
return __awaiter(this, void 0, void 0, function () {
|
||
|
|
var _a, _b, from, _c, to, text, customFromLang, customToLang, _d, _e, _f, _g, _h, _j, _k;
|
||
|
|
return __generator(this, function (_l) {
|
||
|
|
switch (_l.label) {
|
||
|
|
case 0:
|
||
|
|
_a = typeof options === 'string' ? { text: options } : options, _b = _a.from, from = _b === void 0 ? undefined : _b, _c = _a.to, to = _c === void 0 ? undefined : _c, text = _a.text;
|
||
|
|
if (!!from) return [3 /*break*/, 2];
|
||
|
|
return [4 /*yield*/, detect(text)];
|
||
|
|
case 1:
|
||
|
|
from = _l.sent();
|
||
|
|
_l.label = 2;
|
||
|
|
case 2:
|
||
|
|
if (!to) {
|
||
|
|
to = from.startsWith('zh') ? 'en' : 'zh-CN';
|
||
|
|
}
|
||
|
|
customFromLang = standard2custom[from];
|
||
|
|
customToLang = standard2custom[to];
|
||
|
|
if (!customFromLang || !customToLang) {
|
||
|
|
throw getError("UNSUPPORTED_LANG" /* UNSUPPORTED_LANG */);
|
||
|
|
}
|
||
|
|
_d = transformRaw;
|
||
|
|
_e = [text];
|
||
|
|
_f = request;
|
||
|
|
_g = {
|
||
|
|
url: root + '/v2transapi',
|
||
|
|
type: 'form',
|
||
|
|
method: 'post'
|
||
|
|
};
|
||
|
|
_j = (_h = Object).assign;
|
||
|
|
_k = [{
|
||
|
|
from: customFromLang,
|
||
|
|
to: customToLang,
|
||
|
|
query: text,
|
||
|
|
transtype: 'translang',
|
||
|
|
simple_means_flag: 3
|
||
|
|
}];
|
||
|
|
return [4 /*yield*/, sign$1(text)];
|
||
|
|
case 3: return [4 /*yield*/, _f.apply(void 0, [(_g.body = _j.apply(_h, _k.concat([_l.sent()])),
|
||
|
|
_g.headers = headers$1,
|
||
|
|
_g)])];
|
||
|
|
case 4: return [2 /*return*/, _d.apply(void 0, _e.concat([_l.sent()]))];
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
function transformRaw(text, body) {
|
||
|
|
var transResult = body.trans_result;
|
||
|
|
var customFrom = getValue(transResult, 'from');
|
||
|
|
var customTo = getValue(transResult, 'to');
|
||
|
|
var result = {
|
||
|
|
text: text,
|
||
|
|
raw: body,
|
||
|
|
link: root + ("/#" + customFrom + "/" + customTo + "/" + encodeURIComponent(text)),
|
||
|
|
from: custom2standard[customFrom],
|
||
|
|
to: custom2standard[customTo]
|
||
|
|
};
|
||
|
|
var symbols = getValue(body, [
|
||
|
|
'dict_result',
|
||
|
|
'simple_means',
|
||
|
|
'symbols',
|
||
|
|
'0'
|
||
|
|
]);
|
||
|
|
if (symbols) {
|
||
|
|
// 解析音标
|
||
|
|
var phonetic = [];
|
||
|
|
var ph_am = symbols.ph_am, ph_en = symbols.ph_en;
|
||
|
|
if (ph_am) {
|
||
|
|
phonetic.push({
|
||
|
|
name: '美',
|
||
|
|
ttsURI: getAudioURI(text, 'en'),
|
||
|
|
value: ph_am
|
||
|
|
});
|
||
|
|
}
|
||
|
|
if (ph_en) {
|
||
|
|
phonetic.push({
|
||
|
|
name: '英',
|
||
|
|
ttsURI: getAudioURI(text, 'en-GB'),
|
||
|
|
value: ph_en
|
||
|
|
});
|
||
|
|
}
|
||
|
|
if (phonetic.length) {
|
||
|
|
result.phonetic = phonetic;
|
||
|
|
}
|
||
|
|
// 解析词典数据
|
||
|
|
try {
|
||
|
|
result.dict = symbols.parts.map(function (part) {
|
||
|
|
return (part.part ? part.part + ' ' : '') + part.means.join(';');
|
||
|
|
});
|
||
|
|
}
|
||
|
|
catch (e) { }
|
||
|
|
}
|
||
|
|
// 解析普通的翻译结果
|
||
|
|
try {
|
||
|
|
result.result = transResult.data.map(function (d) { return d.dst; });
|
||
|
|
}
|
||
|
|
catch (e) { }
|
||
|
|
if (!result.dict && !result.result) {
|
||
|
|
throw getError("API_SERVER_ERROR" /* API_SERVER_ERROR */);
|
||
|
|
}
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
var index = /*#__PURE__*/Object.freeze({
|
||
|
|
__proto__: null,
|
||
|
|
translate: translate,
|
||
|
|
detect: detect,
|
||
|
|
audio: audio
|
||
|
|
});
|
||
|
|
|
||
|
|
function getRoot(com) {
|
||
|
|
return 'https://translate.google.c' + (com ? 'om' : 'n');
|
||
|
|
}
|
||
|
|
|
||
|
|
var window = {
|
||
|
|
TKK: '0'
|
||
|
|
};
|
||
|
|
|
||
|
|
var yr = null;
|
||
|
|
var xr = function(a, b) {
|
||
|
|
for (var c = 0; c < b.length - 2; c += 3) {
|
||
|
|
var d = b.charAt(c + 2),
|
||
|
|
d = 'a' <= d ? d.charCodeAt(0) - 87 : Number(d),
|
||
|
|
d = '+' == b.charAt(c + 1) ? a >>> d : a << d;
|
||
|
|
a = '+' == b.charAt(c) ? (a + d) & 4294967295 : a ^ d;
|
||
|
|
}
|
||
|
|
return a
|
||
|
|
};
|
||
|
|
|
||
|
|
function sM(a) {
|
||
|
|
var b;
|
||
|
|
if (null !== yr) {
|
||
|
|
b = yr;
|
||
|
|
} else {
|
||
|
|
b = (yr = window.TKK || '') || '';
|
||
|
|
}
|
||
|
|
var d = b.split('.');
|
||
|
|
b = Number(d[0]) || 0;
|
||
|
|
for (var e = [], f = 0, g = 0; g < a.length; g++) {
|
||
|
|
var l = a.charCodeAt(g);
|
||
|
|
128 > l
|
||
|
|
? (e[f++] = l)
|
||
|
|
: (2048 > l
|
||
|
|
? (e[f++] = (l >> 6) | 192)
|
||
|
|
: (55296 == (l & 64512) &&
|
||
|
|
g + 1 < a.length &&
|
||
|
|
56320 == (a.charCodeAt(g + 1) & 64512)
|
||
|
|
? ((l = 65536 + ((l & 1023) << 10) + (a.charCodeAt(++g) & 1023)),
|
||
|
|
(e[f++] = (l >> 18) | 240),
|
||
|
|
(e[f++] = ((l >> 12) & 63) | 128))
|
||
|
|
: (e[f++] = (l >> 12) | 224),
|
||
|
|
(e[f++] = ((l >> 6) & 63) | 128)),
|
||
|
|
(e[f++] = (l & 63) | 128));
|
||
|
|
}
|
||
|
|
a = b;
|
||
|
|
for (f = 0; f < e.length; f++) (a += e[f]), (a = xr(a, '+-a^+6'));
|
||
|
|
a = xr(a, '+-3^+b+-f');
|
||
|
|
a ^= Number(d[1]) || 0;
|
||
|
|
0 > a && (a = (a & 2147483647) + 2147483648);
|
||
|
|
a %= 1e6;
|
||
|
|
return a.toString() + '.' + (a ^ b)
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 代码来自 https://github.com/matheuss/google-translate-token
|
||
|
|
* 做了一些修改以适应本项目
|
||
|
|
*/
|
||
|
|
function updateTKK(com) {
|
||
|
|
return __awaiter(this, void 0, void 0, function () {
|
||
|
|
var now, html, code;
|
||
|
|
return __generator(this, function (_a) {
|
||
|
|
switch (_a.label) {
|
||
|
|
case 0:
|
||
|
|
now = Math.floor(Date.now() / 3600000);
|
||
|
|
if (Number(window.TKK.split('.')[0]) === now) {
|
||
|
|
return [2 /*return*/];
|
||
|
|
}
|
||
|
|
return [4 /*yield*/, request({
|
||
|
|
url: getRoot(com),
|
||
|
|
responseType: 'text'
|
||
|
|
})];
|
||
|
|
case 1:
|
||
|
|
html = _a.sent();
|
||
|
|
code = html.match(/tkk:'(\d+\.\d+)'/);
|
||
|
|
if (code) {
|
||
|
|
window.TKK = code[1];
|
||
|
|
}
|
||
|
|
return [2 /*return*/];
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
function sign$2 (text, com) {
|
||
|
|
return __awaiter(this, void 0, void 0, function () {
|
||
|
|
return __generator(this, function (_a) {
|
||
|
|
switch (_a.label) {
|
||
|
|
case 0: return [4 /*yield*/, updateTKK(com)];
|
||
|
|
case 1:
|
||
|
|
_a.sent();
|
||
|
|
return [2 /*return*/, sM(text)];
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
function detect$1 (options) {
|
||
|
|
return __awaiter(this, void 0, void 0, function () {
|
||
|
|
var _a, text, _b, com, result, _c, _d, _e, src;
|
||
|
|
return __generator(this, function (_f) {
|
||
|
|
switch (_f.label) {
|
||
|
|
case 0:
|
||
|
|
_a = typeof options === 'string' ? { text: options } : options, text = _a.text, _b = _a.com, com = _b === void 0 ? false : _b;
|
||
|
|
_c = request;
|
||
|
|
_d = {
|
||
|
|
url: getRoot(com) + '/translate_a/single'
|
||
|
|
};
|
||
|
|
_e = {
|
||
|
|
client: 'webapp',
|
||
|
|
sl: 'auto',
|
||
|
|
tl: 'zh-CN',
|
||
|
|
hl: 'zh-CN',
|
||
|
|
ssel: '3',
|
||
|
|
tsel: '0',
|
||
|
|
kc: '0'
|
||
|
|
};
|
||
|
|
return [4 /*yield*/, sign$2(text, com)];
|
||
|
|
case 1: return [4 /*yield*/, _c.apply(void 0, [(_d.query = (_e.tk = _f.sent(),
|
||
|
|
_e.q = text,
|
||
|
|
_e),
|
||
|
|
_d)])];
|
||
|
|
case 2:
|
||
|
|
result = _f.sent();
|
||
|
|
src = result && result[2];
|
||
|
|
if (src)
|
||
|
|
return [2 /*return*/, src];
|
||
|
|
throw getError("UNSUPPORTED_LANG" /* UNSUPPORTED_LANG */);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
function audio$1 (options) {
|
||
|
|
return __awaiter(this, void 0, void 0, function () {
|
||
|
|
var _a, text, _b, from, _c, com, _d;
|
||
|
|
return __generator(this, function (_e) {
|
||
|
|
switch (_e.label) {
|
||
|
|
case 0:
|
||
|
|
_a = typeof options === 'string' ? { text: options } : options, text = _a.text, _b = _a.from, from = _b === void 0 ? '' : _b, _c = _a.com, com = _c === void 0 ? false : _c;
|
||
|
|
if (!!from) return [3 /*break*/, 2];
|
||
|
|
return [4 /*yield*/, detect$1(text)];
|
||
|
|
case 1:
|
||
|
|
from = _e.sent();
|
||
|
|
_e.label = 2;
|
||
|
|
case 2:
|
||
|
|
_d = getRoot(com) + "/translate_tts?ie=UTF-8&q=" + encodeURIComponent(text) + "&tl=" + from + "&total=1&idx=0&textlen=" + text.length + "&tk=";
|
||
|
|
return [4 /*yield*/, sign$2(text, com)];
|
||
|
|
case 3: return [2 /*return*/, _d + (_e.sent()) + "&client=webapp&prev=input"];
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
function translate$1 (options) {
|
||
|
|
return __awaiter(this, void 0, void 0, function () {
|
||
|
|
var _a, text, _b, com, _c, from, _d, to, _e, _f, _g, _h;
|
||
|
|
return __generator(this, function (_j) {
|
||
|
|
switch (_j.label) {
|
||
|
|
case 0:
|
||
|
|
_a = typeof options === 'string' ? { text: options } : options, text = _a.text, _b = _a.com, com = _b === void 0 ? false : _b, _c = _a.from, from = _c === void 0 ? '' : _c, _d = _a.to, to = _d === void 0 ? '' : _d;
|
||
|
|
if (!!from) return [3 /*break*/, 2];
|
||
|
|
return [4 /*yield*/, detect$1(options)];
|
||
|
|
case 1:
|
||
|
|
from = _j.sent();
|
||
|
|
_j.label = 2;
|
||
|
|
case 2:
|
||
|
|
if (!to) {
|
||
|
|
to = from.startsWith('zh') ? 'en' : 'zh-CN';
|
||
|
|
}
|
||
|
|
_e = transformRaw$1;
|
||
|
|
_f = request;
|
||
|
|
_g = {
|
||
|
|
url: getRoot(com) + '/translate_a/single'
|
||
|
|
};
|
||
|
|
_h = {
|
||
|
|
client: 'webapp',
|
||
|
|
sl: from,
|
||
|
|
tl: to,
|
||
|
|
hl: 'zh-CN',
|
||
|
|
dt: ['at', 'bd', 'ex', 'ld', 'md', 'qca', 'rw', 'rm', 'ss', 't'],
|
||
|
|
otf: '2',
|
||
|
|
ssel: '3',
|
||
|
|
tsel: '0',
|
||
|
|
kc: '6'
|
||
|
|
};
|
||
|
|
return [4 /*yield*/, sign$2(text, com)];
|
||
|
|
case 3: return [4 /*yield*/, _f.apply(void 0, [(_g.query = (_h.tk = _j.sent(),
|
||
|
|
_h.q = text,
|
||
|
|
_h),
|
||
|
|
_g)])];
|
||
|
|
case 4: return [2 /*return*/, _e.apply(void 0, [_j.sent(),
|
||
|
|
{
|
||
|
|
from: from,
|
||
|
|
to: to,
|
||
|
|
com: com,
|
||
|
|
text: text
|
||
|
|
}])];
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
function transformRaw$1(body, queryObj) {
|
||
|
|
var text = queryObj.text, com = queryObj.com, to = queryObj.to;
|
||
|
|
var googleFrom = body[2];
|
||
|
|
var result = {
|
||
|
|
text: text,
|
||
|
|
raw: body,
|
||
|
|
from: googleFrom,
|
||
|
|
to: to,
|
||
|
|
link: getRoot(com) + "/#view=home&op=translate&sl=" + googleFrom + "&tl=" + to + "&text=" + encodeURIComponent(text)
|
||
|
|
};
|
||
|
|
try {
|
||
|
|
result.dict = body[1].map(function (arr) {
|
||
|
|
return arr[0] + ':' + arr[1].join(',');
|
||
|
|
});
|
||
|
|
}
|
||
|
|
catch (e) { }
|
||
|
|
try {
|
||
|
|
result.result = body[0]
|
||
|
|
.map(function (arr) { return arr[0]; })
|
||
|
|
.filter(function (x) { return x; })
|
||
|
|
.map(function (x) { return x.trim(); });
|
||
|
|
}
|
||
|
|
catch (e) { }
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
var index$1 = /*#__PURE__*/Object.freeze({
|
||
|
|
__proto__: null,
|
||
|
|
detect: detect$1,
|
||
|
|
audio: audio$1,
|
||
|
|
translate: translate$1
|
||
|
|
});
|
||
|
|
|
||
|
|
// blueimp-md5 是一个 CommonJS 模块,为了跟 ./node.ts 保持一致,这里将它转换为 ES6 模块
|
||
|
|
|
||
|
|
var client = 'fanyideskweb';
|
||
|
|
var navigatorAppVersion = navigator.appVersion;
|
||
|
|
var bv = bluemd5(navigatorAppVersion);
|
||
|
|
/**
|
||
|
|
* 有道翻译接口的签名算法
|
||
|
|
* @param text
|
||
|
|
*/
|
||
|
|
function sign$3 (text) {
|
||
|
|
var ts = Date.now() + '';
|
||
|
|
var salt = ts + parseInt(10 * Math.random() + '', 10);
|
||
|
|
return {
|
||
|
|
client: client,
|
||
|
|
ts: ts,
|
||
|
|
bv: bv,
|
||
|
|
salt: salt,
|
||
|
|
sign: bluemd5(client + text + salt + 'mmbP%A-r6U3Nw(n]BjuEU')
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
var standard2custom$1 = {
|
||
|
|
en: 'en',
|
||
|
|
ru: 'ru',
|
||
|
|
pt: 'pt',
|
||
|
|
es: 'es',
|
||
|
|
'zh-CN': 'zh-CHS',
|
||
|
|
ja: 'ja',
|
||
|
|
ko: 'ko',
|
||
|
|
fr: 'fr'
|
||
|
|
};
|
||
|
|
var custom2standard$1 = invert(standard2custom$1);
|
||
|
|
var link = 'http://fanyi.youdao.com';
|
||
|
|
var translateAPI = link + '/translate_o?smartresult=dict&smartresult=rule';
|
||
|
|
// 有道跟百度一样,通过添加一个 Cookie 鉴别请求是否来自网页
|
||
|
|
var headers$2 = undefined;
|
||
|
|
function webAPI (options) {
|
||
|
|
return __awaiter(this, void 0, void 0, function () {
|
||
|
|
var _a, text, _b, from, _c, to, _d;
|
||
|
|
return __generator(this, function (_e) {
|
||
|
|
switch (_e.label) {
|
||
|
|
case 0:
|
||
|
|
_a = typeof options === 'string' ? { text: options } : options, text = _a.text, _b = _a.from, from = _b === void 0 ? '' : _b, _c = _a.to, to = _c === void 0 ? '' : _c;
|
||
|
|
text = text.slice(0, 5000);
|
||
|
|
if (from) {
|
||
|
|
from = standard2custom$1[from];
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
from = 'AUTO';
|
||
|
|
}
|
||
|
|
if (to) {
|
||
|
|
to = standard2custom$1[to];
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
to = 'AUTO';
|
||
|
|
}
|
||
|
|
// 有道网页翻译的接口的语种与目标语种中必须有一个是中文,或者两个都是 AUTO
|
||
|
|
if (!((from === 'AUTO' && to === 'AUTO') ||
|
||
|
|
(from === 'zh-CHS' || to === 'zh-CHS'))) {
|
||
|
|
throw getError("UNSUPPORTED_LANG" /* UNSUPPORTED_LANG */);
|
||
|
|
}
|
||
|
|
_d = transformRaw$2;
|
||
|
|
return [4 /*yield*/, request({
|
||
|
|
method: 'post',
|
||
|
|
url: translateAPI,
|
||
|
|
type: 'form',
|
||
|
|
body: Object.assign({
|
||
|
|
i: text,
|
||
|
|
from: from,
|
||
|
|
to: to,
|
||
|
|
smartresult: 'dict',
|
||
|
|
doctype: 'json',
|
||
|
|
version: '2.1',
|
||
|
|
keyfrom: 'fanyi.web',
|
||
|
|
action: 'FY_BY_REALTIME',
|
||
|
|
typoResult: 'false'
|
||
|
|
}, sign$3(text)),
|
||
|
|
headers: headers$2
|
||
|
|
})];
|
||
|
|
case 1: return [2 /*return*/, _d.apply(void 0, [_e.sent(),
|
||
|
|
text])];
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
function transformRaw$2(body, text) {
|
||
|
|
if (body.errorCode !== 0) {
|
||
|
|
throw getError("API_SERVER_ERROR" /* API_SERVER_ERROR */);
|
||
|
|
}
|
||
|
|
var _a = body.type.split('2'), from = _a[0], to = _a[1];
|
||
|
|
from = custom2standard$1[from];
|
||
|
|
to = custom2standard$1[to];
|
||
|
|
var smartResult = body.smartResult;
|
||
|
|
var result = {
|
||
|
|
raw: body,
|
||
|
|
text: text,
|
||
|
|
from: from,
|
||
|
|
to: to,
|
||
|
|
link: smartResult
|
||
|
|
? "https://dict.youdao.com/search?q=" + encodeURIComponent(text) + "&keyfrom=fanyi.smartResult"
|
||
|
|
: "http://fanyi.youdao.com/translate?i=" + encodeURIComponent(text)
|
||
|
|
};
|
||
|
|
if (smartResult) {
|
||
|
|
try {
|
||
|
|
result.dict = smartResult.entries.filter(function (s) { return s; }).map(function (s) { return s.trim(); });
|
||
|
|
}
|
||
|
|
catch (e) { }
|
||
|
|
}
|
||
|
|
try {
|
||
|
|
result.result = body.translateResult.map(function (part) {
|
||
|
|
return part.map(function (o) { return o.tgt.trim(); }).join('');
|
||
|
|
});
|
||
|
|
}
|
||
|
|
catch (e) { }
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
function detect$2 (options) {
|
||
|
|
return __awaiter(this, void 0, void 0, function () {
|
||
|
|
var result;
|
||
|
|
return __generator(this, function (_a) {
|
||
|
|
switch (_a.label) {
|
||
|
|
case 0: return [4 /*yield*/, webAPI(typeof options === 'string' ? options : options.text)];
|
||
|
|
case 1:
|
||
|
|
result = _a.sent();
|
||
|
|
return [2 /*return*/, result.from];
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
var standard2custom$2 = {
|
||
|
|
en: 'eng',
|
||
|
|
ja: 'jap',
|
||
|
|
ko: 'ko',
|
||
|
|
fr: 'fr'
|
||
|
|
};
|
||
|
|
function audio$2 (options) {
|
||
|
|
return __awaiter(this, void 0, void 0, function () {
|
||
|
|
var _a, text, _b, from, voiceLang;
|
||
|
|
return __generator(this, function (_c) {
|
||
|
|
switch (_c.label) {
|
||
|
|
case 0:
|
||
|
|
_a = typeof options === 'string' ? { text: options } : options, text = _a.text, _b = _a.from, from = _b === void 0 ? '' : _b;
|
||
|
|
if (!!from) return [3 /*break*/, 2];
|
||
|
|
return [4 /*yield*/, detect$2(text)];
|
||
|
|
case 1:
|
||
|
|
from = _c.sent();
|
||
|
|
_c.label = 2;
|
||
|
|
case 2:
|
||
|
|
voiceLang = standard2custom$2[from];
|
||
|
|
if (!voiceLang)
|
||
|
|
throw getError("UNSUPPORTED_LANG" /* UNSUPPORTED_LANG */);
|
||
|
|
return [2 /*return*/, "http://tts.youdao.com/fanyivoice?word=" + encodeURIComponent(text) + "&le=" + voiceLang + "&keyfrom=speaker-target"];
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
var index$2 = /*#__PURE__*/Object.freeze({
|
||
|
|
__proto__: null,
|
||
|
|
detect: detect$2,
|
||
|
|
audio: audio$2,
|
||
|
|
translate: webAPI
|
||
|
|
});
|
||
|
|
|
||
|
|
exports.baidu = index;
|
||
|
|
exports.google = index$1;
|
||
|
|
exports.youdao = index$2;
|
||
|
|
|
||
|
|
return exports;
|
||
|
|
|
||
|
|
}({}, md5));
|