web_translate_it 2.6.0 → 2.6.3.pre1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fe142160ce726176d6463e38dff4cbabe3c65a2629e537afd070aa9a273e44c2
4
- data.tar.gz: 447cc0c48efca6fbf66588f4426c1583f6945f59118593b5d8be5a7c81db40a4
3
+ metadata.gz: 173ab262e04fc47e5c64636a93414ca39f69ee400950a57fb6df13f0df2cd9e2
4
+ data.tar.gz: d0e5e1acc433b7fd4b42c685b55d9df142fe93e1f09e99ca86c3f1f4f722e52e
5
5
  SHA512:
6
- metadata.gz: 11cc21a06894851d8ead43d573ef69c197e0132f1b38b0c65b27c29541ce5409e0a076147f323f61d1fc1e8f0d89f91050d4011e421e5907e5d7d493a4939806
7
- data.tar.gz: 9b8bad87f54a5ff65265b34e71523fbd3bb6aca4f95293d8c59bb970d8bc6de7fae9ea7d2cf3078a0004ffdd4720c03bc0f9ca59a3198390585698a73b6f08bb
6
+ metadata.gz: 5460467df6c3b1276fe83c9c7d60f80810c4f91211251babd3d1fd7d37e9619b2793d39063cccb9731267074d52197f2c5dc2288c95f9d9ac03d90930a80a5f1
7
+ data.tar.gz: 390ff085d8d5ede3e6d146c9f5b7620aa62b8d1502a4d97410f42a9b7fe4f0ccaf643b5c633b110546a666716f0fae41d238b65400ee9aae78babbdca73db109
data/history.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## Version 2.6.3.pre1 / 2022-06-14
2
+
3
+ * Fix deprecation warning. #181
4
+ * Set minimum ruby version to 2.6. It is [EOL since December 2018](https://endoflife.date/ruby), but it’s still the default ruby shipped with Mac OS Monterey.
5
+
6
+ ## Version 2.6.2 / 2022-04-05
7
+
8
+ * Fix `wti init` command with ruby 3.1. #177
9
+
10
+ ## Version 2.6.1 / 2022-03-09
11
+
12
+ * Display error message for `before_pull`, `after_pull`, `before_push`, `after_push` hooks.
13
+ * Remove `silence_errors` option in configuration file. If SSL isn’t properly configured, it needs to be fixed by updating your cert chain.
14
+
1
15
  ## Version 2.6.0 / 2022-03-08
2
16
 
3
17
  * Code cleaning using Rubocop.
@@ -51,7 +51,7 @@ module WebTranslateIt
51
51
  end
52
52
  files = found_files if parameters.any?
53
53
  files = files.uniq.sort { |a, b| a.file_path <=> b.file_path }
54
- if files.size == 0
54
+ if files.empty?
55
55
  puts 'No files to pull.'
56
56
  else
57
57
  # Now actually pulling files
@@ -82,10 +82,10 @@ module WebTranslateIt
82
82
  return unless configuration.before_pull
83
83
 
84
84
  output = `#{configuration.before_pull}`
85
- if $?.success?
85
+ if $CHILD_STATUS.success?
86
86
  puts output
87
87
  else
88
- abort 'Error: exit code for before_pull command is not zero'
88
+ abort "Error: before_pull command exited with: #{output}"
89
89
  end
90
90
  end
91
91
 
@@ -93,10 +93,10 @@ module WebTranslateIt
93
93
  return unless configuration.after_pull
94
94
 
95
95
  output = `#{configuration.after_pull}`
96
- if $?.success?
96
+ if $CHILD_STATUS.success?
97
97
  puts output
98
98
  else
99
- abort 'Error: exit code for after_pull command is not zero'
99
+ abort "Error: after_pull command exited with: #{output}"
100
100
  end
101
101
  end
102
102
 
@@ -111,7 +111,7 @@ module WebTranslateIt
111
111
  else
112
112
  configuration.files.find_all { |file| file.locale == locale }.sort { |a, b| a.file_path <=> b.file_path }
113
113
  end
114
- if files.size == 0
114
+ if files.empty?
115
115
  puts "Couldn't find any local files registered on WebTranslateIt to push."
116
116
  else
117
117
  files.each do |file|
@@ -129,10 +129,10 @@ module WebTranslateIt
129
129
  return unless configuration.before_push
130
130
 
131
131
  output = `#{configuration.before_push}`
132
- if $?.success?
132
+ if $CHILD_STATUS.success?
133
133
  puts output
134
134
  else
135
- abort 'Error: exit code for before_push command is not zero'
135
+ abort "Error: before_push command exited with: #{output}"
136
136
  end
137
137
  end
138
138
 
@@ -140,10 +140,10 @@ module WebTranslateIt
140
140
  return unless configuration.after_push
141
141
 
142
142
  output = `#{configuration.after_push}`
143
- if $?.success?
143
+ if $CHILD_STATUS.success?
144
144
  puts output
145
145
  else
146
- abort 'Error: exit code for after_push command is not zero'
146
+ abort "Error: after_push command exited with: #{output}"
147
147
  end
148
148
  end
149
149
 
@@ -294,7 +294,11 @@ module WebTranslateIt
294
294
  path = Util.ask(' Path to configuration file:', '.wti')
295
295
  end
296
296
  FileUtils.mkpath(path.split('/')[0..path.split('/').size - 2].join('/')) unless path.split('/').size == 1
297
- project = YAML.load WebTranslateIt::Project.fetch_info(api_key)
297
+ project = if RUBY_VERSION >= '3.1'
298
+ YAML.safe_load WebTranslateIt::Project.fetch_info(api_key), permitted_classes: [Time]
299
+ else
300
+ YAML.load WebTranslateIt::Project.fetch_info(api_key)
301
+ end
298
302
  project_info = project['project']
299
303
  if File.exist?(path) && !File.writable?(path)
300
304
  puts StringUtil.failure("Error: `#{path}` file is not writable.")
@@ -414,30 +418,35 @@ module WebTranslateIt
414
418
 
415
419
  def generate_configuration(api_key, project_info)
416
420
  <<~FILE
421
+ # Required - The Project API Token from WebTranslateIt.com
422
+ # More information: https://github.com/webtranslateit/webtranslateit/wiki#configuration-file
423
+
417
424
  api_key: #{api_key}
418
425
 
419
- # Optional: locales not to sync with WebTranslateIt.
426
+ # Optional - Locales not to sync with WebTranslateIt.
427
+ # Takes a string, a symbol, or an array of string or symbol.
428
+
429
+ # ignore_locales: [#{project_info['source_locale']['code']}]
430
+
431
+ # Optional - Locales to sync with WebTranslateIt.
420
432
  # Takes a string, a symbol, or an array of string or symbol.
421
- # More information here: https://github.com/AtelierConvivialite/webtranslateit/wiki
422
- # ignore_locales: '#{project_info['source_locale']['code']}'
423
433
 
424
- # Or if you prefer a list of locales to sync with WebTranslateIt:
425
434
  # needed_locales: #{project_info['target_locales'].map { |locale| locale['code'] }}
426
435
 
427
436
  # Optional: files not to sync with WebTranslateIt.
428
437
  # Takes an array of globs.
438
+
429
439
  # ignore_files: ['somefile*.csv']
430
440
 
431
- # Optional
441
+ # Optional - Hooks
442
+ # Takes a string containing a command to run.
443
+
432
444
  # before_pull: "echo 'some unix command'" # Command executed before pulling files
433
445
  # after_pull: "touch tmp/restart.txt" # Command executed after pulling files
434
- #
446
+
435
447
  # before_push: "echo 'some unix command'" # Command executed before pushing files
436
448
  # after_push: "touch tmp/restart.txt" # Command executed after pushing files
437
449
 
438
- # Silence SSL errors
439
- # silence_errors: true
440
-
441
450
  FILE
442
451
  end
443
452
 
@@ -17,7 +17,7 @@ module WebTranslateIt
17
17
  self.path = root_path
18
18
  self.logger = logger
19
19
  if File.exist?(File.expand_path(path_to_config_file, path))
20
- self.api_key = ENV['WTI_PROJECT_API_KEY'] || configuration['api_key']
20
+ self.api_key = ENV.fetch('WTI_PROJECT_API_KEY') { configuration['api_key'] }
21
21
  self.before_pull = configuration['before_pull']
22
22
  self.after_pull = configuration['after_pull']
23
23
  self.before_push = configuration['before_push']
@@ -32,7 +32,6 @@ module WebTranslateIt
32
32
  set_locales_needed(configuration)
33
33
  set_files(project_info['project'])
34
34
  set_locales(project_info['project'])
35
- WebTranslateIt::Connection.turn_silent_on if configuration['silence_errors']
36
35
  self.project_name = project_info['project']['name']
37
36
  else
38
37
  puts StringUtil.failure("\nNo configuration file found in #{File.expand_path(path_to_config_file, path)}")
@@ -42,13 +41,12 @@ module WebTranslateIt
42
41
 
43
42
  # Reload project data
44
43
  #
45
- def reload # rubocop:todo Metrics/AbcSize
44
+ def reload
46
45
  project_info = YAML.load WebTranslateIt::Project.fetch_info(api_key)
47
46
  set_locales_to_ignore(configuration)
48
47
  set_locales_needed(configuration)
49
48
  set_files(project_info['project'])
50
49
  set_locales(project_info['project'])
51
- WebTranslateIt::Connection.turn_silent_on if configuration['silence_errors']
52
50
  self.project_name = project_info['project']['name']
53
51
  end
54
52
 
@@ -70,7 +68,7 @@ module WebTranslateIt
70
68
  def set_files(project) # rubocop:todo Metrics/AbcSize
71
69
  self.files = []
72
70
  project['project_files'].each do |project_file|
73
- if project_file['name'].nil? or project_file['name'].strip == ''
71
+ if project_file['name'].nil? || (project_file['name'].strip == '')
74
72
  puts "File #{project_file['id']} not set up"
75
73
  elsif ignore_files&.any? { |glob| File.fnmatch(glob, project_file['name']) }
76
74
  puts "Ignoring #{project_file['name']}"
@@ -1,15 +1,16 @@
1
+ require 'English'
1
2
  module WebTranslateIt
2
3
  class Connection
4
+ attr_reader :api_key, :http_connection
5
+
3
6
  require 'net/http'
4
7
  require 'net/https'
5
8
  require 'openssl'
6
9
  require 'uri'
7
- require 'ostruct'
8
10
 
9
- @@api_key = nil
10
- @@http_connection = nil
11
- @@debug = false
12
- @@silent = false
11
+ @api_key = nil
12
+ @http_connection = nil
13
+ @debug = false
13
14
 
14
15
  #
15
16
  # Initialize and yield a HTTPS Keep-Alive connection to WebTranslateIt.com
@@ -27,44 +28,32 @@ module WebTranslateIt
27
28
  # end
28
29
  #
29
30
  def initialize(api_key) # rubocop:todo Metrics/CyclomaticComplexity, Metrics/AbcSize, Metrics/MethodLength
30
- @@api_key = api_key
31
- proxy = ENV['http_proxy'] ? URI.parse(ENV['http_proxy']) : OpenStruct.new
31
+ @api_key = api_key
32
+ proxy = ENV['http_proxy'] ? URI.parse(ENV['http_proxy']) : Struct.new(:host, :port, :user, :password).new
32
33
  http = Net::HTTP::Proxy(proxy.host, proxy.port, proxy.user, proxy.password).new('webtranslateit.com', 443)
33
34
  http.use_ssl = true
34
35
  http.open_timeout = http.read_timeout = 60
35
- http.set_debug_output($stderr) if @@debug
36
+ http.set_debug_output($stderr) if @debug
36
37
  begin
37
- http.verify_mode = OpenSSL::SSL::VERIFY_PEER
38
- @@http_connection = http.start
39
- yield @@http_connection if block_given?
38
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
39
+ @http_connection = http.start
40
+ yield @http_connection if block_given?
40
41
  rescue OpenSSL::SSL::SSLError
41
- puts 'Unable to verify SSL certificate.' unless @@silent
42
+ puts 'Unable to verify SSL certificate.' unless @silent
42
43
  http = Net::HTTP::Proxy(proxy.host, proxy.port, proxy.user, proxy.password).new('webtranslateit.com', 443)
43
- http.set_debug_output($stderr) if @@debug
44
+ http.set_debug_output($stderr) if @debug
44
45
  http.use_ssl = true
45
46
  http.open_timeout = http.read_timeout = 60
46
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
47
- @@http_connection = http.start
48
- yield @@http_connection if block_given?
47
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
48
+ @http_connection = http.start
49
+ yield @http_connection if block_given?
49
50
  rescue
50
- puts $!
51
+ puts $ERROR_INFO
51
52
  end
52
53
  end
53
54
 
54
- def self.http_connection
55
- @@http_connection
56
- end
57
-
58
55
  def self.turn_debug_on
59
- @@debug = true
60
- end
61
-
62
- def self.turn_silent_on
63
- @@silent = true
64
- end
65
-
66
- def self.api_key
67
- @@api_key
56
+ @debug = true
68
57
  end
69
58
  end
70
59
  end
@@ -1,3 +1,4 @@
1
+ require 'English'
1
2
  module WebTranslateIt
2
3
  class Project
3
4
  def self.fetch_info(api_key) # rubocop:todo Metrics/AbcSize, Metrics/MethodLength
@@ -16,14 +17,14 @@ module WebTranslateIt
16
17
  end
17
18
  rescue Timeout::Error
18
19
  puts 'Request timeout. Will retry in 5 seconds.'
19
- if (tries -= 1) > 0
20
+ if (tries -= 1).positive?
20
21
  sleep(5)
21
22
  retry
22
23
  else
23
24
  success = false
24
25
  end
25
26
  rescue
26
- puts $!.inspect
27
+ puts $ERROR_INFO.inspect
27
28
  end
28
29
  success
29
30
  end
@@ -39,7 +40,7 @@ module WebTranslateIt
39
40
  end
40
41
  rescue Timeout::Error
41
42
  puts 'Request timeout. Will retry in 5 seconds.'
42
- if (tries -= 1) > 0
43
+ if (tries -= 1).positive?
43
44
  sleep(5)
44
45
  retry
45
46
  else
@@ -59,7 +60,7 @@ module WebTranslateIt
59
60
  Util.handle_response(Connection.http_connection.request(request), true)
60
61
  rescue Timeout::Error
61
62
  puts 'Request timeout. Will retry in 5 seconds.'
62
- if (tries -= 1) > 0
63
+ if (tries -= 1).positive?
63
64
  sleep(5)
64
65
  retry
65
66
  else
@@ -78,7 +79,7 @@ module WebTranslateIt
78
79
  Util.handle_response(Connection.http_connection.request(request), true)
79
80
  rescue Timeout::Error
80
81
  puts 'Request timeout. Will retry in 5 seconds.'
81
- if (tries -= 1) > 0
82
+ if (tries -= 1).positive?
82
83
  sleep(5)
83
84
  retry
84
85
  else
@@ -78,7 +78,7 @@ module WebTranslateIt
78
78
  return strings
79
79
  rescue Timeout::Error
80
80
  puts 'Request timeout. Will retry in 5 seconds.'
81
- if (tries -= 1) > 0
81
+ if (tries -= 1).positive?
82
82
  sleep(5)
83
83
  retry
84
84
  else
@@ -102,7 +102,7 @@ module WebTranslateIt
102
102
  # to find and instantiate the String which ID is `1234`.
103
103
  #
104
104
 
105
- def self.find(id) # rubocop:todo Metrics/MethodLength
105
+ def self.find(id) # rubocop:todo Metrics/MethodLength, Metrics/AbcSize
106
106
  success = true
107
107
  tries ||= 3
108
108
  request = Net::HTTP::Get.new("/api/projects/#{Connection.api_key}/strings/#{id}.yaml")
@@ -116,7 +116,7 @@ module WebTranslateIt
116
116
  return string
117
117
  rescue Timeout::Error
118
118
  puts 'Request timeout. Will retry in 5 seconds.'
119
- if (tries -= 1) > 0
119
+ if (tries -= 1).positive?
120
120
  sleep(5)
121
121
  retry
122
122
  else
@@ -160,7 +160,7 @@ module WebTranslateIt
160
160
  Util.handle_response(Connection.http_connection.request(request), true, true)
161
161
  rescue Timeout::Error
162
162
  puts 'Request timeout. Will retry in 5 seconds.'
163
- if (tries -= 1) > 0
163
+ if (tries -= 1).positive?
164
164
  sleep(5)
165
165
  retry
166
166
  else
@@ -198,7 +198,7 @@ module WebTranslateIt
198
198
  return translation
199
199
  rescue Timeout::Error
200
200
  puts 'Request timeout. Will retry in 5 seconds.'
201
- if (tries -= 1) > 0
201
+ if (tries -= 1).positive?
202
202
  sleep(5)
203
203
  retry
204
204
  else
@@ -229,7 +229,7 @@ module WebTranslateIt
229
229
  Util.handle_response(Connection.http_connection.request(request), true, true)
230
230
  rescue Timeout::Error
231
231
  puts 'Request timeout. Will retry in 5 seconds.'
232
- if (tries -= 1) > 0
232
+ if (tries -= 1).positive?
233
233
  sleep(5)
234
234
  retry
235
235
  else
@@ -255,7 +255,7 @@ module WebTranslateIt
255
255
  return true
256
256
  rescue Timeout::Error
257
257
  puts 'Request timeout. Will retry in 5 seconds.'
258
- if (tries -= 1) > 0
258
+ if (tries -= 1).positive?
259
259
  sleep(5)
260
260
  retry
261
261
  else
@@ -69,7 +69,7 @@ module WebTranslateIt
69
69
  return terms
70
70
  rescue Timeout::Error
71
71
  puts 'Request timeout. Will retry in 5 seconds.'
72
- if (tries -= 1) > 0
72
+ if (tries -= 1).positive?
73
73
  sleep(5)
74
74
  retry
75
75
  else
@@ -93,7 +93,7 @@ module WebTranslateIt
93
93
  # to find and instantiate the Term which ID is `1234`.
94
94
  #
95
95
 
96
- def self.find(term_id) # rubocop:todo Metrics/MethodLength
96
+ def self.find(term_id) # rubocop:todo Metrics/MethodLength, Metrics/AbcSize
97
97
  success = true
98
98
  tries ||= 3
99
99
  request = Net::HTTP::Get.new("/api/projects/#{Connection.api_key}/terms/#{term_id}.yaml")
@@ -107,7 +107,7 @@ module WebTranslateIt
107
107
  return term
108
108
  rescue Timeout::Error
109
109
  puts 'Request timeout. Will retry in 5 seconds.'
110
- if (tries -= 1) > 0
110
+ if (tries -= 1).positive?
111
111
  sleep(5)
112
112
  retry
113
113
  else
@@ -151,7 +151,7 @@ module WebTranslateIt
151
151
  Util.handle_response(Connection.http_connection.request(request), true, true)
152
152
  rescue Timeout::Error
153
153
  puts 'Request timeout. Will retry in 5 seconds.'
154
- if (tries -= 1) > 0
154
+ if (tries -= 1).positive?
155
155
  sleep(5)
156
156
  retry
157
157
  else
@@ -193,7 +193,7 @@ module WebTranslateIt
193
193
  return translations
194
194
  rescue Timeout::Error
195
195
  puts 'Request timeout. Will retry in 5 seconds.'
196
- if (tries -= 1) > 0
196
+ if (tries -= 1).positive?
197
197
  sleep(5)
198
198
  retry
199
199
  else
@@ -221,7 +221,7 @@ module WebTranslateIt
221
221
  Util.handle_response(Connection.http_connection.request(request), true, true)
222
222
  rescue Timeout::Error
223
223
  puts 'Request timeout. Will retry in 5 seconds.'
224
- if (tries -= 1) > 0
224
+ if (tries -= 1).positive?
225
225
  sleep(5)
226
226
  retry
227
227
  else
@@ -245,7 +245,7 @@ module WebTranslateIt
245
245
  return true
246
246
  rescue Timeout::Error
247
247
  puts 'Request timeout. Will retry in 5 seconds.'
248
- if (tries -= 1) > 0
248
+ if (tries -= 1).positive?
249
249
  sleep(5)
250
250
  retry
251
251
  else
@@ -69,7 +69,7 @@ module WebTranslateIt
69
69
  return true
70
70
  rescue Timeout::Error
71
71
  puts 'Request timeout. Will retry in 5 seconds.'
72
- if (tries -= 1) > 0
72
+ if (tries -= 1).positive?
73
73
  sleep(5)
74
74
  retry
75
75
  else
@@ -89,7 +89,7 @@ module WebTranslateIt
89
89
  Util.handle_response(Connection.http_connection.request(request), true, true)
90
90
  rescue Timeout::Error
91
91
  puts 'Request timeout. Will retry in 5 seconds.'
92
- if (tries -= 1) > 0
92
+ if (tries -= 1).positive?
93
93
  sleep(5)
94
94
  retry
95
95
  else
@@ -45,7 +45,7 @@ module WebTranslateIt
45
45
  Util.handle_response(Connection.http_connection.request(request), true, true)
46
46
  rescue Timeout::Error
47
47
  puts 'Request timeout. Will retry in 5 seconds.'
48
- if (tries -= 1) > 0
48
+ if (tries -= 1).positive?
49
49
  sleep(5)
50
50
  retry
51
51
  end
@@ -46,25 +46,25 @@ module WebTranslateIt
46
46
  display.push("*#{file_path}")
47
47
  end
48
48
  display.push "#{StringUtil.checksumify(local_checksum.to_s)}..#{StringUtil.checksumify(remote_checksum.to_s)}"
49
- if !File.exist?(file_path) or force or remote_checksum != local_checksum
49
+ if !File.exist?(file_path) || force || (remote_checksum != local_checksum)
50
50
  begin
51
51
  request = Net::HTTP::Get.new(api_url)
52
52
  WebTranslateIt::Util.add_fields(request)
53
- FileUtils.mkpath(file_path.split('/')[0..-2].join('/')) unless File.exist?(file_path) or file_path.split('/')[0..-2].join('/') == ''
53
+ FileUtils.mkpath(file_path.split('/')[0..-2].join('/')) unless File.exist?(file_path) || (file_path.split('/')[0..-2].join('/') == '')
54
54
  begin
55
55
  response = http_connection.request(request)
56
56
  File.open(file_path, 'wb') { |file| file << response.body } if response.code.to_i == 200
57
57
  display.push Util.handle_response(response)
58
58
  rescue Timeout::Error
59
59
  puts StringUtil.failure('Request timeout. Will retry in 5 seconds.')
60
- if (tries -= 1) > 0
60
+ if (tries -= 1).positive?
61
61
  sleep(5)
62
62
  retry
63
63
  else
64
64
  success = false
65
65
  end
66
66
  rescue
67
- display.push StringUtil.failure("An error occured: #{$!}")
67
+ display.push StringUtil.failure("An error occured: #{$ERROR_INFO}")
68
68
  success = false
69
69
  end
70
70
  end
@@ -97,9 +97,9 @@ module WebTranslateIt
97
97
  display.push(file_path)
98
98
  display.push "#{StringUtil.checksumify(local_checksum.to_s)}..#{StringUtil.checksumify(remote_checksum.to_s)}"
99
99
  if File.exist?(file_path)
100
- if force or remote_checksum != local_checksum
100
+ if force || (remote_checksum != local_checksum)
101
101
  File.open(file_path) do |file|
102
- params = { 'file' => UploadIO.new(file, 'text/plain', file.path), 'merge' => merge, 'ignore_missing' => ignore_missing, 'label' => label, 'low_priority' => low_priority, 'minor_changes' => minor_changes }
102
+ params = { 'file' => Multipart::Post::UploadIO.new(file, 'text/plain', file.path), 'merge' => merge, 'ignore_missing' => ignore_missing, 'label' => label, 'low_priority' => low_priority, 'minor_changes' => minor_changes }
103
103
  params['name'] = destination_path unless destination_path.nil?
104
104
  params['rename_others'] = rename_others
105
105
  request = Net::HTTP::Put::Multipart.new(api_url, params)
@@ -107,14 +107,14 @@ module WebTranslateIt
107
107
  display.push Util.handle_response(http_connection.request(request))
108
108
  rescue Timeout::Error
109
109
  puts StringUtil.failure('Request timeout. Will retry in 5 seconds.')
110
- if (tries -= 1) > 0 # rubocop:todo Metrics/BlockNesting
110
+ if (tries -= 1).positive? # rubocop:todo Metrics/BlockNesting
111
111
  sleep(5)
112
112
  retry
113
113
  else
114
114
  success = false
115
115
  end
116
116
  rescue
117
- display.push StringUtil.failure("An error occured: #{$!}")
117
+ display.push StringUtil.failure("An error occured: #{$ERROR_INFO}")
118
118
  success = false
119
119
  end
120
120
  else
@@ -150,20 +150,20 @@ module WebTranslateIt
150
150
  display.push "#{StringUtil.checksumify(local_checksum.to_s)}..[ ]"
151
151
  if File.exist?(file_path)
152
152
  File.open(file_path) do |file|
153
- request = Net::HTTP::Post::Multipart.new(api_url_for_create, { 'name' => file_path, 'file' => UploadIO.new(file, 'text/plain', file.path), 'low_priority' => low_priority })
153
+ request = Net::HTTP::Post::Multipart.new(api_url_for_create, { 'name' => file_path, 'file' => Multipart::Post::UploadIO.new(file, 'text/plain', file.path), 'low_priority' => low_priority })
154
154
  WebTranslateIt::Util.add_fields(request)
155
155
  display.push Util.handle_response(http_connection.request(request))
156
156
  puts ArrayUtil.to_columns(display)
157
157
  rescue Timeout::Error
158
158
  puts StringUtil.failure('Request timeout. Will retry in 5 seconds.')
159
- if (tries -= 1) > 0
159
+ if (tries -= 1).positive?
160
160
  sleep(5)
161
161
  retry
162
162
  else
163
163
  success = false
164
164
  end
165
165
  rescue
166
- display.push StringUtil.failure("An error occured: #{$!}")
166
+ display.push StringUtil.failure("An error occured: #{$ERROR_INFO}")
167
167
  success = false
168
168
  end
169
169
  else
@@ -187,14 +187,14 @@ module WebTranslateIt
187
187
  puts ArrayUtil.to_columns(display)
188
188
  rescue Timeout::Error
189
189
  puts StringUtil.failure('Request timeout. Will retry in 5 seconds.')
190
- if (tries -= 1) > 0
190
+ if (tries -= 1).positive?
191
191
  sleep(5)
192
192
  retry
193
193
  else
194
194
  success = false
195
195
  end
196
196
  rescue
197
- display.push StringUtil.failure("An error occured: #{$!}")
197
+ display.push StringUtil.failure("An error occured: #{$ERROR_INFO}")
198
198
  success = false
199
199
  end
200
200
  else
@@ -1,7 +1,7 @@
1
1
  class ArrayUtil
2
2
  def self.to_columns(arr)
3
3
  if arr[0][0] == '*'
4
- "*#{StringUtil.backward_truncate(arr[0][1..-1])} | #{arr[1]} #{arr[2]}\n"
4
+ "*#{StringUtil.backward_truncate(arr[0][1..])} | #{arr[1]} #{arr[2]}\n"
5
5
  else
6
6
  " #{StringUtil.backward_truncate(arr[0])} | #{arr[1]} #{arr[2]}\n"
7
7
  end
@@ -14,7 +14,7 @@ class ArrayUtil
14
14
  start = 0
15
15
  1.upto(pieces) do |i|
16
16
  last = start + mid
17
- last = last - 1 unless len % pieces >= i
17
+ last -= 1 unless len % pieces >= i
18
18
  chunks << (arr[start..last] || [])
19
19
  start = last + 1
20
20
  end
@@ -10,7 +10,7 @@ module WebTranslateIt
10
10
  end
11
11
 
12
12
  def self.calculate_percentage(processed, total)
13
- return 0 if total == 0
13
+ return 0 if total.zero?
14
14
 
15
15
  ((processed * 10) / total).to_f.ceil * 10
16
16
  end
@@ -19,7 +19,7 @@ module WebTranslateIt
19
19
  # rubocop:todo Metrics/MethodLength
20
20
  # rubocop:todo Metrics/AbcSize
21
21
  def self.handle_response(response, return_response = false, raise_exception = false) # rubocop:todo Metrics/CyclomaticComplexity, Metrics/AbcSize, Metrics/MethodLength, Metrics/PerceivedComplexity
22
- if response.code.to_i >= 400 and response.code.to_i < 500
22
+ if (response.code.to_i >= 400) && (response.code.to_i < 500)
23
23
  raise "Error: #{MultiJson.load(response.body)['error']}" if raise_exception
24
24
 
25
25
  puts StringUtil.failure(MultiJson.load(response.body)['error'])
@@ -80,13 +80,13 @@ module WebTranslateIt
80
80
  # Ask a question. Returns an answer.
81
81
 
82
82
  def self.ask(question, default = nil)
83
- question = question + " (Default: #{default})" unless default.nil?
83
+ question += " (Default: #{default})" unless default.nil?
84
84
  print("#{question} ")
85
85
  $stdout.flush
86
86
 
87
87
  result = $stdin.gets
88
88
  result&.chomp!
89
- result = default if result.nil? or result == ''
89
+ result = default if result.nil? || (result == '')
90
90
  result
91
91
  end
92
92
 
@@ -13,6 +13,8 @@ require 'web_translate_it/auto_fetch'
13
13
  require 'web_translate_it/command_line'
14
14
  require 'web_translate_it/project'
15
15
 
16
+ require 'English'
17
+
16
18
  module WebTranslateIt
17
19
  def self.fetch_translations # rubocop:todo Metrics/AbcSize
18
20
  config = Configuration.new
data/readme.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # WebTranslateIt Synchronization Tool : wti
2
2
 
3
- [RubyDoc](https://rubydoc.info/github/webtranslateit/webtranslateit/master) |
4
- [Report a bug](https://github.com/webtranslateit/webtranslateit/issues) |
3
+ [RubyDoc](https://www.rubydoc.info/gems/web_translate_it/) |
4
+ [Report a bug](https://github.com/webtranslateit/webtranslateit/issues) |
5
5
  [Support](https://webtranslateit.com/support) |
6
6
  [WebTranslateIt.com Homepage](https://webtranslateit.com)
7
7
 
@@ -32,7 +32,7 @@ Fetching: web_translate_it-2.1.3.gem (100%)
32
32
  Successfully installed web_translate_it-2.1.3
33
33
  1 gem installed
34
34
  ```
35
-
35
+
36
36
  At this point you should have the `wti` executable working:
37
37
 
38
38
  ``` bash
@@ -83,9 +83,9 @@ Please refer to [our documentation about syncing multiple projects](https://gith
83
83
  Execute `wti --help` to see the usage:
84
84
 
85
85
  Usage: wti <command> [options]+
86
-
86
+
87
87
  The most commonly used wti commands are:
88
-
88
+
89
89
  pull Pull target language file(s)
90
90
  push Push master language file(s)
91
91
  match Display matching of local files with File Manager
@@ -96,7 +96,7 @@ Execute `wti --help` to see the usage:
96
96
  init Configure your project to sync
97
97
 
98
98
  See `wti <command> --help` for more information on a specific command.
99
-
99
+
100
100
  [options] are:
101
101
  --config, -c <s>: Path to a translation.yml file (default: .wti)
102
102
  --version, -v: Print version and exit
@@ -217,7 +217,7 @@ There are 4 hooks:
217
217
  * `before_push`
218
218
  * `after_push`
219
219
 
220
- Check the [sample `.wti`](https://github.com/webtranslateit/webtranslateit/blob/master/examples/.wti#L9..L13) file for implementation.
220
+ Check the [sample `.wti`](https://github.com/webtranslateit/webtranslateit/blob/master/examples/.wti#L16-L21) file for implementation.
221
221
 
222
222
  ## Exit codes
223
223
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: web_translate_it
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.6.0
4
+ version: 2.6.3.pre1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Edouard Briere
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-03-08 00:00:00.000000000 Z
11
+ date: 2022-06-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: multi_json
@@ -156,12 +156,6 @@ files:
156
156
  - man/wti.1.html
157
157
  - man/wti.1.ron
158
158
  - readme.md
159
- - spec/examples/config/translation.yml
160
- - spec/examples/en.yml
161
- - spec/spec_helper.rb
162
- - spec/web_translate_it/auto_fetch_spec.rb
163
- - spec/web_translate_it/string_spec.rb
164
- - spec/web_translate_it/term_spec.rb
165
159
  homepage: https://webtranslateit.com
166
160
  licenses:
167
161
  - MIT
@@ -183,21 +177,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
183
177
  requirements:
184
178
  - - ">="
185
179
  - !ruby/object:Gem::Version
186
- version: '2.5'
180
+ version: '2.6'
187
181
  required_rubygems_version: !ruby/object:Gem::Requirement
188
182
  requirements:
189
- - - ">="
183
+ - - ">"
190
184
  - !ruby/object:Gem::Version
191
- version: '0'
185
+ version: 1.3.1
192
186
  requirements: []
193
- rubygems_version: 3.1.6
187
+ rubygems_version: 3.3.13
194
188
  signing_key:
195
189
  specification_version: 4
196
190
  summary: A CLI tool to sync locale files with WebTranslateIt.com.
197
- test_files:
198
- - spec/web_translate_it/auto_fetch_spec.rb
199
- - spec/web_translate_it/term_spec.rb
200
- - spec/web_translate_it/string_spec.rb
201
- - spec/spec_helper.rb
202
- - spec/examples/config/translation.yml
203
- - spec/examples/en.yml
191
+ test_files: []
@@ -1,9 +0,0 @@
1
- # The Project API Token from Web Translate It
2
- api_key: 4af21ce1fb3a4f7127a60b31ebc41c1446b38bb2
3
-
4
- # Optional: locales not to sync with Web Translate It.
5
- # eg. [:en, :fr] or just 'en'
6
- # ignore_locales: :en
7
-
8
- # Silence SSL errors
9
- # silence_errors: true
data/spec/examples/en.yml DELETED
@@ -1,38 +0,0 @@
1
- en:
2
- activerecord:
3
- errors:
4
- templates:
5
- header:
6
- one: "1 error prohibited this {{model}} from being saved"
7
- other: "{{count}} errors prohibited this {{model}} from being saved"
8
- body: "there were problems with the following fields:"
9
- messages:
10
- accepted: "must be accepted"
11
- blank: "can't be blank"
12
- confirmation: "doesn't match confirmation"
13
- empty: "can't be empty"
14
- equal_to: "must be equal to {{count}}"
15
- even: "must be even"
16
- exclusion: "is reserved"
17
- greater_than: "must be greater than {{count}}"
18
- greater_than_or_equal_to: "must be greater than or equal to {{count}}"
19
- inclusion: "is not included in the list"
20
- invalid: "is invalid"
21
- less_than: "must be less than {{count}}"
22
- less_than_or_equal_to: "must be less than or equal to {{count}}"
23
- not_a_number: "is not a number"
24
- odd: "must be odd"
25
- taken: "is already taken"
26
- too_long: "is too long (maximum is {{count}} characters)"
27
- too_short: "is too short (minimum is {{count}} characters)"
28
- wrong_length: "is the wrong length (should be {{count}} characters)"
29
- models:
30
- invitation:
31
- attributes:
32
- email:
33
- user_already_invited: "This user has already been invited"
34
- user_already_member: "This user is already a member"
35
- project_file:
36
- attributes:
37
- file:
38
- file_format_not_supported: "Sorry, we currenly support only Gettext .pot/.po, .yml/.yaml and .strings"
data/spec/spec_helper.rb DELETED
@@ -1,11 +0,0 @@
1
- if ENV['COVERAGE']
2
- require 'simplecov'
3
- SimpleCov.start
4
- end
5
-
6
- require File.expand_path('../lib/web_translate_it', __dir__)
7
- require 'rspec'
8
-
9
- class I18n
10
- def self.reload!; end
11
- end
@@ -1,47 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe WebTranslateIt::AutoFetch do
4
- let(:application) { double(:application, call: []) }
5
-
6
- let(:env) do
7
- { 'PATH_INFO' => path }
8
- end
9
-
10
- subject { described_class.new(application) }
11
-
12
- before { WebTranslateIt.stub(:fetch_translations) }
13
-
14
- after { subject.call(env) }
15
-
16
- context 'path is /' do
17
- let(:path) { '/' }
18
-
19
- it 'should call the application' do
20
- application.should_receive(:call).with(env)
21
- end
22
-
23
- it 'should update the translations' do
24
- WebTranslateIt.should_receive(:fetch_translations)
25
- end
26
-
27
- it 'should reload the I18n definitions' do
28
- I18n.should_receive(:reload!)
29
- end
30
- end
31
-
32
- context 'path is /assets/application.js' do
33
- let(:path) { '/assets/application.js' }
34
-
35
- it 'should call the application' do
36
- application.should_receive(:call).with(env)
37
- end
38
-
39
- it 'should not update the translations' do
40
- WebTranslateIt.should_not_receive(:fetch_translations)
41
- end
42
-
43
- it 'should not reload the I18n definitions' do
44
- I18n.should_not_receive(:reload!)
45
- end
46
- end
47
- end
@@ -1,153 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe WebTranslateIt::String do
4
- let(:api_key) { 'proj_pvt_glzDR250FLXlMgJPZfEyHQ' }
5
-
6
- describe '#initialize' do
7
- it 'should assign api_key and many parameters' do
8
- string = WebTranslateIt::String.new({ 'id' => 1234, 'key' => 'bacon' })
9
- string.id.should == 1234
10
- string.key.should == 'bacon'
11
- end
12
-
13
- it 'should assign parameters using symbols' do
14
- string = WebTranslateIt::String.new({ id: 1234, key: 'bacon' })
15
- string.id.should == 1234
16
- string.key.should == 'bacon'
17
- end
18
- end
19
-
20
- describe '#save' do
21
- it 'should create a new String' do
22
- WebTranslateIt::Connection.new(api_key) do
23
- string = WebTranslateIt::String.new({ 'key' => 'bacon' })
24
- string.save
25
- string.id.should_not be_nil
26
- string_fetched = WebTranslateIt::String.find(string.id)
27
- string_fetched.should_not be_nil
28
- string_fetched.should be_a(WebTranslateIt::String)
29
- string_fetched.id.should == string.id
30
- string.delete
31
- end
32
- end
33
-
34
- it 'should update an existing String' do
35
- WebTranslateIt::Connection.new(api_key) do
36
- string = WebTranslateIt::String.new({ 'key' => 'bacony' })
37
- string.save
38
- string.key = 'bacon changed'
39
- string.save
40
- string_fetched = WebTranslateIt::String.find(string.id)
41
- string_fetched.key.should == 'bacon changed'
42
- string.delete
43
- end
44
- end
45
-
46
- it 'should create a new String with Translation' do
47
- translation1 = WebTranslateIt::Translation.new({ 'locale' => 'en', 'text' => 'Hello' })
48
- translation2 = WebTranslateIt::Translation.new({ 'locale' => 'fr', 'text' => 'Bonjour' })
49
-
50
- string = WebTranslateIt::String.new({ 'key' => 'bacon', 'translations' => [translation1, translation2] })
51
- WebTranslateIt::Connection.new(api_key) do
52
- string.save
53
- string_fetched = WebTranslateIt::String.find(string.id)
54
- string_fetched.translation_for('en').should_not be_nil
55
- string_fetched.translation_for('en').text.should == 'Hello'
56
- string_fetched.translation_for('fr').should_not be_nil
57
- string_fetched.translation_for('fr').text.should == 'Bonjour'
58
- string_fetched.translation_for('es').should be_nil
59
- string.delete
60
- end
61
- end
62
-
63
- it 'should update a String and save its Translation' do
64
- translation1 = WebTranslateIt::Translation.new({ 'locale' => 'en', 'text' => 'Hello' })
65
- translation2 = WebTranslateIt::Translation.new({ 'locale' => 'fr', 'text' => 'Bonjour' })
66
-
67
- string = WebTranslateIt::String.new({ 'key' => 'bacon' })
68
- WebTranslateIt::Connection.new(api_key) do
69
- string.save
70
- string_fetched = WebTranslateIt::String.find(string.id)
71
- string_fetched.translation_for('fr').should be_nil
72
-
73
- string_fetched.translations = [translation1, translation2]
74
- string_fetched.save
75
-
76
- string_fetched = WebTranslateIt::String.find(string.id)
77
- string_fetched.translation_for('en').should_not be_nil
78
- string_fetched.translation_for('en').text.should == 'Hello'
79
- string_fetched.translation_for('fr').should_not be_nil
80
- string_fetched.translation_for('fr').text.should == 'Bonjour'
81
- string.delete
82
- end
83
- end
84
- end
85
-
86
- describe '#delete' do
87
- it 'should delete a String' do
88
- string = WebTranslateIt::String.new({ 'key' => 'bacon' })
89
- WebTranslateIt::Connection.new(api_key) do
90
- string.save
91
- string_fetched = WebTranslateIt::String.find(string.id)
92
- string_fetched.should_not be_nil
93
-
94
- string_fetched.delete
95
- WebTranslateIt::String.find(string.id).should be_nil
96
- end
97
- end
98
- end
99
-
100
- describe '#find_all' do
101
- it 'should find many strings' do
102
- WebTranslateIt::Connection.new(api_key) do
103
- string1 = WebTranslateIt::String.new({ 'key' => 'one two three' })
104
- string1.save
105
- string2 = WebTranslateIt::String.new({ 'key' => 'four five six' })
106
- string2.save
107
- string3 = WebTranslateIt::String.new({ 'key' => 'six seven eight' })
108
- string3.save
109
-
110
- strings = WebTranslateIt::String.find_all({ 'key' => 'six' })
111
- strings.count.should == 2
112
- strings[0].key.should == 'four five six'
113
- strings[1].key.should == 'six seven eight'
114
-
115
- strings = WebTranslateIt::String.find_all({ key: 'six' })
116
- strings.count.should == 2
117
- strings[0].key.should == 'four five six'
118
- strings[1].key.should == 'six seven eight'
119
-
120
- strings = WebTranslateIt::String.find_all({ 'key' => 'eight' })
121
- strings.count.should == 1
122
- strings[0].key.should == 'six seven eight'
123
-
124
- strings = WebTranslateIt::String.find_all({ 'key' => 'three' })
125
- strings.count.should == 1
126
- strings[0].key.should == 'one two three'
127
- end
128
- end
129
- end
130
-
131
- describe '#translation_for' do
132
- it 'should fetch translations' do
133
- translation = WebTranslateIt::Translation.new({ 'locale' => 'en', 'text' => 'Hello' })
134
- string = WebTranslateIt::String.new({ 'key' => 'greetings', 'translations' => [translation] })
135
- WebTranslateIt::Connection.new(api_key) do
136
- string.save
137
- string_fetched = WebTranslateIt::String.find(string.id)
138
- string_fetched.translation_for('en').should_not be_nil
139
- string_fetched.translation_for('en').text.should == 'Hello'
140
- string_fetched.translation_for('fr').should be_nil
141
- string.delete
142
- end
143
- end
144
-
145
- it 'should not return a stale object' do
146
- string = WebTranslateIt::String.new({ key: 'greetings 2' })
147
- translation = WebTranslateIt::Translation.new({ locale: 'es', text: 'text', string_id: string.id })
148
- string.translations << translation
149
- string.translation_for('fr').should be_nil
150
- string.translation_for('es').should_not be_nil
151
- end
152
- end
153
- end
@@ -1,121 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe WebTranslateIt::Term do
4
- let(:api_key) { 'proj_pvt_glzDR250FLXlMgJPZfEyHQ' }
5
-
6
- describe '#initialize' do
7
- it 'should assign api_key and many parameters' do
8
- term = WebTranslateIt::Term.new({ 'id' => 1234, 'text' => 'bacon' })
9
- term.id.should == 1234
10
- term.text.should == 'bacon'
11
- end
12
-
13
- it 'should assign parameters using symbols' do
14
- term = WebTranslateIt::Term.new({ id: 1234, text: 'bacon' })
15
- term.id.should == 1234
16
- term.text.should == 'bacon'
17
- end
18
- end
19
-
20
- describe '#save' do
21
- it 'should create a new Term' do
22
- WebTranslateIt::Connection.new(api_key) do
23
- term = WebTranslateIt::Term.new({ 'text' => 'Term', 'description' => 'A description' })
24
- term.save
25
- term.id.should_not be_nil
26
- term_fetched = WebTranslateIt::Term.find(term.id)
27
- term_fetched.should_not be_nil
28
- term_fetched.should be_a(WebTranslateIt::Term)
29
- term_fetched.id.should == term.id
30
- term.delete
31
- end
32
- end
33
-
34
- it 'should update an existing Term' do
35
- WebTranslateIt::Connection.new(api_key) do
36
- term = WebTranslateIt::Term.new({ 'text' => 'Term 2', 'description' => 'A description' })
37
- term.save
38
- term.text = 'A Term'
39
- term.save
40
- term_fetched = WebTranslateIt::Term.find(term.id)
41
- term_fetched.text.should == 'A Term'
42
- term.delete
43
- end
44
- end
45
-
46
- it 'should create a new Term with a TermTranslation' do
47
- translation1 = WebTranslateIt::TermTranslation.new({ 'locale' => 'fr', 'text' => 'Bonjour' })
48
- translation2 = WebTranslateIt::TermTranslation.new({ 'locale' => 'fr', 'text' => 'Salut' })
49
-
50
- term = WebTranslateIt::Term.new({ 'text' => 'Hello', 'translations' => [translation1, translation2] })
51
- WebTranslateIt::Connection.new(api_key) do
52
- term.save
53
- term_fetched = WebTranslateIt::Term.find(term.id)
54
- term_fetched.translation_for('fr').should_not be_nil
55
- term_fetched.translation_for('fr')[0].text.should == 'Salut'
56
- term_fetched.translation_for('fr')[1].text.should == 'Bonjour'
57
- term_fetched.translation_for('es').should be_nil
58
- term.delete
59
- end
60
- end
61
-
62
- it 'should update a Term and save its Translation' do
63
- translation1 = WebTranslateIt::TermTranslation.new({ 'locale' => 'fr', 'text' => 'Bonjour' })
64
- translation2 = WebTranslateIt::TermTranslation.new({ 'locale' => 'fr', 'text' => 'Salut' })
65
-
66
- term = WebTranslateIt::Term.new({ 'text' => 'Hi!' })
67
- WebTranslateIt::Connection.new(api_key) do
68
- term.save
69
- term_fetched = WebTranslateIt::Term.find(term.id)
70
- term_fetched.translation_for('fr').should be_nil
71
-
72
- term_fetched.translations = [translation1, translation2]
73
- term_fetched.save
74
-
75
- term_fetched = WebTranslateIt::Term.find(term.id)
76
- term_fetched.translation_for('fr').should_not be_nil
77
- term_fetched.translation_for('fr')[0].text.should == 'Salut'
78
- term_fetched.translation_for('fr')[1].text.should == 'Bonjour'
79
- term.delete
80
- end
81
- end
82
- end
83
-
84
- describe '#delete' do
85
- it 'should delete a Term' do
86
- term = WebTranslateIt::Term.new({ 'text' => 'bacon' })
87
- WebTranslateIt::Connection.new(api_key) do
88
- term.save
89
- term_fetched = WebTranslateIt::Term.find(term.id)
90
- term_fetched.should_not be_nil
91
-
92
- term_fetched.delete
93
- term_fetched = WebTranslateIt::Term.find(term.id)
94
- term_fetched.should be_nil
95
- end
96
- end
97
- end
98
-
99
- describe '#find_all' do
100
- it 'should fetch many terms' do
101
- WebTranslateIt::Connection.new(api_key) do
102
- terms = WebTranslateIt::Term.find_all
103
- count = terms.count
104
-
105
- term1 = WebTranslateIt::Term.new({ 'text' => 'greeting 1' })
106
- term1.save
107
- term2 = WebTranslateIt::Term.new({ 'text' => 'greeting 2' })
108
- term2.save
109
- term3 = WebTranslateIt::Term.new({ 'text' => 'greeting 3' })
110
- term3.save
111
-
112
- terms = WebTranslateIt::Term.find_all
113
- count - terms.count.should == 3
114
-
115
- term1.delete
116
- term2.delete
117
- term3.delete
118
- end
119
- end
120
- end
121
- end