帮助与文档 > 产品文档 > 自然语言翻译 > API文档 > 文本翻译服务
文本翻译服务

有道智云翻译 API 简介

Hi,您好,欢迎使用有道智云文本翻译API接口服务。如果您想快速体验服务,建议您前往翻译体验中心 或者在体验中心右下侧找到小程序二维码,扫描进行体验。

本文档主要针对需要集成HTTP API的技术开发工程师,详细描述文本翻译能力相关的技术内容。

如果您有与我们商务合作的需求,可以通过一下方式联系我们:

商务邮箱: AIcloud_Business@corp.youdao.com

如果您对文档内容有任何疑问,可以通过以下几种方式联系我们:

客服QQ:1906538062

智云翻译技术交流QQ 1群: 652880659(已满)

智云翻译技术交流QQ 2群: 669384425

智云OCR技术交流QQ 1群: 654064748(已满)

智云OCR技术交流QQ 2群: 471638046

智云语音技术交流QQ群:861723255

联系邮箱: zyservice@corp.youdao.com

温馨提示:

  • 本文档主要针对开发人员,接入测试前需要获取应用ID(appKey)和应用密钥;如果您还没有,请按照新手指南获取。
  • 平台向每个账户赠送50元的体验金,供用户集成前测试所用,具体资费规则详见文本翻译服务报价

接口能力

有道翻译API接口提供有道的翻译服务,包含了中英翻译和小语种翻译功能。您只需要通过调用有道翻译API,传入待翻译的内容,并指定要翻译的源语言(支持源语言语种自动检测)和目标语言种类,就可以得到相应的翻译结果。

有道翻译API HTTP地址:

http://openapi.youdao.com/api

有道翻译API HTTPS地址:

https://openapi.youdao.com/api

协议须知

调用方在集成文本翻译API时,请遵循以下规则。

规则描述
传输方式HTTP/HTTPS
请求方式GET/POST
字符编码统一使用UTF-8 编码
相应格式统一采用JSON格式

接口调用参数

调用API需要向接口发送以下字段来访问服务。

字段名类型含义必填备注
qtext要翻译的文本True必须是UTF-8编码
fromtext源语言True参考下方语言列表(可设置为auto)
totext目标语言True参考下方语言列表(可设置为auto)
appKeytext应用标识(应用ID)True可在 应用管理 查看
salttext随机字符串Truehfa12lak56ja9gjl
signtext签名信息:sha256(appKey+input+salt+curtime+密钥)Truef9976efca9dd9e280d4c6637230da5d94c2df6e520605db5a5a4d1d91ba45761
exttext翻译结果音频格式,支持mp3falsemp3
voicetext翻译结果发音选择,0为女声,1为男声,默认为女声false0
signTypetext签名类型truev3
curtimetext当前UTC时间戳true1543199847

注意:

  • voice 没有男声的,会输出女声
  • 发音需要在控制台创建tts实例,并绑定应用才能使用,否则点击发音会报110错误。
  • 接口salt+curtime来防重放(即一个请求不可以被请求2次),所以salt最好为UUID。

签名生成算法如下:

signType=v3,sha256(应用ID+input+salt+curtime+密钥),推荐使用
sha256签名计算方法为:sha256(应用ID+input+salt+当前UTC时间戳+密钥)。

其中,input的计算方式为:input=q前10个字符 + q长度 + q后十个字符(当q长度大于20)或 input=q字符串(当q长度小于等于20)。

不同语言获取时间戳,请参看此此链接

如果对签名有疑问,可以参看各语言demo。

输出结果

返回的结果是json格式,包含字段与FROM和TO的值有关,具体说明如下:

字段名类型含义备注
errorCodetext错误返回码一定存在
querytext源语言查询正确时,一定存在
translationtext翻译结果查询正确时一定存在
basictext词义基本词典,查词时才有
webtext词义网络释义,该结果不一定存在
ltext源语言和目标语言一定存在
dicttext词典deeplink查询语种为支持语言时,存在
webdicttextwebdeeplink查询语种为支持语言时,存在
tSpeakUrltext翻译结果发音地址翻译成功一定存在,需要应用绑定语音合成实例才能正常播放,否则返回110错误码
speakUrltext源语言发音地址翻译成功一定存在,需要应用绑定语音合成实例才能正常播放,否则返回110错误码
returnPhrasetext单词校验后的结果主要校验字母大小写、单词前含符号、中文简繁体

注:

a.英文查词的basic字段中又包含以下字段,中文查词basic只包含explains字段。

