ruby-lokalise-api 1.0.1

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 (81) hide show
  1. checksums.yaml +7 -0
  2. data/.github/CODE_OF_CONDUCT.md +46 -0
  3. data/.github/CONTRIBUTING.md +14 -0
  4. data/.github/ISSUE_TEMPLATE.md +13 -0
  5. data/.github/PULL_REQUEST_TEMPLATE.md +11 -0
  6. data/CHANGELOG.md +5 -0
  7. data/Gemfile +3 -0
  8. data/LICENSE +22 -0
  9. data/README.md +917 -0
  10. data/Rakefile +16 -0
  11. data/lib/ruby-lokalise-api.rb +60 -0
  12. data/lib/ruby-lokalise-api/client.rb +22 -0
  13. data/lib/ruby-lokalise-api/collections/base.rb +46 -0
  14. data/lib/ruby-lokalise-api/collections/contributor.rb +13 -0
  15. data/lib/ruby-lokalise-api/collections/file.rb +13 -0
  16. data/lib/ruby-lokalise-api/collections/key.rb +13 -0
  17. data/lib/ruby-lokalise-api/collections/key_comment.rb +13 -0
  18. data/lib/ruby-lokalise-api/collections/project.rb +13 -0
  19. data/lib/ruby-lokalise-api/collections/project_comment.rb +13 -0
  20. data/lib/ruby-lokalise-api/collections/project_language.rb +13 -0
  21. data/lib/ruby-lokalise-api/collections/screenshot.rb +13 -0
  22. data/lib/ruby-lokalise-api/collections/snapshot.rb +13 -0
  23. data/lib/ruby-lokalise-api/collections/system_language.rb +13 -0
  24. data/lib/ruby-lokalise-api/collections/task.rb +13 -0
  25. data/lib/ruby-lokalise-api/collections/team.rb +13 -0
  26. data/lib/ruby-lokalise-api/collections/team_user.rb +13 -0
  27. data/lib/ruby-lokalise-api/collections/translation.rb +13 -0
  28. data/lib/ruby-lokalise-api/connection.rb +17 -0
  29. data/lib/ruby-lokalise-api/data/attributes.json +127 -0
  30. data/lib/ruby-lokalise-api/error.rb +47 -0
  31. data/lib/ruby-lokalise-api/request.rb +60 -0
  32. data/lib/ruby-lokalise-api/resources/base.rb +117 -0
  33. data/lib/ruby-lokalise-api/resources/contributor.rb +13 -0
  34. data/lib/ruby-lokalise-api/resources/file.rb +25 -0
  35. data/lib/ruby-lokalise-api/resources/key.rb +13 -0
  36. data/lib/ruby-lokalise-api/resources/key_comment.rb +15 -0
  37. data/lib/ruby-lokalise-api/resources/project.rb +18 -0
  38. data/lib/ruby-lokalise-api/resources/project_comment.rb +7 -0
  39. data/lib/ruby-lokalise-api/resources/project_language.rb +15 -0
  40. data/lib/ruby-lokalise-api/resources/screenshot.rb +13 -0
  41. data/lib/ruby-lokalise-api/resources/snapshot.rb +17 -0
  42. data/lib/ruby-lokalise-api/resources/system_language.rb +7 -0
  43. data/lib/ruby-lokalise-api/resources/task.rb +13 -0
  44. data/lib/ruby-lokalise-api/resources/team.rb +6 -0
  45. data/lib/ruby-lokalise-api/resources/team_user.rb +13 -0
  46. data/lib/ruby-lokalise-api/resources/translation.rb +13 -0
  47. data/lib/ruby-lokalise-api/rest/comments.rb +57 -0
  48. data/lib/ruby-lokalise-api/rest/contributors.rb +54 -0
  49. data/lib/ruby-lokalise-api/rest/files.rb +33 -0
  50. data/lib/ruby-lokalise-api/rest/keys.rb +75 -0
  51. data/lib/ruby-lokalise-api/rest/languages.rb +63 -0
  52. data/lib/ruby-lokalise-api/rest/projects.rb +58 -0
  53. data/lib/ruby-lokalise-api/rest/screenshots.rb +54 -0
  54. data/lib/ruby-lokalise-api/rest/snapshots.rb +43 -0
  55. data/lib/ruby-lokalise-api/rest/tasks.rb +54 -0
  56. data/lib/ruby-lokalise-api/rest/team_users.rb +44 -0
  57. data/lib/ruby-lokalise-api/rest/teams.rb +12 -0
  58. data/lib/ruby-lokalise-api/rest/translations.rb +35 -0
  59. data/lib/ruby-lokalise-api/utils/attribute_helpers.rb +52 -0
  60. data/lib/ruby-lokalise-api/utils/string_utils.rb +21 -0
  61. data/lib/ruby-lokalise-api/version.rb +3 -0
  62. data/ruby-lokalise-api.gemspec +32 -0
  63. data/spec/lib/ruby-lokalise-api/error_spec.rb +23 -0
  64. data/spec/lib/ruby-lokalise-api/rest/comments_spec.rb +78 -0
  65. data/spec/lib/ruby-lokalise-api/rest/contributors_spec.rb +79 -0
  66. data/spec/lib/ruby-lokalise-api/rest/files_spec.rb +53 -0
  67. data/spec/lib/ruby-lokalise-api/rest/keys_spec.rb +119 -0
  68. data/spec/lib/ruby-lokalise-api/rest/languages_spec.rb +91 -0
  69. data/spec/lib/ruby-lokalise-api/rest/projects_spec.rb +79 -0
  70. data/spec/lib/ruby-lokalise-api/rest/screenshots_spec.rb +76 -0
  71. data/spec/lib/ruby-lokalise-api/rest/snapshots_spec.rb +61 -0
  72. data/spec/lib/ruby-lokalise-api/rest/tasks_spec.rb +89 -0
  73. data/spec/lib/ruby-lokalise-api/rest/team_users_spec.rb +56 -0
  74. data/spec/lib/ruby-lokalise-api/rest/teams_spec.rb +22 -0
  75. data/spec/lib/ruby-lokalise-api/rest/translations_spec.rb +54 -0
  76. data/spec/lib/ruby-lokalise-api/utils/snakecase_spec.rb +17 -0
  77. data/spec/lib/ruby-lokalise-api_spec.rb +13 -0
  78. data/spec/spec_helper.rb +15 -0
  79. data/spec/support/test_client.rb +5 -0
  80. data/spec/support/vcr.rb +8 -0
  81. metadata +255 -0
