module I18n::Processes::GoogleTranslation

Constants

INTERPOLATION_KEY_RE
UNTRANSLATABLE_STRING

Public Instance Methods

fetch_google_translations(list, opts) click to toggle source

@param [Array<[String, Object]>] list of key-value pairs @return [Array<[String, Object]>] translated list

# File lib/i18n/processes/google_translation.rb, line 39
def fetch_google_translations(list, opts)
  from_values(list, EasyTranslate.translate(to_values(list), opts)).tap do |result|
    fail CommandError, 'Google Translate returned no results. Make sure billing information is set at https://code.google.com/apis/console.' if result.blank?
  end
end
google_translate_forest(forest, from) click to toggle source

@param [I18n::Processes::Tree::Siblings] forest to translate to the locales of its root nodes @param [String] from locale @return [I18n::Processes::Tree::Siblings] translated forest

# File lib/i18n/processes/google_translation.rb, line 11
def google_translate_forest(forest, from)
  forest.inject empty_forest do |result, root|
    translated = google_translate_list(root.key_values(root: true), to: root.key, from: from)
    result.merge! Data::Tree::Siblings.from_flat_pairs(translated)
  end
end
google_translate_list(list, opts) click to toggle source

@param [Array<[String, Object]>] list of key-value pairs @return [Array<[String, Object]>] translated list

# File lib/i18n/processes/google_translation.rb, line 20
def google_translate_list(list, opts) # rubocop:disable Metrics/AbcSize
  return [] if list.empty?
  opts = opts.dup
  opts[:key] ||= translation_config[:api_key]
  validate_google_translate_api_key! opts[:key]
  key_pos = list.each_with_index.inject({}) { |idx, ((k, _v), i)| idx.update(k => i) }
  # copy reference keys as is, instead of translating
  reference_key_vals = list.select { |_k, v| v.is_a? Symbol } || []
  list -= reference_key_vals
  result = list.group_by { |k_v| html_key? k_v[0], opts[:from] }.map do |is_html, list_slice|
    fetch_google_translations list_slice, opts.merge(is_html ? { html: true } : { format: 'text' })
  end.reduce(:+) || []
  result.concat(reference_key_vals)
  result.sort! { |a, b| key_pos[a[0]] <=> key_pos[b[0]] }
  result
end

Private Instance Methods

dump_value(value) click to toggle source

Prepare value for translation. @return [String, Array<String, nil>, nil] value for Google Translate or nil for non-string values

# File lib/i18n/processes/google_translation.rb, line 68
def dump_value(value)
  case value
  when Array
    # dump recursively
    value.map { |v| dump_value v }
  when String
    replace_interpolations value
  end
end
from_values(list, translated_values) click to toggle source

@param [Array<[String, Object]>] list @param [Array<String>] translated_values @return [Array<[String, Object]>] translated key-value pairs

# File lib/i18n/processes/google_translation.rb, line 60
def from_values(list, translated_values)
  keys                = list.map(&:first)
  untranslated_values = list.map(&:last)
  keys.zip parse_value(untranslated_values, translated_values.to_enum)
end
parse_value(untranslated, each_translated) click to toggle source

Parse translated value from the each_translated enumerator @param [Object] untranslated @param [Enumerator] each_translated @return [Object] final translated value

# File lib/i18n/processes/google_translation.rb, line 82
def parse_value(untranslated, each_translated)
  case untranslated
  when Array
    # implode array
    untranslated.map { |from| parse_value(from, each_translated) }
  when String
    restore_interpolations untranslated, each_translated.next
  else
    untranslated
  end
end
replace_interpolations(value) click to toggle source

@param [String] value @return [String] 'hello, %{name}' => 'hello, <round-trippable string>'

# File lib/i18n/processes/google_translation.rb, line 99
def replace_interpolations(value)
  i = -1
  value.gsub INTERPOLATION_KEY_RE do
    i += 1
    "#{UNTRANSLATABLE_STRING}#{i}"
  end
end
restore_interpolations(untranslated, translated) click to toggle source

@param [String] untranslated @param [String] translated @return [String] 'hello, <round-trippable string>' => 'hello, %{name}'

# File lib/i18n/processes/google_translation.rb, line 110
    def restore_interpolations(untranslated, translated)
      return translated if untranslated !~ INTERPOLATION_KEY_RE
      values = untranslated.scan(INTERPOLATION_KEY_RE)
      translated.gsub(/#{Regexp.escape(UNTRANSLATABLE_STRING)}\d+/i) do |m|
        values[m[UNTRANSLATABLE_STRING.length..-1].to_i]
      end
    rescue StandardError => e
      raise CommandError.new(e, <<-TEXT.strip)
Error when restoring interpolations:
  original: "#{untranslated}"
  response: "#{translated}"
  error: #{e.message} (#{e.class.name})
      TEXT
    end
to_values(list) click to toggle source

@param [Array<[String, Object]>] list of key-value pairs @return [Array<String>] values for translation extracted from list

# File lib/i18n/processes/google_translation.rb, line 53
def to_values(list)
  list.map { |l| dump_value l[1] }.flatten.compact
end
validate_google_translate_api_key!(key) click to toggle source
# File lib/i18n/processes/google_translation.rb, line 47
def validate_google_translate_api_key!(key)
  fail CommandError, 'Set Google API key via GOOGLE_TRANSLATE_API_KEY environment variable or translation.api_key in config/i18n-processes.yml. Get the key at https://code.google.com/apis/console.' if key.blank?
end