ruby-lokalise-api 2.9.0 → 4.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.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODE_OF_CONDUCT.md +1 -1
  3. data/.github/CONTRIBUTING.md +9 -2
  4. data/CHANGELOG.md +1 -75
  5. data/LICENSE +9 -18
  6. data/README.md +18 -1734
  7. data/lib/ruby-lokalise-api.rb +2 -0
  8. data/lib/ruby-lokalise-api/client.rb +16 -4
  9. data/lib/ruby-lokalise-api/collections/base.rb +5 -3
  10. data/lib/ruby-lokalise-api/collections/queued_process.rb +15 -0
  11. data/lib/ruby-lokalise-api/connection.rb +1 -1
  12. data/lib/ruby-lokalise-api/data/attributes.json +29 -13
  13. data/lib/ruby-lokalise-api/request.rb +8 -1
  14. data/lib/ruby-lokalise-api/resources/base.rb +55 -25
  15. data/lib/ruby-lokalise-api/resources/branch.rb +1 -1
  16. data/lib/ruby-lokalise-api/resources/contributor.rb +1 -1
  17. data/lib/ruby-lokalise-api/resources/custom_translation_status.rb +1 -1
  18. data/lib/ruby-lokalise-api/resources/file.rb +3 -1
  19. data/lib/ruby-lokalise-api/resources/key.rb +1 -1
  20. data/lib/ruby-lokalise-api/resources/key_comment.rb +1 -1
  21. data/lib/ruby-lokalise-api/resources/order.rb +2 -0
  22. data/lib/ruby-lokalise-api/resources/payment_card.rb +1 -1
  23. data/lib/ruby-lokalise-api/resources/project.rb +2 -2
  24. data/lib/ruby-lokalise-api/resources/project_language.rb +1 -1
  25. data/lib/ruby-lokalise-api/resources/queued_process.rb +18 -0
  26. data/lib/ruby-lokalise-api/resources/screenshot.rb +1 -1
  27. data/lib/ruby-lokalise-api/resources/snapshot.rb +3 -1
  28. data/lib/ruby-lokalise-api/resources/task.rb +1 -1
  29. data/lib/ruby-lokalise-api/resources/team_user.rb +1 -1
  30. data/lib/ruby-lokalise-api/resources/team_user_group.rb +2 -1
  31. data/lib/ruby-lokalise-api/resources/translation.rb +1 -1
  32. data/lib/ruby-lokalise-api/resources/translation_provider.rb +3 -0
  33. data/lib/ruby-lokalise-api/resources/webhook.rb +11 -3
  34. data/lib/ruby-lokalise-api/rest/comments.rb +5 -5
  35. data/lib/ruby-lokalise-api/rest/contributors.rb +5 -5
  36. data/lib/ruby-lokalise-api/rest/custom_translation_statuses.rb +6 -6
  37. data/lib/ruby-lokalise-api/rest/files.rb +3 -3
  38. data/lib/ruby-lokalise-api/rest/keys.rb +7 -7
  39. data/lib/ruby-lokalise-api/rest/languages.rb +6 -6
  40. data/lib/ruby-lokalise-api/rest/payment_cards.rb +3 -3
  41. data/lib/ruby-lokalise-api/rest/projects.rb +6 -6
  42. data/lib/ruby-lokalise-api/rest/queued_processes.rb +26 -0
  43. data/lib/ruby-lokalise-api/rest/screenshots.rb +5 -5
  44. data/lib/ruby-lokalise-api/rest/snapshots.rb +4 -4
  45. data/lib/ruby-lokalise-api/rest/tasks.rb +5 -5
  46. data/lib/ruby-lokalise-api/rest/team_user_group.rb +4 -4
  47. data/lib/ruby-lokalise-api/rest/team_users.rb +4 -4
  48. data/lib/ruby-lokalise-api/rest/teams.rb +1 -1
  49. data/lib/ruby-lokalise-api/rest/translation_providers.rb +2 -2
  50. data/lib/ruby-lokalise-api/rest/translations.rb +3 -3
  51. data/lib/ruby-lokalise-api/rest/webhooks.rb +16 -5
  52. data/lib/ruby-lokalise-api/utils/attribute_helpers.rb +11 -6
  53. data/lib/ruby-lokalise-api/version.rb +1 -1
  54. data/ruby-lokalise-api.gemspec +7 -7
  55. data/spec/lib/ruby-lokalise-api/custom_json_parser_spec.rb +4 -4
  56. data/spec/lib/ruby-lokalise-api/error_spec.rb +8 -0
  57. data/spec/lib/ruby-lokalise-api/rest/branches_spec.rb +12 -0
  58. data/spec/lib/ruby-lokalise-api/rest/comments_spec.rb +12 -0
  59. data/spec/lib/ruby-lokalise-api/rest/contributors_spec.rb +12 -0
  60. data/spec/lib/ruby-lokalise-api/rest/custom_translation_statuses_spec.rb +12 -0
  61. data/spec/lib/ruby-lokalise-api/rest/files_spec.rb +17 -9
  62. data/spec/lib/ruby-lokalise-api/rest/keys_spec.rb +38 -20
  63. data/spec/lib/ruby-lokalise-api/rest/languages_spec.rb +12 -0
  64. data/spec/lib/ruby-lokalise-api/rest/orders_spec.rb +12 -0
  65. data/spec/lib/ruby-lokalise-api/rest/payment_cards_spec.rb +19 -5
  66. data/spec/lib/ruby-lokalise-api/rest/projects_spec.rb +12 -0
  67. data/spec/lib/ruby-lokalise-api/rest/queued_processes_spec.rb +57 -0
  68. data/spec/lib/ruby-lokalise-api/rest/screenshots_spec.rb +12 -0
  69. data/spec/lib/ruby-lokalise-api/rest/snapshots_spec.rb +25 -0
  70. data/spec/lib/ruby-lokalise-api/rest/tasks_spec.rb +20 -7
  71. data/spec/lib/ruby-lokalise-api/rest/team_user_groups_spec.rb +84 -0
  72. data/spec/lib/ruby-lokalise-api/rest/team_users_spec.rb +13 -0
  73. data/spec/lib/ruby-lokalise-api/rest/translation_providers_spec.rb +5 -0
  74. data/spec/lib/ruby-lokalise-api/rest/translations_spec.rb +12 -0
  75. data/spec/lib/ruby-lokalise-api/rest/webhooks_spec.rb +50 -0
  76. metadata +25 -20
