CUI翻訳ソフト

と言う訳でさらしてみる。


Excite,Yahoo,Google,Webservicexを利用して翻訳するソフトです。
個人的趣味によりCUIのみですけど。


今まで、公開しなかったのは各サイトの利用規約に反するかな?と思ったからです。
けど検索したら結構ソースがあるし、まあいいかなあと。
どうせ誰も使わないだろうし。


ながいので以下"続きを読む記法"で


まずはライブラリ。
というか処理の実態
rnettrans.rb
注:~/lib/以下に置いてある。

#!/usr/bin/env ruby

require 'net/http'
require 'jcode'
require 'kconv'
require 'rss'
require 'open-uri'
require 'cgi'

require 'rubygems'
require 'mechanize'
require 'hpricot'

$KCODE = 'utf'

class String
  def to_url
    return CGI.escape(self)
  end
end

class NetTranslator
end


#メモ
#基本的な流れ
#NetTranslatorBaseをスーパークラスにした、新クラスHogeを作る
#Hogeクラスはinitializeとtransメソッドを作れば良い。
#後はen2jaとja2enメソッドがtransメソッドを自動的に呼ぶ。
class NetTranslatorBase
  def initialize
    @proxy_addr = nil
    @proxy_port = nil
  end
  attr_accessor :proxy_addr, :proxy_port

  def nkf(text, code)
    ret = nil

    case code.downcase
    when 'euc'
      ret = Kconv.toeuc(text)
    when 'jis'
      ret = Kconv.tojis(text)
    when 'sjis'
      ret = Kconv.tosjis(text)
    when 'utf8'
      ret = Kconv.toutf8(text)
    else
      raise
    end

    ret
  end

  def trans(lang, text)
  end

  def en2ja(text)
    trans("en2ja", text)
  end

  def ja2en(text)
    trans("ja2en", text)
  end
end

#参考:http://d.hatena.ne.jp/nack01/20070518/p2
class NetTranslator::Excite < NetTranslatorBase
  def initialize
    @agent = WWW::Mechanize.new
    @agent.user_agent_alias = 'Linux Mozilla'

    @proxy_user = nil
    @proxy_password = nil
  end
  attr_accessor :proxy_user, :proxy_password

  def trans(lang, text)
    if @proxy_addr and @proxy_port
      @agent.set_proxy(@proxy_address, @proxy_port, @proxy_user, @proxy_password)
    end

    page = @agent.get('http://www.excite.co.jp/world/english/')
    search_form = page.forms.with.name('world').first

    case lang
    when 'en2ja'
      search_form.wb_lp = 'ENJA'
    when 'ja2en'
      search_form.wb_lp = 'JAEN'
    else
      raise
    end

    search_form.before = nkf(text, 'sjis')
    search_results = @agent.submit(search_form, search_form.buttons.with.name('start').first)

    ret = search_results.forms.with.name('world').first.after
    return nkf(ret, 'utf8')
  end
end

#参考:http://jugyo.org/blog/?p=2650
class NetTranslator::Google < NetTranslatorBase
  def initialize
    Net::HTTP.version_1_2
    @url='translate.google.com'
    @port=80
  end

  def trans(lang, text)
    ret = nil

    if @proxy_addr and @proxy_port
      http = Net::HTTP::Proxy(@proxy_addr, @proxy_port).start(@url, @port)
    else
      http = Net::HTTP.start(@url, @port)
    end

    case lang
    when 'en2ja'
      langpair = 'en|ja'
    when 'ja2en'
      langpair = 'ja|en'
    else
      raise
    end

    ret = http.post('/translate_t', "langpair=#{langpair}&text=#{nkf(text, 'sjis')}")
    doc = Hpricot(ret.body)
    ret = (doc/"#result_box").inner_text.toutf8
    http.finish

    ret
  end
end

#使用Web API
#http://muumoo.jp/news/2007/05/09/0translationapi.html
class NetTranslator::Yahoo_Pipes < NetTranslatorBase
  def initialize
    @e2j_url = "http://pipes.yahoo.com/poolmmjp/ej_translation_api?_render=rss&text="
    @j2e_url = "http://pipes.yahoo.com/poolmmjp/je_translation_api?_render=rss&text="
  end

  def trans(lang, text)
    ret = nil

    #if @proxy_addr and @proxy_port
    #  puts "Sorry.Don't use proxy"
    #else
    #  puts "Sorry.Don't use proxy"
    #end

    url = nil
    case lang
    when 'en2ja'
      url = @e2j_url+text.to_url
    when 'ja2en'
      url = @j2e_url+text.to_url
    else
      raise
    end

    #p url
    rss = RSS::Parser.parse(url, true)
    rss.channel.item.description
  end
