translatomatic 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitattributes +1 -0
- data/.gitignore +15 -12
- data/.rspec +3 -3
- data/.travis.yml +32 -50
- data/CODE_OF_CONDUCT.md +74 -74
- data/Gemfile +29 -5
- data/Guardfile +48 -0
- data/LICENSE.txt +21 -21
- data/README.de.md +92 -0
- data/README.es.md +92 -0
- data/README.fr.md +92 -0
- data/README.it.md +92 -0
- data/README.ja.md +92 -0
- data/README.md +96 -74
- data/Rakefile +6 -6
- data/bin/setup +8 -8
- data/bin/translatomatic +6 -6
- data/bin/travis +26 -0
- data/db/database.yml +9 -9
- data/db/migrate/201712170000_initial.rb +24 -23
- data/lib/translatomatic/cli.rb +204 -80
- data/lib/translatomatic/config.rb +12 -26
- data/lib/translatomatic/converter.rb +206 -142
- data/lib/translatomatic/converter_stats.rb +27 -27
- data/lib/translatomatic/database.rb +139 -99
- data/lib/translatomatic/escaped_unicode.rb +90 -90
- data/lib/translatomatic/extractor/base.rb +14 -0
- data/lib/translatomatic/extractor/ruby.rb +5 -0
- data/lib/translatomatic/extractor.rb +4 -0
- data/lib/translatomatic/http_request.rb +133 -0
- data/lib/translatomatic/locale.rb +52 -0
- data/lib/translatomatic/logger.rb +28 -0
- data/lib/translatomatic/model/locale.rb +21 -22
- data/lib/translatomatic/model/text.rb +17 -13
- data/lib/translatomatic/model.rb +4 -4
- data/lib/translatomatic/option.rb +24 -24
- data/lib/translatomatic/progress_updater.rb +15 -0
- data/lib/translatomatic/resource_file/base.rb +169 -137
- data/lib/translatomatic/resource_file/html.rb +46 -28
- data/lib/translatomatic/resource_file/markdown.rb +54 -0
- data/lib/translatomatic/resource_file/plist.rb +30 -29
- data/lib/translatomatic/resource_file/properties.rb +72 -60
- data/lib/translatomatic/resource_file/resw.rb +30 -0
- data/lib/translatomatic/resource_file/text.rb +29 -28
- data/lib/translatomatic/resource_file/xcode_strings.rb +71 -65
- data/lib/translatomatic/resource_file/xml.rb +79 -59
- data/lib/translatomatic/resource_file/yaml.rb +82 -80
- data/lib/translatomatic/resource_file.rb +76 -74
- data/lib/translatomatic/string.rb +160 -0
- data/lib/translatomatic/tmx/document.rb +100 -0
- data/lib/translatomatic/tmx/translation_unit.rb +19 -0
- data/lib/translatomatic/tmx.rb +4 -0
- data/lib/translatomatic/translation_result.rb +75 -57
- data/lib/translatomatic/translator/base.rb +83 -47
- data/lib/translatomatic/translator/frengly.rb +57 -64
- data/lib/translatomatic/translator/google.rb +31 -30
- data/lib/translatomatic/translator/microsoft.rb +33 -32
- data/lib/translatomatic/translator/my_memory.rb +64 -55
- data/lib/translatomatic/translator/yandex.rb +39 -37
- data/lib/translatomatic/translator.rb +63 -63
- data/lib/translatomatic/util.rb +15 -24
- data/lib/translatomatic/version.rb +4 -3
- data/lib/translatomatic.rb +32 -27
- data/translatomatic.gemspec +43 -45
- metadata +52 -18
- data/Gemfile.lock +0 -137
@@ -1,47 +1,83 @@
|
|
1
|
-
require 'bing_translator'
|
2
|
-
|
3
|
-
module Translatomatic
|
4
|
-
module Translator
|
5
|
-
@abstract
|
6
|
-
class Base
|
7
|
-
|
8
|
-
class << self
|
9
|
-
attr_reader :options
|
10
|
-
private
|
11
|
-
include Translatomatic::DefineOptions
|
12
|
-
end
|
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
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
1
|
+
require 'bing_translator'
|
2
|
+
|
3
|
+
module Translatomatic
|
4
|
+
module Translator
|
5
|
+
# @abstract
|
6
|
+
class Base
|
7
|
+
|
8
|
+
class << self
|
9
|
+
attr_reader :options
|
10
|
+
private
|
11
|
+
include Translatomatic::DefineOptions
|
12
|
+
end
|
13
|
+
|
14
|
+
# @private
|
15
|
+
attr_accessor :listener
|
16
|
+
|
17
|
+
def initialize(options = {})
|
18
|
+
@listener = options[:listener]
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [String] The name of this translator.
|
22
|
+
def name
|
23
|
+
self.class.name.demodulize
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [Array<String>] A list of languages supported by this translator.
|
27
|
+
def languages
|
28
|
+
[]
|
29
|
+
end
|
30
|
+
|
31
|
+
# Translate strings from one locale to another
|
32
|
+
# @param [Array<String>] strings A list of strings to translate.
|
33
|
+
# @param [String, Translatomatic::Locale] from The locale of the given strings.
|
34
|
+
# @param [String, Translatomatic::Locale] to The locale to translate to.
|
35
|
+
# @return [Array<String>] Translated strings
|
36
|
+
def translate(strings, from, to)
|
37
|
+
strings = [strings] unless strings.kind_of?(Array)
|
38
|
+
from = locale(from)
|
39
|
+
to = locale(to)
|
40
|
+
return strings if from.language == to.language
|
41
|
+
translated = perform_translate(strings, from, to)
|
42
|
+
update_translated(translated) unless @updated_listener
|
43
|
+
translated
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
include Translatomatic::Util
|
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.
|
53
|
+
# (subclass must implement fetch_translation if this method is used)
|
54
|
+
def perform_fetch_translations(url, strings, from, to)
|
55
|
+
translated = []
|
56
|
+
request = Translatomatic::HTTPRequest.new(url)
|
57
|
+
request.start do |http|
|
58
|
+
strings.each do |string|
|
59
|
+
result = fetch_translation(request, string, from, to)
|
60
|
+
translated << result
|
61
|
+
update_translated(result)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
translated
|
65
|
+
end
|
66
|
+
|
67
|
+
def fetch_translation(request, strings, from, to)
|
68
|
+
raise "subclass must implement fetch_translation"
|
69
|
+
end
|
70
|
+
|
71
|
+
def update_translated(texts)
|
72
|
+
texts = [texts] unless texts.kind_of?(Array)
|
73
|
+
@updated_listener = true
|
74
|
+
@listener.translated_texts(texts) if @listener
|
75
|
+
end
|
76
|
+
|
77
|
+
def perform_translate(strings, from, to)
|
78
|
+
raise "subclass must implement perform_translate"
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -1,64 +1,57 @@
|
|
1
|
-
require 'net/http'
|
2
|
-
|
3
|
-
module Translatomatic
|
4
|
-
module Translator
|
5
|
-
|
6
|
-
class Frengly < Base
|
7
|
-
|
8
|
-
define_options({
|
9
|
-
name: :frengly_api_key, desc: "Frengly API key", use_env: true
|
10
|
-
},
|
11
|
-
{ name: :frengly_email, desc: "Email address", use_env: true
|
12
|
-
},
|
13
|
-
{ name: :frengly_password, desc: "Password", use_env: true
|
14
|
-
})
|
15
|
-
|
16
|
-
# Create a new Frengly translator instance
|
17
|
-
def initialize(options = {})
|
18
|
-
|
19
|
-
@
|
20
|
-
@
|
21
|
-
|
22
|
-
raise "
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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
|
-
|
58
|
-
translated
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
end # class
|
63
|
-
end # module
|
64
|
-
end
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module Translatomatic
|
4
|
+
module Translator
|
5
|
+
|
6
|
+
class Frengly < Base
|
7
|
+
|
8
|
+
define_options({
|
9
|
+
name: :frengly_api_key, desc: "Frengly API key", use_env: true
|
10
|
+
},
|
11
|
+
{ name: :frengly_email, desc: "Email address", use_env: true
|
12
|
+
},
|
13
|
+
{ name: :frengly_password, desc: "Password", use_env: true
|
14
|
+
})
|
15
|
+
|
16
|
+
# Create a new Frengly translator instance
|
17
|
+
def initialize(options = {})
|
18
|
+
super(options)
|
19
|
+
@key = options[:frengly_api_key] || ENV["FRENGLY_API_KEY"] # optional
|
20
|
+
@email = options[:frengly_email]
|
21
|
+
@password = options[:frengly_password]
|
22
|
+
raise "email address required" unless @email
|
23
|
+
raise "password required" unless @password
|
24
|
+
end
|
25
|
+
|
26
|
+
# (see Translatomatic::Translator::Base#languages)
|
27
|
+
def languages
|
28
|
+
['en','fr','de','es','pt','it','nl','tl','fi','el','iw','pl','ru','sv']
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
URL = 'http://frengly.com/frengly/data/translateREST'
|
34
|
+
|
35
|
+
def perform_translate(strings, from, to)
|
36
|
+
perform_fetch_translations(URL, strings, from, to)
|
37
|
+
end
|
38
|
+
|
39
|
+
def fetch_translation(request, string, from, to)
|
40
|
+
body = {
|
41
|
+
src: from.language,
|
42
|
+
dest: to.language,
|
43
|
+
text: string,
|
44
|
+
email: @email,
|
45
|
+
password: @password,
|
46
|
+
premiumkey: @key
|
47
|
+
}.to_json
|
48
|
+
|
49
|
+
# TODO: work out what the response looks like
|
50
|
+
response = request.post(body, content_type: 'application/json')
|
51
|
+
data = JSON.parse(response.body)
|
52
|
+
data['text']
|
53
|
+
end
|
54
|
+
|
55
|
+
end # class
|
56
|
+
end # module
|
57
|
+
end
|
@@ -1,30 +1,31 @@
|
|
1
|
-
module Translatomatic
|
2
|
-
module Translator
|
3
|
-
|
4
|
-
class Google < Base
|
5
|
-
|
6
|
-
define_options({ name: :google_api_key, desc: "Google API key",
|
7
|
-
use_env: true
|
8
|
-
})
|
9
|
-
|
10
|
-
# Create a new Google translator instance
|
11
|
-
def initialize(options = {})
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
end
|
1
|
+
module Translatomatic
|
2
|
+
module Translator
|
3
|
+
|
4
|
+
class Google < Base
|
5
|
+
|
6
|
+
define_options({ name: :google_api_key, desc: "Google API key",
|
7
|
+
use_env: true
|
8
|
+
})
|
9
|
+
|
10
|
+
# Create a new Google translator instance
|
11
|
+
def initialize(options = {})
|
12
|
+
super(options)
|
13
|
+
key = options[:google_api_key] || ENV["GOOGLE_API_KEY"]
|
14
|
+
raise "google api key required" if key.nil?
|
15
|
+
EasyTranslate.api_key = key
|
16
|
+
end
|
17
|
+
|
18
|
+
# (see Translatomatic::Translator::Base#languages)
|
19
|
+
def languages
|
20
|
+
EasyTranslate::LANGUAGES.keys
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def perform_translate(strings, from, to)
|
26
|
+
EasyTranslate.translate(strings, from: from.language, to: to.language)
|
27
|
+
end
|
28
|
+
|
29
|
+
end # class
|
30
|
+
end # module
|
31
|
+
end
|
@@ -1,32 +1,33 @@
|
|
1
|
-
require 'bing_translator'
|
2
|
-
|
3
|
-
module Translatomatic
|
4
|
-
module Translator
|
5
|
-
|
6
|
-
class Microsoft < Base
|
7
|
-
|
8
|
-
define_options({
|
9
|
-
name: :microsoft_api_key, desc: "Microsoft API key", use_env: true
|
10
|
-
})
|
11
|
-
|
12
|
-
# Create a new Microsoft translator instance
|
13
|
-
def initialize(options = {})
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
end
|
1
|
+
require 'bing_translator'
|
2
|
+
|
3
|
+
module Translatomatic
|
4
|
+
module Translator
|
5
|
+
|
6
|
+
class Microsoft < Base
|
7
|
+
|
8
|
+
define_options({
|
9
|
+
name: :microsoft_api_key, desc: "Microsoft API key", use_env: true
|
10
|
+
})
|
11
|
+
|
12
|
+
# Create a new Microsoft translator instance
|
13
|
+
def initialize(options = {})
|
14
|
+
super(options)
|
15
|
+
key = options[:microsoft_api_key] || ENV["MICROSOFT_API_KEY"]
|
16
|
+
raise "microsoft api key required" if key.nil?
|
17
|
+
@impl = BingTranslator.new(key)
|
18
|
+
end
|
19
|
+
|
20
|
+
# TODO: implement language list
|
21
|
+
# (see Translatomatic::Translator::Base#languages)
|
22
|
+
#def languages
|
23
|
+
#end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def perform_translate(strings, from, to)
|
28
|
+
@impl.translate_array(strings, from: from.language, to: to.language)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,55 +1,64 @@
|
|
1
|
-
require 'bing_translator'
|
2
|
-
|
3
|
-
module Translatomatic
|
4
|
-
module Translator
|
5
|
-
|
6
|
-
class MyMemory < Base
|
7
|
-
|
8
|
-
define_options(
|
9
|
-
{ name: :mymemory_api_key, desc: "MyMemory API key", use_env: true },
|
10
|
-
{ name: :mymemory_email, desc: "Email address", use_env: true }
|
11
|
-
)
|
12
|
-
|
13
|
-
# Create a new MyMemory translator instance
|
14
|
-
def initialize(options = {})
|
15
|
-
|
16
|
-
@
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
end
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
1
|
+
require 'bing_translator'
|
2
|
+
|
3
|
+
module Translatomatic
|
4
|
+
module Translator
|
5
|
+
|
6
|
+
class MyMemory < Base
|
7
|
+
|
8
|
+
define_options(
|
9
|
+
{ name: :mymemory_api_key, desc: "MyMemory API key", use_env: true },
|
10
|
+
{ name: :mymemory_email, desc: "Email address", use_env: true }
|
11
|
+
)
|
12
|
+
|
13
|
+
# Create a new MyMemory translator instance
|
14
|
+
def initialize(options = {})
|
15
|
+
super(options)
|
16
|
+
@key = options[:mymemory_api_key] || ENV["MYMEMORY_API_KEY"]
|
17
|
+
@email = options[:mymemory_email] || ENV["MYMEMORY_EMAIL"]
|
18
|
+
@query_options = {}
|
19
|
+
@query_options.merge!(de: @email) if @email
|
20
|
+
@query_options.merge!(key: @key) if @key
|
21
|
+
end
|
22
|
+
|
23
|
+
# TODO: implement language list
|
24
|
+
# (see Translatomatic::Translator::Base#languages)
|
25
|
+
#def languages
|
26
|
+
#end
|
27
|
+
|
28
|
+
# Upload a set of translations to MyMemory
|
29
|
+
# @param [Translatomatic::TMX::Document] TMX document
|
30
|
+
def upload(tmx)
|
31
|
+
request = Translatomatic::HTTPRequest.new(UPLOAD_URL)
|
32
|
+
request.start do |http|
|
33
|
+
body = [
|
34
|
+
request.file(key: :tmx, filename: "import.tmx",
|
35
|
+
content: tmx.to_xml, mime_type: "application/xml"
|
36
|
+
),
|
37
|
+
request.param(key: :private, value: 0)
|
38
|
+
]
|
39
|
+
response = request.post(body, multipart: true)
|
40
|
+
log.debug("share response: #{response.body}")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
GET_URL = 'https://api.mymemory.translated.net/get'
|
47
|
+
UPLOAD_URL = 'https://api.mymemory.translated.net/tmx/import'
|
48
|
+
|
49
|
+
def perform_translate(strings, from, to)
|
50
|
+
perform_fetch_translations(GET_URL, strings, from, to)
|
51
|
+
end
|
52
|
+
|
53
|
+
def fetch_translation(request, string, from, to)
|
54
|
+
response = request.get({
|
55
|
+
langpair: from.to_s + "|" + to.to_s,
|
56
|
+
q: string
|
57
|
+
}.merge(@query_options)
|
58
|
+
)
|
59
|
+
data = JSON.parse(response.body)
|
60
|
+
data['responseData']['translatedText']
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -1,37 +1,39 @@
|
|
1
|
-
require 'yandex-translator'
|
2
|
-
|
3
|
-
module Translatomatic
|
4
|
-
module Translator
|
5
|
-
|
6
|
-
class Yandex < Base
|
7
|
-
|
8
|
-
define_options({
|
9
|
-
name: :yandex_api_key, desc: "Yandex API key", use_env: true
|
10
|
-
})
|
11
|
-
|
12
|
-
# Create a new Yandex translator instance
|
13
|
-
def initialize(options = {})
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
end
|
1
|
+
require 'yandex-translator'
|
2
|
+
|
3
|
+
module Translatomatic
|
4
|
+
module Translator
|
5
|
+
|
6
|
+
class Yandex < Base
|
7
|
+
|
8
|
+
define_options({
|
9
|
+
name: :yandex_api_key, desc: "Yandex API key", use_env: true
|
10
|
+
})
|
11
|
+
|
12
|
+
# Create a new Yandex translator instance
|
13
|
+
def initialize(options = {})
|
14
|
+
super(options)
|
15
|
+
key = options[:yandex_api_key] || ENV["YANDEX_API_KEY"]
|
16
|
+
raise "yandex api key required" if key.nil?
|
17
|
+
@impl = ::Yandex::Translator.new(key)
|
18
|
+
end
|
19
|
+
|
20
|
+
# (see Translatomatic::Translator::Base#languages)
|
21
|
+
def languages
|
22
|
+
@languages ||= @impl.langs.collect { |i| i[0, 2] }.uniq
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def perform_translate(strings, from, to)
|
28
|
+
translated = []
|
29
|
+
strings.each do |string|
|
30
|
+
result = @impl.translate(string, from: from.language, to: to.language) || ""
|
31
|
+
translated.push(result)
|
32
|
+
update_translated(result)
|
33
|
+
end
|
34
|
+
translated
|
35
|
+
end
|
36
|
+
|
37
|
+
end # class
|
38
|
+
end # module
|
39
|
+
end
|