lokalise_manager 5.1.1 → 6.0.0

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: 82874b49ae901318d91845641a40e1c0b085764e53179799dffb54f84e205fc0
4
- data.tar.gz: 5c8035fed54faf4dbd82eba23acaf172af60bf0d0cd4f4b0705bace632b1049a
3
+ metadata.gz: f0df6efdcebd1ef7b1f3992a14c997d56859553cf0e1b089d43fe496f479bb1e
4
+ data.tar.gz: 762127da9ea96e1b5ad532a5217d0f06556b3d9f61b65f722f79a50a406bba23
5
5
  SHA512:
6
- metadata.gz: 473fc616ce635982fe180396a3f2be51c974fd05bbca4e5f1a4780cdda9f10951a0763ce1c366abccae96ba618a20f7d9d94b150c4f9423ba72d678dec2f53cf
7
- data.tar.gz: 24b1bd4791c79ef2ff0e6f1fc096b23a50a63878f55c66c10b0830d4ac614e76890a7b50d376cef649dae6970ded2215088ca95b9c96ee3124574b7594eda086
6
+ metadata.gz: 42c3990642e4598cc746f1f991d57bceb1793b0de6f8a9ff8b7a33d42194c47a9d84243ee045658a4925dda13d2b6ee63bb0464bd48c8094951b60c2b83e8c9b
7
+ data.tar.gz: 156793b3c527be7e88fa4790db675f98958ba80a2be717259f4e3fca937a1369b9660210d8778b727cce1249f9237873507c6800e88eec33d40aac3bf9b42c8a
data/CHANGELOG.md CHANGED
@@ -1,6 +1,22 @@
1
1
  # Changelog
2
2
 
3
- ## 5.1.1
3
+ ## 6.0.0 (29-Nov-2024)
4
+
5
+ * **Breaking change**: rename the `timeouts` config method to `additional_client_opts`. It has the same usage but now enables you to set both client timeouts and override the API host to send requests to.
6
+
7
+ ```ruby
8
+ additional_client_opts: {
9
+ open_timeout: 100,
10
+ timeout: 500,
11
+ api_host: 'http://example.com/api'
12
+ }
13
+ ```
14
+
15
+ ## 5.1.2 (01-Nov-2024)
16
+
17
+ * Update dependencies
18
+
19
+ ## 5.1.1 (10-May-2024)
4
20
 
5
21
  * Update documentation, minor code fixes
6
22
 
data/README.md CHANGED
@@ -108,7 +108,7 @@ Please don't forget that Lokalise API has rate limiting and you cannot send more
108
108
  * `project_id` (`string`, required) — Lokalise project ID. You must have import/export permissions in the specified project.
109
109
  * `locales_path` (`string`) — path to the directory with your translation files. Defaults to `"#{Dir.getwd}/locales"`.
110
110
  * `branch` (`string`) — Lokalise project branch to use. Defaults to `""` (no branch is provided).
