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,29 +1,91 @@
1
- module Translatomatic::CLI
2
- # Database functions for the command line interface
3
- class Database < Base
4
-
5
- desc "search string [locale]", t("cli.database.search")
6
- thor_options(self, Translatomatic::CLI::CommonOptions)
7
- thor_options(self, Translatomatic::Database)
8
- # Search database for the given string
9
- # @param string [String] String to search for
10
- # @param locale [String] Optional locale, by default search all locales
11
- # @return [void]
12
- def search(string, locale = nil)
13
- Translatomatic::Database.new(options)
14
- texts = Translatomatic::Model::Text.where('value LIKE ?', "%#{string}%")
15
- if locale
16
- db_locale = Translatomatic::Model::Locale.from_tag(locale)
17
- texts = texts.where(locale: db_locale)
1
+ module Translatomatic
2
+ module CLI
3
+ # Database functions for the command line interface
4
+ class Database < Base
5
+ desc 'search string [locale]', t('cli.database.search')
6
+ thor_options(self, Translatomatic::CLI::CommonOptions)
7
+ thor_options(self, Translatomatic::Database)
8
+ # Search database for the given string
9
+ # @param string [String] String to search for
10
+ # @param locale [String] Optional locale, by default search all locales
11
+ # @return [void]
12
+ def search(string, locale = nil)
13
+ run do
14
+ db = Translatomatic::Database.new(options)
15
+
16
+ # find all matching texts
17
+ texts = db.text.where('value LIKE ?', "%#{string}%")
18
+ if locale
19
+ db_locale = db.locale.from_tag(locale)
20
+ texts = texts.where(locale: db_locale)
21
+ end
22
+
23
+ # get all the associated original texts
24
+ original_texts = texts.where(from_text_id: nil)
25
+ from_ids = texts.where('from_text_id IS NOT NULL')
26
+ .select(:from_text_id).collect(&:from_text_id)
27
+ original2 = db.text.where('id IN (?)', from_ids)
28
+ original_texts += original2
29
+
30
+ original_texts.uniq.each do |text|
31
+ value = highlight(text.value, string)
32
+ puts
33
+ puts format('id:%<id>d (%<locale>s) %<value>s',
34
+ id: text.id, locale: text.locale, value: value)
35
+ rows = []
36
+ text.translations.each do |t|
37
+ rows << [' -> ', t.provider, "(#{t.locale})",
38
+ highlight(t.value, string)]
39
+ end
40
+ print_table(rows)
41
+ end
42
+ end
18
43
  end
19
- texts.find_each do |text|
20
- puts "(%s) %s" % [text.locale, text.value]
21
- text.translations.each do |translation|
22
- puts " -> (%s) %s" % [translation.locale, translation.value]
44
+
45
+ desc 'delete text_id', t('cli.database.delete_text')
46
+ thor_options(self, Translatomatic::CLI::CommonOptions)
47
+ thor_options(self, Translatomatic::Database)
48
+ # Delete a text and its translations from the database
49
+ # @param text_id [Number] id of text to delete
50
+ # @return [void]
51
+ def delete(text_id)
52
+ run do
53
+ db = Translatomatic::Database.new(options)
54
+ text = db.text.find(text_id)
55
+ raise t('cli.database.text_not_found', id: text_id) unless text
56
+ text.destroy
57
+ end
58
+ end
59
+
60
+ desc 'drop', t('cli.database.drop')
61
+ thor_options(self, Translatomatic::CLI::CommonOptions)
62
+ thor_options(self, Translatomatic::Database)
63
+ # Drop the database
64
+ def drop
65
+ run { Translatomatic::Database.new(options).drop }
66
+ end
67
+
68
+ desc 'info', t('cli.database.info')
69
+ thor_options(self, Translatomatic::CLI::CommonOptions)
70
+ thor_options(self, Translatomatic::Database)
71
+ # Show information about the database
72
+ def info
73
+ run do
74
+ db = Translatomatic::Database.new(options)
75
+ puts t('cli.database.text_count', count: db.text.count)
76
+ texts_by_locale = db.text.group(:locale).count
77
+ texts_by_locale.each do |locale, count|
78
+ puts format(' (%<locale>s) %<count>d',
79
+ locale: locale.to_s, count: count)
80
+ end
23
81
  end