end

#http://www.webservicex.net/
#http://www.webservicex.net/TranslateService.asmx?op=Translate
class NetTranslator::Webservicex < NetTranslatorBase
  def initialize
    @url='www.webservicex.net'
    @port=80
    @e2j_url = "http://www.webservicex.net/TranslateService.asmx/Translate?LanguageMode=EnglishTOJapanese&Text="
    @j2e_url = "http://www.webservicex.net/TranslateService.asmx/Translate?LanguageMode=JapaneseTOEnglish&Text="
  end

  #発生したエラーのメモ
  def error
    "The remote server returned an error: (999) Unable to process request at this time -- error 999."
  end
  private :error

  def trans(lang, text)
    ret = nil

    if @proxy_addr and @proxy_port
      http = Net::HTTP::Proxy(@proxy_addr, @proxy_port).start(@url, @port)
    else
      http = Net::HTTP.start(@url, @port)
    end

    case lang
    when 'en2ja'
      url = @e2j_url+text.to_url
    when 'ja2en'
      url = @j2e_url+nkf(text, 'utf8').to_url
    else
      raise
    end

    #p url
    #exit
    ret = open(url).read
    doc = Hpricot(ret)
    ret = (doc).inner_text.toutf8.strip
    http.finish

    ret
  end
end


if $0 == __FILE__
  trans = NetTranslator::Yahoo_Pipes.new
  puts trans.en2ja("I love Ruby.") 
  puts trans.ja2en("わたしはRubyがすきです.") 
  exit

  #trans = NetTranslator::Google.new
  #puts trans.en2ja("I love Ruby.") 
  #puts trans.ja2en("わたしはRubyがすきです.") 

  trans = NetTranslator::Excite.new
  #puts trans.ja2en("割り込み番号") 
  puts trans.ja2en("変数命名") 
  #puts trans.en2ja("You may distribute copies of this etext electronically, or by disk, book or any other medium if you either delete this \"Small Print!\" and all other references to Project Gutenberg, or:")
  #puts trans.en2ja("I love Ruby.") 
  #puts trans.ja2en("わたしはRubyが好きです.") 
end

次にインターフェース部分
rnettrans.rb

#!/usr/bin/env ruby

require "optparse"

require '~/lib/nettrans'

parser = OptionParser.new

site = :google
option = :e2j

parser.banner = "Usage: #{File.basename($0)} [-E|-G|-Y|-W] [-e|-j|]|[-h]"
parser.on("-j", "--english-to-japnaese", "Translate english to japanese. default."){
  option = :e2j
}
parser.on("-e", "--japanese-to-english", "Translate japanese to english."){
  option = :j2e
}
parser.on("-E", "--excite", "Use excite."){
  site = :excite
}
parser.on("-G", "--google", "Use google."){
  site = :google
}
parser.on("-Y", "--yahoo-pipe", "Use yahoo-pipe."){
  site = :yahoo_pipe
}
parser.on("-W", "--webservicex", "Use Webservicex."){
  site = :webservicex
}

begin
  parser.parse!
rescue OptionParser::ParseError => err
  $stderr.puts err.message
  $stderr.puts parser.help
  exit 1
end

case site
when :excite
  STDERR.write "Use excite.\n"
  trans = NetTranslator::Excite.new
when :google
  STDERR.write "Use google.\n"
  trans = NetTranslator::Google.new
when :yahoo_pipe
  STDERR.write "Use yahoo_pipe.\n"
  trans = NetTranslator::Yahoo_Pipes.new
when :webservicex
  STDERR.write "Use webservicex.\n"
  trans = NetTranslator::Webservicex.new
else
  exit 1
end

while arg = ARGV.shift
  case option
  when :e2j
    puts str = trans.en2ja(arg)
  when :j2e
    puts str = trans.ja2en(arg)
  end
end


Webservicexって一時繋がらなかったけど、今日試したら普通に使えました。
なんなんだろう?