Merge pull request #5089 from consul/bing-translator
Use Bing Translator instead of TranslatorText
This commit is contained in:
2
Gemfile
2
Gemfile
@@ -9,6 +9,7 @@ gem "airbrake", "~> 13.0.2"
|
||||
gem "ancestry", "~> 4.2.0"
|
||||
gem "audited", "~> 5.0.2"
|
||||
gem "autoprefixer-rails", "~> 8.2.0"
|
||||
gem "bing_translator", "~> 6.2.0"
|
||||
gem "cancancan", "~> 3.4.0"
|
||||
gem "caxlsx", "~> 3.2.0"
|
||||
gem "caxlsx_rails", "~> 0.6.3"
|
||||
@@ -55,7 +56,6 @@ gem "savon", "~> 2.13.0"
|
||||
gem "sitemap_generator", "~> 6.3.0"
|
||||
gem "social-share-button", "~> 1.2.4"
|
||||
gem "sprockets", "~> 4.1.1"
|
||||
gem "translator-text", "~> 0.1.0"
|
||||
gem "turbolinks", "~> 5.2.1"
|
||||
gem "turnout", "~> 2.5.0"
|
||||
gem "uglifier", "~> 4.2.0"
|
||||
|
||||
33
Gemfile.lock
33
Gemfile.lock
@@ -96,6 +96,8 @@ GEM
|
||||
parser (>= 2.4)
|
||||
smart_properties
|
||||
bindex (0.8.1)
|
||||
bing_translator (6.2.0)
|
||||
json
|
||||
builder (3.2.4)
|
||||
bullet (7.0.3)
|
||||
activesupport (>= 3.0.0)
|
||||
@@ -178,31 +180,6 @@ GEM
|
||||
devise (>= 4.3.0, < 5.0)
|
||||
diff-lcs (1.5.0)
|
||||
docile (1.4.0)
|
||||
dry-configurable (0.7.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
dry-container (0.6.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
dry-configurable (~> 0.1, >= 0.1.3)
|
||||
dry-core (0.4.7)
|
||||
concurrent-ruby (~> 1.0)
|
||||
dry-equalizer (0.2.1)
|
||||
dry-inflector (0.1.2)
|
||||
dry-logic (0.4.2)
|
||||
dry-container (~> 0.2, >= 0.2.6)
|
||||
dry-core (~> 0.2)
|
||||
dry-equalizer (~> 0.2)
|
||||
dry-struct (0.5.1)
|
||||
dry-core (~> 0.4, >= 0.4.3)
|
||||
dry-equalizer (~> 0.2)
|
||||
dry-types (~> 0.13)
|
||||
ice_nine (~> 0.11)
|
||||
dry-types (0.13.3)
|
||||
concurrent-ruby (~> 1.0)
|
||||
dry-container (~> 0.3)
|
||||
dry-core (~> 0.4, >= 0.4.4)
|
||||
dry-equalizer (~> 0.2)
|
||||
dry-inflector (~> 0.1, >= 0.1.2)
|
||||
dry-logic (~> 0.4, >= 0.4.2)
|
||||
email_spec (2.2.0)
|
||||
htmlentities (~> 4.3.3)
|
||||
launchy (~> 2.1)
|
||||
@@ -309,7 +286,6 @@ GEM
|
||||
rails-i18n
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
terminal-table (>= 1.5.1)
|
||||
ice_nine (0.11.2)
|
||||
image_processing (1.12.2)
|
||||
mini_magick (>= 4.9.5, < 5)
|
||||
ruby-vips (>= 2.0.17, < 3)
|
||||
@@ -640,9 +616,6 @@ GEM
|
||||
thread_safe (0.3.6)
|
||||
tilt (2.0.10)
|
||||
tomlrb (1.3.0)
|
||||
translator-text (0.1.0)
|
||||
dry-struct (~> 0.5.0)
|
||||
httparty (~> 0.15)
|
||||
turbolinks (5.2.1)
|
||||
turbolinks-source (~> 5.2)
|
||||
turbolinks-source (5.2.0)
|
||||
@@ -701,6 +674,7 @@ DEPENDENCIES
|
||||
ancestry (~> 4.2.0)
|
||||
audited (~> 5.0.2)
|
||||
autoprefixer-rails (~> 8.2.0)
|
||||
bing_translator (~> 6.2.0)
|
||||
bullet (~> 7.0.3)
|
||||
byebug (~> 11.1.3)
|
||||
cancancan (~> 3.4.0)
|
||||
@@ -785,7 +759,6 @@ DEPENDENCIES
|
||||
spring (~> 2.1.1)
|
||||
spring-commands-rspec (~> 1.0.4)
|
||||
sprockets (~> 4.1.1)
|
||||
translator-text (~> 0.1.0)
|
||||
turbolinks (~> 5.2.1)
|
||||
turnout (~> 2.5.0)
|
||||
uglifier (~> 4.2.0)
|
||||
|
||||
@@ -6,29 +6,32 @@ require "json"
|
||||
class RemoteTranslations::Microsoft::AvailableLocales
|
||||
def self.available_locales
|
||||
daily_cache("locales") do
|
||||
remote_available_locales.map(&:first)
|
||||
remote_available_locales.map { |locale| remote_locale_to_app_locale(locale) }
|
||||
end
|
||||
end
|
||||
|
||||
def self.parse_locale(locale)
|
||||
case locale
|
||||
when :"pt-BR"
|
||||
:pt
|
||||
when :"zh-CN"
|
||||
:"zh-Hans"
|
||||
when :"zh-TW"
|
||||
:"zh-Hant"
|
||||
else
|
||||
locale
|
||||
end
|
||||
def self.app_locale_to_remote_locale(locale)
|
||||
app_locale_to_remote_locale_map[locale] || locale
|
||||
end
|
||||
|
||||
def self.include_locale?(locale)
|
||||
available_locales.include?(parse_locale(locale).to_s)
|
||||
available_locales.include?(locale.to_s)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def self.remote_locale_to_app_locale(locale)
|
||||
app_locale_to_remote_locale_map.invert[locale] || locale
|
||||
end
|
||||
|
||||
def self.app_locale_to_remote_locale_map
|
||||
{
|
||||
"pt-BR" => "pt",
|
||||
"zh-CN" => "zh-Hans",
|
||||
"zh-TW" => "zh-Hant"
|
||||
}
|
||||
end
|
||||
|
||||
def self.remote_available_locales
|
||||
host = "https://api.cognitive.microsofttranslator.com"
|
||||
path = "/languages?api-version=3.0"
|
||||
@@ -44,7 +47,7 @@ class RemoteTranslations::Microsoft::AvailableLocales
|
||||
|
||||
result = response.body.force_encoding("utf-8")
|
||||
|
||||
JSON.parse(result)["translation"]
|
||||
JSON.parse(result)["translation"].map(&:first)
|
||||
end
|
||||
|
||||
def self.daily_cache(key, &block)
|
||||
|
||||
@@ -1,18 +1,11 @@
|
||||
require "translator-text"
|
||||
include RemoteTranslations::Microsoft::SentencesParser
|
||||
|
||||
class RemoteTranslations::Microsoft::Client
|
||||
include SentencesParser
|
||||
CHARACTERS_LIMIT_PER_REQUEST = 5000
|
||||
PREVENTING_TRANSLATION_KEY = "notranslate".freeze
|
||||
|
||||
def initialize
|
||||
api_key = Tenant.current_secrets.microsoft_api_key
|
||||
@client = TranslatorText::Client.new(api_key)
|
||||
end
|
||||
|
||||
def call(fields_values, locale)
|
||||
texts = prepare_texts(fields_values)
|
||||
valid_locale = RemoteTranslations::Microsoft::AvailableLocales.parse_locale(locale)
|
||||
valid_locale = RemoteTranslations::Microsoft::AvailableLocales.app_locale_to_remote_locale(locale)
|
||||
request_translation(texts, valid_locale)
|
||||
end
|
||||
|
||||
@@ -28,12 +21,16 @@ class RemoteTranslations::Microsoft::Client
|
||||
|
||||
private
|
||||
|
||||
def client
|
||||
@client ||= BingTranslator.new(Tenant.current_secrets.microsoft_api_key)
|
||||
end
|
||||
|
||||
def request_translation(texts, locale)
|
||||
response = []
|
||||
split_response = false
|
||||
|
||||
if characters_count(texts) <= CHARACTERS_LIMIT_PER_REQUEST
|
||||
response = @client.translate(texts, to: locale)
|
||||
response = client.translate_array(texts, to: locale)
|
||||
else
|
||||
texts.each do |text|
|
||||
response << translate_text(text, locale)
|
||||
@@ -46,27 +43,26 @@ class RemoteTranslations::Microsoft::Client
|
||||
|
||||
def translate_text(text, locale)
|
||||
fragments_for(text).map do |fragment|
|
||||
@client.translate([fragment], to: locale)
|
||||
client.translate_array([fragment], to: locale)
|
||||
end.flatten
|
||||
end
|
||||
|
||||
def parse_response(response, split_response)
|
||||
response.map do |object|
|
||||
response.map do |translation|
|
||||
if split_response
|
||||
build_translation(object)
|
||||
build_translation(translation)
|
||||
else
|
||||
get_field_value(object)
|
||||
get_field_value(translation)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def build_translation(objects)
|
||||
objects.map { |object| get_field_value(object) }.join
|
||||
def build_translation(translations)
|
||||
translations.map { |translation| get_field_value(translation) }.join
|
||||
end
|
||||
|
||||
def get_field_value(object)
|
||||
text = object.translations[0].text
|
||||
notranslate?(text) ? nil : text
|
||||
def get_field_value(translation)
|
||||
notranslate?(translation) ? nil : translation
|
||||
end
|
||||
|
||||
def prepare_texts(texts)
|
||||
|
||||
@@ -5,7 +5,7 @@ describe Layout::RemoteTranslationsButtonComponent do
|
||||
let(:component) { Layout::RemoteTranslationsButtonComponent.new(translations) }
|
||||
|
||||
before do
|
||||
allow(RemoteTranslations::Microsoft::AvailableLocales).to receive(:available_locales)
|
||||
allow(RemoteTranslations::Microsoft::AvailableLocales).to receive(:remote_available_locales)
|
||||
.and_return(%w[de en es fr pt zh-Hans])
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
require "rails_helper"
|
||||
|
||||
describe RemoteTranslations::Microsoft::AvailableLocales do
|
||||
describe ".available_locales" do
|
||||
it "includes locales with the same format as I18n.available_locales" do
|
||||
allow(RemoteTranslations::Microsoft::AvailableLocales).to receive(:remote_available_locales)
|
||||
.and_return(%w[de en es fr pt zh-Hans])
|
||||
|
||||
available_locales = RemoteTranslations::Microsoft::AvailableLocales.available_locales
|
||||
expect(available_locales).to eq %w[de en es fr pt-BR zh-CN]
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -6,9 +6,9 @@ describe RemoteTranslations::Microsoft::Client do
|
||||
describe "#call" do
|
||||
context "when characters from request are less than the characters limit" do
|
||||
it "response has the expected result" do
|
||||
response = create_response("Nuevo título", "Nueva descripción")
|
||||
response = ["Nuevo título", "Nueva descripción"]
|
||||
|
||||
expect_any_instance_of(TranslatorText::Client).to receive(:translate).and_return(response)
|
||||
expect_any_instance_of(BingTranslator).to receive(:translate_array).and_return(response)
|
||||
|
||||
result = client.call(["New title", "New description"], :es)
|
||||
|
||||
@@ -16,9 +16,9 @@ describe RemoteTranslations::Microsoft::Client do
|
||||
end
|
||||
|
||||
it "response nil has the expected result when request has nil value" do
|
||||
response = create_response("Notranslate", "Nueva descripción")
|
||||
response = ["Notranslate", "Nueva descripción"]
|
||||
|
||||
expect_any_instance_of(TranslatorText::Client).to receive(:translate).and_return(response)
|
||||
expect_any_instance_of(BingTranslator).to receive(:translate_array).and_return(response)
|
||||
|
||||
result = client.call([nil, "New description"], :es)
|
||||
|
||||
@@ -34,15 +34,15 @@ describe RemoteTranslations::Microsoft::Client do
|
||||
|
||||
translated_text_es = Faker::Lorem.characters(number: 11)
|
||||
another_translated_text_es = Faker::Lorem.characters(number: 11)
|
||||
response_text = create_response(translated_text_es)
|
||||
response_another_text = create_response(another_translated_text_es)
|
||||
response_text = [translated_text_es]
|
||||
response_another_text = [another_translated_text_es]
|
||||
|
||||
expect_any_instance_of(TranslatorText::Client).to receive(:translate).exactly(1)
|
||||
.times
|
||||
.and_return(response_text)
|
||||
expect_any_instance_of(TranslatorText::Client).to receive(:translate).exactly(1)
|
||||
.times
|
||||
.and_return(response_another_text)
|
||||
expect_any_instance_of(BingTranslator).to receive(:translate_array).exactly(1)
|
||||
.times
|
||||
.and_return(response_text)
|
||||
expect_any_instance_of(BingTranslator).to receive(:translate_array).exactly(1)
|
||||
.times
|
||||
.and_return(response_another_text)
|
||||
|
||||
result = client.call([text_en, another_text_en], :es)
|
||||
|
||||
@@ -58,14 +58,14 @@ describe RemoteTranslations::Microsoft::Client do
|
||||
start_translated_text_es = Faker::Lorem.characters(number: 10) + " "
|
||||
end_translated_text_es = Faker::Lorem.characters(number: 10)
|
||||
translated_text_es = start_translated_text_es + end_translated_text_es
|
||||
response_start_text = create_response(start_translated_text_es)
|
||||
response_end_text = create_response(end_translated_text_es)
|
||||
response_start_text = [start_translated_text_es]
|
||||
response_end_text = [end_translated_text_es]
|
||||
|
||||
expect_any_instance_of(TranslatorText::Client).to receive(:translate).with([start_text_en], to: :es)
|
||||
expect_any_instance_of(BingTranslator).to receive(:translate_array).with([start_text_en], to: :es)
|
||||
.exactly(1)
|
||||
.times
|
||||
.and_return(response_start_text)
|
||||
expect_any_instance_of(TranslatorText::Client).to receive(:translate).with([end_text_en], to: :es)
|
||||
expect_any_instance_of(BingTranslator).to receive(:translate_array).with([end_text_en], to: :es)
|
||||
.exactly(1)
|
||||
.times
|
||||
.and_return(response_end_text)
|
||||
@@ -77,14 +77,14 @@ describe RemoteTranslations::Microsoft::Client do
|
||||
another_start_translated_text_es = Faker::Lorem.characters(number: 12) + "."
|
||||
another_end_translated_text_es = Faker::Lorem.characters(number: 12)
|
||||
another_translated_text_es = another_start_translated_text_es + another_end_translated_text_es
|
||||
response_another_start_text = create_response(another_start_translated_text_es)
|
||||
response_another_end_text = create_response(another_end_translated_text_es)
|
||||
response_another_start_text = [another_start_translated_text_es]
|
||||
response_another_end_text = [another_end_translated_text_es]
|
||||
|
||||
expect_any_instance_of(TranslatorText::Client).to receive(:translate).with([start_another_text_en], to: :es)
|
||||
expect_any_instance_of(BingTranslator).to receive(:translate_array).with([start_another_text_en], to: :es)
|
||||
.exactly(1)
|
||||
.times
|
||||
.and_return(response_another_start_text)
|
||||
expect_any_instance_of(TranslatorText::Client).to receive(:translate).with([end_another_text_en], to: :es)
|
||||
expect_any_instance_of(BingTranslator).to receive(:translate_array).with([end_another_text_en], to: :es)
|
||||
.exactly(1)
|
||||
.times
|
||||
.and_return(response_another_end_text)
|
||||
@@ -146,16 +146,3 @@ describe RemoteTranslations::Microsoft::Client do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def create_response(*args)
|
||||
# response = [#<TranslatorText::Types::TranslationResult translations=[#<TranslatorText::Types::Translation text="Nuevo título" to=:es>] detectedLanguage={"language"=>"en", "score"=>1.0}>, #<TranslatorText::Types::TranslationResult translations=[#<TranslatorText::Types::Translation text="Nueva descripción" to=:es>] detectedLanguage={"language"=>"en", "score"=>1.0}>]
|
||||
translations = Struct.new(:translations)
|
||||
text = Struct.new(:text)
|
||||
response = []
|
||||
|
||||
args.each do |text_to_response|
|
||||
response << translations.new([text.new(text_to_response)])
|
||||
end
|
||||
|
||||
response
|
||||
end
|
||||
|
||||
@@ -49,6 +49,16 @@ describe RemoteTranslation, :remote_translations do
|
||||
expect(remote_translation).to be_valid
|
||||
end
|
||||
|
||||
it "is valid with a locale that uses a different name in the remote service" do
|
||||
allow(RemoteTranslations::Microsoft::AvailableLocales).to receive(:available_locales).and_call_original
|
||||
allow(RemoteTranslations::Microsoft::AvailableLocales).to receive(:remote_available_locales)
|
||||
.and_return(["pt"])
|
||||
|
||||
remote_translation.locale = :"pt-BR"
|
||||
|
||||
expect(remote_translation).to be_valid
|
||||
end
|
||||
|
||||
describe "#enqueue_remote_translation", :delay_jobs do
|
||||
it "after create enqueue Delayed Job" do
|
||||
expect { remote_translation.save }.to change { Delayed::Job.count }.by(1)
|
||||
|
||||
Reference in New Issue
Block a user