浏览器端使用javascript调用腾讯翻译api

最近在学习的小玩意,发现腾讯的文档十分坑爹,里面有很多错误的指示。

不过腾讯的机器翻译还是很牛的,我觉得翻译水准比谷歌好很多。

腾讯的机器翻译貌似在试用阶段,不收费,用QQ或微信登录即可申请使用。

首先获得SecretId和SecretKey,最好是创建一个子用户,因为这两个“秘密”都要明文写在js里。创建一个工程,这样就有了ProjectId。

准备好如下的参数:

var reqParams = [
         [ "Action", "TextTranslate" ],
         [ "Nonce", Nonce ],  // 随机整数
         [ "ProjectId", ProjectId],
         ["Region", "ap-beijing"],
         ["SecretId", SecretId],
         ["Source","auto"],  // 自动检测要翻译的文本的语种
         ["SourceText", sourceText],  // 要翻译的文本。生成签名时,必须使用原文本,即没有做uri编码的
         ["Target","zh"],  // 翻译成哪个语种,这里是翻译成中文
         ["Timestamp",timestamp ],  // 时间戳,以秒为单位,而js里用Date对象获取的时间戳是毫秒的,注意。腾讯文档说时间戳是0时区的,但其实就是东八区(北京时区)
 ["Version","2018-03-21"]
];

上面是一个嵌套的数组,或者说二维数组,这是为了方便排序(上面的顺序已经是排好了的)。必须先按参数的字母顺序排序后,拼成字符串,再做签名。

参数对转字符串函数:

// 参数对转成字符串
function paramsToStr(params)
{
    // 按参数名的字典序排序

    params.sort(function(a,b){
        if(a[0] < b[0]) return -1;
        else if(a[0] > b[0]) return 1;
        return 0;
    });

    // 连成字符串

    var parPairStrArr = [];
    for (var i in params)
    {
        var par = params[i];
        var parStr = par.join("=");
        parPairStrArr.push(parStr);
    }
    var str = parPairStrArr.join("&");
    return str;
}

有了参数字符串,再构造签名用的字符串,它需要包含请求方法、请求路径、请求参数。

// 签名原文字符串
    var signStr = reqMethod + makeBaseUrl(host, hostPath) + "?" + paramsStr;  // reqMethod 就是 GET 或 POST
// makeBaseUrl 只是简单的返回了腾讯翻译的域名(不包括https://),在这里是tmt.tencentcloudapi.com

    // 签名
    var hs = CryptoJS.HmacSHA1(signStr, SecretKey);
    var rawSig = CryptoJS.enc.Base64.stringify(hs);
    console.log("rawSig=" + rawSig);
    var sig = encodeURIComponent(rawSig);  // 必须使用 encodeURIComponent,对base64字符串中的特殊字符也做uri编码
    return sig;

获取到 sig 后,下面要生成真正用于http请求的url,在这里使用 GET 方法,所以参数都直接附在Url中。这时,sourceText,也就是待翻译文本,需要先把空格替换成+号、在做uri编码。

var iSourceText = reqParams.findIndex((p)=>(p[0]=="SourceText"));
    reqParams[iSourceText][1] = encodeURI(sourceText.replace(/\ /g,"+"));
    var paramsStr = paramsToStr(reqParams);

    var url = "https://" + makeBaseUrl(host, hostPath) + "?" + paramsStr + "&Signature=" + sig;
    console.log("url=" + url);

接下来就是使用 XMLHttpRequest 做http请求了。但是腾讯翻译服务器那边没有允许跨域。可以装个插件解决此问题。

允许浏览器跨域请求http的插件:https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi

完整代码:

  1 // 参数对转成字符串
  2 function paramsToStr(params)
  3 {
  4     // 按参数名的字典序排序
  5 
  6     params.sort(function(a,b){
  7         if(a[0] < b[0]) return -1;
  8         else if(a[0] > b[0]) return 1;
  9         return 0;
 10     });
 11 
 12     // 连成字符串
 13 
 14     var parPairStrArr = [];
 15     for (var i in params)
 16     {
 17         var par = params[i];
 18         var parStr = par.join("=");
 19         parPairStrArr.push(parStr);
 20     }
 21     var str = parPairStrArr.join("&");
 22     return str;
 23 }
 24 
 25 function makeBaseUrl(host, hostPath)
 26 {
 27     return host + hostPath;
 28 }
 29 
 30 // 声称签名
 31 function makeSignature(reqMethod, host, hostPath, reqParams)
 32 {
 33     var paramsStr = paramsToStr(reqParams);
 34 
 35     // 签名原文字符串
 36     var signStr = reqMethod + makeBaseUrl(host, hostPath) + "?" + paramsStr;
 37 
 38     // 签名
 39     var hs = CryptoJS.HmacSHA1(signStr, SecretKey);
 40     var rawSig = CryptoJS.enc.Base64.stringify(hs);
 41     console.log("rawSig=" + rawSig);
 42     var sig = encodeURIComponent(rawSig);
 43     return sig;
 44 }
 45 
 46 // 发送翻译请求
 47 function sendTrans(sourceText, cb)
 48 {
 49     if(sourceText == null || sourceText == "")
 50     {
 51         cb("");
 52         return;
 53     }
 54 
 55     var SecretId = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
 56     var SecretKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
 57 
 58     var reqMethod = "GET";
 59     var host = "tmt.tencentcloudapi.com";
 60     var hostPath = "/";
 61 
 62     var Nonce = Math.floor(Math.random() * 1000000000);
 63     var date = new Date();
 64     var timestamp = Math.floor(date.getTime() / 1000);
 65 
 66     var reqParams = [
 67         [ "Action", "TextTranslate" ],
 68         [ "Nonce", Nonce ],
 69         [ "ProjectId", xxxxxxxx],
 70         ["Region", "ap-beijing"],
 71         ["SecretId", SecretId],
 72         ["Source","auto"],
 73         ["SourceText", sourceText],  // 生成签名时,使用原文本
 74         ["Target","zh"],
 75         ["Timestamp",timestamp ],
 76         ["Version","2018-03-21"]
 77     ];
 78 
 79     // 生成签名
 80     var sig = makeSignature(reqMethod, host, hostPath, reqParams);
 81 
 82     // 原文本中所有的空格替换成+号,然后uri编码
 83     var iSourceText = reqParams.findIndex((p)=>(p[0]=="SourceText"));
 84     reqParams[iSourceText][1] = encodeURI(sourceText.replace(/\ /g,"+"));
 85     var paramsStr = paramsToStr(reqParams);
 86 
 87     var url = "https://" + makeBaseUrl(host, hostPath) + "?" + paramsStr + "&Signature=" + sig;
 88     console.log("url=" + url);
 89 
 90     var xhr = new XMLHttpRequest();
 91     xhr.timeout = 3000;
 92     xhr.ontimeout = function()
 93     {
 94         cb("超时,翻译失败");
 95     };
 96     xhr.onerror = function()
 97     {
 98         cb("错误,翻译失败");
 99     };
100 
101     xhr.open(reqMethod, url, true);
102     xhr.responseType = "json";
103     var sendRet = xhr.send();
104     xhr.onreadystatechange = function()
105     {
106         if(xhr.readyState == 4)
107         {
108             if(xhr.status == 200 || xhr.status == 304)
109             {
110                 var ret = xhr.response;
111                 cb(ret.Response.TargetText);
112             }
113             else
114             {
115                 cb(xhr.responseText);
116             }
117         }
118     };
119 }

猜你喜欢

转载自www.cnblogs.com/Dolaham/p/10594059.html