Microsoft Translator API を Google Apps Script から使う方法


Google Apps Script でどこまでやれるかの実験を兼ねて、トランプさんの発言を自動翻訳して表示するサイトを作りました。

- [Trump JP](https://trump-jp.tumblr.com)
- [トランプさんの自動翻訳サイトを作りました](http://ina6ra.hateblo.jp/entry/2017/02/03/213002)

そこで Microsoft Translator API を Google Apps Script から使ったのですが、検索に出てくる記事のほとんどが古いものだったので、正しく使う方法をまとめておきます。

## 旧 API は今年の 3/31 に死ぬ

- [Microsoft Translator APIを使ってみる - Qiita](http://qiita.com/kemayako/items/21fe36005e6e729aff77)
- [Microsoft Translator APIを使ってみた - Qiita](http://qiita.com/lm0x/items/707ea4051b92bf839a1a)

まずはググって上位に出てくる２つの記事。
記事内のリンクからアプリケーションを登録しようとMSのサイトにアクセスすると赤いバーが出て全力で警告してきます。

- [登録 | Microsoft Azure Marketplace](http://datamarket.azure.com/register?redirect=%2fbrowse%2fapplications)

> DataMarket and Data Services are being retired and will stop accepting new orders after 12/31/2016. Existing subscriptions will be retired and cancelled starting 3/31/2017. Please reach out to your service provider for options if you want to continue service.

Google 翻訳すると

> データマーケットとデータサービスは廃止され、2016年12月31日以降は新しい受注の受付が停止されます。既存のサブスクリプションは、2013年3月31日に退職し、キャンセルされます。サービスを継続したい場合は、サービスプロバイダにお問い合わせください。

これはもう現時点では使えないのね。。。

## Microsoft Translator API を正しく使う方法

ドキュメントが分散していてかなり厄介でした。。

まずは以下のサイトにアクセスしてアプリケーションの登録と認証キーの取得を行います。

- [Microsoft Cognitive Services](http://docs.microsofttranslator.com/text-translate.html)

登録時のグループについては以下に記述があります。

- [Use Azure portal to manage Azure resources | Microsoft Docs](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-portal)

キーの取得が完了したら、次はそのキーを使ってアクセストークンを取得する必要があり、以下に手順が記されています。

- [Microsoft Cognitive Services](http://docs.microsofttranslator.com/oauth-token.html)

ドキュメントにある通りにアクセストークンを取得する処理を Google Apps Script で書くと、以下のようになります。

````javascript:microsoft.gs
function myMicroSoft() {
  var sp = PropertiesService.getScriptProperties();
  
  var url = 'https://api.cognitive.microsoft.com/sts/v1.0/issueToken';
  var key = 'APIKey';
  var hd = {
    'Ocp-Apim-Subscription-Key': key
  };
  var pl = {
    'data': ''
  };
  var json = UrlFetchApp.fetch(url, {
    'method': 'post',
    'headers': hd,
    'payload': pl
  });
  json = json.getContentText();
  sp.setProperty('ms_token', json);
}
````

これで取得したアクセストークンが ``ms_token`` という名前でスクリプトプロパティに保存されました。
（ファイル→プロジェクトのプロパティ→スクリプトのプロパティ で確認できます。）

このアクセストークンは10分ごとに更新する必要があるため、上記のスクリプトが10分ごとに動くようトリガーを登録すれば準備は完了です。

- [Microsoft Cognitive Services](http://docs.microsofttranslator.com/text-translate.html)

> Consider your subscription key and the access token as secrets that should be hidden from view. The acces token is valid for 10 minutes. Obtain a new acces token every 10 minutes, and keep using the same access token for repeated requests within these 10 minutes.

> あなたのサブスクリプションキーとアクセストークンは、隠れているはずの秘密であると考えてください。アクセストークンは10分間有効です。 10分ごとに新しいアクセストークンを取得し、この10分以内に繰り返しアクセスするために同じアクセストークンを使用し続けます。

## 翻訳する

準備が完了したので実際に翻訳を行ってみます。
API の仕様については最初のドキュメントに書いてあります。

- [Microsoft Cognitive Services](http://docs.microsofttranslator.com/text-translate.html)

しかしながらベースとなる URL が書いてないので、サンプルコードを確認します。

- [HTTP-Code-Samples/TranslateMethod.php at master · MicrosoftTranslator/HTTP-Code-Samples](https://github.com/MicrosoftTranslator/HTTP-Code-Samples/blob/master/PHP/TranslateMethod.php)

サンプルコードを見ると、ベース URL は ``http://api.microsofttranslator.com/v2/Http.svc`` であることがわかります。
（https でも動作しました。）

以上の情報を元に、翻訳処理を実装すると以下のようになります。

````javascript:translate.gs
function myTranslate() {
  var sp = PropertiesService.getScriptProperties();
  var token = sp.getProperty('ms_token');
  
  var url = 'https://api.microsofttranslator.com/v2/Http.svc/Translate';
  var hd = {
    'Authorization': 'Bearer '+token
  };
  url += '?from=en&to=ja&text=';
  url += encodeURIComponent('Hello, World!');
  
  var xml = UrlFetchApp.fetch(url, {
    'method': 'get',
    'headers': hd
  });
  xml = xml.getContentText();
  xml = xml.match(/^<string\s.*>(.*)<\/string>$/);
  Logger.log(xml[1]);
}
````

結果は JSON ではなく XML で返ってきます。
上記のコードでは、パースするのが面倒なので正規表現で無理矢理取得しています。

終わってみれば意外と簡単でしたね〜。

注意点とすれば翻訳するテキストをきちんとエンコードすることでしょうか。

- [JavaScriptでURIエンコード（URLエンコード）を行う｜プログラムメモ](http://logic.moo.jp/data/archives/438.html)

## まとめ

実は Google Apps Script には標準で LanguageApp というものがついています。

- [Class LanguageApp  |  Apps Script  |  Google Developers](https://developers.google.com/apps-script/reference/language/language-app)

[Trump JP](https://trump-jp.tumblr.com) を作り始める前は LanguageApp を使うつもりでした。
しかしながら、実際に使ってみると精度が悪すぎて全く使い物にならなかったです。

Google 翻訳よりは精度が低いですが、とりあえず気軽にそれなりのものを使いたいという方はぜひお試しくださいませ。