lokalise_manager 7.0.0 → 8.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +1 -1
- data/lib/lokalise_manager/error.rb +0 -4
- data/lib/lokalise_manager/global_config.rb +2 -0
- data/lib/lokalise_manager/task_definitions/base.rb +2 -2
- data/lib/lokalise_manager/task_definitions/exporter.rb +2 -2
- data/lib/lokalise_manager/task_definitions/importer.rb +10 -14
- data/lib/lokalise_manager/utils/hash_utils.rb +1 -1
- data/lib/lokalise_manager/version.rb +1 -1
- data/lokalise_manager.gemspec +3 -3
- metadata +7 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 47771de487435a3744c042598ce442ecd0e7f1c52080cd2f089974efd6176350
|
|
4
|
+
data.tar.gz: f774cae469107a4816ec6267ec1f4a9201e40ec9f74b26396d8e09c0c4dcbd78
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6a27dd2250f829fc5accad0798504ed18900937bdfec79a1afe046582a381b0c703a6027fb548d98210ef2292096a31beba742e3db814607e9abf935baef31b8
|
|
7
|
+
data.tar.gz: 8f812892db1740c61486f2e16e2579394a51b3f804753aeffecdf6f13a80110de5d8d58a4c7e7730203f0ce02b9f0fd8096a566ceb7cda89344bba7743a8d6fb
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
|
@@ -192,7 +192,7 @@ c.export_preprocessor = ->(raw_data, _path) { raw_data.upcase }
|
|
|
192
192
|
c.export_filename_generator = ->(_full_path, relative_path) { relative_path.to_s.upcase }
|
|
193
193
|
```
|
|
194
194
|
|
|
195
|
-
* `max_retries_export` (`integer`) —
|
|
195
|
+
* `max_retries_export` (`integer`) — controls how many times LokaliseManager retries an export when the Lokalise API returns HTTP status `429` (Too Many Requests) or when a temporary response parsing error occurs. Retries use exponential backoff based on `2 ** retries`, with a small random jitter added to each delay. If the maximum number of retries is reached, the original exception is raised and the export operation is halted. By default, LokaliseManager performs up to `5` retries, resulting in base delays of `1 + 2 + 4 + 8 + 16 = 31` seconds in total, plus up to approximately `5` seconds of additional jitter. If `max_retries_export` is less than `1`, LokaliseManager does not retry and gives up immediately after the first failure.
|
|
196
196
|
* `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:
|
|
197
197
|
|
|
198
198
|
```ruby
|
|
@@ -5,9 +5,5 @@ module LokaliseManager
|
|
|
5
5
|
# allowing the library to raise specific errors that can be easily identified
|
|
6
6
|
# and handled separately from other StandardError exceptions in Ruby.
|
|
7
7
|
class Error < StandardError
|
|
8
|
-
# Initializes a new Error object
|
|
9
|
-
def initialize(message = '')
|
|
10
|
-
super
|
|
11
|
-
end
|
|
12
8
|
end
|
|
13
9
|
end
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'yaml'
|
|
4
|
+
|
|
3
5
|
module LokaliseManager
|
|
4
6
|
# GlobalConfig provides a central place to manage configuration settings for LokaliseManager.
|
|
5
7
|
# It allows setting various operational parameters such as API tokens, paths, and behavior modifiers.
|
|
@@ -31,8 +31,8 @@ module LokaliseManager
|
|
|
31
31
|
raise_on_export_fail import_async export_preprocessor export_filename_generator
|
|
32
32
|
].freeze
|
|
33
33
|
|
|
34
|
-
BACKOFF_BASE_SECONDS = 1
|
|
35
|
-
BACKOFF_CAP_SECONDS
|
|
34
|
+
BACKOFF_BASE_SECONDS = 1 # base multiplier (1,2,4,8...)
|
|
35
|
+
BACKOFF_CAP_SECONDS = 32 # max exponential backoff before jitter
|
|
36
36
|
BACKOFF_JITTER_RANGE = 1.0 # adds rand * range
|
|
37
37
|
|
|
38
38
|
# Initializes a new task object with merged global and custom configurations.
|
|
@@ -6,7 +6,7 @@ module LokaliseManager
|
|
|
6
6
|
module TaskDefinitions
|
|
7
7
|
# Handles exporting translation files from a local project to Lokalise.
|
|
8
8
|
class Exporter < Base
|
|
9
|
-
#
|
|
9
|
+
# Number of files uploaded concurrently in each batch.
|
|
10
10
|
MAX_THREADS = 6
|
|
11
11
|
|
|
12
12
|
ProcessResult = Struct.new(:success, :process, :path, :error, keyword_init: true)
|
|
@@ -15,7 +15,7 @@ module LokaliseManager
|
|
|
15
15
|
#
|
|
16
16
|
# - Validates configuration.
|
|
17
17
|
# - Gathers translation files from the project directory.
|
|
18
|
-
# - Uploads files to Lokalise in parallel
|
|
18
|
+
# - Uploads files to Lokalise in parallel and retries rate-limited requests.
|
|
19
19
|
# - Handles errors and ensures failed uploads are reported.
|
|
20
20
|
#
|
|
21
21
|
# @return [Array] An array of process results for each uploaded file.
|
|
@@ -71,7 +71,9 @@ module LokaliseManager
|
|
|
71
71
|
# @return [QueuedProcess] The process object when completed successfully.
|
|
72
72
|
# @raise [LokaliseManager::Error] If the process fails or takes too long.
|
|
73
73
|
def wait_for_async_download(process_id)
|
|
74
|
-
|
|
74
|
+
max_retries = [config.max_retries_import.to_i, 0].max
|
|
75
|
+
|
|
76
|
+
(max_retries + 1).times do |i|
|
|
75
77
|
process = reload_process(process_id)
|
|
76
78
|
|
|
77
79
|
case process.status
|
|
@@ -79,7 +81,7 @@ module LokaliseManager
|
|
|
79
81
|
when 'finished' then return process
|
|
80
82
|
end
|
|
81
83
|
|
|
82
|
-
sleep_with_backoff(i)
|
|
84
|
+
sleep_with_backoff(i) if i < max_retries
|
|
83
85
|
end
|
|
84
86
|
|
|
85
87
|
raise LokaliseManager::Error, "Asynchronous download process timed out after #{config.max_retries_import} tries"
|
|
@@ -90,7 +92,9 @@ module LokaliseManager
|
|
|
90
92
|
# @param process_id [String] The process ID to check.
|
|
91
93
|
# @return [QueuedProcess] The process object with updated status.
|
|
92
94
|
def reload_process(process_id)
|
|
93
|
-
|
|
95
|
+
fetch_with_retry do
|
|
96
|
+
api_client.queued_process(project_id_with_branch, process_id)
|
|
97
|
+
end
|
|
94
98
|
end
|
|
95
99
|
|
|
96
100
|
# Extracts and processes files from a ZIP archive.
|
|
@@ -146,7 +150,7 @@ module LokaliseManager
|
|
|
146
150
|
|
|
147
151
|
$stdout.puts "The target directory #{path} is not empty!"
|
|
148
152
|
$stdout.print 'Enter Y to continue: '
|
|
149
|
-
$stdin.gets
|
|
153
|
+
$stdin.gets&.strip&.upcase == 'Y'
|
|
150
154
|
end
|
|
151
155
|
|
|
152
156
|
# Opens a local file or downloads a remote file.
|
|
@@ -170,16 +174,8 @@ module LokaliseManager
|
|
|
170
174
|
#
|
|
171
175
|
# @yield The operation to retry.
|
|
172
176
|
# @return [Object] The result of the successful operation.
|
|
173
|
-
def fetch_with_retry(&
|
|
174
|
-
with_exp_backoff(config.max_retries_import, &
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
# Extracts the subdirectory and filename from a given path.
|
|
178
|
-
#
|
|
179
|
-
# @param entry [String] The file path.
|
|
180
|
-
# @return [Array<Pathname, Pathname>] An array containing the subdirectory and filename.
|
|
181
|
-
def subdir_and_filename_for(entry)
|
|
182
|
-
Pathname.new(entry).split
|
|
177
|
+
def fetch_with_retry(&)
|
|
178
|
+
with_exp_backoff(config.max_retries_import, &)
|
|
183
179
|
end
|
|
184
180
|
end
|
|
185
181
|
end
|
|
@@ -6,7 +6,7 @@ module LokaliseManager
|
|
|
6
6
|
module HashUtils
|
|
7
7
|
refine Hash do
|
|
8
8
|
# Deeply merges two hashes
|
|
9
|
-
# Taken from https://
|
|
9
|
+
# Taken from https://api.rubyonrails.org/files/activesupport/lib/active_support/core_ext/hash/deep_merge_rb.html
|
|
10
10
|
def deep_merge(other_hash, &block)
|
|
11
11
|
dup.deep_merge!(other_hash, &block)
|
|
12
12
|
end
|
data/lokalise_manager.gemspec
CHANGED
|
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
|
|
|
13
13
|
spec.homepage = 'https://github.com/bodrovis/lokalise_manager'
|
|
14
14
|
spec.license = 'MIT'
|
|
15
15
|
spec.platform = Gem::Platform::RUBY
|
|
16
|
-
spec.required_ruby_version = '>= 3.
|
|
16
|
+
spec.required_ruby_version = '>= 3.2'
|
|
17
17
|
|
|
18
18
|
spec.files = Dir['README.md', 'LICENSE',
|
|
19
19
|
'CHANGELOG.md', 'lib/**/*.rb',
|
|
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
|
|
|
22
22
|
spec.require_paths = ['lib']
|
|
23
23
|
|
|
24
24
|
spec.add_dependency 'base64', '~> 0.3.0'
|
|
25
|
-
spec.add_dependency 'ruby-lokalise-api', '~>
|
|
25
|
+
spec.add_dependency 'ruby-lokalise-api', '~> 10.0'
|
|
26
26
|
spec.add_dependency 'rubyzip', '>= 2.3', '< 4.0'
|
|
27
27
|
spec.add_dependency 'zeitwerk', '~> 2.4'
|
|
28
28
|
|
|
@@ -33,7 +33,7 @@ Gem::Specification.new do |spec|
|
|
|
33
33
|
spec.add_development_dependency 'rubocop-performance', '~> 1.5'
|
|
34
34
|
spec.add_development_dependency 'rubocop-rake', '~> 0.7'
|
|
35
35
|
spec.add_development_dependency 'rubocop-rspec', '~> 3.0'
|
|
36
|
-
spec.add_development_dependency 'simplecov', '~> 0
|
|
36
|
+
spec.add_development_dependency 'simplecov', '~> 1.0'
|
|
37
37
|
spec.add_development_dependency 'webmock', '~> 3.18'
|
|
38
38
|
spec.metadata = {
|
|
39
39
|
'rubygems_mfa_required' => 'true',
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lokalise_manager
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 8.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ilya Krukowski
|
|
@@ -29,14 +29,14 @@ dependencies:
|
|
|
29
29
|
requirements:
|
|
30
30
|
- - "~>"
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: '
|
|
32
|
+
version: '10.0'
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
37
|
- - "~>"
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: '
|
|
39
|
+
version: '10.0'
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
41
41
|
name: rubyzip
|
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -175,14 +175,14 @@ dependencies:
|
|
|
175
175
|
requirements:
|
|
176
176
|
- - "~>"
|
|
177
177
|
- !ruby/object:Gem::Version
|
|
178
|
-
version: '0
|
|
178
|
+
version: '1.0'
|
|
179
179
|
type: :development
|
|
180
180
|
prerelease: false
|
|
181
181
|
version_requirements: !ruby/object:Gem::Requirement
|
|
182
182
|
requirements:
|
|
183
183
|
- - "~>"
|
|
184
184
|
- !ruby/object:Gem::Version
|
|
185
|
-
version: '0
|
|
185
|
+
version: '1.0'
|
|
186
186
|
- !ruby/object:Gem::Dependency
|
|
187
187
|
name: webmock
|
|
188
188
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -234,14 +234,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
234
234
|
requirements:
|
|
235
235
|
- - ">="
|
|
236
236
|
- !ruby/object:Gem::Version
|
|
237
|
-
version: '3.
|
|
237
|
+
version: '3.2'
|
|
238
238
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
239
239
|
requirements:
|
|
240
240
|
- - ">="
|
|
241
241
|
- !ruby/object:Gem::Version
|
|
242
242
|
version: '0'
|
|
243
243
|
requirements: []
|
|
244
|
-
rubygems_version: 4.0.
|
|
244
|
+
rubygems_version: 4.0.19
|
|
245
245
|
specification_version: 4
|
|
246
246
|
summary: Lokalise integration for Ruby
|
|
247
247
|
test_files: []
|