Перестал работать Microsoft Translate Text - PHP

Я использовал эту библиотеку для перевода текста с помощью когнитивного переводчика Microsoft.

Пакет PHP Microsoft Translate

У меня есть учетная запись Azure, и я думаю, что мои конечные точки и ключи все еще действительны. За это время я ничего не менял, хотя у меня есть «бесплатный» пакет.

Код, который я переводил на несколько языков, и раньше работал нормально. По какой-то причине он недавно перестал работать. Я отредактировал сообщение, чтобы установить:

$host = "https://api.cognitive.microsofttranslator.com", thank you (typo).

Это действительно сработает, если я установлю в $ text что-нибудь простое, например:

$text = 'Guten Morgen!  Mit Corona zusammenraufen.Milde gesagt: Es sind keine besonders beruhigenden Nachrichten.';

возвращает английский:

{"text":"Good morning! To put it mildly, it's not particularly reassuring news.","to":"en"}

Если немного удлинить струну до:

$text = 'Guten Morgen!  Mit Corona zusammenraufen.  Milde gesagt: Es sind keine besonders beruhigenden Nachrichten. Milde gesagt: Es sind keine besonders beruhigenden Nachrichten.';

Я получаю:

failed to open stream: HTTP request failed! HTTP/1.1 400 Bad Request

Раньше это работало с гораздо более длинными строками для ввода. У меня есть «бесплатный» тарифный план с Azure. Возможно ли, что теперь в моей учетной записи Azure есть ограничение на длину строки?

Код, который у меня есть. Есть еще кое-что для помещения переводов в базу данных.

$key = 'MicrosoftKEY';
$host = "https://api.cognitive.microsofttranslator.com";
$path = "/translate?api-version=3.0";
$languages = $data['languagearray'];  // array of languages to translate to.
$params = '&from=' . $data["from"] ;  // language to translate from
foreach ($languages as $language) {
$params .= "&to=" . $language;
}
$params .= "&textType=html";
$text = $data["text"];  // text to translate

if (!function_exists('com_create_guid')) {
  function com_create_guid() {
    return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
        mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
        mt_rand( 0, 0xffff ),
        mt_rand( 0, 0x0fff ) | 0x4000,
        mt_rand( 0, 0x3fff ) | 0x8000,
        mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff )
    );
  }
}
// function to return the translated text, seem below, $json = jsonp_decode($result, true)[0]["translations"];

function Translate ($host, $path, $key, $params, $content) {

    $headers = "Content-type: application/json\r\n" .
        "Content-length: " . strlen($content) . "\r\n" .
        "Ocp-Apim-Subscription-Key: $key\r\n" .
        "X-ClientTraceId: " . com_create_guid() . "\r\n";
    // NOTE: Use the key 'http' even if you are making an HTTPS request. See:
    // http://php.net/manual/en/function.stream-context-create.php
    $options = array (
        'http' => array (
            'header' => $headers,
            'method' => 'POST',
            'content' => $content
        )
    );
    $context  = stream_context_create ($options);
    $result = file_get_contents ($host . $path . $params, false, $context);
    echo $result;
    return $result;
}
$requestBody = array (
    array (
        'Text' => $text,
    ),
);

function jsonp_decode($jsonp, $assoc = false) { // PHP 5.3 adds depth as third parameter to json_decode
    if($jsonp[0] !== '[' && $jsonp[0] !== '{') { // we have JSONP
       $jsonp = substr($jsonp, strpos($jsonp, '('));
    }
    return json_decode(trim($jsonp,'();'), $assoc);
}

$content = json_encode($requestBody);
$result = Translate ($host, $path, $key, $params, $content);
// Note: We convert result, which is JSON, to and from an object so we can pretty-print it.
// We want to avoid escaping any Unicode characters that result contains. See:
// http://php.net/manual/en/function.json-encode.php
$json = jsonp_decode($result, true)[0]["translations"];
$conn = DatabaseFactory::getFactory()->getConnection();

foreach ($json as $language) {
    $query = 'UPDATE kronen_translations SET translated_text = ? WHERE language_code = ?';
    $parameters = [$language['text'], $language['to']];
    $stmt = $conn->prepare($query);
    $stmt->execute($parameters);
    echo $language['to'] . '<br>';
    echo $language['text'] . '<br>';
}

person SScotti    schedule 10.03.2020    source источник
comment
Я не понимаю, как это должно было когда-либо работать - вы пытаетесь открыть здесь путь к локальной файловой системе. Если api.cognitive.microsofttranslator.com/translate?… должен быть URL, то, конечно, отсутствует протокол.   -  person CBroe    schedule 10.03.2020


Ответы (1)


Я провел еще немного расследования и в конце концов открыл заявку в Microsoft Cognitive Services. Скрипт в том виде, в каком он есть / был, работал нормально несколько месяцев назад, и я фактически переводил пару абзацев примерно на 40 разных языков (почти все, что они поддерживают), используя единый вызов объединенного вызова, и я получил ответ, имея все переводы. Раньше это работало нормально.

Однако существуют ограничения на количество символов для запросов API для служб перевода:

См. Пределы запросов для текста переводчика

"Каждый запрос на перевод ограничен 5000 символов для всех целевых языков, на которые вы переводите. Например, отправка запроса на перевод 1500 символов для перевода на 3 разных языка приводит к размеру запроса 1500x3 = 4500 символов. , что соответствует ограничению количества запросов. Плата взимается за символ, а не за количество запросов. Рекомендуется отправлять более короткие запросы ".