@@ -17,6 +17,7 @@ require 'ruby-lokalise-api/resources/base'
17
17
  require 'ruby-lokalise-api/resources/branch'
18
18
  require 'ruby-lokalise-api/resources/project'
19
19
  require 'ruby-lokalise-api/resources/project_language'
20
+ require 'ruby-lokalise-api/resources/queued_process'
20
21
  require 'ruby-lokalise-api/resources/key_comment'
21
22
  require 'ruby-lokalise-api/resources/contributor'
22
23
  require 'ruby-lokalise-api/resources/file'
@@ -43,6 +44,7 @@ require 'ruby-lokalise-api/collections/team'
43
44
  require 'ruby-lokalise-api/collections/system_language'
44
45
  require 'ruby-lokalise-api/collections/project_language'
45
46
  require 'ruby-lokalise-api/collections/project_comment'
47
+ require 'ruby-lokalise-api/collections/queued_process'
46
48
  require 'ruby-lokalise-api/collections/key_comment'
47
49
  require 'ruby-lokalise-api/collections/key'
48
50
  require 'ruby-lokalise-api/collections/contributor'
@@ -4,6 +4,7 @@ require 'ruby-lokalise-api/rest/branches'
4
4
  require 'ruby-lokalise-api/rest/languages'
5
5
  require 'ruby-lokalise-api/rest/teams'
6
6
  require 'ruby-lokalise-api/rest/projects'
7
+ require 'ruby-lokalise-api/rest/queued_processes'
7
8
  require 'ruby-lokalise-api/rest/comments'
8
9
  require 'ruby-lokalise-api/rest/keys'
9
10
  require 'ruby-lokalise-api/rest/contributors'
@@ -27,14 +28,25 @@ module Lokalise
27
28
 
