translatomatic 0.1.0 → 0.1.1
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 +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
|