translatomatic 0.1.3 → 0.2.0
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 +5 -5
- data/.gitattributes +20 -20
- data/.gitignore +19 -15
- data/.rspec +3 -3
- data/.rubocop.yml +28 -0
- data/.translatomatic/config.yml +4 -0
- data/.travis.yml +4 -6
- data/.yardopts +9 -9
- data/Gemfile +8 -4
- data/Guardfile +4 -5
- data/README.de.md +55 -50
- data/README.en.md +177 -0
- data/README.es.md +53 -48
- data/README.fr.md +53 -48
- data/README.it.md +54 -49
- data/README.ja.md +63 -58
- data/README.ko.md +59 -54
- data/README.md +17 -13
- data/README.ms.md +50 -45
- data/README.pt.md +54 -49
- data/README.ru.md +57 -52
- data/README.sv.md +51 -46
- data/README.zh.md +60 -55
- data/Rakefile +3 -3
- data/TODO.txt +6 -0
- data/bin/console +3 -3
- data/bin/translatomatic +4 -2
- data/config/i18n-tasks.yml +130 -0
- data/config/locales/translatomatic/de.yml +141 -99
- data/config/locales/translatomatic/en.yml +129 -89
- data/config/locales/translatomatic/es.yml +136 -99
- data/config/locales/translatomatic/fr.yml +139 -100
- data/config/locales/translatomatic/it.yml +135 -97
- data/config/locales/translatomatic/ja.yml +137 -98
- data/config/locales/translatomatic/ko.yml +138 -98
- data/config/locales/translatomatic/ms.yml +138 -100
- data/config/locales/translatomatic/pt.yml +137 -101
- data/config/locales/translatomatic/ru.yml +136 -98
- data/config/locales/translatomatic/sv.yml +134 -96
- data/config/locales/translatomatic/zh.yml +136 -97
- data/db/migrate/201712170000_initial.rb +2 -3
- data/lib/translatomatic.rb +40 -25
- data/lib/translatomatic/cli.rb +5 -1
- data/lib/translatomatic/cli/base.rb +61 -58
- data/lib/translatomatic/cli/common_options.rb +14 -11
- data/lib/translatomatic/cli/config.rb +96 -91
- data/lib/translatomatic/cli/database.rb +85 -23
- data/lib/translatomatic/cli/main.rb +158 -104
- data/lib/translatomatic/cli/thor.rb +29 -0
- data/lib/translatomatic/cli/translate.rb +134 -157
- data/lib/translatomatic/config.rb +10 -301
- data/lib/translatomatic/config/display.rb +78 -0
- data/lib/translatomatic/config/files.rb +60 -0
- data/lib/translatomatic/config/location_settings.rb +133 -0
- data/lib/translatomatic/config/options.rb +68 -0
- data/lib/translatomatic/config/selector.rb +127 -0
- data/lib/translatomatic/config/settings.rb +148 -0
- data/lib/translatomatic/converter.rb +40 -28
- data/lib/translatomatic/database.rb +127 -110
- data/lib/translatomatic/define_options.rb +4 -5
- data/lib/translatomatic/escaped_unicode.rb +86 -76
- data/lib/translatomatic/extractor.rb +5 -2
- data/lib/translatomatic/extractor/base.rb +12 -12
- data/lib/translatomatic/extractor/ruby.rb +7 -6
- data/lib/translatomatic/file_translator.rb +101 -244
- data/lib/translatomatic/flattenation.rb +39 -0
- data/lib/translatomatic/http.rb +13 -0
- data/lib/translatomatic/http/client.rb +144 -0
- data/lib/translatomatic/http/exception.rb +43 -0
- data/lib/translatomatic/http/file_param.rb +27 -0
- data/lib/translatomatic/http/param.rb +37 -0
- data/lib/translatomatic/http/request.rb +91 -0
- data/lib/translatomatic/i18n.rb +43 -0
- data/lib/translatomatic/locale.rb +71 -59
- data/lib/translatomatic/logger.rb +43 -28
- data/lib/translatomatic/metadata.rb +58 -0
- data/lib/translatomatic/model.rb +4 -2
- data/lib/translatomatic/model/locale.rb +5 -5
- data/lib/translatomatic/model/text.rb +5 -5
- data/lib/translatomatic/option.rb +57 -34
- data/lib/translatomatic/path_utils.rb +126 -0
- data/lib/translatomatic/progress_updater.rb +13 -16
- data/lib/translatomatic/provider.rb +101 -0
- data/lib/translatomatic/provider/base.rb +136 -0
- data/lib/translatomatic/provider/frengly.rb +55 -0
- data/lib/translatomatic/provider/google.rb +78 -0
- data/lib/translatomatic/provider/google_web.rb +50 -0
- data/lib/translatomatic/provider/microsoft.rb +144 -0
- data/lib/translatomatic/provider/my_memory.rb +75 -0
- data/lib/translatomatic/provider/yandex.rb +61 -0
- data/lib/translatomatic/resource_file.rb +59 -53
- data/lib/translatomatic/resource_file/base.rb +171 -237
- data/lib/translatomatic/resource_file/csv.rb +176 -24
- data/lib/translatomatic/resource_file/html.rb +21 -42
- data/lib/translatomatic/resource_file/key_value_support.rb +117 -0
- data/lib/translatomatic/resource_file/markdown.rb +36 -38
- data/lib/translatomatic/resource_file/plist.rb +121 -126
- data/lib/translatomatic/resource_file/po.rb +104 -82
- data/lib/translatomatic/resource_file/properties.rb +48 -77
- data/lib/translatomatic/resource_file/properties.treetop +87 -0
- data/lib/translatomatic/resource_file/resw.rb +56 -41
- data/lib/translatomatic/resource_file/subtitle.rb +86 -54
- data/lib/translatomatic/resource_file/text.rb +18 -18
- data/lib/translatomatic/resource_file/xcode_strings.rb +32 -63
- data/lib/translatomatic/resource_file/xcode_strings.treetop +85 -0
- data/lib/translatomatic/resource_file/xml.rb +94 -81
- data/lib/translatomatic/resource_file/yaml.rb +54 -68
- data/lib/translatomatic/retry_executor.rb +37 -0
- data/lib/translatomatic/slurp.rb +32 -0
- data/lib/translatomatic/string_batcher.rb +50 -0
- data/lib/translatomatic/string_escaping.rb +61 -0
- data/lib/translatomatic/text.rb +263 -0
- data/lib/translatomatic/text_collection.rb +66 -0
- data/lib/translatomatic/tmx.rb +5 -3
- data/lib/translatomatic/tmx/document.rb +107 -82
- data/lib/translatomatic/tmx/translation_unit.rb +19 -18
- data/lib/translatomatic/translation.rb +8 -28
- data/lib/translatomatic/translation/collection.rb +199 -0
- data/lib/translatomatic/translation/fetcher.rb +123 -0
- data/lib/translatomatic/translation/munging.rb +112 -0
- data/lib/translatomatic/translation/result.rb +50 -0
- data/lib/translatomatic/translation/sharer.rb +32 -0
- data/lib/translatomatic/translation/stats.rb +44 -0
- data/lib/translatomatic/translator.rb +91 -88
- data/lib/translatomatic/type_cast.rb +63 -0
- data/lib/translatomatic/util.rb +37 -33
- data/lib/translatomatic/version.rb +2 -2
- data/translatomatic.gemspec +57 -46
- metadata +136 -59
- data/lib/translatomatic/http_request.rb +0 -162
- data/lib/translatomatic/string.rb +0 -188
- data/lib/translatomatic/translation_result.rb +0 -86
- data/lib/translatomatic/translation_stats.rb +0 -31
- data/lib/translatomatic/translator/base.rb +0 -128
- data/lib/translatomatic/translator/frengly.rb +0 -62
- data/lib/translatomatic/translator/google.rb +0 -37
- data/lib/translatomatic/translator/microsoft.rb +0 -41
- data/lib/translatomatic/translator/my_memory.rb +0 -68
- data/lib/translatomatic/translator/yandex.rb +0 -56
@@ -1,128 +0,0 @@
|
|
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
|
-
fail_count = 0 # number of consecutive translation failures
|
60
|
-
|
61
|
-
while !untranslated.empty? # request start block
|
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,62 +0,0 @@
|
|
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,37 +0,0 @@
|
|
1
|
-
require 'easy_translate'
|
2
|
-
|
3
|
-
module Translatomatic
|
4
|
-
module Translator
|
5
|
-
|
6
|
-
# Interface to the Google translation API
|
7
|
-
# @see https://cloud.google.com/translate/
|
8
|
-
class Google < Base
|
9
|
-
|
10
|
-
define_options(name: :google_api_key,
|
11
|
-
desc: t("translator.google_api_key"), use_env: true
|
12
|
-
)
|
13
|
-
|
14
|
-
# Create a new Google translator instance
|
15
|
-
def initialize(options = {})
|
16
|
-
super(options)
|
17
|
-
key = options[:google_api_key] || ENV["GOOGLE_API_KEY"]
|
18
|
-
raise t("translator.google_key_required") if key.nil?
|
19
|
-
EasyTranslate.api_key = key
|
20
|
-
end
|
21
|
-
|
22
|
-
# (see Translatomatic::Translator::Base#languages)
|
23
|
-
def languages
|
24
|
-
EasyTranslate::LANGUAGES.keys
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def perform_translate(strings, from, to)
|
30
|
-
attempt_with_retries(3) do
|
31
|
-
EasyTranslate.translate(strings, from: from.language, to: to.language)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
end # class
|
36
|
-
end # module
|
37
|
-
end
|
@@ -1,41 +0,0 @@
|
|
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
|
@@ -1,68 +0,0 @@
|
|
1
|
-
require 'bing_translator'
|
2
|
-
|
3
|
-
module Translatomatic
|
4
|
-
module Translator
|
5
|
-
|
6
|
-
# Interface to the MyMemory translation API
|
7
|
-
# @see https://mymemory.translated.net/doc/
|
8
|
-
class MyMemory < Base
|
9
|
-
|
10
|
-
define_options(
|
11
|
-
{ name: :mymemory_api_key, desc: t("translator.mymemory_api_key"), use_env: true },
|
12
|
-
{ name: :mymemory_email, desc: t("translator.email_address"), use_env: true }
|
13
|
-
)
|
14
|
-
|
15
|
-
# Create a new MyMemory translator instance
|
16
|
-
def initialize(options = {})
|
17
|
-
super(options)
|
18
|
-
@key = options[:mymemory_api_key] || ENV["MYMEMORY_API_KEY"]
|
19
|
-
@email = options[:mymemory_email] || ENV["MYMEMORY_EMAIL"]
|
20
|
-
@query_options = {}
|
21
|
-
@query_options.merge!(de: @email) if @email
|
22
|
-
@query_options.merge!(key: @key) if @key
|
23
|
-
end
|
24
|
-
|
25
|
-
# TODO: implement language list
|
26
|
-
# (see Translatomatic::Translator::Base#languages)
|
27
|
-
#def languages
|
28
|
-
#end
|
29
|
-
|
30
|
-
# Upload a set of translations to MyMemory
|
31
|
-
# @param tmx [Translatomatic::TMX::Document] TMX document
|
32
|
-
# @return [void]
|
33
|
-
def upload(tmx)
|
34
|
-
request = Translatomatic::HTTPRequest.new(UPLOAD_URL)
|
35
|
-
request.start do |http|
|
36
|
-
body = [
|
37
|
-
request.file(key: :tmx, filename: "import.tmx",
|
38
|
-
content: tmx.to_xml, mime_type: "application/xml"
|
39
|
-
),
|
40
|
-
request.param(key: :private, value: 0)
|
41
|
-
]
|
42
|
-
response = request.post(body, multipart: true)
|
43
|
-
log.debug(t("translator.share_response",
|
44
|
-
response: response.body.inspect))
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
private
|
49
|
-
|
50
|
-
GET_URL = 'https://api.mymemory.translated.net/get'
|
51
|
-
UPLOAD_URL = 'https://api.mymemory.translated.net/tmx/import'
|
52
|
-
|
53
|
-
def perform_translate(strings, from, to)
|
54
|
-
perform_fetch_translations(GET_URL, strings, from, to)
|
55
|
-
end
|
56
|
-
|
57
|
-
def fetch_translation(request, string, from, to)
|
58
|
-
response = request.get({
|
59
|
-
langpair: from.to_s + "|" + to.to_s,
|
60
|
-
q: string # multiple q strings not supported (tested 20180101)
|
61
|
-
}.merge(@query_options)
|
62
|
-
)
|
63
|
-
data = JSON.parse(response.body)
|
64
|
-
data['responseData']['translatedText']
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
@@ -1,56 +0,0 @@
|
|
1
|
-
module Translatomatic
|
2
|
-
module Translator
|
3
|
-
|
4
|
-
# Interface to the Yandex translation API
|
5
|
-
# @see https://tech.yandex.com/translate/
|
6
|
-
class Yandex < Base
|
7
|
-
|
8
|
-
define_options({
|
9
|
-
name: :yandex_api_key, desc: t("translator.yandex_api_key"), use_env: true
|
10
|
-
})
|
11
|
-
|
12
|
-
# Create a new Yandex translator instance
|
13
|
-
def initialize(options = {})
|
14
|
-
super(options)
|
15
|
-
@api_key = options[:yandex_api_key] || ENV["YANDEX_API_KEY"]
|
16
|
-
raise t("translator.yandex_key_required") if @api_key.nil?
|
17
|
-
end
|
18
|
-
|
19
|
-
# (see Translatomatic::Translator::Base#languages)
|
20
|
-
def languages
|
21
|
-
@languages ||= begin
|
22
|
-
request = Translatomatic::HTTPRequest.new(LANGUAGES_URL)
|
23
|
-
response = request.post(key: @api_key, ui: "en")
|
24
|
-
data = JSON.parse(response.body) || {}
|
25
|
-
langs = data["langs"] || {}
|
26
|
-
langs.keys.flatten.uniq
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
31
|
-
|
32
|
-
TRANSLATE_URL = 'https://translate.yandex.net/api/v1.5/tr.json/translate'
|
33
|
-
LANGUAGES_URL = 'https://translate.yandex.net/api/v1.5/tr.json/getLangs'
|
34
|
-
|
35
|
-
def perform_translate(strings, from, to)
|
36
|
-
attempt_with_retries(3) do
|
37
|
-
fetch_translations(strings, from, to)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def fetch_translations(strings, from, to)
|
42
|
-
request = Translatomatic::HTTPRequest.new(TRANSLATE_URL)
|
43
|
-
body = {
|
44
|
-
key: @api_key,
|
45
|
-
text: strings,
|
46
|
-
lang: from.language + "-" + to.language,
|
47
|
-
format: "plain"
|
48
|
-
}
|
49
|
-
response = request.post(body)
|
50
|
-
data = JSON.parse(response.body)
|
51
|
-
data['text']
|
52
|
-
end
|
53
|
-
|
54
|
-
end # class
|
55
|
-
end # module
|
56
|
-
end
|