24
- puts
25
82
  end
26
- end
27
83
 
84
+ private
85
+
86
+ def highlight(text, highlighted)
87
+ text.gsub(highlighted) { |i| rainbow.wrap(i).bright.inverse }
88
+ end
89
+ end
28
90
  end
29
91
  end
@@ -1,125 +1,179 @@
1
1
  # Command line interface to translatomatic
2
- module Translatomatic::CLI
3
- # Main command line interface
4
- class Main < Base
5
-
6
- default_task :translate
7
-
8
- begin
9
- I18n.default_locale = Translatomatic.config.default_locale
10
- end
2
+ module Translatomatic
3
+ module CLI
4
+ # Main command line interface
5
+ class Main < Base
6
+ package_name 'Translatomatic'
7
+ map %w[-v --version] => :version
8
+ map %w[-L --list] => :providers
9
+
10
+ desc 'translate', t('cli.translate.subcommand')
11
+ subcommand 'translate', Translate
12
+
13
+ desc 'database', t('cli.database.subcommand')
14
+ subcommand 'database', Database
15
+
16
+ desc 'config', t('cli.config.subcommand')
17
+ subcommand 'config', Config
18
+
19
+ desc 'display file [key...]', t('cli.display_values')
20
+ thor_options(self, Translatomatic::CLI::CommonOptions)
21
+ method_option :target_locales, type: :string,
22
+ desc: t('cli.locales_to_display')
23
+ method_option :sentences, type: :boolean,
24
+ desc: t('cli.display_sentences')
25
+ # Display values from a resource bundle
26
+ # @param file [String] Path to resource file
27
+ # @param keys [Array<String>] Optional list of locales
28
+ # @return [void]
29
+ def display(file = nil, *keys)
30
+ run do
31
+ source_files = parse_list(file, conf.get(:source_files))
32
+ locales = conf.get(:target_locales, for_file: file)
33
+ source_files.each do |path|
34
+ raise t('file.not_found', file: path) unless File.exist?(path)
35
+ source = Translatomatic::ResourceFile.load(path)
36
+ display_properties(source, keys)
37
+ locales.each do |locale|
38
+ path = source.locale_path(locale)
39
+ next if path == source.path || !path.exist?
40
+ resource = Translatomatic::ResourceFile.load(path)
41
+ display_properties(resource, keys)
42
+ end
43
+ end
44
+ end
45
+ end
11
46
 
12
- package_name "Translatomatic"
13
- map %W[-v --version] => :version
14
- map %W[-L --list] => :translators
15
-
16
- desc "translate", t("cli.translate.subcommand")
17
- subcommand "translate", Translate
18
-
19
- desc "database", t("cli.database.subcommand")
20
- subcommand "database", Database
21
-
22
- desc "config", t("cli.config.subcommand")
23
- subcommand "config", Config
24
-
25
- desc "display file [key...]", t("cli.display_values")
26
- thor_options(self, Translatomatic::CLI::CommonOptions)
27
- method_option :locales, type: :string, desc: t("cli.locales_to_display")
28
- method_option :sentences, type: :boolean, desc: t("cli.display_sentences")
29
- # Display values from a resource bundle
30
- # @param file [String] Path to resource file
31
- # @param keys [Array<String>] Optional list of locales
32
- # @return [void]
33
- def display(file, *keys)
34
- run do
35
- source = Translatomatic::ResourceFile.load(file)
36
- keys = source.properties.keys if keys.empty?
37
- display_keys(source, keys)
38
-
39
- # TODO: if locales not specified, determine the list of locales from
40
- # all the files in the resource bundle.
41
- locales = parse_list(options[:locales])
42
- locales << Translatomatic::Locale.default.to_s if locales.empty?
43
- locales.each do |tag|
44
- locale = locale(tag)
45
- next if locale == source.locale
46
- display_properties(source, keys, locale)
47
+ desc 'strings file [file...]', t('cli.extract_strings')
48
+ thor_options(self, Translatomatic::CLI::CommonOptions)
49
+ # Extract strings from non-resource files
50
+ # @param files [Array<String>] List of paths to files
51
+ # @return [void]
52
+ def strings(*files)
53
+ run do
54
+ strings = []
55
+ files.each do |file|
56
+ extractor = Translatomatic::Extractor::Base.new(file)
57
+ strings << extractor.extract
58
+ end
59
+ puts strings.join("\n")
47
60
  end
