ruby-lokalise-api 3.1.0 → 4.3.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.
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'faraday'
4
+ require 'faraday_middleware'
4
5
  require 'yaml'
5
6
  require 'addressable'
6
7
 
@@ -24,12 +24,13 @@ require 'ruby-lokalise-api/rest/webhooks'
24
24
  module Lokalise
25
25
  class Client
26
26
  attr_reader :token
27
- attr_accessor :timeout, :open_timeout
27
+ attr_accessor :timeout, :open_timeout, :enable_compression
28
28
 
29
29
  def initialize(token, params = {})
30
30
  @token = token
31
31
  @timeout = params.fetch(:timeout, nil)
32
32
  @open_timeout = params.fetch(:open_timeout, nil)
33
+ @enable_compression = params.fetch(:enable_compression, false)
33
34
  end
34
35
 
35
36
  # rubocop:disable Metrics/ParameterLists
@@ -56,7 +57,7 @@ module Lokalise
56
57
  return params unless object_key
57
58
 
58
59
  params = [params] unless params.is_a?(Array)
59
- Hash[object_key, params]
60
+ {object_key => params}
60
61
  end
61
62
 
62
63
  alias c_r construct_request
@@ -91,7 +91,7 @@ module Lokalise
91
91
  # Collection example: `{ "content": {"comments": [ ... ]} }`
92
92
  def produce_collection_for(response)
93
93
  model_class = self.class.name.base_class_name
94
- data_key_plural = data_key_for model_class, true, true
94
+ data_key_plural = data_key_for model_class: model_class, plural: true, collection: true
95
95
 
96
96
  # Fetch collection data and instantiate an individual resource for each object
97
97
  # We also preserve the `client` to be able to chain API methods later
@@ -5,7 +5,16 @@ module Lokalise
5
5
  BASE_URL = 'https://api.lokalise.com/api2/'
6
6
 
7
7
  def connection(client)
8
- options = {
8
+ Faraday.new(options(client), request_params_for(client)) do |faraday|
9
+ faraday.use(:gzip) if client.enable_compression
10
+ faraday.adapter Faraday.default_adapter
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def options(client)
17
+ {
9
18
  headers: {
10
19
  accept: 'application/json',
11
20
  user_agent: "ruby-lokalise-api gem/#{Lokalise::VERSION}",
@@ -13,11 +22,8 @@ module Lokalise
13
22
  },
14
23
  url: BASE_URL
15
24
  }
16
- Faraday.new(options, request_params_for(client)) { |faraday| faraday.adapter Faraday.default_adapter }
17
25
  end
18
26
 
19
- private
20
-
21
27
  # Allows to customize request params per-client
22
28
  def request_params_for(client)
23
29
  {request: {timeout: client.timeout, open_timeout: client.open_timeout}}
@@ -86,7 +86,9 @@
86
86
  "translation_tier",
87
87
  "translation_tier_name",
88
88
  "briefing",
89
- "total"
89
+ "total",
90
+ "payment_method",
91
+ "dry_run"
90
92
  ],
91
93
  "payment_card": [
92
94
  "card_id",
@@ -162,6 +164,7 @@
162
164
  "languages",
163
165
  "auto_close_languages",
164
166
  "auto_close_task",
167
+ "auto_close_items",
165
168
  "completed_at",
166
169
  "completed_at_timestamp",
167
170
  "completed_by",
@@ -207,7 +210,8 @@
207
210
  "is_fuzzy",
208
211
  "is_reviewed",
209
212
  "words",
210
- "custom_translation_statuses"
213
+ "custom_translation_statuses",
214
+ "task_id"
211
215
  ],
