我正在尝试使用Microsoft Translator API将中文(简体)翻译成英文。
几个要求
我必须使用HTTP方法
POST
,而不是GET
与查询字符串,因为我的查询超过了微软的URI限制15,845个字符(注意,这是可能的,即使我使用少于10,000个字符的情况下,中文字符的限制。原因是查询字符串必须经过URL编码,这大大增加了长度,但在确定字符数之前,它由Microsoft解码。唯一允许
POST
s的HTTP转换方法是TranslateArrayMethod
,例如TranslateMethod
只允许GET
s。不幸的是,TranslateArrayMethod
只接受XML文档,所以我必须使用XML。
下面是我发送的XML文档的示例:
<TranslateArrayRequest>
<AppId/>
<From>es</From>
<Options>
<ContentType xmlns="http://schemas.datacontract.org/2004/07/Microsoft.MT.Web.Service.V2">text/plain</ContentType>
</Options>
<Texts>
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<![CDATA[Hola]]>
</string>
</Texts>
<To>en</To>
</TranslateArrayRequest>
这很好,结果是:
<ArrayOfTranslateArrayResponse xmlns="http://schemas.datacontract.org/2004/07/Microsoft.MT.Web.Service.V2" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<TranslateArrayResponse>
<From>es</From>
<OriginalTextSentenceLengths xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<a:int>4</a:int>
</OriginalTextSentenceLengths>
<TranslatedText>Hello</TranslatedText>
<TranslatedTextSentenceLengths xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<a:int>5</a:int>
</TranslatedTextSentenceLengths>
</TranslateArrayResponse>
</ArrayOfTranslateArrayResponse>
但是,如果我接着添加任何中文字符,像这样:
<TranslateArrayRequest>
<AppId/>
<From>zh-CHS</From>
<Options>
<ContentType xmlns="http://schemas.datacontract.org/2004/07/Microsoft.MT.Web.Service.V2">text/plain</ContentType>
</Options>
<Texts>
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<![CDATA[南]]>
</string>
</Texts>
<To>en</To>
</TranslateArrayRequest>
我得到一个奇怪的回应:
<html>
<body/>
<h1>System.Runtime.Serialization.SerializationException</h1>
<p>Message: There was an error deserializing the object of type Microsoft.MT.MDistributor.V2.TranslateArrayRequest. Unexpected end of file. Following elements are not closed: TranslateArrayRequest. Line 1, position 298.</p>
</html>
请注意,我也尝试不使用CDATA转义,但它没有帮助。修改From
语言也没有效果。
我正在使用Node.js (Javascript),尽管由于这是一个通用的HTTP API,我认为这应该无关紧要。
好吧,我在从Node.js调用Microsoft Translator POST api时遇到了完全相同的问题。只要没有非ascii字符,API就可以正常工作-返回预期的翻译,但是当我向POST主体的适当<string>
部分添加单个重音'
<html><body/><h1>System.Runtime.Serialization.SerializationException</h1>
<p>Message: There was an error deserializing the object of type Microsoft.MT.MDistributor.V2.TranslateArrayRequest. Unexpected end of file. Following elements are not closed: TranslateArrayRequest. Line 1, position 782.</p>
</html>
我发现问题是Content-Length
头希望以字节为单位的长度,但我一直在发送字符长度。为什么会发生这种情况?衡量Node http请求正文长度的典型方法是调用
var length = body.length
并获取字符串的"长度",即字符数。当所有字符都是ASCII时,此操作有效。然而,事实证明,在UTF-8中,非ascii字符(包括我的重音'
相反,我们需要用调用(在Node.js中)
来测量字节长度。var length = Buffer.byteLength(body, 'utf8')
并在Content-Length
头中发送该长度,Microsoft Translator API再次工作。
问题很可能不是中文,而是微软翻译不喜欢新的行符号。当我遇到这个错误消息时,我做了如下更改:
- 在
节点的每个内容中,用空字符串替换换行符。这些字符具有Unicode值:0xA, 0xB, 0xC, 0xD, 0x85, 0x2028, 0x2029 在
节点的每个内容中,用它们的替代表示替换XML保留字: ,→,amp;
& lt;→,lt;
比;→和gt;
'→'
→"
- 将整个XML重新排列成单行
之后,一切都很顺利。关于你的特殊例子,符号"中国"被翻译成"南方"。我没有使用CDATA转义