48
61
  end
49
- end
50
62
 
51
- desc "strings file [file...]", t("cli.extract_strings")
52
- thor_options(self, Translatomatic::CLI::CommonOptions)
53
- # Extract strings from non-resource files
54
- # @param files [Array<String>] List of paths to files
55
- # @return [void]
56
- def strings(*files)
57
- run do
58
- strings = []
59
- files.each do |file|
60
- extractor = Translatomatic::Extractor::Base.new(file)
61
- strings << extractor.extract
63
+ desc 'convert source target', t('cli.convert')
64
+ # Convert a resource file from one format to another
65
+ # @param source [String] An existing resource file
66
+ # @param target [String] The name of a target resource file
67
+ # @return [void]
68
+ def convert(source, target)
69
+ run do
70
+ converter = Translatomatic::Converter.new
71
+ converter.convert(source, target)
62
72
  end
63
- puts strings.join("\n")
64
73
  end
65
- end
66
74
 
67
- desc "convert source target", t("cli.convert")
68
- # Convert a resource file from one format to another
69
- # @param source [String] An existing resource file
70
- # @param target [String] The name of a target resource file
71
- # @return [void]
72
- def convert(source, target)
73
- run do
74
- converter = Translatomatic::Converter.new
75
- converter.convert(source, target)
75
+ desc 'providers', t('cli.providers')
76
+ thor_options(self, Translatomatic::CLI::CommonOptions)
77
+ # List available translation providers
78
+ # @return [void]
79
+ def providers
80
+ run { display_providers }
76
81
  end
77
- end
78
82
 
79
- desc "services", t("cli.list_backends")
80
- thor_options(self, Translatomatic::CLI::CommonOptions)
81
- # List available translator services
82
- # @return [void]
83
- def services
84
- run { puts Translatomatic::Translator.list }
85
- end
83
+ desc 'version', t('cli.display_version')
84
+ thor_options(self, Translatomatic::CLI::CommonOptions)
85
+ # Display version number
86
+ # @return [void]
87
+ def version
88
+ puts "Translatomatic v#{Translatomatic::VERSION}"
89
+ end
86
90
 
87
- desc 'version', t("cli.display_version")
88
- thor_options(self, Translatomatic::CLI::CommonOptions)
89
- # Display version number
90
- # @return [void]
91
- def version
92
- puts "Translatomatic v#{Translatomatic::VERSION}"
93
- end
91
+ private
94
92
 
95
- private
93
+ # @return [String] A description of all providers and options
94
+ def display_providers
95
+ puts t('provider.options') + "\n\n"
96
+ display_provider_options
97
+ puts
96
98
 
97
- def display_properties(source, keys, locale)
98
- path = source.locale_path(locale)
99
- if path.exist?
100
- resource = Translatomatic::ResourceFile.load(path)
101
- display_keys(resource, keys)
99
+ puts t('provider.status') + "\n\n"
100
+ display_provider_status
101
+ puts
102
102
  end
103
- end
104
103
 