28
29
  def initialize(token, params = {})
29
30
  @token = token
30
- @timeout = params.fetch(:timeout) { nil }
31
- @open_timeout = params.fetch(:open_timeout) { nil }
31
+ @timeout = params.fetch(:timeout, nil)
32
+ @open_timeout = params.fetch(:open_timeout, nil)
32
33
  end
33
34
 
34
- def construct_request(klass, method, endpoint_ids, params = {}, object_key = nil)
35
+ # rubocop:disable Metrics/ParameterLists
36
+ # Constructs request to perform the specified action
37
+ # @param klass The actual class to call the method upon
38
+ # @param method [Symbol] The method to call (:new, :update, :create etc)
39
+ # @param endpoint_ids [Array, Hash] IDs that are used to generate the proper path to the endpoint
40
+ # @param params [Array, Hash] Request parameters
41
+ # @param object_key [String, Symbol] Key that should be used to wrap parameters into
42
+ # @param initial_ids [Array] IDs that should be used to generate base endpoint path. The base path is used for method chaining
43
+ def construct_request(klass, method, endpoint_ids, params = {}, object_key = nil, initial_ids = nil)
35
44
  path = klass.endpoint(*endpoint_ids)
36
- klass.send method, self, path, format_params(params, object_key)
45
+ formatted_params = format_params(params, object_key)
46
+ formatted_params[:_initial_path] = klass.endpoint(*initial_ids) if initial_ids
47
+ klass.send method, self, path, formatted_params
37
48
  end
49
+ # rubocop:enable Metrics/ParameterLists
38
50
 
39
51
  # Converts `params` to hash with arrays under the `object_key` key.
40
52
  # Used in bulk operations
@@ -9,7 +9,7 @@ module Lokalise
9
9
  extend Lokalise::Utils::EndpointHelpers
10
10
 
11
11
  attr_reader :total_pages, :total_results, :results_per_page, :current_page, :collection,
12
- :project_id, :team_id, :request_params, :client, :path
12
+ :project_id, :team_id, :request_params, :client, :path, :branch, :user_id
13
13
 
14
14
  # Initializes a new collection based on the response
15
15
  #
@@ -19,9 +19,11 @@ module Lokalise
19
19
  def initialize(response, params = {})
20
20
  produce_collection_for response
21
21
  populate_pagination_data_for response
22
- # Project and team id may not be present in some cases
22
+ # Project, team id, user id, and branch may not be present in some cases
23
23
  @project_id = response['content']['project_id']
24
24
  @team_id = response['content']['team_id']
25
+ @user_id = response['content']['user_id']
26
+ @branch = response['content']['branch']
25
27
  @request_params = params
26
28
  @client = response['client']
27
29
  @path = response['path']
@@ -89,7 +91,7 @@ module Lokalise
89
91
  # Collection example: `{ "content": {"comments": [ ... ]} }`
90
92
  def produce_collection_for(response)
91
93
  model_class = self.class.name.base_class_name
92
- 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
93
95
 
94
96
  # Fetch collection data and instantiate an individual resource for each object
95
97
  # We also preserve the `client` to be able to chain API methods later
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lokalise
4
+ module Collections
5
+ class QueuedProcess < Base
6
+ DATA_KEY_PLURAL = 'Processes'
7
+
8
+ class << self
9
+ def endpoint(project_id, *_args)
10
+ path_from projects: [project_id, 'processes']
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Lokalise
4
4
  module Connection
5
- BASE_URL = 'https://api.lokalise.co/api2/'
5
+ BASE_URL = 'https://api.lokalise.com/api2/'
6
6
 
7
7
  def connection(client)
8
8
  options = {
@@ -21,11 +21,11 @@
21
21
  "email",
22
22
  "fullname",
23
23
  "created_at",
24
+ "created_at_timestamp",
24
25
  "is_admin",
25
26
  "is_reviewer",
26
27
  "languages",
27
- "admin_rights",
28
- "created_at_timestamp"
28
+ "admin_rights"
29
29
  ],
