JavaScriptでAzure Translatorを使って翻訳した結果のtranslationsプロパティからtext文字列だけを取得して表示する


色々なAPIを触ってお勉強中なのですが、面白そうなAPIの取得結果が英語だったりすると、「日本語に翻訳した結果をプロトタイプに使いたいなー」という場面が出てきました。無料で翻訳する方法は検索で色々出てきますが、せっかくMicrosoft Azureの従量課金サブスクリプションを使える状況にあるので、今回はAzure Cognitive ServiceのTranslatorサービスで翻訳に挑戦したいと思います。

Qiita、意外とAzureの記事は多くないのですね('ω')

この記事の概要

JacaScriptでAzure Translatorサービスを使って翻訳し、翻訳結果のtext文字列のみを取り出して表示します。REST-APIでリクエストしてからレスポンスを得るまでは順調だったのですが、そもそもJSON形式のデータの扱い、変換に慣れておらずかなり時間を消費しましたので・・、ここに記録しておきます。

  • Azure Translatorサービスをデプロイする
  • ますは翻訳結果をREST-APIで取得できるか試してみる
  • 取得したJSON配列からtext文字列だけを取り出して表示したい(のに、中々できない・・)

環境は以下の通りです。

Module Version
Node.js 15.13.0
npm 7.7.6
request 2.88.2
uuid 8.3.2

Azure Translatorサービスをデプロイする

こちらの記事が、Azureポータルの操作画面付きで親切に紹介してくれていますので、これを参考にTranslatorサービスの作成・デプロイを行います。
【Microsoft Azure Translator Text 】Pythonで機械翻訳をしてみる(REST API)

今回はあくまでもお試し用なので、フリープランで用意しました。
APIで使用するエンドポイントとキーは、Azureポータルの以下画面で確認できます。今回は検証目的のためソースに直接記入してしまいますが、絶対に公開・漏洩しないように気をつけてください。本当はAzure Key Vaultなど使用してセキュアに使うのが推奨ですね。

ますは翻訳結果をREST-APIで取得できるか試してみる

requestモジュールを使用してリクエストを実行しますので、インストールしておきます。

npm install request

作成したコードはコチラです。コーディング勉強中で見様見真似ですので、おかしな箇所がありましたら容赦なく突っ込みをお願いします('ω')

get_translator_response.js
//package require
const request = require('request');
const uuidv4 = require('uuid/v4');

// 今回は次の英文を翻訳します
const SourceText = 'When in doubt, just take the next small step.'

// REST APIのPOST要求のパラメータを定義します
function translateText(SourceText){
  let options = {
      method: 'POST',
      baseUrl: 'https://api.cognitive.microsofttranslator.com/',
      url: 'translate',
      qs: {
        'api-version': '3.0',
        'from': ['en'],
        'to': ['ja']
      },
      headers: {
        'Ocp-Apim-Subscription-Key': 'YourSubscriptionKey',
        'Ocp-Apim-Subscription-Region': 'YourServiceRegion',
        'Content-type': 'application/json',
        'X-ClientTraceId': uuidv4().toString()
      },
      body: [{
            'text': SourceText
      }],
      json: true,
  };

  // 応答本文(JSON配列)を受け取って表示します
  request(options, function(err, res, body){

    // レスポンスデータを確認します(オブジェクトのまま)
    console.log(body);

    // JSON形式の文字列に変換します
    const jsonText = JSON.stringify(body, null, 4)
    console.log(jsonText);

  });
};

// 処理の呼び出し
translateText(SourceText);

さて、実行結果です。

[
  {
    detectedLanguage: { language: 'en', score: 1 },
    translations: [ [Object] ]
  }
]
[
    {
        "detectedLanguage": {
            "language": "en",
            "score": 1
        },
        "translations": [
            {
                "text": "疑わしい場合は、次の小さな一歩を踏み出してください。",
                "to": "ja"
            }
        ]
    }
]

おぉ、ちゃんと動きましたね('ω')
なるほど、最初の出力がレスポンスで得られるJSON配列(入れ子オブジェクトあり)で、こう表示されるのですね。二番目の出力は、JSON.stringifyで文字列変換を掛けているので、しっかりとtranslationsプロパティ内の翻訳textまでしっかり確認できます。

取得したJSON配列からtext文字列だけを取り出して表示したい(のに、中々できない・・)

後は煮るなり焼くなりと、目的の翻訳text文字列だけ取り出して完成!となるはずが、ここから大ハマりしました。

  • そもそもJavaScriptのコードは今月から触り始めた初心者
  • よく理解していない状況で他人様のコードをコピペして動かしては喜んでいた

というレベルですので、配列やオブジェクトの変換とか操作を全く分かっていませんでした。「JSON.parseとJSON.stringifyでオブジェクトと文字列を行き来すればよいのでしょ、オブジェクトでないと子プロパティ指定でデータ取れないのでしょ(分かってない)」という感じで、あーでもない、こーでもないと数時間。

あれ?おかしいな?
よし!「(オブジェクト)['translations'][0]['text'] 」で行けるだろう!

TypeError: Cannot read property '0' of undefined

無理('ω')

その後のんびりとWeb記事でお勉強しながら、ふとコードとデータを見ていると「そもそも全体が配列で返ってきているのか・・(゚Д゚)」もしかして・・、こうか!

  request(options, function(err, res, body){

    console.log(body[0]['translations'][0]['text']);

  });

結果。

疑わしい場合は、次の小さな一歩を踏み出してください。

おぉ('ω')
いったい私は何に時間を取られていたのでしょう・・。こんな不幸な初心者を増やさないよう、この記事を捧げます。