105
- def display_keys(source, keys)
106
- puts t("cli.file_source", file: source)
107
- rows = []
108
- keys.each do |key|
109
- value = source.get(key)
110
- rows << [key + ":", value]
104
+ def display_provider_options
105
+ rows = []
106
+ Translatomatic::Provider.types.each do |klass|
107
+ rows += provider_option_rows(klass)
108
+ end
109
+ headers = %i[name option description env]
110
+ heading = headers.collect { |i| t("cli.provider.#{i}") }
111
+ print_table(add_table_heading(rows, heading), indent: 2)
111
112
  end
112
- print_table(rows, indent: 2)
113
113
 
114
- if options[:sentences]
115
- puts t("cli.sentences")
116
- source.sentences.each do |sentence|
117
- puts "- " + sentence.to_s
114
+ def provider_option_rows(klass)
115
+ name = klass.name.demodulize
116
+ opts = klass.options || []
117
+ opts.collect { |i| provider_option_row(name, i) }
118
+ end
119
+
120
+ def provider_option_row(name, opt)
121
+ args = []
122
+ args << name
123
+ args << '--' + opt.name.to_s.tr('_', '-')
124
+ args << opt.description
125
+ args << opt.env_name ? "ENV[#{opt.env_name}]" : ''
126
+ args
127
+ end
128
+
129
+ def display_provider_status
130
+ types = Translatomatic::Provider.types
131
+ available = available_providers
132
+ rows = types.sort_by { |i| available[i.name] ? 0 : 1 }.map do |klass|
133
+ provider_status_row(klass, available)
118
134
  end
135
+ headers = %i[name available]
136
+ heading = headers.collect { |i| t("cli.provider.#{i}") }
137
+ print_table(add_table_heading(rows, heading), indent: 2)
119
138
  end
120
139
 
121
- puts
122
- end
140
+ def available_providers
141
+ config_all = Translatomatic.config.all
142
+ available = {}
143
+ configured = Translatomatic::Provider.available(config_all)
144
+ configured.each { |i| available[i.class.name] = true }
145
+ available
146
+ end
147
+
148
+ def provider_status_row(klass, available)
149
+ name = klass.name.demodulize
150
+ avail = available[klass.name] ? 'yes' : 'no'
151
+ args = []
152
+ args << name
153
+ args << t('cli.provider.available_' + avail)
154
+ args << Translatomatic::Provider.get_error(name)
155
+ args
156
+ end
123
157
 
124
- end # class
125
- end # module
158
+ def display_properties(source, keys)
159
+ puts t('cli.file_source', file: source)
160
+ rows = []
161
+ keys = source.properties.keys if keys.empty?
162
+ keys.each do |key|
163
+ value = source.get(key)
164
+ rows << [key + ':', value]
165
+ end
166
+ print_table(rows, indent: 2)
167
+
168
+ if options[:sentences]
169
+ puts t('cli.sentences')
170
+ source.sentences.each do |sentence|
171
+ puts '- ' + sentence.to_s
172
+ end
173
+ end
174
+
175
+ puts
176
+ end
177
+ end
178
+ end
179
+ end
@@ -0,0 +1,29 @@
1
+ module Translatomatic
2
+ module CLI
3
+ # @private
4
+ module ThorPatch
5
+ # disable --no booleans
6
+ # @private
7
+ module NoNo
8
+ def usage(padding = 0)
9
+ sample = usage_banner
10
+ sample = "[#{sample}]".dup unless required?
11
+
12
+ if aliases.empty?
13
+ (' ' * padding) << sample
14
+ else
15
+ "#{aliases.join(', ')}, #{sample}"
16
+ end
17
+ end
18
+
19
+ def usage_banner
20
+ if banner && !banner.to_s.empty?
21
+ "#{switch_name}=#{banner}".dup
22
+ else
23
+ switch_name
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,181 +1,158 @@
1
1
  require 'ruby-progressbar'
2
2
 
