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.
Files changed (139) hide show
  1. checksums.yaml +5 -5
  2. data/.gitattributes +20 -20
  3. data/.gitignore +19 -15
  4. data/.rspec +3 -3
  5. data/.rubocop.yml +28 -0
  6. data/.translatomatic/config.yml +4 -0
  7. data/.travis.yml +4 -6
  8. data/.yardopts +9 -9
  9. data/Gemfile +8 -4
  10. data/Guardfile +4 -5
  11. data/README.de.md +55 -50
  12. data/README.en.md +177 -0
  13. data/README.es.md +53 -48
  14. data/README.fr.md +53 -48
  15. data/README.it.md +54 -49
  16. data/README.ja.md +63 -58
  17. data/README.ko.md +59 -54
  18. data/README.md +17 -13
  19. data/README.ms.md +50 -45
  20. data/README.pt.md +54 -49
  21. data/README.ru.md +57 -52
  22. data/README.sv.md +51 -46
  23. data/README.zh.md +60 -55
  24. data/Rakefile +3 -3
  25. data/TODO.txt +6 -0
  26. data/bin/console +3 -3
  27. data/bin/translatomatic +4 -2
  28. data/config/i18n-tasks.yml +130 -0
  29. data/config/locales/translatomatic/de.yml +141 -99
  30. data/config/locales/translatomatic/en.yml +129 -89
  31. data/config/locales/translatomatic/es.yml +136 -99
  32. data/config/locales/translatomatic/fr.yml +139 -100
  33. data/config/locales/translatomatic/it.yml +135 -97
  34. data/config/locales/translatomatic/ja.yml +137 -98
  35. data/config/locales/translatomatic/ko.yml +138 -98
  36. data/config/locales/translatomatic/ms.yml +138 -100
  37. data/config/locales/translatomatic/pt.yml +137 -101
  38. data/config/locales/translatomatic/ru.yml +136 -98
  39. data/config/locales/translatomatic/sv.yml +134 -96
  40. data/config/locales/translatomatic/zh.yml +136 -97
  41. data/db/migrate/201712170000_initial.rb +2 -3
  42. data/lib/translatomatic.rb +40 -25
  43. data/lib/translatomatic/cli.rb +5 -1
  44. data/lib/translatomatic/cli/base.rb +61 -58
  45. data/lib/translatomatic/cli/common_options.rb +14 -11
  46. data/lib/translatomatic/cli/config.rb +96 -91
  47. data/lib/translatomatic/cli/database.rb +85 -23
  48. data/lib/translatomatic/cli/main.rb +158 -104
  49. data/lib/translatomatic/cli/thor.rb +29 -0
  50. data/lib/translatomatic/cli/translate.rb +134 -157
  51. data/lib/translatomatic/config.rb +10 -301
  52. data/lib/translatomatic/config/display.rb +78 -0
  53. data/lib/translatomatic/config/files.rb +60 -0
  54. data/lib/translatomatic/config/location_settings.rb +133 -0
  55. data/lib/translatomatic/config/options.rb +68 -0
  56. data/lib/translatomatic/config/selector.rb +127 -0
  57. data/lib/translatomatic/config/settings.rb +148 -0
  58. data/lib/translatomatic/converter.rb +40 -28
  59. data/lib/translatomatic/database.rb +127 -110
  60. data/lib/translatomatic/define_options.rb +4 -5
  61. data/lib/translatomatic/escaped_unicode.rb +86 -76
  62. data/lib/translatomatic/extractor.rb +5 -2
  63. data/lib/translatomatic/extractor/base.rb +12 -12
  64. data/lib/translatomatic/extractor/ruby.rb +7 -6
  65. data/lib/translatomatic/file_translator.rb +101 -244
  66. data/lib/translatomatic/flattenation.rb +39 -0
  67. data/lib/translatomatic/http.rb +13 -0
  68. data/lib/translatomatic/http/client.rb +144 -0
  69. data/lib/translatomatic/http/exception.rb +43 -0
  70. data/lib/translatomatic/http/file_param.rb +27 -0
  71. data/lib/translatomatic/http/param.rb +37 -0
  72. data/lib/translatomatic/http/request.rb +91 -0
  73. data/lib/translatomatic/i18n.rb +43 -0
  74. data/lib/translatomatic/locale.rb +71 -59
  75. data/lib/translatomatic/logger.rb +43 -28
  76. data/lib/translatomatic/metadata.rb +58 -0
  77. data/lib/translatomatic/model.rb +4 -2
  78. data/lib/translatomatic/model/locale.rb +5 -5
  79. data/lib/translatomatic/model/text.rb +5 -5
  80. data/lib/translatomatic/option.rb +57 -34
  81. data/lib/translatomatic/path_utils.rb +126 -0
  82. data/lib/translatomatic/progress_updater.rb +13 -16
  83. data/lib/translatomatic/provider.rb +101 -0
  84. data/lib/translatomatic/provider/base.rb +136 -0
  85. data/lib/translatomatic/provider/frengly.rb +55 -0
  86. data/lib/translatomatic/provider/google.rb +78 -0
  87. data/lib/translatomatic/provider/google_web.rb +50 -0
  88. data/lib/translatomatic/provider/microsoft.rb +144 -0
  89. data/lib/translatomatic/provider/my_memory.rb +75 -0
  90. data/lib/translatomatic/provider/yandex.rb +61 -0
  91. data/lib/translatomatic/resource_file.rb +59 -53
  92. data/lib/translatomatic/resource_file/base.rb +171 -237
  93. data/lib/translatomatic/resource_file/csv.rb +176 -24
  94. data/lib/translatomatic/resource_file/html.rb +21 -42
  95. data/lib/translatomatic/resource_file/key_value_support.rb +117 -0
  96. data/lib/translatomatic/resource_file/markdown.rb +36 -38
  97. data/lib/translatomatic/resource_file/plist.rb +121 -126
  98. data/lib/translatomatic/resource_file/po.rb +104 -82
  99. data/lib/translatomatic/resource_file/properties.rb +48 -77
  100. data/lib/translatomatic/resource_file/properties.treetop +87 -0
  101. data/lib/translatomatic/resource_file/resw.rb +56 -41
  102. data/lib/translatomatic/resource_file/subtitle.rb +86 -54
  103. data/lib/translatomatic/resource_file/text.rb +18 -18
  104. data/lib/translatomatic/resource_file/xcode_strings.rb +32 -63
  105. data/lib/translatomatic/resource_file/xcode_strings.treetop +85 -0
  106. data/lib/translatomatic/resource_file/xml.rb +94 -81
  107. data/lib/translatomatic/resource_file/yaml.rb +54 -68
  108. data/lib/translatomatic/retry_executor.rb +37 -0
  109. data/lib/translatomatic/slurp.rb +32 -0
  110. data/lib/translatomatic/string_batcher.rb +50 -0
  111. data/lib/translatomatic/string_escaping.rb +61 -0
  112. data/lib/translatomatic/text.rb +263 -0
  113. data/lib/translatomatic/text_collection.rb +66 -0
  114. data/lib/translatomatic/tmx.rb +5 -3
  115. data/lib/translatomatic/tmx/document.rb +107 -82
  116. data/lib/translatomatic/tmx/translation_unit.rb +19 -18
  117. data/lib/translatomatic/translation.rb +8 -28
  118. data/lib/translatomatic/translation/collection.rb +199 -0
  119. data/lib/translatomatic/translation/fetcher.rb +123 -0
  120. data/lib/translatomatic/translation/munging.rb +112 -0
  121. data/lib/translatomatic/translation/result.rb +50 -0
  122. data/lib/translatomatic/translation/sharer.rb +32 -0
  123. data/lib/translatomatic/translation/stats.rb +44 -0
  124. data/lib/translatomatic/translator.rb +91 -88
  125. data/lib/translatomatic/type_cast.rb +63 -0
  126. data/lib/translatomatic/util.rb +37 -33
  127. data/lib/translatomatic/version.rb +2 -2
  128. data/translatomatic.gemspec +57 -46
  129. metadata +136 -59
  130. data/lib/translatomatic/http_request.rb +0 -162
  131. data/lib/translatomatic/string.rb +0 -188
  132. data/lib/translatomatic/translation_result.rb +0 -86
  133. data/lib/translatomatic/translation_stats.rb +0 -31
  134. data/lib/translatomatic/translator/base.rb +0 -128
  135. data/lib/translatomatic/translator/frengly.rb +0 -62
  136. data/lib/translatomatic/translator/google.rb +0 -37
  137. data/lib/translatomatic/translator/microsoft.rb +0 -41
  138. data/lib/translatomatic/translator/my_memory.rb +0 -68
  139. 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