30
30
  "custom_translation_status": [
31
31
  "status_id",
@@ -39,6 +39,7 @@
39
39
  "key": [
40
40
  "key_id",
41
41
  "created_at",
42
+ "created_at_timestamp",
42
43
  "key_name",
43
44
  "filenames",
44
45
  "description",
@@ -55,7 +56,10 @@
55
56
  "base_words",
56
57
  "char_limit",
57
58
  "custom_attributes",
58
- "created_at_timestamp"
59
+ "modified_at",
60
+ "modified_at_timestamp",
61
+ "translations_modified_at",
62
+ "translations_modified_at_timestamp"
59
63
  ],
60
64
  "language": [
61
65
  "lang_id",
@@ -70,6 +74,7 @@
70
74
  "card_id",
71
75
  "status",
72
76
  "created_at",
77
+ "created_at_timestamp",
73
78
  "created_by",
74
79
  "created_by_email",
75
80
  "source_language_iso",
@@ -81,8 +86,7 @@
81
86
  "translation_tier",
82
87
  "translation_tier_name",
83
88
  "briefing",
84
- "total",
85
- "created_at_timestamp"
89
+ "total"
86
90
  ],
87
91
  "payment_card": [
88
92
  "card_id",
@@ -96,15 +100,26 @@
96
100
  "name",
97
101
  "description",
98
102
  "created_at",
103
+ "created_at_timestamp",
99
104
  "created_by",
100
105
  "created_by_email",
101
106
  "team_id",
102
- "created_at_timestamp",
103
107
  "base_language_id",
104
108
  "base_language_iso",
105
109
  "settings",
106
110
  "statistics"
107
111
  ],
112
+ "queued_process": [
113
+ "process_id",
114
+ "type",
115
+ "status",
116
+ "message",
117
+ "created_by",
118
+ "created_by_email",
119
+ "created_at",
120
+ "created_at_timestamp",
121
+ "details"
122
+ ],
108
123
  "screenshot": [
109
124
  "screenshot_id",
110
125
  "key_ids",
@@ -121,9 +136,9 @@
121
136
  "snapshot_id",
122
137
  "title",
123
138
  "created_at",
139
+ "created_at_timestamp",
124
140
  "created_by",
125
- "created_by_email",
126
- "created_at_timestamp"
141
+ "created_by_email"
127
142
  ],
128
143
  "task": [
129
144
  "task_id",
@@ -147,6 +162,7 @@
147
162
  "languages",
148
163
  "auto_close_languages",
149
164
  "auto_close_task",
165
+ "auto_close_items",
150
166
  "completed_at",
151
167
  "completed_at_timestamp",
152
168
  "completed_by",
@@ -157,18 +173,18 @@
157
173
  "team_id",
158
174
  "name",
159
175
  "created_at",
176
+ "created_at_timestamp",
160
177
  "plan",
161
178
  "quota_usage",
162
- "quota_allowed",
163
- "created_at_timestamp"
179
+ "quota_allowed"
164
180
  ],
165
181
  "team_user": [
166
182
  "user_id",
167
183
  "email",
168
184
  "fullname",
169
185
  "created_at",
170
- "role",
171
- "created_at_timestamp"
186
+ "created_at_timestamp",
187
+ "role"
172
188
  ],
173
189
  "team_user_group": [
174
190
  "group_id",
@@ -211,4 +227,4 @@
211
227
  "events",
212
228
  "event_lang_map"
213
229
  ]
214
- }
230
+ }
@@ -29,6 +29,13 @@ module Lokalise
29
29
  )
30
30
  end
31
31
 
32
+ def patch(path, client, params = {})
33
+ respond_with(
34
+ connection(client).patch(prepare(path), params.any? ? custom_dump(params) : nil),
35
+ client
36
+ )
37
+ end
38
+
32
39
  def delete(path, client, params = {})