3
- # Command line interface to translatomatic
4
- module Translatomatic::CLI
5
- # Translation functions for the command line interface
6
- class Translate < Base
7
-
8
- default_task :file
9
-
10
- define_options(
11
- { name: :translator, type: :array, aliases: "-t",
12
- desc: t("cli.translate.translator"),
13
- enum: Translatomatic::Translator.names
14
- },
15
- { name: :source_locale, desc: t("cli.source_locale") },
16
- { name: :share, desc: t("cli.share"), default: false },
17
- { name: :target_locales, desc: t("cli.target_locales"),
18
- type: :array
19
- },
20
- { name: :source_files, desc: t("cli.source_files"),
21
- type: :array
22
- },
23
- )
24
-
25
- desc "string text locale...", t("cli.translate.string")
26
- thor_options(self, Translatomatic::CLI::CommonOptions)
27
- thor_options(self, Translatomatic::CLI::Translate)
28
- thor_options(self, Translatomatic::Translator.modules)
29
- # Translate a string to target locales
30
- # @param text [String] String to translate
31
- # @param locales [Array<String>] List of target locales, can also be set
32
- # with the --target-locales option
33
- # @return [void]
34
- def string(text, *locales)
35
- run do
36
- setup_translation
37
- determine_target_locales(locales)
38
-
39
- puts "(%s) %s" % [@source_locale, text]
40
- @translators.each do |translator|
41
- puts t("cli.using_translator", name: translator.name)
42
- @target_locales.each do |target_locale|
43
- result = translator.translate([text], @source_locale, target_locale)
44
- puts " -> (%s) %s" % [target_locale, result]
3
+ module Translatomatic
4
+ module CLI
5
+ # Translation functions for the command line interface
6
+ class Translate < Base
7
+ default_task :file
8
+
9
+ define_option :provider, type: :array, aliases: '-t',
10
+ desc: t('cli.translate.provider'),
11
+ enum: Translatomatic::Provider.names
12
+ define_option :source_locale, desc: t('cli.source_locale')
13
+ define_option :target_locales, desc: t('cli.target_locales'),
14
+ type: :array
15
+ define_option :source_files, desc: t('cli.source_files'),
16
+ type: :path_array
17
+ define_option :share, desc: t('cli.translate.share'), default: false
18
+
19
+ desc 'string text locale...', t('cli.translate.string')
20
+ thor_options(self, Translatomatic::CLI::CommonOptions)
21
+ thor_options(self, Translatomatic::CLI::Translate)
22
+ thor_options(self, Translatomatic::Provider.types)
23
+ # Translate a string to target locales
24
+ # @param text [String] String to translate
25
+ # @param locales [Array<String>] List of target locales, can also be set
26
+ # with the --target-locales option
27
+ # @return [void]
28
+ def string(text, *locales)
29
+ run do
30
+ all_conf = conf.all
31
+ source_locale = conf.get(:source_locale) || Locale.default.to_s
32
+ target_locales = determine_target_locales(locales)
33
+ providers = Provider.resolve(conf.get(:provider), all_conf)
34
+
35
+ template = '(%<locale>s) %<text>s'
36
+ puts format(template, locale: source_locale, text: text)
37
+ providers.each do |provider|
38
+ puts t('cli.translate.using_provider', name: provider.name)
39
+ target_locales.each do |l|
40
+ translations = provider.translate([text], source_locale, l)
41
+ translations.each do |translation|
42
+ puts format(' -> ' + template, locale: l, text: translation)
43
+ end
44
+ end
45
+ puts
45
46
  end
46
- puts
47
- end
48
47
 
49
- finish_log
48
+ finish_log
49
+ end
50
50
  end
51
- end
52
51
 
