现在翻译API各种各样,非常多,在我看来,有道算是不错的一个,专做翻译有一手,所以便去有道平台开通了一个翻译功能。
需要验证手机,有50块免费额度,感觉能用蛮久的,等免费用完,换个平台继续用。
从这进入 有道平台入口
下面这个类是基于Laravel框架的,其他框架的话,自行改下curlApi 和 writeErrorLog 两个方法
把代码放入app的Service目录,把有道平台申请好的APP_ID和APP_KEY填入,就可以直接用了,非常方便
调用方法如下:
$translator = new \App\Service\YoudaoTranslator();
$result = $translator->getTranslation('中国好地方', 'en');
dd($result);
<?php
namespace App\Service;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
class YoudaoTranslator
{
const APP_ID = '';//请填入申请的APP_ID
const APP_KEY = '';//请填入申请的APP_KEY
const API_TIMEOUT = 1;
const API_URL = 'https://openapi.youdao.com/api';
const KEY_QUERY = 'q';
const KEY_FROM = 'from';
const KEY_TO = 'to';
const KEY_APPID = 'appKey';
const KEY_SALT = 'salt';
const KEY_SIGN = 'sign';
const KEY_SIGN_TYPE = 'signType';
const KEY_CURTIME = 'curtime';
const KEY_ERROR_CODE = 'errorCode';
const KEY_TRANSLATION = 'translation';
const KEY_LANG = 'l';
const DEFAULT_SIGN_TYPE = 'v3';
const ERROR_CODES_MAPPER = [
101 => '缺少必填的参数,首先确保必填参数齐全,然后确认参数书写是否正确。',
102 => '不支持的语言类型',
103 => '翻译文本过长',
104 => '不支持的API类型',
105 => '不支持的签名类型',
106 => '不支持的响应类型',
107 => '不支持的传输加密类型',
108 => '应用ID无效,注册账号,登录后台创建应用和实例并完成绑定,可获得应用ID和应用密钥等信息',
109 => 'batchLog格式不正确',
110 => '无相关服务的有效实例,应用没有绑定服务实例,可以新建服务实例,绑定服务实例。注:某些服务的翻译结果发音需要tts实例,需要在控制台创建语音合成实例绑定应用后方能使用。',
111 => '开发者账号无效',
112 => '请求服务无效',
113 => 'q不能为空',
114 => '不支持的图片传输方式',
116 => 'strict字段取值无效,请参考文档填写正确参数值',
201 => '解密失败,可能为DES,BASE64,URLDecode的错误',
202 => '签名检验失败,如果确认应用ID和应用密钥的正确性,仍返回202,一般是编码问题。请确保翻译文本 q 为UTF-8编码.',
203 => '访问IP地址不在可访问IP列表',
205 => '请求的接口与应用的平台类型不一致,确保接入方式(Android SDK、IOS SDK、API)与创建的应用平台类型一致。如有疑问请参考入门指南',
206 => '因为时间戳无效导致签名校验失败',
207 => '重放请求',
301 => '辞典查询失败',
302 => '翻译查询失败',
303 => '服务端的其它异常',
304 => '会话闲置太久超时',
401 => '账户已经欠费,请进行账户充值',
402 => 'offlinesdk不可用',
411 => '访问频率受限,请稍后访问',
412 => '长请求过于频繁,请稍后访问',
1001 => '无效的OCR类型',
1002 => '不支持的OCR image类型',
1003 => '不支持的OCR Language类型',
1004 => '识别图片过大',
1201 => '图片base64解密失败',
1301 => 'OCR段落识别失败',
1411 => '访问频率受限',
1412 => '超过最大识别字节数',
2003 => '不支持的语言识别Language类型',
2004 => '合成字符过长',
2005 => '不支持的音频文件类型',
2006 => '不支持的发音类型',
2201 => '解密失败',
2301 => '服务的异常',
2411 => '访问频率受限,请稍后访问',
2412 => '超过最大请求字符数',
3001 => '不支持的语音格式',
3002 => '不支持的语音采样率',
3003 => '不支持的语音声道',
3004 => '不支持的语音上传类型',
3005 => '不支持的语言类型',
3006 => '不支持的识别类型',
3007 => '识别音频文件过大',
3008 => '识别音频时长过长',
3009 => '不支持的音频文件类型',
3010 => '不支持的发音类型',
3201 => '解密失败',
3301 => '语音识别失败',
3302 => '语音翻译失败',
3303 => '服务的异常',
3411 => '访问频率受限,请稍后访问',
3412 => '超过最大请求字符数',
4001 => '不支持的语音识别格式',
4002 => '不支持的语音识别采样率',
4003 => '不支持的语音识别声道',
4004 => '不支持的语音上传类型',
4005 => '不支持的语言类型',
4006 => '识别音频文件过大',
4007 => '识别音频时长过长',
4201 => '解密失败',
4301 => '语音识别失败',
4303 => '服务的异常',
4411 => '访问频率受限,请稍后访问',
4412 => '超过最大请求时长',
5001 => '无效的OCR类型',
5002 => '不支持的OCR image类型',
5003 => '不支持的语言类型',
5004 => '识别图片过大',
5005 => '不支持的图片类型',
5006 => '文件为空',
5201 => '解密错误,图片base64解密失败',
5301 => 'OCR段落识别失败',
5411 => '访问频率受限',
5412 => '超过最大识别流量',
9001 => '不支持的语音格式',
9002 => '不支持的语音采样率',
9003 => '不支持的语音声道',
9004 => '不支持的语音上传类型',
9005 => '不支持的语音识别 Language类型',
9301 => 'ASR识别失败',
9303 => '服务器内部错误',
9411 => '访问频率受限(超过最大调用次数)',
9412 => '超过最大处理语音长度',
10001 => '无效的OCR类型',
10002 => '不支持的OCR image类型',
10004 => '识别图片过大',
10201 => '图片base64解密失败',
10301 => 'OCR段落识别失败',
10411 => '访问频率受限',
10412 => '超过最大识别流量',
11001 => '不支持的语音识别格式',
11002 => '不支持的语音识别采样率',
11003 => '不支持的语音识别声道',
11004 => '不支持的语音上传类型',
11005 => '不支持的语言类型',
11006 => '识别音频文件过大',
11007 => '识别音频时长过长,最大支持30s',
11201 => '解密失败',
11301 => '语音识别失败',
11303 => '服务的异常',
11411 => '访问频率受限,请稍后访问',
11412 => '超过最大请求时长',
12001 => '图片尺寸过大',
12002 => '图片base64解密失败',
12003 => '引擎服务器返回错误',
12004 => '图片为空',
12005 => '不支持的识别图片类型',
12006 => '图片无匹配结果',
13001 => '不支持的角度类型',
13002 => '不支持的文件类型',
13003 => '表格识别图片过大',
13004 => '文件为空',
13301 => '表格识别失败',
15001 => '需要图片',
15002 => '图片过大(1M)',
15003 => '服务调用失败',
17001 => '需要图片',
17002 => '图片过大(1M)',
17003 => '识别类型未找到',
17004 => '不支持的识别类型',
17005 => '服务调用失败',
];
/**
* get translation
* @param $string
* @param string $toLang
* @param string $fromLang
* @return mixed|null
*/
public function getTranslation($string, $toLang = '', &$fromLang = '')
{
$params = $this->getQueryParams($string, $toLang, $fromLang);
$response = $this->curlApi($params);
if ($response->failed()) {
$this->writeErrorLog(sprintf('curl api error, code: %d, error: %s', $response->status(), $response->body()));
return $string;
} else {
$result = $response->json();
if (isset(self::ERROR_CODES_MAPPER[$result[self::KEY_ERROR_CODE]])) {
$errCode = $result[self::KEY_ERROR_CODE] ?? 0;
$errMsg = self::ERROR_CODES_MAPPER[$result[self::KEY_ERROR_CODE]] ?? 'translate api return error';
$this->writeErrorLog(sprintf('translate api error, code: %d, error: %s', $errCode, $errMsg));
return $string;
}
if (isset($result[self::KEY_LANG]) && $result[self::KEY_LANG]) {
$fromLang = explode('2', $result[self::KEY_LANG])[0] ?? '';
}
if (isset($result[self::KEY_TRANSLATION])) {
if (is_array($result[self::KEY_TRANSLATION])) {
$trans = array_pop($result[self::KEY_TRANSLATION]);
return $trans;
} else {
return $result[self::KEY_TRANSLATION] ?? $string;
}
}
}
return $string;
}
/**
* if not using laravel framework, please change this
*/
protected function curlApi($params)
{
$params = is_array($params) ? http_build_query($params) : $params;
return Http::timeout(self::API_TIMEOUT)
->get(self::API_URL, $params);
}
/**
* if not using laravel framework, please change this
*/
protected function writeErrorLog($msg)
{
Log::error($msg);
}
protected function getQueryParams($string, $toLang = '', $fromLang = '')
{
$salt = $this->createGuid();
$args = [
self::KEY_QUERY => $string,
self::KEY_APPID => self::APP_ID,
self::KEY_SALT => $salt,
];
$args[self::KEY_FROM] = $fromLang;
$args[self::KEY_TO] = $toLang;
$args[self::KEY_SIGN_TYPE] = self::DEFAULT_SIGN_TYPE;
$curtime = time();
$args[self::KEY_CURTIME] = $curtime;
$signStr = self::APP_ID . $this->truncateStr($string) . $salt . $curtime . self::APP_KEY;
$args[self::KEY_SIGN] = hash("sha256", $signStr);
return $args;
}
protected function createGuid()
{
$microTime = microtime();
list($a_dec, $a_sec) = explode(" ", $microTime);
$dec_hex = dechex($a_dec* 1000000);
$sec_hex = dechex($a_sec);
$this->ensureLength($dec_hex, 5);
$this->ensureLength($sec_hex, 6);
$guid = "";
$guid .= $dec_hex;
$guid .= $this->createGuidSection(3);
$guid .= '-';
$guid .= $this->createGuidSection(4);
$guid .= '-';
$guid .= $this->createGuidSection(4);
$guid .= '-';
$guid .= $this->createGuidSection(4);
$guid .= '-';
$guid .= $sec_hex;
$guid .= $this->createGuidSection(6);
return $guid;
}
protected function ensureLength(&$string, $length)
{
$strlen = strlen($string);
if($strlen < $length) {
$string = str_pad($string, $length, "0");
} else if($strlen > $length) {
$string = substr($string, 0, $length);
}
}
protected function createGuidSection($characters)
{
$return = "";
for($i = 0; $i < $characters; $i++) {
$return .= dechex(mt_rand(0, 15));
}
return $return;
}
protected function truncateStr($q)
{
$len = mb_strlen($q,'utf-8');
return $len <= 20 ? $q : (mb_substr($q, 0, 10) . $len . mb_substr($q, $len - 10, $len));
}
}