在 PHP 中通过 CustomTranslator API 导入文档

Import Document via CustomTranslator API in PHP

我正在尝试通过 PHP 中的 Microsoft 自定义翻译器 API 导入 TMX 文件。不幸的是,我一直 运行 进入以下错误:
"DocumentDetails must follow type IEnumerable[ImportDocumentRequestDetails]."

我已经成功地向 API 发出了其他请求(虽然只有 GET),所以我很难弄清楚这个请求。

到目前为止,我已经尝试了请求的各种排列组合,主要是通过反复试验。我已经尝试通过在门户中上传相同的文件来复制请求,这没有问题地成功了,但我无法在 PHP (7.3) 中复制它。

我还尝试对 GitHub 上的 C# API 示例进行逆向工程。不幸的是,我的 C# 知识并不那么敏锐,而且我确信我遗漏了一些细微差别。我注意到示例使用了 'Language' 字符串,而门户网站似乎使用了 'LanguageCode',以及其他不一致的地方,这并没有使解决这个问题变得容易得多。

我的代码的精简版本,只有相关部分(可以假定有效的访问令牌和本地文件路径到有效的 .tmx)如下:

Class CustomTranslator {

    private $curl;
    private $aAccessToken; // valid, working token

    // Set up connection and login with initial user
    public function __construct() {
        $this->curl = curl_init();
        $aOptions = array(
            CURLOPT_RETURNTRANSFER  => true,
            CURLOPT_FOLLOWLOCATION  => true,
            CURLOPT_CONNECTTIMEOUT  => 5,
            CURLOPT_TIMEOUT         => 60
        );
        curl_setopt_array($this->curl, $aOptions);
    }

    function ImportParallelDocument($strFilePath) {
        $aRequestContent     = [
            'Files'             => new CURLFile($strFilePath, mime_content_type($strFilePath), basename($strFilePath)),
            'DocumentDetails'   => [
                'DocumentName'  => basename($strFilePath),
                'DocumentType'  => 'training',
                'IsParallel'    => true,
                'FileDetails'   => [
                    'Name'              => $strFilePath,
                    'Language'          => 'Dutch',
                    'Type'              => pathinfo($strFilePath, PATHINFO_EXTENSION),
                    'OverwriteIfExists' => true
                ]
            ]
        ];
        return $this->Request("v1.0/documents/import?workspaceId=".CUSTOMTRANSLATOR_WORKSPACEID, $aRequestContent, 'POST');
    }

    // Prototype request function
    private function Request($strRequest, $aData = array(), $strMethod = 'GET') {

        $strRequest = CUSTOMTRANSLATOR_API_URL.$strRequest;

        // Reset between requests
        curl_setopt($this->curl, CURLOPT_POST, false);
        curl_setopt($this->curl, CURLOPT_HTTPHEADER, ['Authorization: Bearer '.$this->aAccessToken['access_token']]);

        if(isset($aData['authorization'])) $aData['authorization'] = $this->aAccessToken['access_token'];

        if ($strMethod == 'GET') {
            $strRequest .= "?".http_build_query($aData);
        }
        else {
            curl_setopt($this->curl, CURLOPT_POST, true);
            curl_setopt($this->curl, CURLOPT_HTTPHEADER, ['Authorization: Bearer '.$this->aAccessToken['access_token'],
                                                          'X-HTTP-Method-Override: '.$strMethod]);
            curl_setopt($this->curl, CURLOPT_POSTFIELDS, $aData);
        }
        curl_setopt($this->curl, CURLOPT_URL, $strRequest);
        $strResponse = curl_exec($this->curl);

        // Return the JSON array if it can be decoded, otherwise the actual curl response
        return json_decode($strResponse, true)?:$strResponse;
    }
}

如前所述,当我尝试使用上述代码上传文件时,我收到的确切错误是 {"message":"DocumentDetails must follow type IEnumerable[ImportDocumentRequestDetails].","display":false},遗憾的是没有进一步说明丢失或不正确的内容。我希望成功导入通过门户本身成功导入的 TMX 文件,据我所知实现了相同的 API.

我想我只是遗漏了一些东西,或者做的事情不太正确,所以我们将不胜感激!

在同事的帮助下,想出了一个暂时解决的方法,只需提供与门户中使用的调用等效的 JSON:

$aRequestContent     = [
    'Files' => new CURLFile($strFilePath, mime_content_type($strFilePath), basename($strFilePath)),
    'DocumentDetails' => 
        '[{ "DocumentName": "",
            "DocumentType": "training",
            "FileDetails": [{
            "Name": "'.basename($strFilePath).'",
                "LanguageCode": "en",
                "OverwriteIfExists": true }]
        }]'
];

这不是最好的解决方案,但出于预览的目的 API,它现在可以使用(直到它最终不可避免地投入生产,唉)。

仔细检查 JSON 让我发现了嵌套数组结构(可能用于多文件上传),起初我并不明显。但是,以下数组结构足以处理请求:

$aDocumentDetails = [[ // Note the nested array here, for index numbering
    'DocumentName'  => '', 
    'DocumentType'  => ucfirst($strType), 
    'FileDetails'   => [[ // As well as here
            'Name'              => basename($strFilePath), 
            'LanguageCode'      => $strLanguageCode,
            'OverwriteIfExists' => $bOverwrite
            ]]
]];

$aRequestContent     = [
    'Files'             => new CURLFile($strFilePath, mime_content_type($strFilePath), basename($strFilePath)),
    'DocumentDetails'   => json_encode($aDocumentDetails)
];

简而言之,API 需要索引子数组中的 DocumentDetails(和 FileDetails):

[0 => [ 'DocumentName' => ...,
        'FileDetails' => [0 => ['Name' => ...]
];

理解这个花絮对我帮助很大。