53
- desc "file filename locale...", t("cli.translate.file")
54
- thor_options(self, Translatomatic::CLI::CommonOptions)
55
- thor_options(self, Translatomatic::CLI::Translate)
56
- thor_options(self, Translatomatic::FileTranslator)
57
- thor_options(self, Translatomatic::Database)
58
- thor_options(self, Translatomatic::Translator.modules)
59
- # Translate files to target locales
60
- # @param file [String] Resource file to translate, can also be set
61
- # with the --source-files option.
62
- # @param locales [Array<String>] List of target locales, can also be set
63
- # with the --target-locales option
64
- # @return [void]
65
- def file(file = nil, *locales)
66
- run do
67
- setup_translation
68
- determine_target_locales(locales)
69
-
70
- # check source file(s) exist and they can be loaded
71
- source_files = parse_list(cli_option(:source_files), file)
72
- source_files.each do |source_file|
73
- path = source_path(source_file)
74
- raise t("file.not_found", file: path) unless File.exist?(path)
75
- source = Translatomatic::ResourceFile.load(path, @source_locale)
76
- raise t("file.unsupported", file: path) unless source
52
+ desc 'file filename locale...', t('cli.translate.file')
53
+ thor_options(self, Translatomatic::CLI::CommonOptions)
54
+ thor_options(self, Translatomatic::CLI::Translate)
55
+ thor_options(self, Translatomatic::FileTranslator)
56
+ thor_options(self, Translatomatic::Database)
57
+ thor_options(self, Translatomatic::Provider.types)
58
+ thor_options(self, Translatomatic::ResourceFile.types)
59
+ # Translate files to target locales
60
+ # @param file [String] Resource file to translate, can also be set
61
+ # with the --source-files option.
62
+ # @param locales [Array<String>] List of target locales, can also be set
63
+ # with the --target-locales option
64
+ # @return [void]
65
+ def file(file = nil, *locales)
66
+ run do
67
+ # set up database and progress updater
68
+ Translatomatic::Database.new(conf.all)
69
+ stats = Translation::Stats.new
70
+
71
+ # translate the files
72
+ source_files = load_source_files(file)
73
+ listener = progress_updater(source_files, locales)
74
+ source_files.each do |source|
75
+ stats += translate_file(source, locales, listener)
76
+ end
77
+ log.info stats
78
+ finish_log
77
79
  end
80
+ end
78
81
 
79
- # set up database
80
- Translatomatic::Database.new(options)
82
+ private
81
83
 
82
- # set up file translatiln
83
- translation_count = calculate_translation_count(source_files, @target_locales)
84
- ft_options = options.merge(
85
- translator: @translators,
86
- listener: progress_updater(translation_count)
87
- )
84
+ def translate_file(source, locales, listener)
85
+ file_opts = conf.all(for_file: source.path)
86
+ target_locales = determine_target_locales(locales, source)
87
+ ft_options = file_opts.merge(listener: listener)
88
88
  ft = Translatomatic::FileTranslator.new(ft_options)
89
-
90
- source_files.each do |path|
91
- # read source file
92
- source = Translatomatic::ResourceFile.load(path, @source_locale)
93
-
94
- # convert source to locale(s) and write files
95
- @target_locales.each do |i|
96
- to_locale = locale(i)
97
- next if to_locale.language == source.locale.language
98
- ft.translate_to_file(source, to_locale)
99
- end
89
+ stats = Translation::Stats.new
90
+
91
+ target_locales.each do |target_locale|
92
+ log.info(t('cli.translate.translating_file',
93
+ source: source, source_locale: source.locale,
94
+ target_locale: target_locale))
95
+ ft.translate_to_file(source, target_locale)
96
+ stats += ft.translator.stats
100
97
  end
101
-
102
- log.info ft.stats
103
- finish_log
104
-
105
- share_translations(ft) if cli_option(:share)
98
+ stats
106
99
  end
107
- end
108
-
109
- private
110
-
111
- def setup_translation
112
- @source_locale = determine_source_locale
113
- # resolve translators
114
- @translators = Translatomatic::Translator.resolve(
115
- cli_option(:translator), options
116
- )
117
- end
118
-
119
- def determine_target_locales(locales)
120
- @target_locales = parse_list(locales, cli_option(:target_locales))
121
- raise t("cli.locales_required") if @target_locales.empty?
122
- end
123
100
 
