1

我正在尝试使用 Microsoft Translator API 将中文(简体)翻译成英文。

几个要求

  • 我必须使用 HTTP 方法POST,而不是GET使用查询字符串,因为我的查询超过了 Microsoft 的 URI 限制 15,845 个字符(请注意,即使我使用的中文字符少于 10,000 个字符限制,这也是可能的。原因是查询字符串必须进行 URL 编码,这会大大增加长度,但在确定字符数之前,它会被 Microsoft 解码。

  • 唯一允许 s 的翻译 HTTP 方法POSTTranslateArrayMethod,例如,TranslateMethod唯一允许GETs。不幸的是,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,我认为这并不重要。

4

2 回答 2

1

好的,我从 Node.js 调用 Microsoft Translator POST API 时遇到了完全相同的问题。API 工作正常 - 按预期返回翻译 - 只要没有非 ASCII 字符,但是当我<string>在 POST 正文的适当部分添加一个带重音的“é”字符时,它会响应错误:

    <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 字符(包括我的重音 'é')每个可以超过一个字节。所以当正文包含非 ASCII 字符时,字节长度将不再等于字符长度,并且字符长度不正确。在这种情况下,它会导致 Microsoft 服务器过早地停止读取消息,从而生成错误消息。

相反,我们需要通过调用(在 Node.js 中)测量长度(以字节为单位)

var length = Buffer.byteLength(body, 'utf8')

并在标头中发送该长度,Content-LengthMicrosoft Translator API 再次工作。

于 2016-05-13T22:51:16.067 回答
1

很可能,问题不在于中文,而是 MS Translator 不喜欢换行符。当我偶然发现此错误消息时,我进行了以下更改:

  1. 在 <string> 节点的每个内容中,将换行符替换为空字符串。这些字符具有 Unicode 值:0xA、0xB、0xC、0xD、0x85、0x2028、0x2029
  2. 在 <string> 节点的每个内容中,将 XML 保留字替换为它们的替代表示:

    & → &

    < → <

    > → >

    ' → '

    “→”

  3. 将整个 XML 重新排列为单行

之后,一切顺利。关于您的特定示例,符号“南”被翻译为“南”。我没有使用 CDATA 转义。

于 2015-11-21T13:43:59.073 回答