111
- * `timeouts` (`hash`) — set [request timeouts for the Lokalise API client](https://lokalise.github.io/ruby-lokalise-api/additional_info/customization#setting-timeouts). By default, requests have no timeouts: `{open_timeout: nil, timeout: nil}`. Both values are in seconds.
111
+ * `additional_client_opts` (`hash`) — set [request timeouts and API host for the Lokalise client](https://lokalise.github.io/ruby-lokalise-api/additional_info/customization). By default, requests have no timeouts and the API host is not overriden: `{open_timeout: nil, timeout: nil, api_host: nil}`. Timeout values are in seconds.
112
112
  * `silent_mode` (`boolean`) — whether you would like to output debugging information to `$stdout`. By default, after a task is performed, a short notification message will be printed out to the terminal. When set to `false`, notifications won't be printed. Please note that currently `import_safe_mode` has higher priority. Even if you enable `silent_mode`, and the `import_safe_mode` is enabled as well, you will be prompted to confirm the import operation if the target directory is not empty.
113
113
 
114
114
  ### Import config
@@ -7,7 +7,7 @@ module LokaliseManager
7
7
  class Error < StandardError
8
8
  # Initializes a new Error object
9
9
  def initialize(message = '')
10
- super(message)
10
+ super
11
11
  end
12
12
  end
13
13
  end
@@ -7,7 +7,7 @@ module LokaliseManager
7
7
  class << self
8
8
  attr_accessor :api_token, :project_id
9
9
  attr_writer :import_opts, :import_safe_mode, :export_opts, :locales_path,
10
- :file_ext_regexp, :skip_file_export, :branch, :timeouts,
10
+ :file_ext_regexp, :skip_file_export, :branch, :additional_client_opts,
11
11
  :translations_loader, :translations_converter, :lang_iso_inferer,
12
12
  :max_retries_export, :max_retries_import, :use_oauth2_token, :silent_mode,
13
13
  :raise_on_export_fail
@@ -42,9 +42,9 @@ module LokaliseManager
42
42
  @branch || ''
43
43
  end
44
44
 
45
- # Return API request timeouts
46
- def timeouts
47
- @timeouts || {}
45
+ # Return additional API client options
46
+ def additional_client_opts
47
+ @additional_client_opts || {}
48
48
  end
49
49
 
50
50
  # Return the max retries for export
@@ -5,9 +5,8 @@ require 'pathname'
5
5
 
6
6
  module LokaliseManager
7
7
  module TaskDefinitions
8
- # Base class for LokaliseManager task definitions, including common methods and logic.
9
- # This class serves as the foundation for importer and exporter classes, handling API
10
- # client interactions and configuration merging.
8
+ # Base class for LokaliseManager task definitions, providing common methods and logic
9
+ # for importer and exporter classes. Handles API client interactions and configuration merging.
11
10
  class Base
12
11
  using LokaliseManager::Utils::HashUtils
13
12
 
@@ -18,31 +17,15 @@ module LokaliseManager
18
17
  # @param custom_opts [Hash] Custom configurations for specific tasks.
19
18
  # @param global_config [Object] Reference to the global configuration.
20
19
  def initialize(custom_opts = {}, global_config = LokaliseManager::GlobalConfig)
21
- primary_opts = global_config
22
- .singleton_methods
23
- .filter { |m| m.to_s.end_with?('=') }
24
- .each_with_object({}) do |method, opts|
25
- reader = method.to_s.delete_suffix('=')
26
- opts[reader.to_sym] = global_config.send(reader)
27
- end
28
-
29
- all_opts = primary_opts.deep_merge(custom_opts)
30
-
31
- config_klass = Struct.new(*all_opts.keys, keyword_init: true)
32
-
33
- @config = config_klass.new all_opts
20
+ merged_opts = merge_configs(global_config, custom_opts)
21
+ @config = build_config_class(merged_opts)
34
22
  end
35
23
 
36
- # Creates or retrieves a Lokalise API client based on configuration.
24
+ # Retrieves or creates a Lokalise API client based on configuration.
37
25
  #
38
26
  # @return [RubyLokaliseApi::Client] Lokalise API client.
39
27
  def api_client
40
- return @api_client if @api_client
41
-
42
- client_opts = [config.api_token, config.timeouts]
43
- client_method = config.use_oauth2_token ? :oauth2_client : :client
44
-
45
- @api_client = ::RubyLokaliseApi.send(client_method, *client_opts)
28
+ @api_client ||= create_api_client
46
29
  end
47
30
 
48
31
  # Resets API client
@@ -54,15 +37,42 @@ module LokaliseManager
54
37
 
55
38
  private
56
39
 
40
+ # Creates a Lokalise API client based on configuration.
41
+ def create_api_client
42
+ client_opts = [config.api_token, config.additional_client_opts]
43
+ client_method = config.use_oauth2_token ? :oauth2_client : :client
44
+
45
+ ::RubyLokaliseApi.public_send(client_method, *client_opts)
46
+ end
47
+
48
+ # Merges global and custom configurations.
49
+ def merge_configs(global_config, custom_opts)
50
+ primary_opts = global_config
51
+ .singleton_methods
52
+ .select { |m| m.to_s.end_with?('=') }
53
+ .each_with_object({}) do |method, opts|
54
+ reader = method.to_s.delete_suffix('=')
55
+ opts[reader.to_sym] = global_config.public_send(reader)
56
+ end
57
+
58
+ primary_opts.deep_merge(custom_opts)
59
+ end
60
+
61
+ # Builds a config class with the given options.
62
+ def build_config_class(all_opts)
63
+ config_klass = Struct.new(*all_opts.keys, keyword_init: true)
64
+ config_klass.new(all_opts)
65
+ end
66
+
57
67
  # Checks and validates task options, raising errors if configurations are missing.
58
68
  def check_options_errors!
59
69
  errors = []
60
70
  errors << 'Project ID is not set!' if config.project_id.nil? || config.project_id.empty?
61
71
  errors << 'Lokalise API token is not set!' if config.api_token.nil? || config.api_token.empty?
62
- raise LokaliseManager::Error, errors.join(' ') if errors.any?
72
+ raise LokaliseManager::Error, errors.join(' ') unless errors.empty?
63
73
  end
64
74
 
65
- # Determines if the file has the correct extension based on the configuration.
75
+ # Checks if the file has the correct extension based on the configuration.
66
76
  #
67
77
  # @param raw_path [String, Pathname] Path to check.
68
78
  # @return [Boolean] True if the extension matches, false otherwise.
@@ -91,7 +101,7 @@ module LokaliseManager
91
101
  # Until this is fixed, we revert to this quick'n'dirty solution.
92
102
  EXCEPTIONS = [JSON::ParserError, RubyLokaliseApi::Error::TooManyRequests].freeze
93
103
 
94
- # Implements an exponential backoff strategy for handling retries after failures.
104
+ # Handles retries with exponential backoff for specific exceptions.
95
105
  def with_exp_backoff(max_retries)
96
106
  return unless block_given?
97
107
 
@@ -15,13 +15,9 @@ module LokaliseManager
15
15
  def export!
16
16
  check_options_errors!
17
17
 
18
- queued_processes = []
19
-
20
- all_files.each_slice(MAX_THREADS) do |files_group|
21
- parallel_upload(files_group).each do |thr|
22
- raise_on_fail(thr) if config.raise_on_export_fail
23
-
24
- queued_processes.push thr
18
+ queued_processes = all_files.each_slice(MAX_THREADS).flat_map do |files_group|
19
+ parallel_upload(files_group).tap do |threads|
20
+ threads.each { |thr| raise_on_fail(thr) if config.raise_on_export_fail }
25
21
  end
26
22
  end
27
23
 
@@ -36,17 +32,19 @@ module LokaliseManager
36
32
  #
37
33
  # @param files_group [Array] Group of files to be uploaded.
38
34
  # @return [Array] Array of threads handling the file uploads.
39
-
40
35
  def parallel_upload(files_group)
41
36
  files_group.map do |file_data|
42
37
  Thread.new { do_upload(*file_data) }
43
38
  end.map(&:value)
44
39
  end
45
40
 
41
+ # Raises an error if a file upload thread failed.
42
+ #
43
+ # @param thread [Struct] The result of the file upload thread.
46
44
  def raise_on_fail(thread)
47
45
  return if thread.success
48
46
 
49
- raise(thread.error.class, "Error while trying to upload #{thread.path}: #{thread.error.message}")
47
+ raise thread.error.class, "Error while trying to upload #{thread.path}: #{thread.error.message}"
50
48
  end
51
49
 
52
50
  # Performs the actual upload of a file to Lokalise.
@@ -56,56 +54,55 @@ module LokaliseManager
56
54
  # @return [Struct] A struct with the success status, process details, and any error information.
57
55
  def do_upload(f_path, r_path)
58
56
  proc_klass = Struct.new(:success, :process, :path, :error, keyword_init: true)
59
- begin
60
- process = with_exp_backoff(config.max_retries_export) do
61
- api_client.upload_file(project_id_with_branch, opts(f_path, r_path))
62
- end
63
- proc_klass.new(success: true, process: process, path: f_path)
64
- rescue StandardError => e
65
- proc_klass.new(success: false, path: f_path, error: e)
57
+
58
+ process = with_exp_backoff(config.max_retries_export) do
59
+ api_client.upload_file(project_id_with_branch, opts(f_path, r_path))
66
60
  end
61
+
62
+ proc_klass.new(success: true, process: process, path: f_path)
63
+ rescue StandardError => e
64
+ proc_klass.new(success: false, path: f_path, error: e)
67
65
  end
68
66
 
69
67
  # Prints a completion message to standard output.
70
68
  def print_completion_message
71
- $stdout.print('Task complete!')
69
+ $stdout.puts 'Task complete!'
72
70
  end
73
71
 
74
- # Gets translation files from the specified directory
72
+ # Retrieves all translation files from the specified directory.
73
+ #
74
+ # @return [Array] Array of [Pathname, Pathname] pairs representing full and relative paths.
75
75
  def all_files
76
- loc_path = config.locales_path
77
- Dir["#{loc_path}/**/*"].filter_map do |f|
78
- full_path = Pathname.new f
76
+ loc_path = Pathname.new(config.locales_path)
79
77
 
80
- next unless file_matches_criteria? full_path
81
-
82
- relative_path = full_path.relative_path_from Pathname.new(loc_path)
78
+ Dir["#{loc_path}/**/*"].filter_map do |file|
79
+ full_path = Pathname.new(file)
80
+ next unless file_matches_criteria?(full_path)
83
81
 
82
+ relative_path = full_path.relative_path_from(loc_path)
84
83
  [full_path, relative_path]
85
84
  end
86
85
  end
87
86
 
88
- # Generates export options
87
+ # Generates options for file upload to Lokalise.
89
88
  #
90
- # @return [Hash]
91
- # @param full_p [Pathname]
92
- # @param relative_p [Pathname]
89
+ # @param full_p [Pathname] Full path to the file.
90
+ # @param relative_p [Pathname] Relative path within the project.
91
+ # @return [Hash] Options for the Lokalise API upload.
93
92
  def opts(full_p, relative_p)
94
- content = File.read full_p
93
+ content = File.read(full_p).strip
95
94
 
96
- initial_opts = {
97
- data: Base64.strict_encode64(content.strip),
98
- filename: relative_p,
95
+ {
96
+ data: Base64.strict_encode64(content),
97
+ filename: relative_p.to_s,
99
98
  lang_iso: config.lang_iso_inferer.call(content, full_p)
100
- }
101
-
102
- initial_opts.merge config.export_opts
99
+ }.merge(config.export_opts)
103
100
  end
104
101
 
105
- # Checks whether the specified file has to be processed or not
102
+ # Checks whether the specified file meets the criteria for upload.
106
103
  #
107
- # @return [Boolean]
108
- # @param full_path [Pathname]
104
+ # @param full_path [Pathname] Full path to the file.
105
+ # @return [Boolean] True if the file matches criteria, false otherwise.
109
106
  def file_matches_criteria?(full_path)
110
107
  full_path.file? && proper_ext?(full_path) &&
111
108
  !config.skip_file_export.call(full_path)
@@ -6,9 +6,8 @@ require 'fileutils'
6
6
 
7
7
  module LokaliseManager
8
8
  module TaskDefinitions
9
- # The Importer class is responsible for downloading translation files from Lokalise
10
- # and importing them into the specified project directory. This class extends the Base class,
11
- # which provides shared functionality and configuration management.
9
+ # The Importer class handles downloading translation files from Lokalise
10
+ # and importing them into the specified project directory.
12
11
  class Importer < Base
13
12
  # Initiates the import process by checking configuration, ensuring safe mode conditions,
14
13
  # downloading files, and processing them. Outputs task completion status.
@@ -46,11 +45,7 @@ module LokaliseManager
46
45
  # @param path [String] The URL or local path to the ZIP archive.
47
46
  def open_and_process_zip(path)
48
47
  Zip::File.open_buffer(open_file_or_remote(path)) do |zip|
49
- zip.each do |entry|
50
- next unless proper_ext?(entry.name)
51
-
52
- process_entry(entry)
53
- end
48
+ zip.each { |entry| process_entry(entry) if proper_ext?(entry.name) }
54
49
  end
55
50
  rescue StandardError => e
56
51
  raise e.class, "Error processing ZIP file: #{e.message}"
@@ -80,8 +75,7 @@ module LokaliseManager
80
75
 
81
76
  $stdout.puts "The target directory #{config.locales_path} is not empty!"
82
77
  $stdout.print 'Enter Y to continue: '
83
- answer = $stdin.gets
84
- answer.to_s.strip == 'Y'
78
+ $stdin.gets.strip.upcase == 'Y'
85
79
  end
86
80
 
87
81
  # Opens a local file or a remote URL using the provided path, safely handling different path schemes.
@@ -89,13 +83,8 @@ module LokaliseManager
89
83
  # @param path [String] The path to the file, either a local path or a URL.
90
84
  # @return [IO] Returns an IO object for the file.
91
85
  def open_file_or_remote(path)
92
- parsed_path = URI.parse(path)
93
-
94
- if parsed_path&.scheme&.include?('http')
95
- parsed_path.open
96
- else
97
- File.open path
98
- end
86
+ uri = URI.parse(path)
87
+ uri.scheme&.start_with?('http') ? uri.open : File.open(path)
99
88
  end
100
89
 
101
90
  # Loads translations from the ZIP file.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LokaliseManager
4
- VERSION = '5.1.1'
4
+ VERSION = '6.0.0'
5
5
  end
@@ -23,7 +23,7 @@ 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', '~> 9.0'
26
+ spec.add_dependency 'ruby-lokalise-api', '~> 9.3'
27
27
  spec.add_dependency 'rubyzip', '~> 2.3'
28
28
  spec.add_dependency 'zeitwerk', '~> 2.4'
29
29
 
@@ -33,7 +33,7 @@ Gem::Specification.new do |spec|
33
33
  spec.add_development_dependency 'rubocop', '~> 1.0'
34
34
  spec.add_development_dependency 'rubocop-performance', '~> 1.5'
35
35
  spec.add_development_dependency 'rubocop-rake', '~> 0.6'
36
- spec.add_development_dependency 'rubocop-rspec', '~> 2.6'
36
+ spec.add_development_dependency 'rubocop-rspec', '~> 3.0'
37
37
  spec.add_development_dependency 'simplecov', '~> 0.16'
38
38
  spec.add_development_dependency 'simplecov-lcov', '~> 0.8'
39
39
  spec.add_development_dependency 'webmock', '~> 3.18'
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: 5.1.1
4
+ version: 6.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ilya Krukowski
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-10 00:00:00.000000000 Z
11
+ date: 2024-11-29 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: '9.0'
19
+ version: '9.3'
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: '9.0'
26
+ version: '9.3'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rubyzip
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -142,14 +142,14 @@ dependencies:
142
142
  requirements:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: '2.6'
145
+ version: '3.0'
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: '2.6'
152
+ version: '3.0'
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: simplecov
155
155
  requirement: !ruby/object:Gem::Requirement
@@ -238,7 +238,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
238
238
  - !ruby/object:Gem::Version
239
239
  version: '0'
240
240
  requirements: []
241
- rubygems_version: 3.5.10
241
+ rubygems_version: 3.5.23
242
242
  signing_key:
243
243
  specification_version: 4
244
244
  summary: Lokalise integration for Ruby