@@ -0,0 +1,47 @@
1
+ module Lokalise
2
+ class Error < StandardError
3
+ ClientError = Class.new(self)
4
+ ServerError = Class.new(self)
5
+
6
+ BadRequest = Class.new(ClientError)
7
+ Unauthorized = Class.new(ClientError)
8
+ NotAcceptable = Class.new(ClientError)
9
+ NotFound = Class.new(ClientError)
10
+ Conflict = Class.new(ClientError)
11
+ TooManyRequests = Class.new(ClientError)
12
+ Forbidden = Class.new(ClientError)
13
+ Locked = Class.new(ClientError)
14
+
15
+ NotImplemented = Class.new(ServerError)
16
+ BadGateway = Class.new(ServerError)
17
+ ServiceUnavailable = Class.new(ServerError)
18
+ GatewayTimeout = Class.new(ServerError)
19
+
20
+ ERRORS = {
21
+ 400 => Lokalise::Error::BadRequest,
22
+ 401 => Lokalise::Error::Unauthorized,
23
+ 403 => Lokalise::Error::Forbidden,
24
+ 404 => Lokalise::Error::NotFound,
25
+ 406 => Lokalise::Error::NotAcceptable,
26
+ 409 => Lokalise::Error::Conflict,
27
+ 423 => Lokalise::Error::Locked,
28
+ 429 => Lokalise::Error::TooManyRequests,
29
+ 500 => Lokalise::Error::ServerError,
30
+ 502 => Lokalise::Error::BadGateway,
31
+ 503 => Lokalise::Error::ServiceUnavailable,
32
+ 504 => Lokalise::Error::GatewayTimeout
33
+ }.freeze
34
+
35
+ class << self
36
+ # Create a new error from an HTTP response
37
+ def from_response(body)
38
+ new body['error']['message'].to_s
39
+ end
40
+ end
41
+
42
+ # Initializes a new Error object
43
+ def initialize(message = '')
44
+ super(message)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,60 @@
1
+ module Lokalise
2
+ module Request
3
+ include Lokalise::Connection
4
+
5
+ PAGINATION_HEADERS = %w[x-pagination-total-count x-pagination-page-count x-pagination-limit x-pagination-page].freeze
6
+
7
+ def get(path, client, params = {})
8
+ respond_with(
9
+ connection(client.token).get(prepare(path), params),
10
+ client
11
+ )
12
+ end
13
+
14
+ def post(path, client, params = {})
15
+ respond_with(
16
+ connection(client.token).post(prepare(path), MultiJson.dump(params)),
17
+ client
18
+ )
19
+ end
20
+
21
+ def put(path, client, params = {})
22
+ respond_with(
23
+ connection(client.token).put(prepare(path), MultiJson.dump(params)),
24
+ client
25
+ )
26
+ end
27
+
28
+ def delete(path, client, params = {})
29
+ respond_with(
30
+ connection(client.token).run_request(:delete, prepare(path), MultiJson.dump(params), {}),
31
+ client
32
+ )
33
+ # TODO: current version of Faraday does not allow to pass DELETE body request
34
+ # As soon as this PR https://github.com/lostisland/faraday/issues/693 is merged,
35
+ # replace above with:
36
+ # delete(path, MultiJson.dump(params))
37
+ end
38
+
39
+ private
40
+
41
+ def prepare(path)
42
+ path.gsub /\/\//, '/'
43
+ end
44
+
45
+ def respond_with(response, client)
46
+ body = MultiJson.load response.body
47
+ respond_with_error(response.status, body) if body.respond_to?(:has_key?) && body.key?('error')
48
+ response.
49
+ headers.
50
+ keep_if { |k, _v| PAGINATION_HEADERS.include?(k) }.
51
+ merge(content: body, client: client)
52
+ end
53
+
54
+ def respond_with_error(code, body)
55
+ raise(Lokalise::Error, body['error']) unless Lokalise::Error::ERRORS.key? code
56
+
57
+ raise Lokalise::Error::ERRORS[code].from_response(body)
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,117 @@
1
+ module Lokalise
2
+ module Resources
3
+ class Base
4
+ extend Lokalise::Request
5
+ extend Lokalise::Utils::AttributeHelpers
6
+ include Lokalise::Utils::AttributeHelpers
7
+
8
+ attr_reader :raw_data, :project_id, :client
9
+
10
+ def initialize(response)
11
+ populate_attributes_for response['content']
12
+
13
+ @raw_data = response['content']
14
+ @project_id = response['content']['project_id']
15
+ @client = response['client']
16
+ end
17
+
18
+ class << self
19
+ # Dynamically add attribute readers for each inherited class.
20
+ # Attributes are defined in the `data/attributes.json` file.
21
+ # Also set the `ATTRIBUTES` constant to assign values to each attribute later when
22
+ # the response arrives from the API
23
+ def inherited(subclass)
24
+ klass_attributes = attributes_for subclass
25
+ subclass.class_exec do
26
+ const_set :ATTRIBUTES, klass_attributes
27
+ attr_reader(*klass_attributes)
28
+ end
29
+ super
30
+ end
31
+
32
+ # Fetches a single record
33
+ def find(client, endpoint_ids, resource_id = '', params = {})
34
+ new get("#{endpoint(*endpoint_ids)}/#{resource_id}",
35
+ client,
36
+ params)
37
+ end
38
+
39
+ # Creates one or multiple records
40
+ def create(client, endpoint_ids, params, object_key = nil)
41
+ response = post(endpoint(*endpoint_ids),
42
+ client,
43
+ body_from(params, object_key))
44
+
45
+ object_from response
46
+ end
47
+
48
+ # Updates one or multiple records
49
+ def update(client, endpoint_ids, resource_id, params, object_key = nil)
50
+ response = put("#{endpoint(*endpoint_ids)}/#{resource_id}",
51
+ client,
52
+ body_from(params, object_key))
53
+
54
+ object_from response
55
+ end
56
+
57
+ # Destroys records by given ids
58
+ #
59
+ # @param client [Lokalise::Client]
60
+ # @return [Hash]
61
+ # @param endpoint_ids [String, Integer, Array]
62
+ # @param resource_id [String, Integer, Hash<Array>]
63
+ def destroy(client, endpoint_ids, resource_id)
64
+ path = endpoint(*endpoint_ids).to_s
65
+ if resource_id.is_a?(Hash)
66
+ delete path, client, resource_id
67
+ else
68
+ delete "#{path}/#{resource_id}", client
69
+ end['content']
70
+ end
71
+
72
+ private
73
+
74
+ # Converts `params` to hash with arrays under the `object_key` key.
75
+ # Used in bulk operations
76
+ #
77
+ # @return [Hash]
78
+ def body_from(params, object_key)
79
+ return params unless object_key
80
+
81
+ params = [params] unless params.is_a?(Array)
82
+ Hash[object_key, params]
83
+ end
84
+
85
+ # Instantiates a new resource or collection based on the given response
86
+ def object_from(response)
87
+ model_class = name.base_class_name
88
+ data_key_plural = data_key_for model_class, true
89
+
90
+ if response['content'].key? data_key_plural
91
+ Module.const_get("Lokalise::Collections::#{model_class}").new response
92
+ else
93
+ new response
94
+ end
95
+ end
96
+ end
97
+
98
+ private
99
+
100
+ # Store all resources attributes under the corresponding instance variables.
101
+ # `ATTRIBUTES` is defined inside resource-specific classes
102
+ def populate_attributes_for(content)
103
+ data_key = data_key_for self.class.name.base_class_name
104
+
105
+ self.class.const_get(:ATTRIBUTES).each do |attr|
106
+ value = if content.key?(data_key) && content[data_key].is_a?(Hash)
107
+ content[data_key][attr]
108
+ else
109
+ content[attr]
110
+ end
111
+
112
+ instance_variable_set "@#{attr}", value
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,13 @@
1
+ module Lokalise
2
+ module Resources
3
+ class Contributor < Base
4
+ class << self
5
+ private
6
+
7
+ def endpoint(project_id)
8
+ "projects/#{project_id}/contributors"
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,25 @@
1
+ module Lokalise
2
+ module Resources
3
+ class File < Base
4
+ class << self
5
+ def download(client, project_id, params)
6
+ up_down client, endpoint(project_id), params, 'download'
7
+ end
8
+
9
+ def upload(client, project_id, params)
10
+ up_down client, endpoint(project_id), params, 'upload'
11
+ end
12
+
13
+ private
14
+
15
+ def up_down(client, path, params, action)
16
+ post("#{path}/#{action}", client, params)['content']
17
+ end
18
+
19
+ def endpoint(project_id)
20
+ "projects/#{project_id}/files"
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,13 @@
1
+ module Lokalise
2
+ module Resources
3
+ class Key < Base
4
+ class << self
5
+ private
6
+
7
+ def endpoint(project_id)
8
+ "projects/#{project_id}/keys"
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ module Lokalise
2
+ module Resources
3
+ class KeyComment < Base
4
+ DATA_KEY = 'Comment'.freeze
5
+
6
+ class << self
7
+ private
8
+
9
+ def endpoint(project_id, key_id)
10
+ "projects/#{project_id}/keys/#{key_id}/comments"
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,18 @@
1
+ module Lokalise
2
+ module Resources
3
+ class Project < Base
4
+ class << self
5
+ def clear(client, project_id)
6
+ put("#{endpoint(project_id)}/empty", client)['content']
7
+ end
8
+
9
+ private
10
+
11
+ def endpoint(project_id = nil)
12
+ 'projects' unless project_id
13
+ "projects/#{project_id}"
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,7 @@
1
+ module Lokalise
2
+ module Resources
3
+ class ProjectComment < Base
4
+ DATA_KEY = 'Comment'.freeze
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,15 @@
1
+ module Lokalise
2
+ module Resources
3
+ class ProjectLanguage < Base
4
+ DATA_KEY = 'Language'.freeze
5
+
6
+ class << self
7
+ private
8
+
9
+ def endpoint(project_id)
10
+ "projects/#{project_id}/languages"
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ module Lokalise
2
+ module Resources
3
+ class Screenshot < Base
4
+ class << self
5
+ private
6
+
7
+ def endpoint(project_id)
8
+ "projects/#{project_id}/screenshots"
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,17 @@
1
+ module Lokalise
2
+ module Resources
3
+ class Snapshot < Base
4
+ class << self
5
+ def restore(client, project_id, snapshot_id)
6
+ Lokalise::Resources::Project.new post(endpoint(project_id, snapshot_id), client)
7
+ end
8
+
9
+ private
10
+
11
+ def endpoint(project_id, snapshot_id = nil)
12
+ "projects/#{project_id}/snapshots/#{snapshot_id}"
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,7 @@
1
+ module Lokalise
2
+ module Resources
3
+ class SystemLanguage < Base
4
+ DATA_KEY = 'Language'.freeze
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ module Lokalise
2
+ module Resources
3
+ class Task < Base
4
+ class << self
5
+ private
6
+
7
+ def endpoint(project_id)
8
+ "projects/#{project_id}/tasks"
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,6 @@
1
+ module Lokalise
2
+ module Resources
3
+ class Team < Base
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,13 @@
1
+ module Lokalise
2
+ module Resources
3
+ class TeamUser < Base
4
+ class << self
5
+ private
6
+
7
+ def endpoint(team_id)
8
+ "teams/#{team_id}/users"
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Lokalise
2
+ module Resources
3
+ class Translation < Base
4
+ class << self
5
+ private
6
+
7
+ def endpoint(project_id)
8
+ "projects/#{project_id}/translations"
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,57 @@
1
+ module Lokalise
2
+ class Client
3
+ # Returns a single comment for the given key
4
+ #
5
+ # @see https://lokalise.co/api2docs/ruby/#transition-retrieve-a-comment-get
6
+ # @return [Lokalise::Resources::Comment]
7
+ # @param project_id [String]
8
+ # @param key_id [String, Integer]
9
+ # @param comment_id [String, Integer]
10
+ def comment(project_id, key_id, comment_id)
11
+ Lokalise::Resources::KeyComment.find self, [project_id, key_id], comment_id
12
+ end
13
+
14
+ # Returns all comments for all keys inside the given project
15
+ #
16
+ # @see https://lokalise.co/api2docs/ruby/#transition-list-project-comments-get
17
+ # @return [Lokalise::Collection::Comment<Lokalise::Resources::Comment>]
18
+ # @param project_id [String]
19
+ # @param params [Hash]
20
+ def project_comments(project_id, params = {})
21
+ Lokalise::Collections::ProjectComment.all self, params, project_id
22
+ end
23
+
24
+ # Returns all comments for the given key inside the given project
25
+ #
26
+ # @see https://lokalise.co/api2docs/ruby/#transition-list-key-comments-get
27
+ # @return [Lokalise::Collection::Comment<Lokalise::Resources::Comment>]
28
+ # @param project_id [String]
29
+ # @param key_id [String, Integer]
30
+ # @param params [Hash]
31
+ def comments(project_id, key_id, params = {})
32
+ Lokalise::Collections::KeyComment.all self, params, project_id, key_id
33
+ end
34
+
35
+ # Creates one or more comments for the given key inside the given project
36
+ #
37
+ # @see https://lokalise.co/api2docs/ruby/#transition-create-comments-post
38
+ # @return [Lokalise::Collection::Comment<Lokalise::Resources::Comment>]
39
+ # @param project_id [String]
40
+ # @param key_id [String, Integer]
41
+ # @param params [Hash, Array<Hash>]
42
+ def create_comments(project_id, key_id, params)
43
+ Lokalise::Resources::KeyComment.create self, [project_id, key_id], params, :comments
44
+ end
45
+
46
+ # Deletes comment for the given key inside the given project
47
+ #
48
+ # @see https://lokalise.co/api2docs/ruby/#transition-delete-a-comment-delete
49
+ # @return [Hash]
50
+ # @param project_id [String]
51
+ # @param key_id [String, Integer]
52
+ # @param comment_id [String, Integer]
53
+ def delete_comment(project_id, key_id, comment_id)
54
+ Lokalise::Resources::KeyComment.destroy self, [project_id, key_id], comment_id
55
+ end
56
+ end
57
+ end