translatomatic 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitattributes +19 -0
- data/.gitignore +0 -0
- data/.travis.yml +7 -7
- data/.yardopts +9 -0
- data/Gemfile +4 -4
- data/Guardfile +0 -0
- data/README.de.md +61 -16
- data/README.es.md +60 -15
- data/README.fr.md +61 -16
- data/README.it.md +60 -15
- data/README.ja.md +59 -14
- data/README.ko.md +137 -0
- data/README.md +58 -13
- data/README.ms.md +137 -0
- data/README.pt.md +137 -0
- data/README.ru.md +137 -0
- data/README.sv.md +137 -0
- data/README.zh.md +137 -0
- data/bin/setup +8 -8
- data/bin/translatomatic +6 -6
- data/bin/travis +1 -1
- data/config/locales/translatomatic/de.yml +104 -0
- data/config/locales/translatomatic/en.yml +101 -0
- data/config/locales/translatomatic/es.yml +105 -0
- data/config/locales/translatomatic/fr.yml +105 -0
- data/config/locales/translatomatic/it.yml +103 -0
- data/config/locales/translatomatic/ja.yml +102 -0
- data/config/locales/translatomatic/ko.yml +101 -0
- data/config/locales/translatomatic/ms.yml +103 -0
- data/config/locales/translatomatic/pt.yml +105 -0
- data/config/locales/translatomatic/ru.yml +103 -0
- data/config/locales/translatomatic/sv.yml +103 -0
- data/config/locales/translatomatic/zh.yml +102 -0
- data/db/migrate/201712170000_initial.rb +2 -1
- data/lib/translatomatic/cli/base.rb +73 -0
- data/lib/translatomatic/cli/common_options.rb +14 -0
- data/lib/translatomatic/cli/config.rb +81 -0
- data/lib/translatomatic/cli/database.rb +29 -0
- data/lib/translatomatic/cli/main.rb +112 -0
- data/lib/translatomatic/cli/translate.rb +146 -0
- data/lib/translatomatic/cli.rb +8 -216
- data/lib/translatomatic/config.rb +143 -0
- data/lib/translatomatic/converter.rb +196 -149
- data/lib/translatomatic/converter_stats.rb +18 -14
- data/lib/translatomatic/database.rb +35 -37
- data/lib/translatomatic/escaped_unicode.rb +1 -1
- data/lib/translatomatic/extractor/base.rb +2 -0
- data/lib/translatomatic/extractor/ruby.rb +1 -0
- data/lib/translatomatic/extractor.rb +1 -0
- data/lib/translatomatic/http_request.rb +43 -14
- data/lib/translatomatic/locale.rb +28 -4
- data/lib/translatomatic/logger.rb +21 -13
- data/lib/translatomatic/model/locale.rb +5 -1
- data/lib/translatomatic/model/text.rb +2 -0
- data/lib/translatomatic/model.rb +1 -0
- data/lib/translatomatic/option.rb +75 -10
- data/lib/translatomatic/progress_updater.rb +7 -3
- data/lib/translatomatic/resource_file/base.rb +41 -18
- data/lib/translatomatic/resource_file/html.rb +11 -14
- data/lib/translatomatic/resource_file/markdown.rb +13 -12
- data/lib/translatomatic/resource_file/plist.rb +3 -14
- data/lib/translatomatic/resource_file/properties.rb +21 -3
- data/lib/translatomatic/resource_file/resw.rb +1 -0
- data/lib/translatomatic/resource_file/text.rb +1 -0
- data/lib/translatomatic/resource_file/xcode_strings.rb +23 -14
- data/lib/translatomatic/resource_file/xml.rb +34 -22
- data/lib/translatomatic/resource_file/yaml.rb +39 -5
- data/lib/translatomatic/resource_file.rb +7 -5
- data/lib/translatomatic/string.rb +40 -12
- data/lib/translatomatic/tmx/document.rb +11 -12
- data/lib/translatomatic/tmx/translation_unit.rb +5 -1
- data/lib/translatomatic/tmx.rb +2 -0
- data/lib/translatomatic/translation.rb +30 -0
- data/lib/translatomatic/translation_result.rb +45 -45
- data/lib/translatomatic/translator/base.rb +128 -83
- data/lib/translatomatic/translator/frengly.rb +62 -57
- data/lib/translatomatic/translator/google.rb +35 -31
- data/lib/translatomatic/translator/microsoft.rb +41 -33
- data/lib/translatomatic/translator/my_memory.rb +68 -64
- data/lib/translatomatic/translator/yandex.rb +56 -39
- data/lib/translatomatic/translator.rb +99 -63
- data/lib/translatomatic/util.rb +31 -1
- data/lib/translatomatic/version.rb +4 -1
- data/lib/translatomatic.rb +17 -0
- data/translatomatic.gemspec +5 -4
- metadata +56 -16
@@ -1,11 +1,14 @@
|
|
1
1
|
require 'set'
|
2
2
|
|
3
|
-
module Translatomatic
|
3
|
+
module Translatomatic
|
4
|
+
# Stores results of a translation
|
4
5
|
class TranslationResult
|
6
|
+
|
7
|
+
# @return [Translatomatic::ResourceFile::Base] The resource file
|
8
|
+
attr_reader :file
|
5
9
|
|
6
|
-
# Translation results
|
7
10
|
# @return [Hash<String,String>] Translation results
|
8
|
-
attr_reader :properties
|
11
|
+
attr_reader :properties
|
9
12
|
|
10
13
|
# @return [Locale] The locale of the original strings
|
11
14
|
attr_reader :from_locale
|
@@ -17,70 +20,67 @@ module Translatomatic
|
|
17
20
|
attr_reader :untranslated
|
18
21
|
|
19
22
|
# Create a translation result
|
20
|
-
# @param [
|
21
|
-
# @param [Locale]
|
22
|
-
|
23
|
-
|
23
|
+
# @param file [Translatomatic::ResourceFile::Base] A resource file
|
24
|
+
# @param to_locale [Locale] The target locale
|
25
|
+
def initialize(file, to_locale)
|
26
|
+
@file = file
|
24
27
|
@value_to_keys = {}
|
25
28
|
@untranslated = Set.new
|
26
|
-
@from_locale =
|
27
|
-
@to_locale = to_locale
|
28
|
-
|
29
|
-
# duplicate strings
|
30
|
-
@properties = properties.transform_values { |i| i.dup }
|
31
|
-
|
32
|
-
properties.each do |key, value|
|
33
|
-
# split property value into sentences
|
34
|
-
string = string(value, from_locale)
|
29
|
+
@from_locale = file.locale
|
30
|
+
@to_locale = to_locale
|
31
|
+
|
32
|
+
# duplicate strings
|
33
|
+
@properties = file.properties.transform_values { |i| i.dup }
|
34
|
+
|
35
|
+
@properties.each do |key, value|
|
36
|
+
# split property value into sentences
|
37
|
+
string = string(value, from_locale)
|
35
38
|
string.sentences.each do |sentence|
|
36
39
|
@untranslated << sentence
|
37
40
|
keylist = (@value_to_keys[sentence.to_s] ||= [])
|
38
|
-
keylist << key
|
41
|
+
keylist << key
|
39
42
|
end
|
40
43
|
end
|
41
44
|
end
|
42
45
|
|
43
|
-
# Update result with a list of translated strings.
|
44
|
-
# @param [Array<
|
45
|
-
# @param [Array<String>] translated Translated strings
|
46
|
+
# Update result with a list of translated strings.
|
47
|
+
# @param translations [Array<Translatomatic::Translation>] Translations
|
46
48
|
# @return [void]
|
47
|
-
def update_strings(
|
48
|
-
|
49
|
-
|
50
|
-
# create list of [from, to] text conversions
|
51
|
-
conversions = []
|
52
|
-
original.zip(translated).each do |text1, text2|
|
53
|
-
conversions << [text1, text2]
|
54
|
-
end
|
55
|
-
|
56
|
-
# sort conversion list by largest offset first so that we replace
|
49
|
+
def update_strings(translations)
|
50
|
+
# sort translation list by largest offset first so that we replace
|
57
51
|
# from the end of the string to the front, so substring offsets
|
58
52
|
# are correct in the target string.
|
59
|
-
conversions.sort_by! do |t1, t2|
|
60
|
-
t1.respond_to?(:offset) ? -t1.offset : 0
|
61
|
-
end
|
62
53
|
|
63
|
-
|
64
|
-
|
54
|
+
#translations.sort_by! do |translation|
|
55
|
+
# t1 = translation.original
|
56
|
+
# t1.respond_to?(:offset) ? -t1.offset : 0
|
57
|
+
#end
|
58
|
+
translations.sort_by! { |t| -t.original.offset }
|
59
|
+
|
60
|
+
translations.each do |translation|
|
61
|
+
update(translation.original, translation.result)
|
65
62
|
end
|
66
|
-
end
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
67
66
|
|
68
|
-
private
|
69
|
-
|
70
67
|
include Translatomatic::Util
|
71
68
|
|
72
69
|
def update(original, translated)
|
73
70
|
keys = @value_to_keys[original.to_s]
|
74
|
-
raise "no key mapping for text '#{original}'" unless keys
|
75
|
-
keys.each do |key|
|
71
|
+
raise "no key mapping for text '#{original}'" unless keys
|
72
|
+
keys.each do |key|
|
73
|
+
#value = @properties[key]
|
76
74
|
if original.kind_of?(Translatomatic::String) && original.substring?
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
75
|
+
#log.debug("#{value[original.offset, original.length]} -> #{translated}")
|
76
|
+
@properties[key][original.offset, original.length] = translated
|
77
|
+
else
|
78
|
+
#log.debug("#{key} -> #{translated}")
|
79
|
+
@properties[key] = translated
|
80
|
+
end
|
81
81
|
end
|
82
82
|
|
83
|
-
@untranslated.delete(original)
|
83
|
+
@untranslated.delete(original) unless translated.nil?
|
84
84
|
end
|
85
85
|
end
|
86
86
|
end
|
@@ -1,83 +1,128 @@
|
|
1
|
-
require 'bing_translator'
|
2
|
-
|
3
|
-
module Translatomatic
|
4
|
-
module Translator
|
5
|
-
|
6
|
-
class
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
#
|
32
|
-
# @
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
from
|
39
|
-
|
40
|
-
|
41
|
-
translated
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
#
|
51
|
-
# opening a http connection to the given url and calling
|
52
|
-
# fetch_translation() on each string.
|
53
|
-
#
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
1
|
+
require 'bing_translator'
|
2
|
+
|
3
|
+
module Translatomatic
|
4
|
+
module Translator
|
5
|
+
|
6
|
+
# Base class for interfaces to translation APIs
|
7
|
+
# @abstract
|
8
|
+
class Base
|
9
|
+
include Translatomatic::DefineOptions
|
10
|
+
|
11
|
+
# Listener for translation events
|
12
|
+
attr_accessor :listener
|
13
|
+
|
14
|
+
def initialize(options = {})
|
15
|
+
@listener = options[:listener]
|
16
|
+
end
|
17
|
+
|
18
|
+
# @return [String] The name of this translator.
|
19
|
+
def name
|
20
|
+
self.class.name.demodulize
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [Array<String>] A list of languages supported by this translator.
|
24
|
+
def languages
|
25
|
+
[]
|
26
|
+
end
|
27
|
+
|
28
|
+
# Translate strings from one locale to another
|
29
|
+
# @param strings [Array<String>] A list of strings to translate.
|
30
|
+
# @param from [String, Translatomatic::Locale] The locale of the given strings.
|
31
|
+
# @param to [String, Translatomatic::Locale] The locale to translate to.
|
32
|
+
# @return [Array<String>] Translated strings
|
33
|
+
def translate(strings, from, to)
|
34
|
+
@updated_listener = false
|
35
|
+
strings = [strings] unless strings.kind_of?(Array)
|
36
|
+
from = locale(from)
|
37
|
+
to = locale(to)
|
38
|
+
return strings if from.language == to.language
|
39
|
+
translated = perform_translate(strings, from, to)
|
40
|
+
update_translated(translated) unless @updated_listener
|
41
|
+
translated
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
include Translatomatic::Util
|
47
|
+
|
48
|
+
TRANSLATION_RETRIES = 3
|
49
|
+
|
50
|
+
# Fetch translations for the given strings, one at a time, by
|
51
|
+
# opening a http connection to the given url and calling
|
52
|
+
# fetch_translation() on each string. Error handling and recovery
|
53
|
+
# is performed by this method.
|
54
|
+
# (subclass must implement fetch_translation if this method is used)
|
55
|
+
def perform_fetch_translations(url, strings, from, to)
|
56
|
+
translated = []
|
57
|
+
untranslated = strings.dup
|
58
|
+
request = Translatomatic::HTTPRequest.new(url)
|
59
|
+
|
60
|
+
while !untranslated.empty? # request start block
|
61
|
+
fail_count = 0 # number of consecutive translation failures
|
62
|
+
|
63
|
+
request.start do |http|
|
64
|
+
while !untranslated.empty?
|
65
|
+
# get next string to translate
|
66
|
+
string = untranslated[0]
|
67
|
+
begin
|
68
|
+
# fetch translation
|
69
|
+
result = fetch_translation(request, string, from, to)
|
70
|
+
|
71
|
+
# successful translation
|
72
|
+
fail_count = 0 # reset fail count
|
73
|
+
translated << result
|
74
|
+
update_translated(result)
|
75
|
+
untranslated.shift
|
76
|
+
|
77
|
+
rescue Exception => e
|
78
|
+
# translation error
|
79
|
+
log.error(e)
|
80
|
+
fail_count += 1
|
81
|
+
if fail_count >= TRANSLATION_RETRIES
|
82
|
+
raise e # re-raise exception
|
83
|
+
else
|
84
|
+
# need to restart http connection
|
85
|
+
# break back out to request.start block
|
86
|
+
break
|
87
|
+
end
|
88
|
+
end # exception
|
89
|
+
end # while untranslated
|
90
|
+
end # request.start
|
91
|
+
end # while untranslated
|
92
|
+
|
93
|
+
translated
|
94
|
+
end
|
95
|
+
|
96
|
+
def fetch_translation(request, strings, from, to)
|
97
|
+
raise "subclass must implement fetch_translation"
|
98
|
+
end
|
99
|
+
|
100
|
+
def update_translated(texts)
|
101
|
+
texts = [texts] unless texts.kind_of?(Array)
|
102
|
+
@updated_listener = true
|
103
|
+
@listener.translated_texts(texts) if @listener
|
104
|
+
end
|
105
|
+
|
106
|
+
def perform_translate(strings, from, to)
|
107
|
+
raise "subclass must implement perform_translate"
|
108
|
+
end
|
109
|
+
|
110
|
+
# Attempt to run a block of code up to retries times.
|
111
|
+
# Reraises the exception if the block fails retries times.
|
112
|
+
# @param retries [Number] The maximum number of times to run
|
113
|
+
# @return [Object] the return value of the block
|
114
|
+
def attempt_with_retries(retries)
|
115
|
+
fail_count = 0
|
116
|
+
begin
|
117
|
+
yield
|
118
|
+
rescue Exception => e
|
119
|
+
log.error(e.message)
|
120
|
+
fail_count += 1
|
121
|
+
retry if fail_count < retries
|
122
|
+
raise e
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -1,57 +1,62 @@
|
|
1
|
-
require 'net/http'
|
2
|
-
|
3
|
-
module Translatomatic
|
4
|
-
module Translator
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module Translatomatic
|
4
|
+
module Translator
|
5
|
+
|
6
|
+
# Interface to the Frengly translation API
|
7
|
+
# @see http://www.frengly.com/api
|
8
|
+
class Frengly < Base
|
9
|
+
|
10
|
+
define_options({
|
11
|
+
name: :frengly_api_key, use_env: true,
|
12
|
+
desc: t("translator.frengly_api_key"),
|
13
|
+
},
|
14
|
+
{ name: :frengly_email, use_env: true,
|
15
|
+
desc: t("translator.email_address")
|
16
|
+
},
|
17
|
+
{ name: :frengly_password, use_env: true,
|
18
|
+
desc: t("translator.password")
|
19
|
+
})
|
20
|
+
|
21
|
+
# Create a new Frengly translator instance
|
22
|
+
def initialize(options = {})
|
23
|
+
super(options)
|
24
|
+
@key = options[:frengly_api_key] || ENV["FRENGLY_API_KEY"] # optional
|
25
|
+
@email = options[:frengly_email]
|
26
|
+
@password = options[:frengly_password]
|
27
|
+
raise t("translator.email_required") unless @email
|
28
|
+
raise t("translator.password_required") unless @password
|
29
|
+
end
|
30
|
+
|
31
|
+
# (see Translatomatic::Translator::Base#languages)
|
32
|
+
def languages
|
33
|
+
['en','fr','de','es','pt','it','nl','tl','fi','el','iw','pl','ru','sv']
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
URL = 'http://frengly.com/frengly/data/translateREST'
|
39
|
+
|
40
|
+
def perform_translate(strings, from, to)
|
41
|
+
perform_fetch_translations(URL, strings, from, to)
|
42
|
+
end
|
43
|
+
|
44
|
+
def fetch_translation(request, string, from, to)
|
45
|
+
body = {
|
46
|
+
src: from.language,
|
47
|
+
dest: to.language,
|
48
|
+
text: string,
|
49
|
+
email: @email,
|
50
|
+
password: @password,
|
51
|
+
premiumkey: @key
|
52
|
+
}.to_json
|
53
|
+
|
54
|
+
# TODO: work out what the response looks like
|
55
|
+
response = request.post(body, content_type: 'application/json')
|
56
|
+
data = JSON.parse(response.body)
|
57
|
+
data['text']
|
58
|
+
end
|
59
|
+
|
60
|
+
end # class
|
61
|
+
end # module
|
62
|
+
end
|
@@ -1,31 +1,35 @@
|
|
1
|
-
module Translatomatic
|
2
|
-
module Translator
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
end
|
1
|
+
module Translatomatic
|
2
|
+
module Translator
|
3
|
+
|
4
|
+
# Interface to the Google translation API
|
5
|
+
# @see https://cloud.google.com/translate/
|
6
|
+
class Google < Base
|
7
|
+
|
8
|
+
define_options(name: :google_api_key,
|
9
|
+
desc: t("translator.google_api_key"), use_env: true
|
10
|
+
)
|
11
|
+
|
12
|
+
# Create a new Google translator instance
|
13
|
+
def initialize(options = {})
|
14
|
+
super(options)
|
15
|
+
key = options[:google_api_key] || ENV["GOOGLE_API_KEY"]
|
16
|
+
raise t("translator.google_key_required") if key.nil?
|
17
|
+
EasyTranslate.api_key = key
|
18
|
+
end
|
19
|
+
|
20
|
+
# (see Translatomatic::Translator::Base#languages)
|
21
|
+
def languages
|
22
|
+
EasyTranslate::LANGUAGES.keys
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def perform_translate(strings, from, to)
|
28
|
+
attempt_with_retries(3) do
|
29
|
+
EasyTranslate.translate(strings, from: from.language, to: to.language)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end # class
|
34
|
+
end # module
|
35
|
+
end
|
@@ -1,33 +1,41 @@
|
|
1
|
-
require 'bing_translator'
|
2
|
-
|
3
|
-
module Translatomatic
|
4
|
-
module Translator
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
#
|
23
|
-
#
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
1
|
+
require 'bing_translator'
|
2
|
+
|
3
|
+
module Translatomatic
|
4
|
+
module Translator
|
5
|
+
|
6
|
+
# Interface to the Microsoft translation API
|
7
|
+
# @see https://www.microsoft.com/en-us/translator/translatorapi.aspx
|
8
|
+
class Microsoft < Base
|
9
|
+
|
10
|
+
define_options({
|
11
|
+
name: :microsoft_api_key, desc: t("translator.microsoft_api_key"), use_env: true
|
12
|
+
})
|
13
|
+
|
14
|
+
# Create a new Microsoft translator instance
|
15
|
+
def initialize(options = {})
|
16
|
+
super(options)
|
17
|
+
key = options[:microsoft_api_key] || ENV["MICROSOFT_API_KEY"]
|
18
|
+
raise t("translator.microsoft_key_required") if key.nil?
|
19
|
+
@impl = BingTranslator.new(key)
|
20
|
+
end
|
21
|
+
|
22
|
+
# TODO: implement language list
|
23
|
+
# (see Translatomatic::Translator::Base#languages)
|
24
|
+
#def languages
|
25
|
+
#end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def perform_translate(strings, from, to)
|
30
|
+
attempt_with_retries(3) do
|
31
|
+
translations = @impl.translate_array(strings,
|
32
|
+
from: from.language,
|
33
|
+
to: to.language
|
34
|
+
)
|
35
|
+
translations.collect { |i| i.to_s }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|