Microsoft TranslatorをRubyから使ってみた

weblioのポップアップウィンドウの方が便利だけどと思いながらも、Rubyの練習のためにMicrosoft Translatorを使ってみた。

MICROSOFT TRANSLATORサブスクリプション登録。
https://datamarket.azure.com/dataset/1899a118-d202-492c-aa16-ba21c33c06cb
今回は、2,000,000文字/月の無料プランで。

アプリケーション登録。
https://datamarket.azure.com/developer/applications/
ここで登録するクライアントIDと自動入力されている顧客の秘密を使用する。
(適当な値設定でいい?)
リダイレクトURLはとりあえず自分所有のURLで。

アカウント情報なんかはこの辺り。
https://datamarket.azure.com/account

翻訳APIを使用するための情報はこの辺り。
http://www.microsofttranslator.com/dev/
今回使用したのはHTTPインターフェイス。

Rubyのバージョンは1.9.3p374で、Cygwinのシェルから起動して使う想定。

# -*- encoding: utf-8 -*-

require 'json'
require 'net/http'
require 'uri'
require 'openssl'
require 'rexml/document'

class Translation
  # プライマリアカウントキー see: https://datamarket.azure.com/account
  MS_TRANSLATOR_PRIMARY_KEY      = "ここに記載"
  # クライアントID see: https://datamarket.azure.com/developer/applications/
  MS_TRANSLATOR_CLIENT_ID        = "ここに記載"
  # クライアントID see: 顧客の秘密
  MS_TRANSLATOR_CLIENT_SECRET    = "ここに記載"
  MS_TRANSLATOR_ACCESSTOKEN_URL  = "https://datamarket.accesscontrol.windows.net/v2/OAuth2-13"
  MS_TRANSLATOR_SCOPE            = "http://api.microsofttranslator.com"
  MS_TRANSLATOR_URL              = "http://api.microsofttranslator.com/V2/Http.svc/Translate"
  MS_TRANSLATOR_GRANT_TYPE       = "client_credentials"

  def initialize
    @cache = {}
  end

  # POSTしてアクセストークンを取得する
  def getAccessTokenMessage
    response = nil

    Net::HTTP.version_1_2
    uri = URI.parse(MS_TRANSLATOR_ACCESSTOKEN_URL)
    https = Net::HTTP.new(uri.host, uri.port)
    https.use_ssl = true
    https.verify_mode = OpenSSL::SSL::VERIFY_NONE

    request = Net::HTTP::Post.new(uri.path)
    request.set_form_data({
      :client_id => MS_TRANSLATOR_CLIENT_ID,
      :client_secret => MS_TRANSLATOR_CLIENT_SECRET,
      :scope => MS_TRANSLATOR_SCOPE,
      :grant_type => MS_TRANSLATOR_GRANT_TYPE
      })

    response = https.request(request)

    if response.message == "OK"
      @updateTime = Time.now
      JSON.parse(response.body)
    else
      raise "access token acquisition failure"
    end

  end

  # キャッシュから、もしくはPOSTしてアクセストークンを取得する
  def getAccessToken(renew = false)
    renewJson = true

    if(@updateTime && @expiresIn)
      delta = Time.now - @updateTime
      if(delta <= @expiresIn.to_i - 10)
        renewJson = false
      end
    end

    if(renew)
     renewJson = true
    end

    # puts "info: renew access token" if renewJson
    @jsonResult = getAccessTokenMessage if renewJson
    @accessToken = @jsonResult["access_token"]
    @expiresIn = @jsonResult["expires_in"]

    return @accessToken
  end

  def existsTransCache(word)
    @cache.has_key?(word)
  end

  def setTransCache(word, resultWord)
    @cache[word] = resultWord
  end

  def getTransCache(word)
    @cache[word]
  end

  # wordを翻訳する
  def trans(word)
    if existsTransCache(word)
      return getTransCache(word)
    end
    access_token = getAccessToken

    Net::HTTP.version_1_2
    uri = URI.parse(MS_TRANSLATOR_URL)
    http = Net::HTTP.new(uri.host, uri.port)

    params = {
      :text => word,
      :from => "en",
      :to => "ja"
      }
    query_string = params.map{ |k,v|
      URI.encode(k.to_s) + "=" + URI.encode(v.to_s)
    }.join("&")

    request = Net::HTTP::Get.new(uri.path + "?" + query_string)
    request['Authorization'] = "Bearer #{access_token}"

    response = http.request(request)

    result = nil
    # response.body
    # => <string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">サンプル</string>
    if response.message == "OK"
      document = REXML::Document.new(response.body)
      result = document.root.text
      setTransCache(word, result)
    end

    result
  end

end

trans = Translation.new

puts "input English word ('!' to quit)"
while true
  print("(word or '!'): ") 
  word = gets.chomp
  if word == "!"
    break
  end
  puts " => " + trans.trans(word)
end

Ruby逆引きハンドブック

Ruby逆引きハンドブック