class Smartdict::Drivers::LingvoYandexDriver

The translation driver for Google Translate service.

DISCLAIMER: It’s was written when I had one hand broken. Refactoring costs a lot of movements so that I’ve left it as it was. I’m gonna refactor it soon. – Sergey Potapov

TODO:

* Refactor

Constants

HOST

Host of Lingvo service.

USER_AGENT

Pretend being Firefox :)

WORD_CLASSES

Mapping for word classes. Default is “other”

Public Instance Methods

escape(str) click to toggle source
# File lib/smartdict/drivers/lingvo_yandex_driver.rb, line 134
def escape(str)
  CGI.escape(str)
end
get_response() click to toggle source
# File lib/smartdict/drivers/lingvo_yandex_driver.rb, line 117
def get_response
  http = Net::HTTP.new(HOST, 80)
  request = Net::HTTP::Get.new(http_path, { "User-Agent" => USER_AGENT })
  http.request(request).read_body
end
grep_meanings(html_element) click to toggle source

TODO: refactor

# File lib/smartdict/drivers/lingvo_yandex_driver.rb, line 69
def grep_meanings(html_element)
  acronym = html_element.css("acronym").first
  return unless acronym

  ru_word_class = acronym["title"]
  word_class = WORD_CLASSES[ru_word_class]
  translations = []

  html_element.css("ul > li").each do |tr|
    # a text line with translations separated by commas
    line = ""

    # use strong tag as an anchor
    strong = tr.css("strong").first
    if strong && strong.text =~ /\d+|[а-я]+\)/
      node = strong
      while(node = node.next_sibling)
        if node.text? || node.name == "a"
          text = node.text
          line << text unless text =~ /\(|\)/
        elsif ["em", "acronym"].include? node.name
          next
        else
          break
        end
      end
    end
    translations += words_from_line(line)
  end


  # sometimes there is only one meaning
  if translations.empty?
    if a_tag = html_element.css("span > a").first
      line = a_tag.text
    elsif span = html_element.css("span").first
      line = span.text
    elsif i_tag = html_element.xpath("i[2]")
      line = i_tag.text
    else
      return nil
    end
    translations = words_from_line(line)
  end

  self.translated[word_class] = translations.uniq
end
http_path() click to toggle source

@return [String] http path for request to translate word.

# File lib/smartdict/drivers/lingvo_yandex_driver.rb, line 124
def http_path
  phrase = case [from_lang, to_lang]
  when ["en", "ru"] then "en-ru"
  when ["ru", "en"] then "ru-en"
  else raise Smartdict::TranslationNotFound
  end

  "/#{escape(word)}/#{phrase}/"
end
translate() click to toggle source

TODO: refactor

# File lib/smartdict/drivers/lingvo_yandex_driver.rb, line 43
def translate
  doc = Nokogiri::HTML(get_response)

  if main = doc.css("div.b-translation__article > ul > li#I").first
  else
    main = doc.css("div.b-translation__article").first
  end

  raise Smartdict::TranslationNotFound unless main

  # Fetch transcription
  self.transcription = doc.css("span.b-translation__tr").first.try(:text)


  self.translated = {}

  if main.xpath("./i/acronym").any?
    grep_meanings(main)
  else
     main.xpath("./ul/li").each do |li|
      grep_meanings(li)
    end
  end
end

Private Instance Methods

words_from_line(line) click to toggle source
# File lib/smartdict/drivers/lingvo_yandex_driver.rb, line 141
def words_from_line(line)
  line.split(/,|;/).map(&:strip).reject(&:empty?)
end