124
- def determine_source_locale
125
- cli_option(:source_locale) || conf.default_locale
126
- end
127
-
128
- def calculate_translation_count(source_files, locales)
129
- count = 0
130
- source_files.each do |file|
131
- source = Translatomatic::ResourceFile.load(file, @source_locale)
132
- count += source.sentences.length * locales.length
101
+ # load the source file(s)
102
+ def load_source_files(file)
103
+ source_files = []
104
+ files = parse_list(file, conf.get(:source_files))
105
+ files.each do |path|
106
+ raise t('file.not_found', file: path) unless File.exist?(path)
107
+ source = resource_file(path)
108
+ raise t('file.unsupported', file: path) unless source
109
+ source_files << source
110
+ end
111
+ source_files
133
112
  end
134
- count
135
- end
136
113
 
137
- def share_translations(ft)
138
- return if ft.db_translations.empty?
114
+ def resource_file(path)
115
+ Translatomatic::ResourceFile.load(path, conf.all(for_file: path))
116
+ end
139
117
 
140
- tmx = Translatomatic::TMX::Document.from_texts(ft.db_translations)
141
- available = Translatomatic::Translator.available(options)
142
- available.each do |translator|
143
- if translator.respond_to?(:upload)
144
- log.info(t("cli.uploading_tmx", name: translator.name))
145
- translator.upload(tmx)
146
- end
118
+ # use list given on command line in preference to configuration
119
+ def determine_target_locales(locales, source = nil)
120
+ source_path = source ? source.path : nil
121
+ config_locales = conf.get(:target_locales, for_file: source_path)
122
+ target_locales = parse_list(locales, config_locales)
123
+ raise t('cli.locales_required') if target_locales.empty?
124
+ target_locales
147
125
  end
148
126
 
149
- ActiveRecord::Base.transaction do
150
- ft.db_translations.each do |text|
151
- text.update(shared: true) if text.is_translated?
127
+ def total_translations(source_files, locales)
128
+ total = 0
129
+ source_files.each do |source|
130
+ property_values = source.properties.values
131
+ texts = property_values.collect { |i| build_text(i, source.locale) }
132
+ providers = resolve_providers(source).length
133
+ to_locales = determine_target_locales(locales, source).length
134
+ total += TextCollection.new(texts).count * providers * to_locales
152
135
  end
136
+ total
153
137
  end
154
- end
155
138
 
156
- # convert the given path to an absolute path if necessary, relative
157
- # to project root.
158
- def source_path(path)
159
- if path.start_with?("~/")
160
- # replace ~/ with home directory
161
- path = path.sub(/\A~\//, Dir.home + "/")
139
+ def resolve_providers(source)
140
+ Provider.resolve(conf.get(:provider, for_file: source.path), conf.all)
162
141
  end
163
- File.absolute_path(path, conf.project_path)
164
- end
165
142
 
166
- # create a progress bar and progress updater
167
- def progress_updater(translation_count)
168
- return nil unless cli_option(:wank)
169
- # set up progress bar
170
- progressbar = ProgressBar.create(
171
- title: t("cli.translating"),
172
- format: "%t: |%B| %E ",
173
- autofinish: false,
174
- total: translation_count
175
- )
176
- conf.logger.progressbar = progressbar
177
- Translatomatic::ProgressUpdater.new(progressbar)
143
+ # create a progress bar and progress updater
144
+ def progress_updater(source_files, locales)
145
+ return nil if conf.get(:no_wank)
146
+ # set up progress bar
147
+ progressbar = ProgressBar.create(
148
+ title: t('cli.translate.translating'),
149
+ format: '%t: |%B| %p%% ',
150
+ autofinish: false,
151
+ total: total_translations(source_files, locales)
152
+ )
153
+ log.progressbar = progressbar if log.respond_to?(:progressbar=)
154
+ Translatomatic::ProgressUpdater.new(progressbar)
155
+ end
178
156
  end
179
-
180
- end # class
181
- end # module
157
+ end
158
+ end