字段含义
us-phonetic美式音标,英文查词成功,一定存在
phonetic默认音标,默认是英式音标,英文查词成功,一定存在
uk-phonetic英式音标,英文查词成功,一定存在
uk-speech英式发音,英文查词成功,一定存在
us-speech美式发音,英文查词成功,一定存在
explains基本释义

b.中文查词的basic字段只包含explains字段。

示例

使用good单词查询作为参考说明json返回结果:

字段名参数数据描述
qgood要翻译的文本
fromen源语言
tozh-CHS目标语言
appKeyff889495-4b45-46d9-8f48-946554334f2a您的应用ID
salt1995882C5064805BC30A39829B779D7B实时计算,生成随机数
signf9976efca9dd9e280d4c6637230da5d94c2df6e520605db5a5a4d1d91ba45761实时计算
signTypev2示例值

输出结果与FROM和TO的值有关:

  1. 当FROM和TO的值都在{zh-CHS, EN}范围内时
{
  "errorCode":"0",
  "query":"good", //查询正确时,一定存在
  "translation": [ //查询正确时一定存在
      "好"
  ],
  "basic":{ // 有道词典-基本词典,查词时才有
      "phonetic":"gʊd"
      "uk-phonetic":"gʊd" //英式音标
      "us-phonetic":"ɡʊd" //美式音标
      "uk-speech": "XXXX",//英式发音
      "us-speech": "XXXX",//美式发音
      "explains":[
          "好处",
          "好的"
          "好"
      ]
  },
  "web":[ // 有道词典-网络释义,该结果不一定存在
      {
          "key":"good",
          "value":["良好","善","美好"]
      },
      {...}
  ]
  ],
  "dict":{
      "url":"yddict://m.youdao.com/dict?le=eng&q=good"
  },
  "webdict":{
      "url":"http://m.youdao.com/dict?le=eng&q=good"
  },
  "l":"EN2zh-CHS",
  "tSpeakUrl":"XXX",//翻译后的发音地址
  "speakUrl": "XXX" //查询文本的发音地址
}
  1. 当FROM和TO的值有在{zh-CHS, EN}范围外的时候
{
   "errorCode": "0",
   "translation": ["大丈夫です"] //小语种翻译,一定存在
   "dict":{
       "url":"yddict://m.youdao.com/dict?le=jap&q=%E6%B2%A1%E5%85%B3%E7%B3%BB%E3%80%82"
   },
   "webdict":{
       "url":"http://m.youdao.com/dict?le=jap&q=%E6%B2%A1%E5%85%B3%E7%B3%BB%E3%80%82"
   },
   "l":"zh-CHS2ja",
   "tSpeakUrl":"XXX",//翻译后的发音地址
   "speakUrl": "XXX" //查询文本的发音地址
}

支持的语言表

语言支持目标语言
中文英文、日文、韩文、法文、西班牙文、葡萄牙文、俄文、越南文、德文、阿拉伯文、印尼文、意大利文
英文中文、日文
日文中文、英文
韩文中文
法文中文
西班牙文中文
葡萄牙文中文
意大利文中文
俄文中文
越南文中文
德文中文
阿拉伯文中文
印尼文中文
意大利文中文
自动识别中文

其中,自动识别支持以上所有语言的自动识别

下表为各语言对应代码:

语言代码
中文zh-CHS
英文en
日文ja
韩文ko
法文fr
西班牙文es
葡萄牙文pt
意大利文it
俄文ru
越南文vi
德文de
阿拉伯文ar
印尼文id
意大利文it
自动识别auto

错误代码列表

错误码含义
101缺少必填的参数,出现这个情况还可能是et的值和实际加密方式不对应
102不支持的语言类型
103翻译文本过长
104不支持的API类型
105不支持的签名类型
106不支持的响应类型
107不支持的传输加密类型
108appKey无效,注册账号, 登录后台创建应用和实例并完成绑定, 可获得应用ID和密钥等信息,其中应用ID就是appKey( 注意不是应用密钥)
109batchLog格式不正确
110无相关服务的有效实例
111开发者账号无效
113q不能为空
201解密失败,可能为DES,BASE64,URLDecode的错误
202签名检验失败
203访问IP地址不在可访问IP列表
205请求的接口与应用的平台类型不一致,如有疑问请参考[入门指南]()
206因为时间戳无效导致签名校验失败
207重放请求
301辞典查询失败
302翻译查询失败
303服务端的其它异常
401账户已经欠费停
411访问频率受限,请稍后访问
412长请求过于频繁,请稍后访问

常见问题及注意事项

  • 点击发音,返回110

发音需要tts实例,需要在控制台创建语音合成实例绑定应用后方能使用。

  • 返回110

