ruby-lokalise-api 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
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