212
216
  "translation_provider": [
213
217
  "provider_id",
@@ -95,7 +95,7 @@ module Lokalise
95
95
  # Instantiates a new resource or collection based on the given response
96
96
  def object_from(response, params)
97
97
  model_class = name.base_class_name
98
- data_key_plural = data_key_for model_class, true
98
+ data_key_plural = data_key_for model_class: model_class, plural: true
99
99
  # Preserve the initial path to allow chaining
100
100
  response['path'] = params.delete(:_initial_path) if params.key?(:_initial_path)
101
101
 
@@ -107,7 +107,7 @@ module Lokalise
107
107
  end
108
108
 
109
109
  def produce_resource(model_class, response)
110
- data_key_singular = data_key_for model_class
110
+ data_key_singular = data_key_for model_class: model_class
111
111
  if response['content'].key? data_key_singular
112
112
  data = response['content'].delete data_key_singular
113
113
  response['content'].merge! data
@@ -124,7 +124,7 @@ module Lokalise
124
124
  # Generates path for the individual resource based on the path for the collection
125
125
  def infer_path_from(response, endpoint_generator = nil)
126
126
  id_key = id_key_for self.class.name.base_class_name
127
- data_key = data_key_for self.class.name.base_class_name
127
+ data_key = data_key_for model_class: self.class.name.base_class_name
128
128
 
129
129
  path_with_id response, id_key, data_key, endpoint_generator
130
130
  end
@@ -164,7 +164,7 @@ module Lokalise
164
164
  # Store all resources attributes under the corresponding instance variables.
165
165
  # `ATTRIBUTES` is defined inside resource-specific classes
166
166
  def populate_attributes_for(content)
167
- data_key = data_key_for self.class.name.base_class_name
167
+ data_key = data_key_for model_class: self.class.name.base_class_name
168
168
 
169
169
  self.class.const_get(:ATTRIBUTES).each do |attr|
170
170
  value = if content.key?(data_key) && content[data_key].is_a?(Hash)
@@ -6,7 +6,7 @@ module Lokalise
6
6
  supports :update, :destroy, [:reload_data, '', :find]
7
7
 
8
8
  def empty
9
- self.class.empty @client, @path + '/empty'
9
+ self.class.empty @client, "#{@path}/empty"
10
10
  end
11
11
 
12
12
  class << self
@@ -6,7 +6,7 @@ module Lokalise
6
6
  supports :update, :destroy, [:reload_data, '', :find]
7
7
 
8
8
  def regenerate_secret
9
- self.class.regenerate_secret @client, @path + '/secret/regenerate'
9
+ self.class.regenerate_secret @client, "#{@path}/secret/regenerate"
10
10
  end
11
11
 
12
12
  class << self
@@ -22,7 +22,8 @@ module Lokalise
22
22
  c_r Lokalise::Resources::File, :download, [project_id, 'download'], params
23
23
  end
24
24
 
25
- # Imports translation file to the given project. File data must base64-encoded
25
+ # Imports translation file to the given project. File data must base64-encoded.
26
+ # To encode your data in Base64, use `Base64.strict_encode64()` method.
26
27
  #
27
28
  # @see https://app.lokalise.com/api2docs/curl/#transition-upload-a-file-post
28
29
  # @return [Hash]
@@ -16,16 +16,21 @@ module Lokalise
16
16
  # @return [String]
17
17
  # @param model_class [String]
18
18
  # @param plural [Boolean] Should the returned value be pluralized?
19
- def data_key_for(model_class, plural = false, collection = false)
20
- data_key_plural = get_key('DATA_KEY_PLURAL', model_class, true, true)
19
+ def data_key_for(model_class:, plural: false, collection: false)
20
+ data_key_plural = get_key(
21
+ name: 'DATA_KEY_PLURAL',
22
+ model_class: model_class,
23
+ collection: true,
24
+ strict: true
25
+ )
21
26
 
22
27
  return data_key_plural if collection && data_key_plural
23
28
 
24
- data_key = get_key 'DATA_KEY', model_class, collection
29
+ data_key = get_key name: 'DATA_KEY', model_class: model_class, collection: collection
25
30
 
26
31
  return data_key unless plural
27
32
 
28
- data_key + 's'
33
+ "#{data_key}s"
29
34
  end
30
35
 
31
36
  # Returns key used to determine resource id (for example `user_id` or `project_id`).
@@ -35,16 +40,14 @@ module Lokalise
35
40
  # @return [String]
36
41
  # @param model_class [String]
37
42
  def id_key_for(model_class)
38
- get_key('ID_KEY', model_class) + '_id'
43
+ "#{get_key(name: 'ID_KEY', model_class: model_class)}_id"
39
44
  end
40
45
 
41
46
  # Loads attributes for the given resource based on its name
42
47
  #
43
48
  # @return [Array<String>]
44
49
  def attributes_for(klass)
45
- @attributes ||= begin
46
- YAML.load_file(File.expand_path('../data/attributes.json', __dir__)).freeze
47
- end
50
+ @attributes ||= YAML.load_file(File.expand_path('../data/attributes.json', __dir__)).freeze
48
51
 
49
52
  name = unify klass.name.snakecase
50
53
  @attributes[name]
@@ -52,7 +55,7 @@ module Lokalise
52
55
 
53
56
  private
54
57
 
55
- def get_key(name, model_class, collection = false, strict = false)
58
+ def get_key(name:, model_class:, collection: false, strict: false)
56
59
  key = if collection && Module.const_defined?("Lokalise::Collections::#{model_class}::#{name}")
57
60
  Module.const_get "Lokalise::Collections::#{model_class}::#{name}"
58
61
  elsif Module.const_defined? "Lokalise::Resources::#{model_class}::#{name}"
@@ -22,6 +22,6 @@ class String
22
22
  end
23
23
 
24
24
  def remove_trailing_slash
25
- gsub %r{/\z}, ''
25
+ delete_suffix '/'
26
26
  end
27
27
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Lokalise
4
- VERSION = '3.1.0'
4
+ VERSION = '4.3.0'
5
5
  end
@@ -10,8 +10,9 @@ Gem::Specification.new do |spec|
10
10
  spec.summary = 'Ruby interface to the Lokalise API'
11
11
  spec.description = 'Opinionated Ruby client for the Lokalise platform API allowing to work with translations, projects, users and other resources as with Ruby objects.'
12
12
  spec.homepage = 'https://github.com/lokalise/ruby-lokalise-api'
13
- spec.license = 'MIT'
13
+ spec.license = 'BSD-3-Clause'
14
14
  spec.platform = Gem::Platform::RUBY
15
+ spec.required_ruby_version = '>= 2.5.0'
15
16
 
16
17
  spec.files = Dir['README.md', 'LICENSE',
17
18
  'CHANGELOG.md', 'lib/**/*.rb', 'lib/ruby-lokalise-api/data/attributes.json',
@@ -23,6 +24,7 @@ Gem::Specification.new do |spec|
23
24
 
24
25
  spec.add_dependency 'addressable', '~> 2.5'
25
26
  spec.add_dependency 'faraday', '~> 1.0'
27
+ spec.add_dependency 'faraday_middleware', '~> 1.0'
26
28
  spec.add_dependency 'json', '>= 1.8.0'
27
29
 
28
30
  spec.add_development_dependency 'codecov', '~> 0.1'
@@ -30,9 +32,9 @@ Gem::Specification.new do |spec|
30
32
  spec.add_development_dependency 'oj', '~> 3.10'
31
33
  spec.add_development_dependency 'rake', '~> 13.0'
32
34
  spec.add_development_dependency 'rspec', '~> 3.6'
33
- spec.add_development_dependency 'rubocop', '~> 0.60'
35
+ spec.add_development_dependency 'rubocop', '~> 1.6'
34
36
  spec.add_development_dependency 'rubocop-performance', '~> 1.5'
35
- spec.add_development_dependency 'rubocop-rspec', '~> 1.37'
37
+ spec.add_development_dependency 'rubocop-rspec', '~> 2.0'
36
38
  spec.add_development_dependency 'simplecov', '~> 0.16'
37
39
  spec.add_development_dependency 'vcr', '~> 6.0'
38
40
  end
@@ -3,6 +3,9 @@
3
3
  RSpec.describe Lokalise::Connection do
4
4
  include described_class
5
5
 
6
+ let(:project_id) { '803826145ba90b42d5d860.46800099' }
7
+ let(:key_id) { 44_596_059 }
8
+
6
9
  before { Lokalise.reset_client! }
7
10
 
8
11
  after do
@@ -10,11 +13,12 @@ RSpec.describe Lokalise::Connection do
10
13
  Faraday.default_adapter = :net_http
11
14
  end
12
15
 
13
- it 'timeouts should not be set by default but the token must be present' do
16
+ it 'timeouts and compression should not be set by default but the token must be present' do
14
17
  conn = connection test_client
15
18
  expect(conn.options.timeout).to be_nil
16
19
  expect(conn.options.open_timeout).to be_nil
17
20
  expect(conn.headers['X-api-token']).to eq(test_client.token)
21
+ expect(conn.builder.handlers).not_to include(FaradayMiddleware::Gzip)
18
22
  end
19
23
 
20
24
  it 'allows to customize timeouts' do
@@ -42,4 +46,38 @@ RSpec.describe Lokalise::Connection do
42
46
  expect(another_conn.builder.adapter).to eq(Faraday::Adapter::Excon)
43
47
  expect(conn.builder.adapter).to eq(Faraday::Adapter::NetHttp)
44
48
  end
49
+
50
+ it 'allows to customize compression' do
51
+ custom_client = Lokalise.client(ENV['LOKALISE_API_TOKEN'], enable_compression: true)
52
+ conn = connection custom_client
53
+ expect(conn.headers['X-api-token']).to eq(custom_client.token)
54
+ expect(conn.builder.handlers).to include(FaradayMiddleware::Gzip)
55
+ end
56
+
57
+ it 'is possible to enable gzip compression' do
58
+ gzip_client = Lokalise.client(ENV['LOKALISE_API_TOKEN'], enable_compression: true)
59
+ keys = VCR.use_cassette('all_keys_gzip') do
60
+ gzip_client.keys project_id
61
+ end.collection
62
+
63
+ expect(keys.first.key_id).to eq(key_id)
64
+ end
65
+
66
+ it 'is possible to disable gzip compression' do
67
+ no_gzip_client = Lokalise.client(ENV['LOKALISE_API_TOKEN'], enable_compression: false)
68
+ keys = VCR.use_cassette('all_keys_no_gzip') do
69
+ no_gzip_client.keys project_id
70
+ end.collection
71
+
72
+ expect(keys.first.key_id).to eq(key_id)
73
+ end
74
+
75
+ it 'gzip compression is off by default' do
76
+ default_gzip_client = Lokalise.client(ENV['LOKALISE_API_TOKEN'])
77
+ keys = VCR.use_cassette('all_keys_default_gzip') do
78
+ default_gzip_client.keys project_id
79
+ end.collection
80
+
81
+ expect(keys.first.key_id).to eq(key_id)
82
+ end
45
83
  end
@@ -27,7 +27,7 @@ RSpec.describe Lokalise::JsonHandler do
27
27
  '{":name":"rspec proj",":description":"demo project for rspec"}'
28
28
  end
29
29
 
30
- # rubocop:disable RSpec/LeakyConstantDeclaration
30
+ # rubocop:disable RSpec/LeakyConstantDeclaration, Lint/ConstantDefinitionInBlock
31
31
  before do
32
32
  module Lokalise
33
33
  module JsonHandler
@@ -55,10 +55,10 @@ RSpec.describe Lokalise::JsonHandler do
55
55
  end
56
56
  end
57
57
  end
58
- # rubocop:enable RSpec/LeakyConstantDeclaration
58
+ # rubocop:enable RSpec/LeakyConstantDeclaration, Lint/ConstantDefinitionInBlock
59
59
 
60
60
  it 'allows to customize #load' do
61
- expect(Oj).to receive(:load).and_return(loaded_json)
61
+ allow(Oj).to receive(:load).and_return(loaded_json)
62
62
  expect(JSON).not_to receive(:parse)
63
63
  projects = VCR.use_cassette('all_projects_pagination') do
64
64
  test_client.projects limit: 1, page: 2
@@ -70,7 +70,7 @@ RSpec.describe Lokalise::JsonHandler do
70
70
  end
71
71
 
72
72
  it 'allows to customize #dump' do
73
- expect(Oj).to receive(:dump).and_return(dumped_json)
73
+ allow(Oj).to receive(:dump).and_return(dumped_json)
74
74
  expect(JSON).not_to receive(:dump)
75
75
  project = VCR.use_cassette('new_project') do
76
76
  test_client.create_project name: 'rspec proj', description: 'demo project for rspec'
@@ -37,8 +37,8 @@ RSpec.describe Lokalise::Client do
37
37
 
38
38
  expect(order.order_id).to eq(order_id)
39
39
  expect(order.project_id).to eq(project_id)
40
- expect(order.card_id).to eq(card_id.to_s)
41
- expect(order.status).to eq('in progress')
40
+ expect(order.card_id).to eq(card_id)
41
+ expect(order.status).to eq('completed')
42
42
  expect(order.created_at).to eq('2019-03-19 18:18:21 (Etc/UTC)')
43
43
  expect(order.created_by).to eq(20_181)
44
44
  expect(order.created_by_email).to eq('bodrovis@protonmail.com')
@@ -52,6 +52,7 @@ RSpec.describe Lokalise::Client do
52
52
  expect(order.translation_tier_name).to eq('Professional translator')
53
53
  expect(order.briefing).to eq('Some briefing')
54
54
  expect(order.total).to eq(0.07)
55
+ expect(order.payment_method).to be_nil
55
56
  end
56
57
 
57
58
  specify '#reload_data' do
@@ -86,4 +87,27 @@ RSpec.describe Lokalise::Client do
86
87
  expect(order.order_id).to eq(order_id)
87
88
  expect(order.status).to eq('in progress')
88
89
  end
90
+
91
+ it 'creates an order with dry run' do
92
+ order = VCR.use_cassette('create_order_dry_run') do
93
+ test_client.create_order team_id,
94
+ project_id: project_id,
95
+ card_id: card_id,
96
+ briefing: 'Some briefing',
97
+ source_language_iso: 'en',
98
+ target_language_isos: [
99
+ 'ru'
100
+ ],
101
+ keys: [
102
+ 74_189_435
103
+ ],
104
+ provider_slug: 'gengo',
105
+ translation_tier: '1',
106
+ dry_run: true
107
+ end
108
+
109
+ expect(order.order_id).to be_nil
110
+ expect(order.status).to eq('draft')
111
+ expect(order.dry_run).to be true
112
+ end
89
113
  end
@@ -36,9 +36,9 @@ RSpec.describe Lokalise::Client do
36
36
  specify '#create_payment_card' do
37
37
  card = VCR.use_cassette('new_payment_card') do
38
38
  test_client.create_payment_card number: '4242424242424242',
39
- "cvc": '123',
40
- "exp_month": 1,
41
- "exp_year": 2030
39
+ cvc: '123',
40
+ exp_month: 1,
41
+ exp_year: 2030
42
42
  end
43
43
 
44
44
  expect(card.card_id).to eq(card_id)
@@ -35,8 +35,8 @@ RSpec.describe Lokalise::Client do
35
35
  expect(task.task_id).to eq(11_925)
36
36
  expect(task.title).to eq('node updated')
37
37
  expect(task.description).to eq('')
38
- expect(task.status).to eq('in progress')
39
- expect(task.progress).to eq(1)
38
+ expect(task.status).to eq('completed')
39
+ expect(task.progress).to eq(0)
40
40
  expect(task.due_date).to eq(nil)
41
41
  expect(task.due_date_timestamp).to eq(nil)
42
42
  expect(task.keys_count).to eq(16)
@@ -45,17 +45,18 @@ RSpec.describe Lokalise::Client do
45
45
  expect(task.created_at_timestamp).to eq(1_557_764_126)
46
46
  expect(task.created_by).to eq(20_181)
47
47
  expect(task.created_by_email).to eq('bodrovis@protonmail.com')
48
- expect(task.can_be_parent).to eq(true)
48
+ expect(task.can_be_parent).to eq(false)
49
49
  expect(task.task_type).to eq('review')
50
50
  expect(task.parent_task_id).to eq(nil)
51
51
  expect(task.closing_tags).to eq([])
52
52
  expect(task.languages.first['language_iso']).to eq('sq')
53
53
  expect(task.auto_close_languages).to eq(true)
54
54
  expect(task.auto_close_task).to eq(true)
55
- expect(task.completed_by).to eq(nil)
56
- expect(task.completed_by_email).to eq(nil)
57
- expect(task.completed_at).to eq(nil)
58
- expect(task.completed_at_timestamp).to eq(nil)
55
+ expect(task.auto_close_items).to eq(true)
56
+ expect(task.completed_by).to eq(20_181)
57
+ expect(task.completed_by_email).to eq('bodrovis@protonmail.com')
58
+ expect(task.completed_at).to eq('2019-10-01 11:09:12 (Etc/UTC)')
59
+ expect(task.completed_at_timestamp).to eq(1_569_928_152)
59
60
  expect(task.do_lock_translations).to eq(false)
60
61
  expect(task.custom_translation_status_ids).to eq([])
61
62
  end