应用没有绑定服务实例,可以新建服务实例,绑定服务实例。

  • 返回108

appKey无效,注册账号, 登录后台创建应用和实例并完成绑定, 可获得应用ID和密钥等信息,其中应用ID就是appKey( 注意不是应用密钥)

  • 返回101

首先确保必填参数齐全,然后,确认参数书写是否正确。

  • 返回202

如果确认 appKeyappSecret 的正确性,仍返回202,一般是编码问题。请确保 q 为UTF-8编码.

版本更新记录

上线日期版本号更新内容
2019.04.22v1.0.0新增中文与意大利文、英文与日文互译;新增单词校验逻辑,对于输入单词大小写混合回小写单词、单词前面存在符号时返回去符号单词、中文繁体返回纯简体内容。

常用语言 Demo

Java 示例

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;


public class FanyiV3DemoInternalTest {

    private static Logger logger = LoggerFactory.getLogger(FanyiV3DemoInternalTest.class);

    private static final String YOUDAO_URL = "http://openapi.youdao.com/api";

    private static final String APP_KEY = "您的应用ID";

    private static final String APP_SECRET = "您的应用密钥";

    public static void main(String[] args) throws IOException {

        Map<String,String> params = new HashMap<String,String>();
        String q = "test";
        String salt = String.valueOf(System.currentTimeMillis());
        params.put("from", "EN");
        params.put("to", "zh-CHS");
        params.put("signType", "v3");
        String curtime = String.valueOf(System.currentTimeMillis() / 1000);
        params.put("curtime", curtime);
        String signStr = APP_KEY + truncate(q) + salt + curtime + APP_SECRET;
        String sign = getDigest(signStr);
        params.put("appKey", APP_KEY);
        params.put("q", q);
        params.put("salt", salt);
        params.put("sign", sign);
        /** 处理结果 */
        requestForHttp(YOUDAO_URL,params);
    }

    public static void requestForHttp(String url,Map<String,String> params) throws IOException {

        /** 创建HttpClient */
        CloseableHttpClient httpClient = HttpClients.createDefault();

        /** httpPost */
        HttpPost httpPost = new HttpPost(url);
        List<NameValuePair> paramsList = new ArrayList<NameValuePair>();
        Iterator<Map.Entry<String,String>> it = params.entrySet().iterator();
        while(it.hasNext()){
            Map.Entry<String,String> en = it.next();
            String key = en.getKey();
            String value = en.getValue();
            paramsList.add(new BasicNameValuePair(key,value));
        }
        httpPost.setEntity(new UrlEncodedFormEntity(paramsList,"UTF-8"));
        CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
        try{
            Header[] contentType = httpResponse.getHeaders("Content-Type");
            logger.info("Content-Type:" + contentType[0].getValue());
            HttpEntity httpEntity = httpResponse.getEntity();
            String json = EntityUtils.toString(httpEntity,"UTF-8");
            EntityUtils.consume(httpEntity);
            logger.info(json);
            System.out.println(json);
        }finally {
            try{
                if(httpResponse!=null){
                    httpResponse.close();
                }
            }catch(IOException e){
                logger.info("## release resouce error ##" + e);
            }
        }
    }