С 40 разными языками и парой абзацев, состоящих из нескольких сотен символов, я превысил лимит. После обмена электронными письмами с поддержкой MS выясняется, что ограничение на количество запросов API не применялось в течение части прошлого года и в последнее время из-за ошибки на их стороне, и они, по-видимому, недавно исправили это.

Для справки: старый код выглядел примерно так: строка запроса содержала около 40 & to = lang &. . . .

$languages = $data['languagearray'];
$params = '&from=' . $data["from"] ;
foreach ($languages as $language) {
$params .= "&to=" . $language;
}
$params .= "&textType=html";
$text = $data["text"];

if (!function_exists('com_create_guid')) {
  function com_create_guid() {
    return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
        mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
        mt_rand( 0, 0xffff ),
        mt_rand( 0, 0x0fff ) | 0x4000,
        mt_rand( 0, 0x3fff ) | 0x8000,
        mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff )
    );
  }
}
function Translate ($host, $path, $key, $params, $content) {

    $headers = "Content-type: application/json\r\n" .
        "Content-length: " . strlen($content) . "\r\n" .
        "Ocp-Apim-Subscription-Key: $key\r\n" .
        "X-ClientTraceId: " . com_create_guid() . "\r\n";
    // NOTE: Use the key 'http' even if you are making an HTTPS request. See:
    // http://php.net/manual/en/function.stream-context-create.php
    $options = array (
        'http' => array (
            'header' => $headers,
            'method' => 'POST',
            'content' => $content
        )
    );
    $context  = stream_context_create ($options);
    $result = file_get_contents ($host . $path . $params, false, $context);
    echo $result;
    return $result;
}
$requestBody = array (
    array (
        'Text' => $text,
    ),
);

function jsonp_decode($jsonp, $assoc = false) { // PHP 5.3 adds depth as third parameter to json_decode
    if($jsonp[0] !== '[' && $jsonp[0] !== '{') { // we have JSONP
       $jsonp = substr($jsonp, strpos($jsonp, '('));
    }
    return json_decode(trim($jsonp,'();'), $assoc);
}

$content = json_encode($requestBody);
$result = Translate ($host, $path, $key, $params, $content);
// Note: We convert result, which is JSON, to and from an object so we can pretty-print it.
// We want to avoid escaping any Unicode characters that result contains. See:
// http://php.net/manual/en/function.json-encode.php
$json = jsonp_decode($result, true)[0]["translations"];
$conn = DatabaseFactory::getFactory()->getConnection();

foreach ($json as $language) {
    $query = 'UPDATE kronen_translations SET translated_text = ? WHERE language_code = ?';
    $parameters = [$language['text'], $language['to']];
    $stmt = $conn->prepare($query);
    $stmt->execute($parameters);
    echo $language['to'] . '<br>';
    echo $language['text'] . '<br>';
}

Вам разрешено выполнять такие групповые вызовы, а затем декодировать полученные результаты.

Решение состояло в том, чтобы сделать серию вызовов (в данном случае по одному), по одному для каждого языка, а затем последовательно обработать результаты. Новый код выглядит примерно так. Возможно, есть способ получше, но, по крайней мере, так я могу обрабатывать фрагменты текста разумного размера. Просто требуется немного времени, чтобы запустить сценарий для 40 языков или около того, хотя все еще только мои 30 секунд, в зависимости от размера текста.

function Translate ($host, $path, $key, $params, $content) {

    $headers = "Content-type: application/json\r\n" .
        "Content-length: " . strlen($content) . "\r\n" .
        "Ocp-Apim-Subscription-Key: $key\r\n" .
        "X-ClientTraceId: " . com_create_guid() . "\r\n";
    // NOTE: Use the key 'http' even if you are making an HTTPS request. See:
    // http://php.net/manual/en/function.stream-context-create.php
    $options = array (
        'http' => array (
            'header' => $headers,
            'method' => 'POST',
            'content' => $content
        )
    );
    $context  = stream_context_create ($options);
    $result = file_get_contents ($host . $path . $params, false, $context);
    echo $result;
    return $result;
}



function jsonp_decode($jsonp, $assoc = false) { // PHP 5.3 adds depth as third parameter to json_decode
    if($jsonp[0] !== '[' && $jsonp[0] !== '{') { // we have JSONP
       $jsonp = substr($jsonp, strpos($jsonp, '('));
    }
    return json_decode(trim($jsonp,'();'), $assoc);
}

$key = 'xxxxx';
$host = "https://api.cognitive.microsofttranslator.com";
$path = "/translate?api-version=3.0";
$languages = $data['languagearray'];
// print_r($languages);
$conn = DatabaseFactory::getFactory()->getConnection();
$text = $data["text"];
foreach ($languages as $language) {
$params = '&from=' . $data["from"] ;
$params .= "&to=" . $language;
$params .= "&textType=html";
$text = $data["text"];

$requestBody = array (
    array (
        'Text' => $text,
    ),
);
$content = json_encode($requestBody);
$result = Translate ($host, $path, $key, $params, $content);
$json = jsonp_decode($result, true)[0]["translations"];

foreach ($json as $language) {
    $query = 'UPDATE kronen_translations SET translated_text = ? WHERE language_code = ?';
    $parameters = [$language['text'], $language['to']];
    $stmt = $conn->prepare($query);
    $stmt->execute($parameters);
    echo $language['to'] . '<br>';
    echo $language['text'] . '<br>';
}
person SScotti    schedule 24.03.2020