kurukuru-papaのブログ

主に、ソフトウェア開発に関連したメモを書き溜めたいと思います。

Microsoft Translator API(HTTP版)を使ってみました

C#.NETで、日本語文字列を英語に翻訳してみたくなったので、少し調べてみました。そして、Microsoftが公開している翻訳API(無償プランあり)を用いて、C#.NETによる翻訳サンプルアプリケーションを作成してみたので、メモしておきます。

はじめに

翻訳APIを公開している主な会社としては、マイクロソフトGoogleがありました(他にも私が知らないだけで有名なAPIがあるかもしれません。)どちらも以前は無料で使えていたようですが、2012/6/9現在は次の料金体系になっていました。

  • Microsoft Translator API
    • 2,000,000文字/月までは無料。月額3,140〜618,552。
    • 料金ページ

とりあえず触ってみたいだけだったので、Microsoftの無償プランで、サンプルアプリケーションを作成してみました。

作成したアプリケーションの画面イメージは次になります。画面左側のテキストボックスに翻訳したい日本語を入力して、翻訳ボタンを押すと、画面右側のテキストボックスに翻訳結果が表示されます。もし、Microsoft Translator APIとのやり取りに問題が発生すると、処理メッセージ欄にエラー内容が表示されます。

準備

Microsoft Translator APIを使えるようになるまでに幾つか手続きが必要でした。

  1. Windows Live IDの取得(既に取得済みであれば不要)
  2. 次のページから、Windows Azure MarketplaceでMicrosoft Translator データに対して、サブスクリプション登録を行う。
  3. 次のページから、自作アプリケーションを登録し、「クライアントID」と「顧客の秘密」を取得する。自作アプリケーションは未作成でも良い。

プログラム

Microsoft Translator APIとHTTP通信を行い、翻訳を行う部分だけ抜粋して、記述します。とはいえ、9割がたはマイクロソフトのサンプルソース通りなので、抜粋する意味はあまりないかもしれません。。。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;

namespace Translator
{
    public class TranslatorApi
    {
        private AdmAccessToken admToken;
        private AdmAuthentication admAuth;

        public TranslatorApi()
        {
            //Get Client Id and Client Secret from https://datamarket.azure.com/developer/applications/
            //Refer obtaining AccessToken (http://msdn.microsoft.com/en-us/library/hh454950.aspx) 
            // clientIDには、事前にマイクロソフトへ登録した「クライアントID」を設定。
            // client secretには、事前にマイクロソフトへ登録した「顧客の秘密」を設定。
            admAuth = new AdmAuthentication("clientID", "client secret");
        }

        public string Translate(string inText)
        {
            string outText = string.Empty;
            string headerValue;
            try
            {
                // アクセストークン取得
                // アクセストークンは10分間有効であるが、当アプリケーションでは簡略化のため考慮せず、
                // 毎回アクセストークンを取得する。
                admToken = admAuth.GetAccessToken();
                // Create a header with the access_token property of the returned token
                headerValue = "Bearer " + admToken.access_token;

                // 翻訳実施
                outText = TranslateMethod(headerValue, inText);
            }
            catch (WebException e)
            {
                throw new ApplicationException(GetErrorMessage(e), e);
            }

            return outText;
        }

        private string TranslateMethod(string authToken, string text)
        {
            string translation = string.Empty;
            string from = "ja";
            string to = "en";

            string uri = "http://api.microsofttranslator.com/v2/Http.svc/Translate?text="
                + System.Web.HttpUtility.UrlEncode(text) + "&from=" + from + "&to=" + to;

            HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(uri);
            httpWebRequest.Headers.Add("Authorization", authToken);
            WebResponse response = null;
            try
            {
                response = httpWebRequest.GetResponse();
                using (Stream stream = response.GetResponseStream())
                {
                    System.Runtime.Serialization.DataContractSerializer dcs =
                        new System.Runtime.Serialization.DataContractSerializer(Type.GetType("System.String"));
                    translation = (string)dcs.ReadObject(stream);
                }
            }
            finally
            {
                if (response != null)
                {
                    response.Close();
                    response = null;
                }
            }

            return translation;
        }

        private string GetErrorMessage(WebException e)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine(e.ToString());

            // Obtain detailed error information
            string strResponse = string.Empty;
            using (HttpWebResponse response = (HttpWebResponse)e.Response)
            {
                using (Stream responseStream = response.GetResponseStream())
                {
                    using (StreamReader sr = new StreamReader(responseStream, System.Text.Encoding.ASCII))
                    {
                        strResponse = sr.ReadToEnd();
                    }
                }
            }
            sb.AppendLine("Http status code=" + e.Status + ", error message=" + strResponse);

            return sb.ToString();
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Web;
using System.Runtime.Serialization.Json;

namespace Translator
{
    class AdmAuthentication
    {
        public static readonly string DatamarketAccessUri = "https://datamarket.accesscontrol.windows.net/v2/OAuth2-13";
        private string clientId;
        private string cientSecret;
        private string request;

        public AdmAuthentication(string clientId, string clientSecret)
        {
            this.clientId = clientId;
            this.cientSecret = clientSecret;
            //If clientid or client secret has special characters, encode before sending request
            this.request = string.Format("grant_type=client_credentials&client_id={0}&client_secret={1}&scope=http://api.microsofttranslator.com",
                HttpUtility.UrlEncode(clientId), HttpUtility.UrlEncode(clientSecret));
        }

        public AdmAccessToken GetAccessToken()
        {
            return HttpPost(DatamarketAccessUri, this.request);
        }

        private AdmAccessToken HttpPost(string DatamarketAccessUri, string requestDetails)
        {
            //Prepare OAuth request 
            WebRequest webRequest = WebRequest.Create(DatamarketAccessUri);
            webRequest.ContentType = "application/x-www-form-urlencoded";
            webRequest.Method = "POST";
            byte[] bytes = Encoding.ASCII.GetBytes(requestDetails);
            webRequest.ContentLength = bytes.Length;
            using (Stream outputStream = webRequest.GetRequestStream())
            {
                outputStream.Write(bytes, 0, bytes.Length);
            }
            using (WebResponse webResponse = webRequest.GetResponse())
            {
                DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(AdmAccessToken));
                //Get deserialized object from JSON stream
                AdmAccessToken token = (AdmAccessToken)serializer.ReadObject(webResponse.GetResponseStream());
                return token;
            }
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace Translator
{
    [DataContract]
    class AdmAccessToken
    {
        [DataMember]
        public string access_token { get; set; }
        [DataMember]
        public string token_type { get; set; }
        [DataMember]
        public string expires_in { get; set; }
        [DataMember]
        public string scope { get; set; }
    }
}

プログラムダウンロード

次のページからソースと実行ファイルをダウンロード出来るようにしました。もし興味がありましたら、ご覧下さい。

補足

今回は「1つの日本語テキスト」を対象に翻訳しました。マイクロソフトのページを見てみると、複数のテキストを変換するAPIがあったり、翻訳結果として音声(MP3データ)を返却してくれるAPIもあったりします。面白いことができそうですね。

動作環境