    /**
     * 生成加密字段
     */
    public static String getDigest(String string) {
        if (string == null) {
            return null;
        }
        char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
        byte[] btInput = string.getBytes();
        try {
            MessageDigest mdInst = MessageDigest.getInstance("SHA-256");
            mdInst.update(btInput);
            byte[] md = mdInst.digest();
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (byte byte0 : md) {
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (NoSuchAlgorithmException e) {
            return null;
        }
    }

    /**
    *
    * @param result 音频字节流
    * @param file 存储路径
    */
    private static void byte2File(byte[] result, String file) {
        File audioFile = new File(file);
        FileOutputStream fos = null;
        try{
            fos = new FileOutputStream(audioFile);
            fos.write(result);

        }catch (Exception e){
            logger.info(e.toString());
        }finally {
            if(fos != null){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

  public static String truncate(String q) {
        if (q == null) {
            return null;
        }
        int len = q.length();
        String result;
        return len <= 20 ? q : (q.substring(0, 10) + len + q.substring(len - 10, len));
    }
}

Python 示例

# -*- coding: utf-8 -*-
import sys
import uuid
import requests
import hashlib
import time

reload(sys)
sys.setdefaultencoding('utf-8')

YOUDAO_URL = 'http://openapi.youdao.com/api'
APP_KEY = '您的应用ID'
APP_SECRET = '您的应用密钥'


def encrypt(signStr):
    hash_algorithm = hashlib.sha256()
    hash_algorithm.update(signStr.encode('utf-8'))
    return hash_algorithm.hexdigest()


def truncate(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]


def do_request(data):
    headers = {'Content-Type': 'application/x-www-form-urlencoded'}
    return requests.post(YOUDAO_URL, data=data, headers=headers)


def connect():
    q = "test"

    data = {}
    data['from'] = 'EN'
    data['to'] = 'zh-CHS'
    data['signType'] = 'v3'
    curtime = str(int(time.time()))
    data['curtime'] = curtime
    salt = str(uuid.uuid1())
    signStr = APP_KEY + truncate(q) + salt + curtime + APP_SECRET
    sign = encrypt(signStr)
    data['appKey'] = APP_KEY
    data['q'] = q
    data['salt'] = salt
    data['sign'] = sign

    response = do_request(data)
    print response.content


if __name__ == '__main__':
    connect()

C#示例

using System;
using System.IO;
using System.Net;
using System.Text;
using System.Collections.Generic;
using System.Security.Cryptography;

namespace zhiyun_csharp_demo
{
    class FanyiV3DemoInternalTest
    {
        public static void Main()
        {
            Dictionary<String, String> dic = new Dictionary<String, String>();
            string url = "http://openapi.youdao.com/api";
            string q = "test";
            string appKey = "您的应用ID";
            string appSecret = "您的应用密钥";
            string salt = DateTime.Now.Millisecond.ToString();
            dic.Add("from", "EN");
            dic.Add("to", "zh-CHS");
            dic.Add("signType", "v3");
            TimeSpan ts = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc));
            long millis = (long) ts.TotalMilliseconds;
            string curtime = Convert.ToString(millis / 1000);
            dic.Add("curtime", curtime);
            string signStr = appKey + Truncate(q) + salt + curtime + appSecret;;
            string sign = ComputeHash(signStr, new SHA256CryptoServiceProvider());
            dic.Add("q", System.Web.HttpUtility.UrlEncode(q));
            dic.Add("appKey", appKey);
            dic.Add("salt", salt);
            dic.Add("sign", sign);
            Post(url, dic);
        }

        protected static string ComputeHash(string input, HashAlgorithm algorithm)
        {
          Byte[] inputBytes = Encoding.UTF8.GetBytes(input);
          Byte[] hashedBytes = algorithm.ComputeHash(inputBytes);
          return BitConverter.ToString(hashedBytes).Replace("-", "");
        }

        protected static void Post(string url, Dictionary<String, String> dic)
        {
            string result = "";
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            req.Method = "POST";
            req.ContentType = "application/x-www-form-urlencoded";
            StringBuilder builder = new StringBuilder();
            int i = 0;
            foreach (var item in dic)
            {
                if (i > 0)
                    builder.Append("&");
                builder.AppendFormat("{0}={1}", item.Key, item.Value);
                i++;
            }
            byte[] data = Encoding.UTF8.GetBytes(builder.ToString());
            req.ContentLength = data.Length;
            using (Stream reqStream = req.GetRequestStream())
            {
                reqStream.Write(data, 0, data.Length);
                reqStream.Close();
            }
            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
            Stream stream = resp.GetResponseStream();
            using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
            {
            result = reader.ReadToEnd();
            }
            Console.WriteLine(result);
        }

        protected static string Truncate(string q)
        {
            if (q == null)
            {
               return null;
            }
            int len = q.Length;
            return len <= 20 ? q : (q.Substring(0, 10) + len + q.Substring(len - 10, 10));
        }

        private static bool SaveBinaryFile(WebResponse response, string FileName)
        {
            string FilePath = FileName + DateTime.Now.Millisecond.ToString() + ".mp3";
            bool Value = true;
            byte[] buffer = new byte[1024];

            try
            {
                if (File.Exists(FilePath))
                    File.Delete(FilePath);
                Stream outStream = System.IO.File.Create(FilePath);
                Stream inStream = response.GetResponseStream();

                int l;
                do
                {
                    l = inStream.Read(buffer, 0, buffer.Length);
                    if (l > 0)
                        outStream.Write(buffer, 0, l);
                }
                while (l > 0);

                outStream.Close();
                inStream.Close();
            }
            catch
            {
                Value = false;
            }
            return Value;
        }
    }
}

PHP 示例

<?php
define("CURL_TIMEOUT",   2000);
define("URL",            "http://openapi.youdao.com/api");
define("APP_KEY",        "您的应用ID"); // 替换为您的应用ID
define("SEC_KEY",        "您的应用密钥"); // 替换为您的密钥

function do_request($q)
{
                    $salt = create_guid();
                    $args = array(
        'q' => $q,
        'appKey' => APP_KEY,
        'salt' => $salt,
    );
                    $args['from'] = 'EN';
                    $args['to'] = 'zh-CHS';
                    $args['signType'] = 'v3';
                    $curtime = strtotime("now");
                    $args['curtime'] = $curtime;
                    $signStr = APP_KEY . truncate($q) . $salt . $curtime . SEC_KEY;
                    $args['sign'] = hash("sha256", $signStr);
                    $ret = call(URL, $args);
    return $ret;
}

// 发起网络请求
function call($url, $args=null, $method="post", $testflag = 0, $timeout = CURL_TIMEOUT, $headers=array())
{
                    $ret = false;
                    $i = 0;
    while($ret === false)
    {
        if($i > 1)
            break;
        if($i > 0)
        {
            sleep(1);
        }
                    $ret = callOnce($url, $args, $method, false, $timeout, $headers);
                    $i++;
    }
    return $ret;
}

function callOnce($url, $args=null, $method="post", $withCookie = false, $timeout = CURL_TIMEOUT, $headers=array())
{
                    $ch = curl_init();
    if($method == "post")
    {
                    $data = convert($args);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_POST, 1);
    }
    else
    {
                    $data = convert($args);
        if($data)
        {
            if(stripos($url, "?") > 0)
            {
                    $url .= "&$data";
            }
            else
            {
                    $url .= "?$data";
            }
        }
    }
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    if(!empty($headers))
    {
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    }
    if($withCookie)
    {
        curl_setopt($ch, CURLOPT_COOKIEJAR, $_COOKIE);
    }
                    $r = curl_exec($ch);
    curl_close($ch);
    return $r;
}

function convert(&$args)
{
                    $data = '';
    if (is_array($args))
    {
        foreach ($args as $key=>$val)
        {
            if (is_array($val))
            {
                foreach ($val as $k=>$v)
                {
                    $data .= $key.'['.$k.']='.rawurlencode($v).'&';
                }
            }
            else
            {
                    $data .="$key=".rawurlencode($val)."&";
            }
        }
        return trim($data, "&");
    }
    return $args;
}

// uuid generator
function create_guid(){
                    $microTime = microtime();
    list($a_dec, $a_sec) = explode(" ", $microTime);
                    $dec_hex = dechex($a_dec* 1000000);
                    $sec_hex = dechex($a_sec);
    ensure_length($dec_hex, 5);
    ensure_length($sec_hex, 6);
                    $guid = "";
                    $guid .= $dec_hex;
                    $guid .= create_guid_section(3);
                    $guid .= '-';
                    $guid .= create_guid_section(4);
                    $guid .= '-';
                    $guid .= create_guid_section(4);
                    $guid .= '-';
                    $guid .= create_guid_section(4);
                    $guid .= '-';
                    $guid .= $sec_hex;
                    $guid .= create_guid_section(6);
    return $guid;
}

function create_guid_section($characters){
                    $return = "";
    for($i = 0; $i < $characters; $i++)
    {
                    $return .= dechex(mt_rand(0,15));
    }
    return $return;
}

function truncate($q) {
                    $len = strlen($q);
    return $len <= 20 ? $q : (substr($q, 0, 10) . $len . substr($q, $len - 10, $len));
}

function ensure_length(&$string, $length){
                    $strlen = strlen($string);
    if($strlen < $length)
    {
                    $string = str_pad($string, $length, "0");
    }
    else if($strlen > $length)
    {
                    $string = substr($string, 0, $length);
    }
}

// 输入
                    $q = "test";

                    $ret = do_request($q);
print_r($ret);
                    $ret = json_decode($ret, true);
?>

JS demo


<!doctype html>
<head>
    <meta charset="utf-8"/>
</head>
<body>
<div>可打开浏览器控制台查看结果</div>
<script src="http://shared.ydstatic.com/js/jquery/jquery-3.1.1.min.js"></script>
<script src="https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.js"></script>
<script type="text/javascript">
var appKey = '您的应用ID';
var key = '您的应用密钥';//注意:暴露appSecret,有被盗用造成损失的风险
var salt = (new Date).getTime();
var query = '你好';
// 多个query可以用\n连接  如 query='apple\norange\nbanana\npear'
var from = '';
var to = 'en';
var str1 = appKey + query + salt +key;
var sign = md5(str1);
$.ajax({
    url: 'http://openapi.youdao.com/api',
    type: 'post',
    dataType: 'jsonp',
    data: {
        q: query,
        appKey: appKey,
        salt: salt,
        from: from,
        to: to,
        sign: sign
    },
    success: function (data) {
        console.log(data);
    } 
});
</script>
</body>