Microsoft Translator テキスト API [TranslateArray] で、複数の語句を翻訳する

## やること

Microsoft Translator テキスト API のエンドポイント [TranslateArray]　を利用して、複数の語句を翻訳する (タイトルの通り)

この記事は、2017年3月時点の情報にもとづいて記述しました。

## 流れ

1. Microsoft Translator テキスト APIを有効化して、APIキーを取得する
2. トークンを取得する
3. トークンを使ってTranslator テキスト APIを叩く
4. サンプルコード
5. 参考情報


## 1-2について

1,2の「APIキーを取得する」「トークンを取得する」については、下記の記事をご参照ください。

* Microsoft Translator テキスト API で、日本語を英語に翻訳するサンプル
 * http://qiita.com/TakeshiNickOsanai/items/a8039ba8d558f7c8a05e
 
## トークンを使ってTranslator テキストAPIを叩く

Microsoft Translator テキスト APIには、複数の語句を翻訳するためのエンドポイントとして「TranslateArray」があります。

* http://docs.microsofttranslator.com/text-translate.html#!/default/post_TranslateArray
* https://msdn.microsoft.com/ja-jp/library/ff512422.aspx

ここに対して、POSTメソッドで複数の語句を送信すると、翻訳されたデータが返ってきます。

個人的にハマった点は以下の2点

* Request Body はXMLで送る必要がある
* JavaScriptによる送信はできない

POSTする際の Request Body はXMLデータとして送信する必要がある、ということです。
JSON,配列などで送信してみたところ、いずれも正常なレスポンスが取得できませんでした。

XMLによるRequestBody のサンプルは、以下に記述されていました。

https://msdn.microsoft.com/ja-jp/library/ff512422.aspx?f=255&MSPPError=-2147217396#phpexample

また、JavaScriptによる通信は不可能なようです。何度か試しましましたが、JavaScriptではどうしても405エラーが返ってしまい、うまく行きませんでした。トークンの取得は、JavaScriptからPOSTしても問題ないのに、なぜだろう。

このため、今回はphpでサンプルコードを書いてみました。

[TranslateArray] にデータを送信する際は、以下の3つが必須となります。

* appid
 * 送信する文字列は [Bearer] + [(半角スペース)] + [トークン] となる。Header に[Authorization]で指定して送信してもOK
* texts
 * 翻訳したい文字列をXMLの配列として指定
* to
 * 翻訳したい言語を指定。日本語に翻訳したい場合は [ja]。英語に翻訳したい場合は [en]となる。
 

## サンプルコード

今回は
* フォーム画面から、テキストおよび複数行テキストの2つのデータを入力する
* jQueryを利用して、翻訳データを取得するphpコードへ値を渡す
* phpからの返り値を、フォーム画面に表示する

という流れで書いてみました。日本語を入力すると、英語の翻訳結果が返ってきます。


### フォーム画面 (html側)

```
<!DOCTYPE html>
<html lang="ja">
<head>
<title>Microsoft Translator テキスト API で複数英訳を行うサンプルコード</title>
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script>

  "use strict"

  $(function() {

    // 文字が入力されたらイベント発火

    $("#translate").click(function() {
      $.ajax({
        url: '翻訳データを取得するphpファイルを指定',
        type: 'POST',
        data: {
          request1: $("#title").val(),
          request2: $("#body").val(),
        }

      }).done(function(data, status, xhr) {

        $("#en-title").val(data.result1[0]);
        $("#en-body").val(data.result2[0]);

      }).fail(function(xhr, status, error) {

        alert("通信に失敗しました。");

      });
    });
  });
</script>
</head>

<body>

  <h1>Microsoft Translator テキスト API サンプル</h1>
  <h2>複数フォームの入力データを英語に翻訳します。</h2>

  <p>  <input type="text" id="title" placeholder="タイトル" size="40"></p>
  <p>  <textarea name="body" rows="4" cols="40" id="body" placeholder="本文"></textarea></p>
  <p>  <input type="submit" id="translate" value="翻訳"></p>

  <p>  <input type="text" id="en-title" size="40"></p>
  <p>  <textarea name="body" rows="4" cols="40" id="en-body"></textarea></p>

</body>
</html>

```


### 翻訳データ取得画面(php側)

```
<?php

// Microsoft Tranlator テキスト API を使うためのAPIキーを定数として設定

define('APIKEY', 'APIキーを記述する');


// 取得した翻訳文字列を返すために Content-type を設定。JSON形式で返す

header('Content-type: application/json; charset=utf-8');


// フォームから2項目の値を受けとり、翻訳関数を実行する。
// どちらかが欠けていた場合エラーとする

if (isset($_POST['request1']) && ($_POST['request2']) ) {

  $response = getTranslation();
  echo ($response);

} else {

// エラー処理

}


// 翻訳用関数 getTranslation　を定義
// フォームから入力されたデータをXMLに整形して、Microsoft Translator テキスト APIへPOSTする

function getTranslation() {

  $token = getToken();
  $key = "Bearer" . " " . $token;
  $uri = 'https://api.microsofttranslator.com/V2/http.svc/TranslateArray';

  $headers = array(
    "Authorization: " . $key,
    "Content-Type: application/xml",
  );

// XMLでパラメーター指定

  $word1 = htmlspecialchars($_POST['request1']);
  $word2 = htmlspecialchars($_POST['request2']);

  $params = <<<EOF

<TranslateArrayRequest>
  <AppId />
  <Texts>
    <string xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">$word1</string>
    <string xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">$word2</string>
    </Texts>
  <To>en</To>
</TranslateArrayRequest>

EOF;

  $ch = curl_init();

  curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_URL, $uri); 
  curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

  $html =  curl_exec($ch);
  curl_close($ch);

// SimpleXMLElementを利用してオブジェクト生成

  $data = new SimpleXMLElement($html);

// 翻訳結果をJSONデータに変換してフォーム画面へ返す

$result =array(
    
'result1' => $data->TranslateArrayResponse[0]->TranslatedText, 
'result2' => $data->TranslateArrayResponse[1]->TranslatedText,

);

$result = json_encode($result);

return $result;

}


// Microsoft Tranlator テキスト APIを利用するためのトークンを取得する関数

function getToken(){

  $headers = array(
    "Content-Type: application/json",
    "Accept: application/jwt",
    "Ocp-Apim-Subscription-Key: " . APIKEY,
    "Content-Length:0"
  );

  $url     = "https://api.cognitive.microsoft.com/sts/v1.0/issueToken";
  $ch      = curl_init();

  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

  $html = curl_exec($ch);

  return $html;
  curl_close($ch);
}

?>
```

![TranslateArray.png](https://qiita-image-store.s3.amazonaws.com/0/83767/378e7996-4f6c-58f5-0358-2254e8bc6233.png)


## 参考情報

https://www.microsoft.com/ja-jp/translator/getstarted.aspx
https://www.microsoft.com/cognitive-services/en-us/documentation
http://docs.microsofttranslator.com/text-translate.html
https://msdn.microsoft.com/ja-jp/library/ff512422.aspx

TranslateArray は

* 項目は2000項目まで
* 全項目の文字数を合わせて最大10,000文字まで

翻訳可能なようです。