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
@@ -0,0 +1,133 @@
1
+ module Translatomatic
2
+ module Config
3
+ # settings for a specific location
4
+ # location can be user settings, project settings, or file specific
5
+ # settings.
6
+ class LocationSettings
7
+ class << self
8
+ # load settings from environment variables
9
+ def from_environment
10
+ settings = {}
11
+ Options.options.each_value do |option|
12
+ if option.env_name && ENV.include?(option.env_name)
13
+ settings[option.name] = ENV[option.env_name]
14
+ end
15
+ end
16
+ new(settings, location: :env, path: Dir.pwd)
17
+ end
18
+
19
+ def runtime(data = {})
20
+ new(data.deep_symbolize_keys, location: :runtime, path: Dir.pwd)
21
+ end
22
+ end
23
+
24
+ # @return [String] The path to the settings file
25
+ attr_reader :path
26
+
27
+ # @return [Symbol] The location of these settings (:user, :project, :env)
28
+ attr_reader :location
29
+
30
+ def initialize(data = {}, options = {})
31
+ @data = data
32
+ @options = options || {}
33
+ @location = @options[:location]
34
+ @path = @options[:path]
35
+ @data[:files] ||= {} unless options[:no_files]
36
+ end
37
+
38
+ # @return [String] Configuration as YAML
39
+ def to_yaml
40
+ data_for_save.to_yaml
41
+ end
42
+
43
+ # @return [Hash] Files data
44
+ def files
45
+ @data[:files]
46
+ end
47
+
48
+ # Get a configuration setting
49
+ # @param key [String] configuration key
50
+ # @return [String] The configuration value
51
+ def get(key, default = nil)
52
+ include?(key) ? @data[key.to_sym] : default
53
+ end
54
+
55
+ # Change a configuration setting.
56
+ # @param key [String] configuration key
57
+ # @param value [Object] new value for the configuration
58
+ # @return [Object] the new value
59
+ def set(key, value)
60
+ update(key) { |option| @data[option.name] = cast(value, option.type) }
61
+ end
62
+
63
+ # Remove a configuration setting
64
+ # @param key [String] configuration key to remove
65
+ # @return [void]
66
+ def unset(key)
67
+ update(key) { |option| @data.delete(option.name) }
68
+ end
69
+
70
+ # If key is an array type, adds the value to the existing list.
71
+ # Raises an error for non array types.
72
+ # @param key [String] configuration key
73
+ # @param value [Object] value to add to the list
74
+ # @return [Object] the new value
75
+ def add(key, value)
76
+ update_array(key, value, :add)
77
+ end
78
+
79
+ # If key is an array type, removes the value from the existing list.
80
+ # Raises an error for non array types.
81
+ # @param key [String] configuration key
82
+ # @param value [Object] value to remove from the list
83
+ # @return [Object] the new value
84
+ def subtract(key, value)
85
+ update_array(key, value, :subtract)
86
+ end
87
+
88
+ # Test if configuration includes the given key
89
+ # @param key [String] configuration key
90
+ # @return [boolean] true if the configuration key is set
91
+ def include?(key)
92
+ Options.check_valid_key(key)
93
+ @data.include?(key.to_sym)
94
+ end
95
+
96
+ private
97
+
98
+ include Translatomatic::Util
99
+ include Translatomatic::TypeCast
100
+
101
+ def data_for_save
102
+ data = @data.dup
103
+ files = data.delete(:files)
104
+ # put files at the bottom
105
+ data[:files] = files unless files.blank?
106
+ data
107
+ end
108
+
109
+ def update_array(key, value, add)
110
+ update(key) do |option|
111
+ assert_array_type(option)
112
+ current = @data[option.name] || []
113
+ casted = cast(value, option.type)
114
+ new_value = add == :add ? current + casted : current - casted
115
+ @data[option.name] = new_value
116
+ end
117
+ end
118
+
119
+ # common functionality for set/unset/add/subtract methods
120
+ def update(key)
121
+ key = Options.check_valid_key(key)
122
+ option = Options.options[key.to_sym]
123
+ raise t('config.command_line_only') if option.command_line_only
124
+ yield option
125
+ end
126
+
127
+ def assert_array_type(option)
128
+ is_array = array_type?(option.type)
129
+ raise t('config.non_array_key', key: option.name) unless is_array
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,68 @@
1
+ module Translatomatic
2
+ module Config
3
+ # A collection of all translatomatic options available
4
+ module Options
5
+ class << self
6
+ # @return [Hash<String,Translatomatic::Option>] options
7
+ def options
8
+ @config_options ||= begin
9
+ # create mapping from option name to option object
10
+ map = {}
11
+ config_sources.each do |source|
12
+ map.merge!(source_options(source))
13
+ end
14
+ map
15
+ end
16
+ end
17
+
18
+ # @param key [Symbol] Option name
19
+ # @return [Translatomatic::Option] The specified option
20
+ def option(key)
21
+ check_valid_key(key)
22
+ options[key.to_sym]
23
+ end
24
+
25
+ # Test if key is a recognised configuration option name.
26
+ # Raise an exception if it isn't
27
+ # @param key [Symbol] Option name
28
+ def check_valid_key(key)
29
+ key = key ? key.to_sym : nil
30
+ raise t('config.invalid_key', key: key) unless valid_key?(key)
31
+ key
32
+ end
33
+
34
+ # @return [Boolean] True if key is a recognised configuration option
35
+ def valid_key?(key)
36
+ options.include?(key.to_sym)
37
+ end
38
+
39
+ private
40
+
41
+ include Translatomatic::Util
42
+
43
+ def config_sources
44
+ [
45
+ Translatomatic::CLI::CommonOptions,
46
+ Translatomatic::CLI::Translate,
47
+ Translatomatic::CLI::Config,
48
+ Translatomatic::Provider.types,
49
+ Translatomatic::ResourceFile.types,
50
+ Translatomatic::Database,
51
+ Translatomatic::Converter,
52
+ Translatomatic::FileTranslator
53
+ ].freeze
54
+ end
55
+
56
+ def source_options(source)
57
+ map = {}
58
+ source_options = Translatomatic::Option.options_from_object(source)
59
+ source_options.each do |sopt|
60
+ optname = sopt.name.to_sym
61
+ map[optname] = sopt
62
+ end
63
+ map
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,127 @@
1
+ module Translatomatic
2
+ module Config
3
+ # Selects which set of config settings to use
4
+ class Selector
5
+ attr_reader :for_file
6
+ attr_reader :location
7
+
8
+ def initialize(settings, default_location, params = {})
9
+ @settings = settings
10
+ @for_file = params[:for_file]
11
+ @location = params[:location]
12
+ @default_location = default_location
13
+ end
14
+
15
+ # Find a settings object for reading the specified option
16
+ # @param key [Symbol] Option name
17
+ # @return [LocationSettings] settings
18
+ def settings_for_read(key)
19
+ if location.nil?
20
+ # no location, find first settings for key according to precedence
21
+ settings_with_precedence(key)
22
+ else
23
+ # location is set
24
+ check_valid_location
25
+ location_settings_for_read(key, location)
26
+ end
27
+ end
28
+
29
+ # Find a settings object for writing the specified option
30
+ # @param key [Symbol] Option name
31
+ # @return [LocationSettings] settings
32
+ def settings_for_write(key)
33
+ effective = effective_location(key, location)
34
+ settings = @settings[effective]
35
+ if for_file
36
+ path = file(settings)
37
+ data = settings.files[path.to_s.to_sym] ||= {}
38
+ file_location_settings(settings, data)
39
+ else
40
+ settings
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ include Translatomatic::TypeCast
47
+
48
+ # valid location list in order of precedence
49
+ LOCATIONS = %i[runtime project user env].freeze
50
+
51
+ def settings_with_precedence(key)
52
+ # find the first setting found by precedence
53
+ LOCATIONS.each do |loc|
54
+ settings = location_settings_for_read(key, loc)
55
+ return settings if settings
56
+ end
57
+ nil
58
+ end
59
+
60
+ def location_settings_for_read(key, loc)
61
+ effective = effective_location(key, loc)
62
+ settings = @settings[effective]
63
+ file_settings = for_file_settings(settings)
64
+ [file_settings, settings].each do |i|
65
+ return i if i && i.include?(key)
66
+ end
67
+ return nil
68
+ end
69
+
70
+ def effective_location(key, loc)
71
+ effective = loc || @default_location
72
+ effective = :user if Options.option(key).user_location_only
73
+ effective
74
+ end
75
+
76
+ def check_valid_location
77
+ valid = valid_location?
78
+ raise t('config.invalid_location', location: location) unless valid
79
+ end
80
+
81
+ def valid_location?
82
+ location.present? && LOCATIONS.include?(location.to_sym)
83
+ end
84
+
85
+ def for_file_settings(settings)
86
+ return nil unless for_file
87
+ data = merged_file_data(settings)
88
+ file_location_settings(settings, data)
89
+ end
90
+
91
+ def file(settings)
92
+ path = Pathname.new(for_file)
93
+ unless path.relative?
94
+ settings_path = Pathname.new(settings.path)
95
+ path = path.relative_path_from(settings_path)
96
+ end
97
+ path
98
+ end
99
+
100
+ # find matching file configurations
101
+ def merged_file_data(settings)
102
+ merged_data = {}
103
+ file = file(settings)
104
+ paths = settings.files.keys.collect(&:to_s)
105
+ paths.sort_by(&:length).each do |path|
106
+ next unless path_match?(file, path)
107
+ merged_data.merge!(settings.files[path.to_sym])
108
+ end
109
+ merged_data
110
+ end
111
+
112
+ # check if file is equal to or a child of the given path
113
+ def path_match?(file, path)
114
+ file.to_s == path || file.to_s.start_with?(path.to_s)
115
+ end
116
+
117
+ def file_location_settings(settings, data)
118
+ options = {
119
+ path: settings.path,
120
+ location: settings.location,
121
+ no_files: true
122
+ }
123
+ LocationSettings.new(data, options)
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,148 @@
1
+ module Translatomatic
2
+ module Config
3
+ # Translatomatic configuration settings.
4
+ # get and set methods accept a params hash, which recognises the
5
+ # following keys:
6
+ # * location: [Symbol] configuration location (:user or :project)
7
+ # * for_file: [String] file path for per-file configuration
8
+ class Settings
9
+ # @return [String] The path to the user home
10
+ attr_reader :user_path
11
+
12
+ # @return [String] The path to the project home
13
+ attr_reader :project_path
14
+
15
+ def initialize(options = {})
16
+ @runtime = options[:runtime] || {}
17
+ @user_path = File.realpath(options[:user_path] || Dir.home)
18
+ @project_path = options[:project_path]
19
+ @project_path ||= Files.find_project(@user_path)
20
+ load
21
+ end
22
+
23
+ # Get a configuration setting
24
+ # @param key [String] configuration key
25
+ # @param params [Hash] options
26
+ # @return [String] The configuration value. If location is nil, returns the
27
+ # effective value by precedence, otherwise it returns the setting for
28
+ # the given configuration file location.
29
+ def get(key, params = {})
30
+ option = Options.option(key)
31
+ settings = settings_read(key, params)
32
+ value = settings ? settings.get(key, option.default) : option.default
33
+
34
+ # cast value to expected type.
35
+ base_path = config_base_path(settings.location) if settings
36
+ cast(value, option.type, base_path: base_path)
37
+ end
38
+
39
+ # Change a configuration setting. By default the project configuration
40
+ # file is changed if a project configuration file exists,
41
+ # otherwise the user configuration file is changed.
42
+ # @param key [String] configuration key
43
+ # @param params [Hash] options
44
+ # @return [void]
45
+ def set(key, value, params = {})
46
+ settings_write(key, params).set(key, value)
47
+ save
48
+ end
49
+
50
+ # Remove a configuration setting
51
+ # @param key [String] configuration key to remove
52
+ # @param params [Hash] options
53
+ # @return [void]
54
+ def unset(key, params = {})
55
+ settings_write(key, params).unset(key)
56
+ save
57
+ end
58
+
59
+ # If key is an array type, adds the value to the existing list.
60
+ # Raises an error for non array types.
61
+ # @param key [String] configuration key
62
+ # @param value [Object] value to add to the list
63
+ # @param params [Hash] options
64
+ # @return [void]
65
+ def add(key, value, params = {})
66
+ settings_write(key, params).add(key, value)
67
+ save
68
+ end
69
+
70
+ # If key is an array type, removes the value from the existing list.
71
+ # Raises an error for non array types.
72
+ # @param key [String] configuration key
73
+ # @param value [Object] value to remove from the list
74
+ # @param params [Hash] options
75
+ # @return [void]
76
+ def subtract(key, value, params = {})
77
+ settings_write(key, params).subtract(key, value)
78
+ save
79
+ end
80
+
81
+ # Get all configuration settings
82
+ # @param params [Hash] options
83
+ def all(params = {})
84
+ settings = {}
85
+ Options.options.each_value do |option|
86
+ settings[option.name] = get(option.name, params)
87
+ end
88
+ settings
89
+ end
90
+
91
+ # Test if configuration includes the given key
92
+ # @param key [String] configuration key
93
+ # @param params [Hash] options
94
+ # @return [boolean] true if the configuration key is set
95
+ def include?(key, params = {})
96
+ settings = settings_read(key, params)
97
+ settings && settings.include?(key)
98
+ end
99
+
100
+ private
101
+
102
+ include Translatomatic::Util
103
+ include Translatomatic::TypeCast
104
+
105
+ # Save configuration settings
106
+ def save
107
+ Files.save(@settings[:user])
108
+ Files.save(@settings[:project])
109
+ end
110
+
111
+ # Load configuration from the config file(s)
112
+ def load
113
+ @settings = {}
114
+ @settings[:env] = LocationSettings.from_environment
115
+ @settings[:user] = Files.load(@user_path, location: :user)
116
+ @settings[:project] = Files.load(@project_path, location: :project)
117
+ @settings[:runtime] = LocationSettings.runtime(@runtime)
118
+ end
119
+
120
+ def settings_write(key, params = {})
121
+ selector = Selector.new(@settings, default_location, params)
122
+ selector.settings_for_write(key)
123
+ end
124
+
125
+ def settings_read(key, params = {})
126
+ selector = Selector.new(@settings, nil, params)
127
+ selector.settings_for_read(key)
128
+ end
129
+
130
+ def default_location
131
+ # use project location if we have project configuration
132
+ @project_path ? :project : :user
133
+ end
134
+
135
+ # return base path for the config file at the given location
136
+ def config_base_path(location)
137
+ case location
138
+ when :user
139
+ user_path
140
+ when :project
141
+ project_path
142
+ when :runtime, :env
143
+ Dir.pwd
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end