Class: TranslationDiff::Providers::Google

Inherits:
HTTPProvider
  • Object
show all
Defined in:
lib/translation_diff/providers/google.rb

Overview

Talks to Cloud Translation v2 directly, not google-cloud-translate-v2, which pulled in grpc for one POST.

Constant Summary collapse

HOST =
"https://translation.googleapis.com".freeze
DEFAULT_FORMAT =

Verified against the live API: text format translates the protected span and drops its markup.

:html

Constants inherited from HTTPProvider

HTTPProvider::RETRY_STATUSES, HTTPProvider::TRANSPORT_FAILURES

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from HTTPProvider

#connection, #headers, #translate

Class Method Details

.capabilities ⇒ Object

Google's documented limits: 128 strings/request, 5,000 chars recommended (hard ceiling 100 KB).



9
10
11
12
13
14
# File 'lib/translation_diff/providers/google.rb', line 9

def self.capabilities
  TranslationDiff::Capabilities.new(
    max_request_size: 5_000, max_batch_size: 128, max_text_size: nil,
    html: :format, notranslate: true, detects_language: true, reports_billing: false
  )
end

.configuration_options ⇒ Object

TRANSLATE_KEY then GOOGLE_CLOUD_KEY, the order google-cloud-translate-v2 read them in.



17
18
19
20
21
# File 'lib/translation_diff/providers/google.rb', line 17

def self.configuration_options
  [:google_api_base,
   { google_api_key: -> { ENV.fetch("TRANSLATE_KEY", nil) || ENV.fetch("GOOGLE_CLOUD_KEY", nil) },
     google_project_id: -> { ENV.fetch("TRANSLATE_PROJECT", nil) } }]
end

.configuration_requirements ⇒ Object



23
# File 'lib/translation_diff/providers/google.rb', line 23

def self.configuration_requirements = %i[google_api_key]

Instance Method Details

#api_base ⇒ Object



25
# File 'lib/translation_diff/providers/google.rb', line 25

def api_base = config.google_api_base || HOST

#detect(text) ⇒ Object



47
48
49
50
# File 'lib/translation_diff/providers/google.rb', line 47

def detect(text)
  response = post(detect_url, { q: [text] })
  response.body.dig("data", "detections", 0, 0, "language")&.downcase
end

#detect_url ⇒ Object



27
# File 'lib/translation_diff/providers/google.rb', line 27

def detect_url = "language/translate/v2/detect?key=#{CGI.escape(config.google_api_key.to_s)}"

#languages ⇒ Object

One list, used in both directions.



53
54
55
56
57
58
# File 'lib/translation_diff/providers/google.rb', line 53

def languages
  codes = Array(get("language/translate/v2/languages?key=#{CGI.escape(config.google_api_key.to_s)}")
                  .body.dig("data", "languages")).map { |entry| entry["language"] }

  { source: codes, target: codes }
end

#languages_endpoint ⇒ Object

The key is left out: it is a credential, not part of what documents where this list comes from.



61
# File 'lib/translation_diff/providers/google.rb', line 61

def languages_endpoint = "#{api_base}/language/translate/v2/languages"

#parse_translate_response(body, _headers, request) ⇒ Object



36
37
38
39
40
41
42
43
44
45
# File 'lib/translation_diff/providers/google.rb', line 36

def parse_translate_response(body, _headers, request)
  translations = Array(body.dig("data", "translations"))

  TranslationDiff::Translation::Response.build(
    request: request,
    texts: translations.map { |t| t["translatedText"] },
    detected_source: translations.first&.dig("detectedSourceLanguage")&.downcase,
    usage: TranslationDiff::Translation::Usage.new(characters: request.texts.sum(&:size))
  )
end

#render_translate_payload(request) ⇒ Object



29
30
31
32
33
34
# File 'lib/translation_diff/providers/google.rb', line 29

def render_translate_payload(request)
  { format: DEFAULT_FORMAT }
    .merge(request.options)
    .merge(q: request.texts, target: language(request.to))
    .tap { |payload| payload[:source] = language(request.from) unless request.from.nil? }
end

#translate_url ⇒ Object



26
# File 'lib/translation_diff/providers/google.rb', line 26

def translate_url = "language/translate/v2?key=#{CGI.escape(config.google_api_key.to_s)}"