33
40
  respond_with(
34
41
  # Rubocop tries to replace `delete` with `gsub` but that's a different method here!
@@ -45,7 +52,7 @@ module Lokalise
45
52
 
46
53
  # Get rid of double slashes in the `path`, leading and trailing slash
47
54
  def prepare(path)
48
- path.gsub(%r{\A/}, '').gsub(%r{//}, '/').gsub(%r{/+\z}, '')
55
+ path.delete_prefix('/').gsub(%r{//}, '/').gsub(%r{/+\z}, '')
49
56
  end
50
57
 
51
58
  def respond_with(response, client)
@@ -8,25 +8,27 @@ module Lokalise
8
8
  include Lokalise::Utils::AttributeHelpers
9
9
  extend Lokalise::Utils::EndpointHelpers
10
10
 
11
- attr_reader :raw_data, :project_id, :client, :path
11
+ attr_reader :raw_data, :project_id, :client, :path, :branch, :user_id, :team_id
12
12
 
13
- # Initializes a new resource based on the response
13
+ # Initializes a new resource based on the response.
14
+ # `endpoint_generator` is used in cases when a new instance is generated
15
+ # from a different resource. For example, restoring from a snapshot
16
+ # creates a totally different project which should have a new path.
14
17
  #
15
18
  # @param response [Hash]
19
+ # @param endpoint_generator [Proc] Generate proper paths for certain resources
16
20
  # @return [Lokalise::Resources::Base]
17
- def initialize(response)
21
+ def initialize(response, endpoint_generator = nil)
18
22
  populate_attributes_for response['content']
19
-
20
- @raw_data = response['content']
21
- @project_id = response['content']['project_id']
23
+ extract_common_attributes_for response['content']
22
24
  @client = response['client']
23
- @path = infer_path_from response
25
+ @path = infer_path_from response, endpoint_generator
24
26
  end
25
27
 
26
28
  class << self
27
- # Dynamically add attribute readers for each inherited class.
29
+ # Dynamically adds attribute readers for each inherited class.
28
30
  # Attributes are defined in the `data/attributes.json` file.
29
- # Also set the `ATTRIBUTES` constant to assign values to each attribute later when
31
+ # Also sets the `ATTRIBUTES` constant to assign values to each attribute later when
30
32
  # the response arrives from the API
31
33
  def inherited(subclass)
32
34
  klass_attributes = attributes_for subclass
@@ -43,10 +45,16 @@ module Lokalise
43
45
  # Usage: `supports :update, :destroy, [:complex_method, '/sub/path', :update]`
44
46
  def supports(*methods)
45
47
  methods.each do |m_data|
46
- method_name, sub_path, c_method = m_data.is_a?(Array) ? m_data : [m_data, '', m_data]
48
+ # `method_name` - the method that the resource should support
49
+ # `sub_path` - a string that has to be appended to a base path
50
+ # `c_method` - method name to delegate the work to
51
+ method_name, sub_path, c_method =
52
+ m_data.is_a?(Array) ? m_data : [m_data, '', m_data]
53
+
47
54
  define_method method_name do |params = {}|
48
55
  path = instance_variable_get(:@path)
49
- # If there's a sub_path, preserve the initial path to allow further chaining
56
+ # If there's a sub_path which is a string,
57
+ # preserve the initial path to allow further chaining
50
58
  params = params.merge(_initial_path: path) if sub_path
51
59
  self.class.send c_method, instance_variable_get(:@client),
52
60
  path + sub_path, params
@@ -56,34 +64,38 @@ module Lokalise
56
64
 
57
65
  # Fetches a single record
58
66
  def find(client, path, params = {})
59
- new get(path, client, params)
67
+ new get(path, client, prepare_params(params))
60
68
  end
61
69
 
62
70
  # Creates one or multiple records
63
71
  def create(client, path, params)
64
- response = post path, client, params
65
-
72
+ response = post path, client, prepare_params(params)
66
73
  object_from response, params
67
74
  end
68
75
 
69
76
  # Updates one or multiple records
70
77
  def update(client, path, params)
71
- response = put path, client, params
72
-
78
+ response = put path, client, prepare_params(params)
73
79
  object_from response, params
74
80
  end
75
81
 
76
82
  # Destroys records by given ids
77
83
  def destroy(client, path, params = {})
78
- delete(path, client, params)['content']
84
+ delete(path, client, prepare_params(params))['content']
79
85
  end
80
86
 
81
87
  private
82
88
 
89
+ # Filters out internal attributes that should not be sent to Lokalise
90
+ def prepare_params(params)
91
+ filter_attrs = %i[_initial_path]
92
+ params.reject { |key, _v| filter_attrs.include?(key) }
93
+ end
94
+
83
95
  # Instantiates a new resource or collection based on the given response
84
96
  def object_from(response, params)
85
97
  model_class = name.base_class_name
86
- data_key_plural = data_key_for model_class, true
98
+ data_key_plural = data_key_for model_class: model_class, plural: true
87
99
  # Preserve the initial path to allow chaining
88
100
  response['path'] = params.delete(:_initial_path) if params.key?(:_initial_path)
89
101
 
@@ -95,8 +107,7 @@ module Lokalise
95
107
  end
96
108
 
97
109
  def produce_resource(model_class, response)
98
- data_key_singular = data_key_for model_class
99
-
110
+ data_key_singular = data_key_for model_class: model_class
100
111
  if response['content'].key? data_key_singular
101
112
  data = response['content'].delete data_key_singular
102
113
  response['content'].merge! data
@@ -111,20 +122,27 @@ module Lokalise
111
122
  end
112
123
 
113
124
  # Generates path for the individual resource based on the path for the collection
114
- def infer_path_from(response)
125
+ def infer_path_from(response, endpoint_generator = nil)
115
126
  id_key = id_key_for self.class.name.base_class_name
116
- 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
117
128
 
118
- path_with_id response, id_key, data_key
129
+ path_with_id response, id_key, data_key, endpoint_generator
119
130
  end
120
131
 
121
- def path_with_id(response, id_key, data_key)
132
+ def path_with_id(response, id_key, data_key, endpoint_generator = nil)
122
133
  # Some resources do not have ids at all
123
134
  return nil unless response['content'].key?(id_key) || response['content'].key?(data_key)
124
135
 
125
136
  # ID of the resource
126
137
  id = id_from response, id_key, data_key
127
138
 
139
+ # If `endpoint_generator` is present, generate a new path
140
+ # based on the fetched id
141
+ if endpoint_generator
142
+ path = endpoint_generator.call project_id, id
143
+ return path.remove_trailing_slash
144
+ end
145
+
128
146
  path = response['path'] || response['base_path']
129
147
  # If path already has id - just return it
130
148
  return path if path.match?(/#{id}\z/)
@@ -146,7 +164,7 @@ module Lokalise
146
164
  # Store all resources attributes under the corresponding instance variables.
147
165
  # `ATTRIBUTES` is defined inside resource-specific classes
148
166
  def populate_attributes_for(content)
149
- 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
150
168
 
151
169
  self.class.const_get(:ATTRIBUTES).each do |attr|
152
170
  value = if content.key?(data_key) && content[data_key].is_a?(Hash)
@@ -158,6 +176,18 @@ module Lokalise
158
176
  instance_variable_set "@#{attr}", value
159
177
  end
160
178
  end
179
+
180
+ # Extracts all common attributes that resources have.
181
+ # Some of them may be absent in certain cases.
182
+ # rubocop:disable Naming/MemoizedInstanceVariableName
183
+ def extract_common_attributes_for(content)
184
+ @raw_data = content
185
+ @project_id ||= content['project_id']
186
+ @user_id ||= content['user_id']
187
+ @team_id ||= content['team_id']
188
+ @branch ||= content['branch']
189
+ end
190
+ # rubocop:enable Naming/MemoizedInstanceVariableName
161
191
  end
162
192
  end
163
193
  end
@@ -3,7 +3,7 @@
3
3
  module Lokalise
4
4
  module Resources
5
5
  class Branch < Base
6
- supports :update, :destroy
6
+ supports :update, :destroy, [:reload_data, '', :find]
7
7
 
8
8
  def merge(params = {})
9
9
  self.class.merge @client, self.class.endpoint(project_id, branch_id, :merge), params
@@ -4,7 +4,7 @@ module Lokalise
4
4
  module Resources
5
5
  class Contributor < Base
6
6
  ID_KEY = 'user'
7
- supports :update, :destroy
7
+ supports :update, :destroy, [:reload_data, '', :find]
8
8
 
9
9
  class << self
10
10
  def endpoint(project_id, contributor_id = nil)