lokalise_manager 2.0.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +58 -0
- data/README.md +40 -9
- data/lib/lokalise_manager/error.rb +1 -0
- data/lib/lokalise_manager/global_config.rb +8 -1
- data/lib/lokalise_manager/task_definitions/base.rb +9 -8
- data/lib/lokalise_manager/task_definitions/exporter.rb +17 -12
- data/lib/lokalise_manager/task_definitions/importer.rb +1 -0
- data/lib/lokalise_manager/utils/hash_utils.rb +3 -2
- data/lib/lokalise_manager/version.rb +1 -1
- data/lib/lokalise_manager.rb +13 -9
- data/lokalise_manager.gemspec +3 -2
- data/spec/lib/lokalise_manager/global_config_spec.rb +5 -0
- data/spec/lib/lokalise_manager/task_definitions/base_spec.rb +11 -7
- data/spec/lib/lokalise_manager/task_definitions/exporter_spec.rb +132 -72
- data/spec/lib/lokalise_manager/task_definitions/importer_spec.rb +18 -23
- data/spec/lib/{utils → lokalise_manager/utils}/hash_utils_spec.rb +0 -0
- data/spec/support/file_manager.rb +3 -1
- metadata +22 -11
- data/lib/lokalise_manager/utils/array_utils.rb +0 -27
- data/spec/lib/utils/array_utils_spec.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f68d621f5413a53e386f1d1f1539e8f824f6f3e90e81c0fb93c71e9e1c271c9a
|
4
|
+
data.tar.gz: ecaf5166531cb24f7fa6162ea11d86f885ead2e911f40543cdd08e717e9731e4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 659795e4573dab1751fa00b7d23ed43d6c9b276561fc763341b9a2d72dabadb9e8eeb638a7888d4f736b42e49efcb75a627d12c3b5bc63c9a46f369077dacb2c
|
7
|
+
data.tar.gz: f3681cca401d48512786731538697a2dcac4a7f47ab8d7037a6ce9444308dc4ab71ee34220218654dc71823c1d1a0b3945494015f6f822ac089ca87627a92d1d
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,63 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 3.0.0 (11-Mar-22)
|
4
|
+
|
5
|
+
* **Breaking change**: Require Ruby 2.7 or above
|
6
|
+
* **Breaking change (potentially)**: Use ruby-lokalise-api v6. In general, this transition should not affect you if you employ `export!` and `import!` methods only. However, please be aware that ruby-lokalise-api has a few breaking changes [listed in its own changelog](https://lokalise.github.io/ruby-lokalise-api/additional_info/changelog)
|
7
|
+
* Use Zeitwerk loader
|
8
|
+
* Prettify and update source code
|
9
|
+
|
10
|
+
## 2.2.0 (23-Feb-22)
|
11
|
+
|
12
|
+
* Use ruby-lokalise-api v5
|
13
|
+
* Don't use any compression options (compression is now enabled by default)
|
14
|
+
* Update tests
|
15
|
+
|
16
|
+
## 2.1.0 (27-Jan-22)
|
17
|
+
|
18
|
+
* **Breaking change**: `export!` will now return an array of objects responding to the following methods:
|
19
|
+
+ `success` — usually returns `true` (to learn more, check documentation for the `:raise_on_export_fail` option below)
|
20
|
+
+ `process` — returns an object (an instance of the `Lokalise::Resources::QueuedProcess`) representing a [queued background process](https://lokalise.github.io/ruby-lokalise-api/api/queued-processes) as uploading is done in the background on Lokalise. You can use this object to check the process status (whether the uploading is completed or not).
|
21
|
+
+ `path` — returns an instance of the `Pathname` class which represent the file being uploaded.
|
22
|
+
* Here's an example:
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
def uploaded?(process)
|
26
|
+
5.times do # try to check the status 5 times
|
27
|
+
process = process.reload_data # load new data
|
28
|
+
return(true) if process.status == 'finished' # return true is the upload has finished
|
29
|
+
sleep 1 # wait for 1 second, adjust this number with regards to the upload size
|
30
|
+
end
|
31
|
+
|
32
|
+
false # if all 5 checks failed, return false (probably something is wrong)
|
33
|
+
end
|
34
|
+
|
35
|
+
processes = exporter.export!
|
36
|
+
puts "Checking status for the #{processes[0].path} file"
|
37
|
+
uploaded? processes[0].process
|
38
|
+
```
|
39
|
+
|
40
|
+
* Introduced a new option `raise_on_export_fail` (`boolean`) which is `true` by default. When this option is enabled, LokaliseManager will re-raise any exceptions that happened during the file uploading. When this option is disabled, the exporting process will continue even if something goes wrong. In this case you'll probably need to check the result yourself and make the necessary actions. For example:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
processes = exporter.export!
|
44
|
+
|
45
|
+
processes.each do |proc_data|
|
46
|
+
if proc_data.success
|
47
|
+
# Everything is good, the uploading is queued
|
48
|
+
puts "#{proc_data.path} is sent to Lokalise!"
|
49
|
+
process = proc_data.process
|
50
|
+
puts "Current process status is #{process.status}"
|
51
|
+
else
|
52
|
+
# Something bad has happened
|
53
|
+
puts "Could not send #{proc_data.path} to Lokalise"
|
54
|
+
puts "Error #{proc_data.error.class}: #{proc_data.error.message}"
|
55
|
+
# Or you could re-raise this exception:
|
56
|
+
# raise proc_data.error.class
|
57
|
+
end
|
58
|
+
end
|
59
|
+
```
|
60
|
+
|
3
61
|
## 2.0.0 (27-Jan-22)
|
4
62
|
|
5
63
|
* `export!` method is now taking advantage of multi-threading (as Lokalise API allows to send requests in parallel since January 2022)
|
data/README.md
CHANGED
@@ -43,7 +43,7 @@ importer = LokaliseManager.importer api_token: '1234abc', project_id: '123.abc'
|
|
43
43
|
exporter = LokaliseManager.exporter api_token: '1234abc', project_id: '123.abc'
|
44
44
|
```
|
45
45
|
|
46
|
-
You *must* provide an API token and a project ID (your project ID can be found under Lokalise project settings). [Other options can be customized as well (see below)](
|
46
|
+
You *must* provide an API token and a project ID (your project ID can be found under Lokalise project settings). [Other options can be customized as well (see below)](#configuration) but they have sensible defaults.
|
47
47
|
|
48
48
|
### Importing files from Lokalise into your project
|
49
49
|
|
@@ -55,7 +55,7 @@ result = importer.import!
|
|
55
55
|
|
56
56
|
The `result` will contain a boolean value which says whether the operation was successfull or not.
|
57
57
|
|
58
|
-
Please note that upon importing translations any duplicating files inside the `locales` directory (or any other directory that you've specified in the options) will be overwritten
|
58
|
+
Please note that upon importing translations any duplicating files inside the `locales` directory (or any other directory that you've specified in the options) **will be overwritten**! You can enable [safe mode](#import-config) to check whether the folder is empty or not.
|
59
59
|
|
60
60
|
### Exporting files from your project to Lokalise
|
61
61
|
|
@@ -65,13 +65,21 @@ To upload your translation files from a local directory (defaults to `locales/`)
|
|
65
65
|
processes = exporter.export!
|
66
66
|
```
|
67
67
|
|
68
|
-
|
68
|
+
The uploading process is multi-threaded.
|
69
|
+
|
70
|
+
`processes` will contain an array of objects responding to the following methods:
|
71
|
+
|
72
|
+
* `#success` — usually returns `true` (to learn more, check documentation for the `:raise_on_export_fail` option below)
|
73
|
+
* `#process` — returns an object (an instance of the `RubyLokaliseApi::Resources::QueuedProcess`) representing a [queued background process](https://lokalise.github.io/ruby-lokalise-api/api/queued-processes) as uploading is done in the background on Lokalise.
|
74
|
+
* `#path` — returns an instance of the `Pathname` class which represent the file being uploaded.
|
75
|
+
|
76
|
+
You can perform periodic checks to read the status of the process. Here's a very simple example:
|
69
77
|
|
70
78
|
```ruby
|
71
79
|
def uploaded?(process)
|
72
80
|
5.times do # try to check the status 5 times
|
73
|
-
process = process.reload_data # load new
|
74
|
-
return(true) if process.status == 'finished' # return true
|
81
|
+
process = process.reload_data # load new info about this process
|
82
|
+
return(true) if process.status == 'finished' # return true if the upload has finished
|
75
83
|
sleep 1 # wait for 1 second, adjust this number with regards to the upload size
|
76
84
|
end
|
77
85
|
|
@@ -79,7 +87,8 @@ def uploaded?(process)
|
|
79
87
|
end
|
80
88
|
|
81
89
|
processes = exporter.export!
|
82
|
-
|
90
|
+
puts "Checking status for the #{processes[0].path} file"
|
91
|
+
uploaded? processes[0].process
|
83
92
|
```
|
84
93
|
|
85
94
|
Please don't forget that Lokalise API has rate limiting and you cannot send more than six requests per second.
|
@@ -130,7 +139,7 @@ importer = LokaliseManager.importer api_token: '1234abc',
|
|
130
139
|
```
|
131
140
|
|
132
141
|
* `import_safe_mode` (`boolean`) — default to `false`. When this option is enabled, the import task will check whether the directory set with `locales_path` is empty or not. If it is not empty, you will be prompted to continue.
|
133
|
-
* `max_retries_import` (`integer`) — this option is introduced to properly handle Lokalise API rate limiting. If the HTTP status code 429 (too many requests) has been received, this gem will apply an exponential backoff mechanism with a very simple formula: `2 ** retries`. If the maximum number of retries has been reached, a `
|
142
|
+
* `max_retries_import` (`integer`) — this option is introduced to properly handle Lokalise API rate limiting. If the HTTP status code 429 (too many requests) has been received, this gem will apply an exponential backoff mechanism with a very simple formula: `2 ** retries`. If the maximum number of retries has been reached, a `RubyLokaliseApi::Error::TooManyRequests` exception will be raised and the operation will be halted.
|
134
143
|
|
135
144
|
### Export config
|
136
145
|
|
@@ -162,7 +171,29 @@ In this case the `export_opts` will have `detect_icu_plurals` set to `true` and
|
|
162
171
|
c.skip_file_export = ->(file) { f.split[1].to_s.include?('fr') }
|
163
172
|
```
|
164
173
|
|
165
|
-
* `max_retries_export` (`integer`) — this option is introduced to properly handle Lokalise API rate limiting. If the HTTP status code 429 (too many requests) has been received,
|
174
|
+
* `max_retries_export` (`integer`) — this option is introduced to properly handle Lokalise API rate limiting. If the HTTP status code 429 (too many requests) has been received, LokaliseManager will apply an exponential backoff mechanism with a very simple formula: `2 ** retries` (initially `retries` is `0`). If the maximum number of retries has been reached, a `RubyLokaliseApi::Error::TooManyRequests` exception will be raised and the export operation will be halted. By default, LokaliseManager will make up to `5` retries which potentially means `1 + 2 + 4 + 8 + 16 + 32 = 63` seconds of waiting time. If the `max_retries_export` is less than `1`, LokaliseManager will not perform any retries and give up immediately after receiving error 429.
|
175
|
+
* `raise_on_export_fail` (`boolean`) — default is `true`. When this option is enabled, LokaliseManager will re-raise any exceptions that happened during the file uploading. In other words, if any uploading thread raised an exception, your exporting process will exit with an exception. Suppose, you are uploading 12 translation files; these files will be split in 2 groups with 6 files each, and each group will be uploaded in parallel (using threads). However, suppose some exception happens when uploading the first group. By default this exception will be re-raised for the whole process and the script will never try to upload the second group. If you would like to continue uploading even if an exception happened, set the `raise_on_export_fail` to `false`. In this case the `export!` method will return an array with scheduled processes and with information about processes that were not successfully scheduled. This information is represented as an object with three methods: `path` (contains an instance of the `Pathname` class which says which file could not be uploaded), `error` (the actual exception), and `success` (returns `false`). So, you can use the following snippet to check your processes:
|
176
|
+
|
177
|
+
```ruby
|
178
|
+
processes = exporter.export!
|
179
|
+
|
180
|
+
processes.each do |proc_data|
|
181
|
+
if proc_data.success
|
182
|
+
# Everything is good, the uploading is queued
|
183
|
+
puts "#{proc_data.path} is sent to Lokalise!"
|
184
|
+
process = proc_data.process
|
185
|
+
puts "Current process status is #{process.status}"
|
186
|
+
else
|
187
|
+
# Something bad has happened
|
188
|
+
puts "Could not send #{proc_data.path} to Lokalise"
|
189
|
+
puts "Error #{proc_data.error.class}: #{proc_data.error.message}"
|
190
|
+
# Or you could re-raise this exception:
|
191
|
+
# raise proc_data.error.class
|
192
|
+
end
|
193
|
+
end
|
194
|
+
```
|
195
|
+
|
196
|
+
* For example, you could collect all the files that were uploaded successfully, re-create the exporter object with the `skip_file_export` option (skipping all files that were successfully imported), and re-run the whole exporting process once again.
|
166
197
|
|
167
198
|
### Config to work with formats other than YAML
|
168
199
|
|
@@ -193,7 +224,7 @@ importer = LokaliseManager.importer api_token: '1234abc',
|
|
193
224
|
|
194
225
|
These options will be merged with the default ones. Please note that per-client config has the highest priority.
|
195
226
|
|
196
|
-
You can also adjust individual options later using the `#config` instance variable (it contains
|
227
|
+
You can also adjust individual options later using the `#config` instance variable (it contains a Struct object):
|
197
228
|
|
198
229
|
```
|
199
230
|
importer.config.project_id = '678xyz'
|
@@ -1,19 +1,26 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module LokaliseManager
|
4
|
+
# Global configuration options available for LokaliseManager
|
4
5
|
class GlobalConfig
|
5
6
|
class << self
|
6
7
|
attr_accessor :api_token, :project_id
|
7
8
|
attr_writer :import_opts, :import_safe_mode, :export_opts, :locales_path,
|
8
9
|
:file_ext_regexp, :skip_file_export, :branch, :timeouts,
|
9
10
|
:translations_loader, :translations_converter, :lang_iso_inferer,
|
10
|
-
:max_retries_export, :max_retries_import, :use_oauth2_token, :silent_mode
|
11
|
+
:max_retries_export, :max_retries_import, :use_oauth2_token, :silent_mode,
|
12
|
+
:raise_on_export_fail
|
11
13
|
|
12
14
|
# Main interface to provide configuration options
|
13
15
|
def config
|
14
16
|
yield self
|
15
17
|
end
|
16
18
|
|
19
|
+
# When enabled, will re-raise any exception that happens during file exporting
|
20
|
+
def raise_on_export_fail
|
21
|
+
@raise_on_export_fail || true
|
22
|
+
end
|
23
|
+
|
17
24
|
# When enabled, won't print any debugging info to $stdout
|
18
25
|
def silent_mode
|
19
26
|
@silent_mode || false
|
@@ -1,10 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'ruby_lokalise_api'
|
4
4
|
require 'pathname'
|
5
5
|
|
6
6
|
module LokaliseManager
|
7
7
|
module TaskDefinitions
|
8
|
+
# Base class for LokaliseManager task definitions that includes common methods and logic
|
8
9
|
class Base
|
9
10
|
using LokaliseManager::Utils::HashUtils
|
10
11
|
|
@@ -33,18 +34,18 @@ module LokaliseManager
|
|
33
34
|
|
34
35
|
# Creates a Lokalise API client
|
35
36
|
#
|
36
|
-
# @return [
|
37
|
+
# @return [RubyLokaliseApi::Client]
|
37
38
|
def api_client
|
38
|
-
client_opts = [config.api_token,
|
39
|
-
client_method = config.use_oauth2_token ? :
|
39
|
+
client_opts = [config.api_token, config.timeouts]
|
40
|
+
client_method = config.use_oauth2_token ? :oauth2_client : :client
|
40
41
|
|
41
|
-
@api_client = ::
|
42
|
+
@api_client = ::RubyLokaliseApi.send(client_method, *client_opts)
|
42
43
|
end
|
43
44
|
|
44
45
|
# Resets API client
|
45
46
|
def reset_api_client!
|
46
|
-
::
|
47
|
-
::
|
47
|
+
::RubyLokaliseApi.reset_client!
|
48
|
+
::RubyLokaliseApi.reset_oauth2_client!
|
48
49
|
@api_client = nil
|
49
50
|
end
|
50
51
|
|
@@ -94,7 +95,7 @@ module LokaliseManager
|
|
94
95
|
retries = 0
|
95
96
|
begin
|
96
97
|
yield
|
97
|
-
rescue
|
98
|
+
rescue RubyLokaliseApi::Error::TooManyRequests => e
|
98
99
|
raise(e.class, "Gave up after #{retries} retries") if retries >= max_retries
|
99
100
|
|
100
101
|
sleep 2**retries
|
@@ -4,8 +4,11 @@ require 'base64'
|
|
4
4
|
|
5
5
|
module LokaliseManager
|
6
6
|
module TaskDefinitions
|
7
|
+
# Exporter class is used when you want to upload translation files from your project to Lokalise
|
7
8
|
class Exporter < Base
|
8
|
-
|
9
|
+
# Lokalise allows no more than 6 requests per second
|
10
|
+
MAX_THREADS = 6
|
11
|
+
|
9
12
|
# Performs translation file export to Lokalise and returns an array of queued processes
|
10
13
|
#
|
11
14
|
# @return [Array]
|
@@ -14,11 +17,11 @@ module LokaliseManager
|
|
14
17
|
|
15
18
|
queued_processes = []
|
16
19
|
|
17
|
-
all_files.
|
20
|
+
all_files.each_slice(MAX_THREADS) do |files_group|
|
18
21
|
parallel_upload(files_group).each do |thr|
|
19
|
-
raise_on_fail
|
22
|
+
raise_on_fail(thr) if config.raise_on_export_fail
|
20
23
|
|
21
|
-
queued_processes.push thr
|
24
|
+
queued_processes.push thr
|
22
25
|
end
|
23
26
|
end
|
24
27
|
|
@@ -30,42 +33,44 @@ module LokaliseManager
|
|
30
33
|
private
|
31
34
|
|
32
35
|
def parallel_upload(files_group)
|
33
|
-
files_group.
|
36
|
+
files_group.map do |file_data|
|
34
37
|
do_upload(*file_data)
|
35
38
|
end.map(&:value)
|
36
39
|
end
|
37
40
|
|
38
41
|
def raise_on_fail(thread)
|
39
|
-
|
42
|
+
return if thread.success
|
43
|
+
|
44
|
+
raise(thread.error.class, "Error while trying to upload #{thread.path}: #{thread.error.message}")
|
40
45
|
end
|
41
46
|
|
42
47
|
# Performs the actual file uploading to Lokalise. If the API rate limit is exceeed,
|
43
48
|
# applies exponential backoff
|
44
49
|
def do_upload(f_path, r_path)
|
50
|
+
proc_klass = Struct.new(:success, :process, :path, :error, keyword_init: true)
|
51
|
+
|
45
52
|
Thread.new do
|
46
53
|
process = with_exp_backoff(config.max_retries_export) do
|
47
54
|
api_client.upload_file project_id_with_branch, opts(f_path, r_path)
|
48
55
|
end
|
49
|
-
|
56
|
+
proc_klass.new success: true, process: process, path: f_path
|
50
57
|
rescue StandardError => e
|
51
|
-
|
58
|
+
proc_klass.new success: false, path: f_path, error: e
|
52
59
|
end
|
53
60
|
end
|
54
61
|
|
55
62
|
# Gets translation files from the specified directory
|
56
63
|
def all_files
|
57
|
-
files = []
|
58
64
|
loc_path = config.locales_path
|
59
|
-
Dir["#{loc_path}/**/*"].
|
65
|
+
Dir["#{loc_path}/**/*"].filter_map do |f|
|
60
66
|
full_path = Pathname.new f
|
61
67
|
|
62
68
|
next unless file_matches_criteria? full_path
|
63
69
|
|
64
70
|
relative_path = full_path.relative_path_from Pathname.new(loc_path)
|
65
71
|
|
66
|
-
|
72
|
+
[full_path, relative_path]
|
67
73
|
end
|
68
|
-
files
|
69
74
|
end
|
70
75
|
|
71
76
|
# Generates export options
|
@@ -1,11 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Taken from https://github.com/rails/rails/blob/83217025a171593547d1268651b446d3533e2019/activesupport/lib/active_support/core_ext/hash/deep_merge.rb
|
4
|
-
|
5
3
|
module LokaliseManager
|
6
4
|
module Utils
|
5
|
+
# Common helper methods for hashes
|
7
6
|
module HashUtils
|
8
7
|
refine Hash do
|
8
|
+
# Deeply merges two hashes
|
9
|
+
# Taken from https://github.com/rails/rails/blob/83217025a171593547d1268651b446d3533e2019/activesupport/lib/active_support/core_ext/hash/deep_merge.rb
|
9
10
|
def deep_merge(other_hash, &block)
|
10
11
|
dup.deep_merge!(other_hash, &block)
|
11
12
|
end
|
data/lib/lokalise_manager.rb
CHANGED
@@ -1,17 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'zeitwerk'
|
3
4
|
require 'yaml'
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
require 'lokalise_manager/version'
|
9
|
-
require 'lokalise_manager/error'
|
10
|
-
require 'lokalise_manager/global_config'
|
11
|
-
require 'lokalise_manager/task_definitions/base'
|
12
|
-
require 'lokalise_manager/task_definitions/importer'
|
13
|
-
require 'lokalise_manager/task_definitions/exporter'
|
6
|
+
loader = Zeitwerk::Loader.for_gem
|
7
|
+
loader.setup
|
14
8
|
|
9
|
+
# LokaliseManager main module that exposes helper methods:
|
10
|
+
#
|
11
|
+
# importer = LokaliseManager.importer api_token: '1234abc', project_id: '123.abc'
|
12
|
+
# exporter = LokaliseManager.exporter api_token: '1234abc', project_id: '123.abc'
|
13
|
+
#
|
14
|
+
# Use the instantiated objects to import or export your translation files:
|
15
|
+
#
|
16
|
+
# importer.import!
|
17
|
+
# exporter.export!
|
18
|
+
#
|
15
19
|
module LokaliseManager
|
16
20
|
class << self
|
17
21
|
# Initializes a new importer client which is used to download
|
data/lokalise_manager.gemspec
CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
|
|
12
12
|
spec.homepage = 'https://github.com/bodrovis/lokalise_manager'
|
13
13
|
spec.license = 'MIT'
|
14
14
|
spec.platform = Gem::Platform::RUBY
|
15
|
-
spec.required_ruby_version = '>= 2.
|
15
|
+
spec.required_ruby_version = '>= 2.7'
|
16
16
|
|
17
17
|
spec.files = Dir['README.md', 'LICENSE',
|
18
18
|
'CHANGELOG.md', 'lib/**/*.rb',
|
@@ -23,8 +23,9 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.extra_rdoc_files = ['README.md']
|
24
24
|
spec.require_paths = ['lib']
|
25
25
|
|
26
|
-
spec.add_dependency 'ruby-lokalise-api', '~>
|
26
|
+
spec.add_dependency 'ruby-lokalise-api', '~> 6.0'
|
27
27
|
spec.add_dependency 'rubyzip', '~> 2.3'
|
28
|
+
spec.add_dependency 'zeitwerk', '~> 2.4'
|
28
29
|
|
29
30
|
spec.add_development_dependency 'codecov', '~> 0.2'
|
30
31
|
spec.add_development_dependency 'dotenv', '~> 2.5'
|
@@ -14,6 +14,11 @@ describe LokaliseManager::GlobalConfig do
|
|
14
14
|
fake_class.project_id = '123.abc'
|
15
15
|
end
|
16
16
|
|
17
|
+
it 'is possible to set raise_on_export_fail' do
|
18
|
+
allow(fake_class).to receive(:raise_on_export_fail=).with(false)
|
19
|
+
fake_class.raise_on_export_fail = false
|
20
|
+
end
|
21
|
+
|
17
22
|
it 'is possible to set silent_mode' do
|
18
23
|
allow(fake_class).to receive(:silent_mode=).with(true)
|
19
24
|
fake_class.silent_mode = true
|
@@ -22,7 +22,7 @@ describe LokaliseManager::TaskDefinitions::Base do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
specify '.reset_client!' do
|
25
|
-
expect(described_object.api_client).to be_an_instance_of(
|
25
|
+
expect(described_object.api_client).to be_an_instance_of(RubyLokaliseApi::Client)
|
26
26
|
described_object.reset_api_client!
|
27
27
|
current_client = described_object.instance_variable_get :@api_client
|
28
28
|
expect(current_client).to be_nil
|
@@ -63,14 +63,18 @@ describe LokaliseManager::TaskDefinitions::Base do
|
|
63
63
|
it 'raises an error when the API key is not set' do
|
64
64
|
allow(LokaliseManager::GlobalConfig).to receive(:api_token).and_return(nil)
|
65
65
|
|
66
|
-
expect
|
66
|
+
expect do
|
67
|
+
described_object.send(:check_options_errors!)
|
68
|
+
end.to raise_error(LokaliseManager::Error, /API token is not set/i)
|
67
69
|
|
68
70
|
expect(LokaliseManager::GlobalConfig).to have_received(:api_token)
|
69
71
|
end
|
70
72
|
|
71
73
|
it 'returns an error when the project_id is not set' do
|
72
74
|
allow_project_id described_object, nil do
|
73
|
-
expect
|
75
|
+
expect do
|
76
|
+
described_object.send(:check_options_errors!)
|
77
|
+
end.to raise_error(LokaliseManager::Error, /ID is not set/i)
|
74
78
|
end
|
75
79
|
end
|
76
80
|
end
|
@@ -95,8 +99,8 @@ describe LokaliseManager::TaskDefinitions::Base do
|
|
95
99
|
})
|
96
100
|
|
97
101
|
client = described_object.api_client
|
98
|
-
expect(client).to be_an_instance_of(
|
99
|
-
expect(client).not_to be_an_instance_of(
|
102
|
+
expect(client).to be_an_instance_of(RubyLokaliseApi::Client)
|
103
|
+
expect(client).not_to be_an_instance_of(RubyLokaliseApi::OAuth2Client)
|
100
104
|
expect(client.open_timeout).to eq(100)
|
101
105
|
expect(client.timeout).to eq(500)
|
102
106
|
end
|
@@ -106,8 +110,8 @@ describe LokaliseManager::TaskDefinitions::Base do
|
|
106
110
|
|
107
111
|
client = described_object.api_client
|
108
112
|
|
109
|
-
expect(client).to be_an_instance_of(
|
110
|
-
expect(client).not_to be_an_instance_of(
|
113
|
+
expect(client).to be_an_instance_of(RubyLokaliseApi::OAuth2Client)
|
114
|
+
expect(client).not_to be_an_instance_of(RubyLokaliseApi::Client)
|
111
115
|
end
|
112
116
|
end
|
113
117
|
end
|
@@ -14,105 +14,157 @@ describe LokaliseManager::TaskDefinitions::Exporter do
|
|
14
14
|
end
|
15
15
|
|
16
16
|
context 'with many translation files' do
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
describe '.export!' do
|
18
|
+
context 'with no errors' do
|
19
|
+
before do
|
20
|
+
add_translation_files! with_ru: true, additional: 5
|
21
|
+
end
|
20
22
|
|
21
|
-
|
22
|
-
|
23
|
-
|
23
|
+
after do
|
24
|
+
rm_translation_files
|
25
|
+
end
|
24
26
|
|
25
|
-
|
26
|
-
|
27
|
-
process = nil
|
27
|
+
it 'sends a proper API request and handles rate limiting' do
|
28
|
+
process = nil
|
28
29
|
|
29
|
-
|
30
|
-
|
30
|
+
VCR.use_cassette('upload_files_multiple') do
|
31
|
+
expect { process = described_object.export!.first.process }.to output(/complete!/).to_stdout
|
32
|
+
end
|
33
|
+
|
34
|
+
expect(process.project_id).to eq(project_id)
|
35
|
+
expect(process.status).to eq('queued')
|
31
36
|
end
|
32
37
|
|
33
|
-
|
34
|
-
|
38
|
+
it 'handles too many requests but does not re-raise anything when raise_on_export_fail is false' do
|
39
|
+
allow(described_object.config).to receive(:max_retries_export).and_return(1)
|
40
|
+
allow(described_object.config).to receive(:raise_on_export_fail).and_return(false)
|
41
|
+
allow(described_object).to receive(:sleep).and_return(0)
|
42
|
+
|
43
|
+
fake_client = instance_double('RubyLokaliseApi::Client')
|
44
|
+
allow(fake_client).to receive(:token).with(any_args).and_return('fake_token')
|
45
|
+
allow(fake_client).to receive(:upload_file).with(any_args).and_raise(RubyLokaliseApi::Error::TooManyRequests)
|
46
|
+
allow(described_object).to receive(:api_client).and_return(fake_client)
|
47
|
+
processes = []
|
48
|
+
expect { processes = described_object.export! }.not_to raise_error
|
49
|
+
|
50
|
+
expect(processes[0].success).to be false
|
51
|
+
expect(processes[1].error.class).to eq(RubyLokaliseApi::Error::TooManyRequests)
|
52
|
+
expect(processes.count).to eq(7)
|
53
|
+
|
54
|
+
expect(described_object).to have_received(:sleep).exactly(7).times
|
55
|
+
expect(described_object).to have_received(:api_client).at_least(14).times
|
56
|
+
expect(fake_client).to have_received(:upload_file).exactly(14).times
|
57
|
+
end
|
35
58
|
end
|
36
59
|
|
37
|
-
|
38
|
-
|
39
|
-
|
60
|
+
context 'with errors' do
|
61
|
+
before do
|
62
|
+
add_translation_files! with_ru: true
|
63
|
+
end
|
64
|
+
|
65
|
+
after do
|
66
|
+
rm_translation_files
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'handles too many requests' do
|
70
|
+
allow(described_object.config).to receive(:max_retries_export).and_return(1)
|
71
|
+
allow(described_object).to receive(:sleep).and_return(0)
|
40
72
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
73
|
+
fake_client = instance_double('RubyLokaliseApi::Client')
|
74
|
+
allow(fake_client).to receive(:token).with(any_args).and_return('fake_token')
|
75
|
+
allow(fake_client).to receive(:upload_file).with(any_args).and_raise(RubyLokaliseApi::Error::TooManyRequests)
|
76
|
+
allow(described_object).to receive(:api_client).and_return(fake_client)
|
45
77
|
|
46
|
-
|
78
|
+
expect do
|
79
|
+
described_object.export!
|
80
|
+
end.to raise_error(RubyLokaliseApi::Error::TooManyRequests, /Gave up after 1 retries/i)
|
47
81
|
|
48
|
-
|
49
|
-
|
50
|
-
|
82
|
+
expect(described_object).to have_received(:sleep).exactly(2).times
|
83
|
+
expect(described_object).to have_received(:api_client).at_least(4).times
|
84
|
+
expect(fake_client).to have_received(:upload_file).exactly(4).times
|
85
|
+
end
|
51
86
|
end
|
52
87
|
end
|
53
88
|
end
|
54
89
|
|
55
90
|
context 'with one translation file' do
|
56
|
-
|
57
|
-
|
58
|
-
|
91
|
+
context 'without files' do
|
92
|
+
it 'halts when the API key is not set' do
|
93
|
+
allow(described_object.config).to receive(:api_token).and_return(nil)
|
59
94
|
|
60
|
-
|
61
|
-
|
95
|
+
expect { described_object.export! }.to raise_error(LokaliseManager::Error, /API token is not set/i)
|
96
|
+
expect(described_object.config).to have_received(:api_token)
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'halts when the project_id is not set' do
|
100
|
+
allow_project_id described_object, nil do
|
101
|
+
expect { described_object.export! }.to raise_error(LokaliseManager::Error, /ID is not set/i)
|
102
|
+
end
|
103
|
+
end
|
62
104
|
end
|
63
105
|
|
64
|
-
|
65
|
-
|
66
|
-
|
106
|
+
context 'with files' do
|
107
|
+
before do
|
108
|
+
add_translation_files!
|
109
|
+
end
|
67
110
|
|
68
|
-
|
111
|
+
after do
|
112
|
+
rm_translation_files
|
113
|
+
end
|
69
114
|
|
70
|
-
|
71
|
-
|
72
|
-
|
115
|
+
describe '.export!' do
|
116
|
+
it 'sends a proper API request but does not output anything when silent_mode is enabled' do
|
117
|
+
allow(described_object.config).to receive(:silent_mode).and_return(true)
|
73
118
|
|
74
|
-
|
75
|
-
expect(described_object.config).to have_received(:silent_mode).at_most(1).times
|
76
|
-
end
|
119
|
+
process = nil
|
77
120
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
end.first
|
121
|
+
VCR.use_cassette('upload_files') do
|
122
|
+
expect { process = described_object.export!.first.process }.not_to output(/complete!/).to_stdout
|
123
|
+
end
|
82
124
|
|
83
|
-
|
84
|
-
|
85
|
-
|
125
|
+
expect(process.status).to eq('queued')
|
126
|
+
expect(described_object.config).to have_received(:silent_mode).at_most(1).times
|
127
|
+
end
|
86
128
|
|
87
|
-
|
88
|
-
|
129
|
+
it 'sends a proper API request' do
|
130
|
+
process = VCR.use_cassette('upload_files') do
|
131
|
+
described_object.export!
|
132
|
+
end.first.process
|
89
133
|
|
90
|
-
|
91
|
-
|
92
|
-
end
|
134
|
+
expect(process.project_id).to eq(project_id)
|
135
|
+
expect(process.status).to eq('queued')
|
136
|
+
end
|
93
137
|
|
94
|
-
|
95
|
-
|
96
|
-
expect(process.status).to eq('queued')
|
97
|
-
end
|
138
|
+
it 'sends a proper API request when a different branch is provided' do
|
139
|
+
allow(described_object.config).to receive(:branch).and_return('develop')
|
98
140
|
|
99
|
-
|
100
|
-
|
141
|
+
process_data = VCR.use_cassette('upload_files_branch') do
|
142
|
+
described_object.export!
|
143
|
+
end.first
|
101
144
|
|
102
|
-
|
103
|
-
|
104
|
-
|
145
|
+
expect(described_object.config).to have_received(:branch).at_most(2).times
|
146
|
+
expect(process_data.success).to be true
|
147
|
+
expect(process_data.path.to_s).to include('en.yml')
|
105
148
|
|
106
|
-
|
107
|
-
|
108
|
-
expect(
|
149
|
+
process = process_data.process
|
150
|
+
expect(process).to be_an_instance_of(RubyLokaliseApi::Resources::QueuedProcess)
|
151
|
+
expect(process.project_id).to eq(project_id)
|
152
|
+
expect(process.status).to eq('queued')
|
109
153
|
end
|
110
154
|
end
|
111
155
|
end
|
112
156
|
|
113
157
|
describe '#all_files' do
|
158
|
+
before do
|
159
|
+
add_translation_files!
|
160
|
+
end
|
161
|
+
|
162
|
+
after do
|
163
|
+
rm_translation_files
|
164
|
+
end
|
165
|
+
|
114
166
|
it 'yield proper arguments' do
|
115
|
-
expect(described_object.send(:all_files).
|
167
|
+
expect(described_object.send(:all_files).flatten).to include(
|
116
168
|
Pathname.new(path),
|
117
169
|
Pathname.new(relative_name)
|
118
170
|
)
|
@@ -120,6 +172,14 @@ describe LokaliseManager::TaskDefinitions::Exporter do
|
|
120
172
|
end
|
121
173
|
|
122
174
|
describe '.opts' do
|
175
|
+
before do
|
176
|
+
add_translation_files!
|
177
|
+
end
|
178
|
+
|
179
|
+
after do
|
180
|
+
rm_translation_files
|
181
|
+
end
|
182
|
+
|
123
183
|
let(:base64content) { Base64.strict_encode64(File.read(path).strip) }
|
124
184
|
|
125
185
|
it 'generates proper options' do
|
@@ -152,11 +212,11 @@ describe LokaliseManager::TaskDefinitions::Exporter do
|
|
152
212
|
let(:filename_ru) { 'ru.yml' }
|
153
213
|
let(:path_ru) { "#{Dir.getwd}/locales/#{filename_ru}" }
|
154
214
|
|
155
|
-
before
|
215
|
+
before do
|
156
216
|
add_translation_files! with_ru: true
|
157
217
|
end
|
158
218
|
|
159
|
-
after
|
219
|
+
after do
|
160
220
|
rm_translation_files
|
161
221
|
end
|
162
222
|
|
@@ -165,7 +225,7 @@ describe LokaliseManager::TaskDefinitions::Exporter do
|
|
165
225
|
allow_project_id described_object, '542886116159f798720dc4.94769464'
|
166
226
|
|
167
227
|
VCR.use_cassette('upload_files_error') do
|
168
|
-
expect { described_object.export! }.to raise_error(
|
228
|
+
expect { described_object.export! }.to raise_error(RubyLokaliseApi::Error::BadRequest, /Unknown `lang_iso`/)
|
169
229
|
end
|
170
230
|
end
|
171
231
|
end
|
@@ -182,14 +242,14 @@ describe LokaliseManager::TaskDefinitions::Exporter do
|
|
182
242
|
end
|
183
243
|
end
|
184
244
|
|
185
|
-
describe '#
|
245
|
+
describe '#all_files' do
|
186
246
|
it 'returns all files' do
|
187
|
-
files = described_object.send(:all_files)
|
188
|
-
expect(files
|
247
|
+
files = described_object.send(:all_files).flatten
|
248
|
+
expect(files).to include(
|
189
249
|
Pathname.new(path),
|
190
250
|
Pathname.new(relative_name)
|
191
251
|
)
|
192
|
-
expect(files
|
252
|
+
expect(files).to include(
|
193
253
|
Pathname.new(path_ru),
|
194
254
|
Pathname.new(filename_ru)
|
195
255
|
)
|
@@ -199,7 +259,7 @@ describe LokaliseManager::TaskDefinitions::Exporter do
|
|
199
259
|
allow(described_object.config).to receive(:skip_file_export).twice.and_return(
|
200
260
|
->(f) { f.split[1].to_s.include?('ru') }
|
201
261
|
)
|
202
|
-
files = described_object.send(:all_files)
|
262
|
+
files = described_object.send(:all_files).sort
|
203
263
|
expect(files[0]).to include(
|
204
264
|
Pathname.new(path),
|
205
265
|
Pathname.new(relative_name)
|
@@ -15,14 +15,14 @@ describe LokaliseManager::TaskDefinitions::Importer do
|
|
15
15
|
entry = double
|
16
16
|
allow(entry).to receive(:name).and_return('fail.yml')
|
17
17
|
allow(described_object).to receive(:data_from).with(entry).and_raise(EncodingError)
|
18
|
-
expect
|
18
|
+
expect { described_object.send(:process!, entry) }.
|
19
19
|
to raise_error(EncodingError, /Error when trying to process fail\.yml/)
|
20
20
|
|
21
21
|
expect(described_object).to have_received(:data_from)
|
22
22
|
end
|
23
23
|
|
24
24
|
it 're-raises errors during file opening' do
|
25
|
-
expect
|
25
|
+
expect { described_object.send(:open_and_process_zip, 'http://fake.url/wrong/path.zip') }.
|
26
26
|
to raise_error(SocketError, /Failed to open TCP connection/)
|
27
27
|
end
|
28
28
|
end
|
@@ -35,15 +35,14 @@ describe LokaliseManager::TaskDefinitions::Importer do
|
|
35
35
|
|
36
36
|
expect(response['project_id']).to eq('672198945b7d72fc048021.15940510')
|
37
37
|
expect(response['bundle_url']).to include('s3-eu-west-1.amazonaws.com')
|
38
|
-
expect(described_object.api_client.enable_compression).to eq(true)
|
39
38
|
end
|
40
39
|
|
41
40
|
it 're-raises errors during file download' do
|
42
41
|
allow_project_id described_object, 'invalid'
|
43
42
|
|
44
43
|
VCR.use_cassette('download_files_error') do
|
45
|
-
expect
|
46
|
-
to raise_error(
|
44
|
+
expect { described_object.send :download_files }.
|
45
|
+
to raise_error(RubyLokaliseApi::Error::BadRequest, /Invalid `project_id` parameter/)
|
47
46
|
end
|
48
47
|
end
|
49
48
|
end
|
@@ -53,11 +52,11 @@ describe LokaliseManager::TaskDefinitions::Importer do
|
|
53
52
|
it 'handles too many requests' do
|
54
53
|
allow(described_object).to receive(:sleep).and_return(0)
|
55
54
|
|
56
|
-
fake_client = instance_double('
|
57
|
-
allow(fake_client).to receive(:download_files).and_raise(
|
55
|
+
fake_client = instance_double('RubyLokaliseApi::Client')
|
56
|
+
allow(fake_client).to receive(:download_files).and_raise(RubyLokaliseApi::Error::TooManyRequests)
|
58
57
|
allow(described_object).to receive(:api_client).and_return(fake_client)
|
59
58
|
|
60
|
-
expect
|
59
|
+
expect { described_object.import! }.to raise_error(RubyLokaliseApi::Error::TooManyRequests, /Gave up after 2 retries/i)
|
61
60
|
|
62
61
|
expect(described_object).to have_received(:sleep).exactly(2).times
|
63
62
|
expect(described_object).to have_received(:api_client).exactly(3).times
|
@@ -66,14 +65,14 @@ describe LokaliseManager::TaskDefinitions::Importer do
|
|
66
65
|
|
67
66
|
it 'halts when the API key is not set' do
|
68
67
|
allow(described_object.config).to receive(:api_token).and_return(nil)
|
69
|
-
expect
|
68
|
+
expect { described_object.import! }.to raise_error(LokaliseManager::Error, /API token is not set/i)
|
70
69
|
expect(described_object.config).to have_received(:api_token)
|
71
70
|
expect(count_translations).to eq(0)
|
72
71
|
end
|
73
72
|
|
74
73
|
it 'halts when the project_id is not set' do
|
75
74
|
allow_project_id described_object, nil do
|
76
|
-
expect
|
75
|
+
expect { described_object.import! }.to raise_error(LokaliseManager::Error, /ID is not set/i)
|
77
76
|
expect(count_translations).to eq(0)
|
78
77
|
end
|
79
78
|
end
|
@@ -82,10 +81,9 @@ describe LokaliseManager::TaskDefinitions::Importer do
|
|
82
81
|
context 'when directory is empty' do
|
83
82
|
before do
|
84
83
|
mkdir_locales
|
85
|
-
rm_translation_files
|
86
84
|
end
|
87
85
|
|
88
|
-
after
|
86
|
+
after do
|
89
87
|
rm_translation_files
|
90
88
|
end
|
91
89
|
|
@@ -110,7 +108,7 @@ describe LokaliseManager::TaskDefinitions::Importer do
|
|
110
108
|
result = nil
|
111
109
|
|
112
110
|
VCR.use_cassette('import') do
|
113
|
-
expect
|
111
|
+
expect { result = described_object.import! }.to output(/complete!/).to_stdout
|
114
112
|
end
|
115
113
|
|
116
114
|
expect(result).to be true
|
@@ -125,7 +123,7 @@ describe LokaliseManager::TaskDefinitions::Importer do
|
|
125
123
|
result = nil
|
126
124
|
|
127
125
|
VCR.use_cassette('import') do
|
128
|
-
expect
|
126
|
+
expect { result = described_object.import! }.not_to output(/complete!/).to_stdout
|
129
127
|
end
|
130
128
|
|
131
129
|
expect(result).to be true
|
@@ -142,16 +140,13 @@ describe LokaliseManager::TaskDefinitions::Importer do
|
|
142
140
|
import_safe_mode: true
|
143
141
|
end
|
144
142
|
|
145
|
-
before :all do
|
146
|
-
mkdir_locales
|
147
|
-
end
|
148
|
-
|
149
143
|
before do
|
144
|
+
mkdir_locales
|
150
145
|
rm_translation_files
|
151
146
|
add_translation_files!
|
152
147
|
end
|
153
148
|
|
154
|
-
after
|
149
|
+
after do
|
155
150
|
rm_translation_files
|
156
151
|
end
|
157
152
|
|
@@ -164,7 +159,7 @@ describe LokaliseManager::TaskDefinitions::Importer do
|
|
164
159
|
)
|
165
160
|
|
166
161
|
allow($stdin).to receive(:gets).and_return('Y')
|
167
|
-
expect
|
162
|
+
expect { safe_mode_obj.import! }.to output(/is not empty/).to_stdout
|
168
163
|
|
169
164
|
expect(count_translations).to eq(5)
|
170
165
|
expect($stdin).to have_received(:gets)
|
@@ -177,18 +172,18 @@ describe LokaliseManager::TaskDefinitions::Importer do
|
|
177
172
|
it 'import halts when a user chooses not to proceed' do
|
178
173
|
allow(safe_mode_obj).to receive(:download_files).at_most(0).times
|
179
174
|
allow($stdin).to receive(:gets).and_return('N')
|
180
|
-
expect
|
175
|
+
expect { safe_mode_obj.import! }.to output(/cancelled/).to_stdout
|
181
176
|
|
182
177
|
expect(safe_mode_obj).not_to have_received(:download_files)
|
183
178
|
expect($stdin).to have_received(:gets)
|
184
179
|
expect(count_translations).to eq(1)
|
185
180
|
end
|
186
181
|
|
187
|
-
it 'import halts when a user chooses
|
182
|
+
it 'import halts when a user chooses to halt and debug info is not printed out when silent_mode is enabled' do
|
188
183
|
allow(safe_mode_obj.config).to receive(:silent_mode).and_return(true)
|
189
184
|
allow(safe_mode_obj).to receive(:download_files).at_most(0).times
|
190
185
|
allow($stdin).to receive(:gets).and_return('N')
|
191
|
-
expect
|
186
|
+
expect { safe_mode_obj.import! }.not_to output(/cancelled/).to_stdout
|
192
187
|
|
193
188
|
expect(safe_mode_obj).not_to have_received(:download_files)
|
194
189
|
expect(safe_mode_obj.config).to have_received(:silent_mode)
|
File without changes
|
@@ -4,7 +4,9 @@ require 'fileutils'
|
|
4
4
|
|
5
5
|
module FileManager
|
6
6
|
def mkdir_locales
|
7
|
-
|
7
|
+
return if File.directory?(LokaliseManager::GlobalConfig.locales_path)
|
8
|
+
|
9
|
+
FileUtils.mkdir_p(LokaliseManager::GlobalConfig.locales_path)
|
8
10
|
end
|
9
11
|
|
10
12
|
def rm_translation_files
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lokalise_manager
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ilya Bodrov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-03-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby-lokalise-api
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '6.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '6.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rubyzip
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '2.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: zeitwerk
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.4'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.4'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: codecov
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -187,7 +201,6 @@ files:
|
|
187
201
|
- lib/lokalise_manager/task_definitions/base.rb
|
188
202
|
- lib/lokalise_manager/task_definitions/exporter.rb
|
189
203
|
- lib/lokalise_manager/task_definitions/importer.rb
|
190
|
-
- lib/lokalise_manager/utils/array_utils.rb
|
191
204
|
- lib/lokalise_manager/utils/hash_utils.rb
|
192
205
|
- lib/lokalise_manager/version.rb
|
193
206
|
- lokalise_manager.gemspec
|
@@ -195,9 +208,8 @@ files:
|
|
195
208
|
- spec/lib/lokalise_manager/task_definitions/base_spec.rb
|
196
209
|
- spec/lib/lokalise_manager/task_definitions/exporter_spec.rb
|
197
210
|
- spec/lib/lokalise_manager/task_definitions/importer_spec.rb
|
211
|
+
- spec/lib/lokalise_manager/utils/hash_utils_spec.rb
|
198
212
|
- spec/lib/lokalise_manager_spec.rb
|
199
|
-
- spec/lib/utils/array_utils_spec.rb
|
200
|
-
- spec/lib/utils/hash_utils_spec.rb
|
201
213
|
- spec/spec_helper.rb
|
202
214
|
- spec/support/file_manager.rb
|
203
215
|
- spec/support/spec_addons.rb
|
@@ -215,14 +227,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
215
227
|
requirements:
|
216
228
|
- - ">="
|
217
229
|
- !ruby/object:Gem::Version
|
218
|
-
version: 2.
|
230
|
+
version: '2.7'
|
219
231
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
220
232
|
requirements:
|
221
233
|
- - ">="
|
222
234
|
- !ruby/object:Gem::Version
|
223
235
|
version: '0'
|
224
236
|
requirements: []
|
225
|
-
rubygems_version: 3.3.
|
237
|
+
rubygems_version: 3.3.8
|
226
238
|
signing_key:
|
227
239
|
specification_version: 4
|
228
240
|
summary: Lokalise integration for Ruby
|
@@ -231,9 +243,8 @@ test_files:
|
|
231
243
|
- spec/lib/lokalise_manager/task_definitions/base_spec.rb
|
232
244
|
- spec/lib/lokalise_manager/task_definitions/exporter_spec.rb
|
233
245
|
- spec/lib/lokalise_manager/task_definitions/importer_spec.rb
|
246
|
+
- spec/lib/lokalise_manager/utils/hash_utils_spec.rb
|
234
247
|
- spec/lib/lokalise_manager_spec.rb
|
235
|
-
- spec/lib/utils/array_utils_spec.rb
|
236
|
-
- spec/lib/utils/hash_utils_spec.rb
|
237
248
|
- spec/spec_helper.rb
|
238
249
|
- spec/support/file_manager.rb
|
239
250
|
- spec/support/spec_addons.rb
|
@@ -1,27 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Taken from https://github.com/rails/rails/blob/6bfc637659248df5d6719a86d2981b52662d9b50/activesupport/lib/active_support/core_ext/array/grouping.rb
|
4
|
-
|
5
|
-
module LokaliseManager
|
6
|
-
module Utils
|
7
|
-
module ArrayUtils
|
8
|
-
refine Array do
|
9
|
-
def in_groups_of(number, fill_with = nil, &block)
|
10
|
-
if number.to_i <= 0
|
11
|
-
raise ArgumentError,
|
12
|
-
"Group size must be a positive integer, was #{number.inspect}"
|
13
|
-
end
|
14
|
-
|
15
|
-
if fill_with == false
|
16
|
-
collection = self
|
17
|
-
else
|
18
|
-
padding = (number - (size % number)) % number
|
19
|
-
collection = dup.concat(Array.new(padding, fill_with))
|
20
|
-
end
|
21
|
-
|
22
|
-
collection.each_slice(number, &block)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
describe LokaliseManager::Utils::ArrayUtils do
|
4
|
-
using described_class
|
5
|
-
let(:arr) { (1..8).to_a }
|
6
|
-
|
7
|
-
describe '#in_groups_of' do
|
8
|
-
it 'raises an exception when the number is less than 1' do
|
9
|
-
expect(-> { arr.in_groups_of(-1) }).to raise_error(ArgumentError)
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'uses collection itself if fill_with is false' do
|
13
|
-
enum = arr.in_groups_of(5, false)
|
14
|
-
enum.next
|
15
|
-
expect(enum.next.count).to eq(3)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|