如果直接使用
string url = "https://translate.googleapis.com/translate_a/single?client=gtx&sl="
+ sourceLang + "&tl=" + targetLang + "&dt=t&q=" + UnityWebRequest.EscapeURL(sourceText);
这种url去谷歌翻译那里获取翻译的话,会有限制,因为没有token值,所以很容易会给谷歌那边屏蔽ip,无法再翻译。后面找了一下资料,发现有些是使用了tk值的方式来访问谷歌翻译,经过验证,很频繁(每隔0.2s翻译一条)翻译,翻译是上万条也没出现给限制的情况。这种方法的难点就在tk值的获取,其实tk值在使用GET方式访问https://translate.google.cn的时候就可以获取到,但是这个tk值还需要做一些处理,才能重新使用。下面说下怎么获取。
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
using YIMEngine;
using System;
using System.Text.RegularExpressions;
using System.Collections.Generic;
public class Translate
{
protected struct ExternalKey
{
///
/// Total hours
///
public long Time { get; }
///
/// Token value
///
public long Value { get; }
/// Unix-formatted total hours
/// Token value
public ExternalKey(long time, long value)
{
Time = time;
Value = value;
}
}
protected static int UnixTotalHours
{
get
{
DateTime unixTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
return (int)DateTime.UtcNow.Subtract(unixTime).TotalHours;
}
}
// We have use googles own api built into google Translator.
public static IEnumerator Process(string targetLang, string sourceText, System.Action
{
yield return Process("auto", targetLang, sourceText, result, times);
}
// Exactly the same as above but allow the user to change from Auto, for when google get's all Jerk Butt-y
public static IEnumerator Process(string sourceLang, string targetLang, string sourceText, System.Action
int times)
{
//第一步,先使用GET方式访问谷歌翻译,拿到html的tk值
string urlte = "https://translate.google.cn";
UnityWebRequest request1 = new UnityWebRequest(urlte, "GET");
request1 .SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36");
request1 .downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
request1 .useHttpContinue = false;//应对某些机型的errorCallback with error=java.io.EOFException
yield return request1.SendWebRequest();
if (request1.isNetworkError || request1.isHttpError)
{
Debug.LogError("获取服务器列表失败 = " + request1.error);
result.Invoke("", times);
yield break;
}
long tkk = 0;
try
{
//这个就是返回的初始tk值
var tkkText = request1.downloadHandler.text.GetTextBetween(@"tkk:'", "',");
if (tkkText == null)
{
result.Invoke("", times);
}
var splitted = tkkText.Split('.');
if (splitted.Length != 2 || !long.TryParse(splitted[1], out tkk))
{
result.Invoke("", times);
}
}
catch (ArgumentException)
{
result.Invoke("", times);
}
var currentExternalKey = new ExternalKey(UnixTotalHours, tkk);
long time = DecrypthAlgorythm(sourceText, currentExternalKey);
string tk = time.ToString() + '.' + (time ^ currentExternalKey.Time);
string address = "https://translate.google.cn/translate_a/single";
string url =$"{ address}" + "?" +
$"sl={sourceLang}&" +
$"tl={targetLang}&" +
$"hl={sourceLang}&" +
$"q={UnityWebRequest.EscapeURL(sourceText)}&" +
$"tk={tk}&" +
"client=t&" +
"dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&" +
"ie=UTF-8&" +
"oe=UTF-8&" +
"otf=1&" +
"ssel=0&" +
"tsel=0&" +
"kc=7";
//Debug.Log("地址=" + url);
//string url = string.Format("https://translate.google.cn/translate_a/single?client=t&sl={0}&tl={1}&hl={0}&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&dt=at&ie=UTF-8&oe=UTF-8&ssel=6&tsel=3&kc=0&tk=" + tk + "&q={2}", sourceLang, targetLang, UnityWebRequest.EscapeURL(sourceText));
/* string url = "https://translate.googleapis.com/translate_a/single?client=gtx&sl="
+ sourceLang + "&tl=" + targetLang + "&dt=t&q=" + UnityWebRequest.EscapeURL(sourceText);*/
UnityWebRequest request = new UnityWebRequest(url, "GET");
//request.SetRequestHeader("Content-Type", "application/json;charset=utf-8");
request.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36");
request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
request.useHttpContinue = false;//应对某些机型的errorCallback with error=java.io.EOFException
yield return request.SendWebRequest();
if (request.isNetworkError || request.isHttpError)
{
Debug.LogError("获取服务器列表失败 = " + request.error);
result.Invoke("", times);
yield break;
}
JsonData jsonData = JsonMapper.ToObject(request.downloadHandler.text);
string translatedText = jsonData[0][0][0].ToString();
//Debug.Log("返回的text=" + request.downloadHandler.text);
Debug.Log("解析后=" + translatedText);
result.Invoke(translatedText, times);
}
private static long DecrypthAlgorythm(string source, ExternalKey CurrentExternalKey)
{
List
for (int g = 0; g < source.Length; g++)
{
int l = source[g];
if (l < 128)
{
code.Add(l);
}
else
{
if (l < 2048)
{
code.Add(l >> 6 | 192);
}
else
{
if (55296 == (l & 64512) && g + 1 < source.Length && 56320 == (source[g + 1] & 64512))
{
l = 65536 + ((l & 1023) << 10) + (source[++g] & 1023);
code.Add(l >> 18 | 240);
code.Add(l >> 12 & 63 | 128);
}
else
{
code.Add(l >> 12 | 224);
}
code.Add(l >> 6 & 63 | 128);
}
code.Add(l & 63 | 128);
}
}
long time = CurrentExternalKey.Time;
foreach (long i in code)
{
time += i;
Xr(ref time, "+-a^+6");
}
Xr(ref time, "+-3^+b+-f");
time ^= CurrentExternalKey.Value;
if (time < 0)
time = (time & int.MaxValue) + 2147483648;
time %= (long)1e6;
return time;
}
private static void Xr(ref long a, string b)
{
for (int c = 0; c < b.Length - 2; c += 3)
{
long d = b[c + 2];
d = 'a' <= d ? d - 87 : (long)char.GetNumericValue((char)d);
d = '+' == b[c + 1] ? (long)((ulong)a >> (int)d) : a << (int)d;
a = '+' == b[c] ? a + d & 4294967295 : a ^ d;
}
}
}
下面是string的拓展方法
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
static class StringExtension
{
internal static string GetTextBetween(this string src, string from, string to, int startIndex = 0)
{
if (src == null)
throw new ArgumentNullException(nameof(src));
if (from == null)
throw new ArgumentNullException(nameof(from));
if (to == null)
throw new ArgumentNullException(nameof(to));
if (startIndex < 0 || startIndex > src.Length - 1)
throw new ArgumentOutOfRangeException(nameof(to));
int index = src.IndexOf(from, startIndex, StringComparison.Ordinal);
if (index == -1)
return null;
int index2 = src.IndexOf(to, index, StringComparison.Ordinal);
if (index2 == -1)
return null;
var result = src.Substring(index + from.Length, index2 - index - from.Length);
return result;
}
internal static string ToCamelCase(this string src)
{
string[] words = src.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
return string.Concat(words.Select(word
=> char.ToUpper(word[0]) + word.Substring(1).ToLower()));
}
}