one_sky 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/Gemfile.lock CHANGED
@@ -1,33 +1,33 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- one_sky (0.0.1)
5
- json (~> 1.4.6)
6
- rest-client (~> 1.6.1)
4
+ one_sky (2.0.0)
5
+ json (>= 1.4.0)
6
+ rest-client (>= 1.4.0)
7
7
 
8
8
  GEM
9
9
  remote: http://rubygems.org/
10
10
  specs:
11
- diff-lcs (1.1.2)
12
- json (1.4.6)
13
- mime-types (1.16)
14
- rest-client (1.6.1)
11
+ diff-lcs (1.1.3)
12
+ json (1.6.3)
13
+ mime-types (1.17.2)
14
+ rest-client (1.6.7)
15
15
  mime-types (>= 1.16)
16
16
  rspec (2.2.0)
17
17
  rspec-core (~> 2.2)
18
18
  rspec-expectations (~> 2.2)
19
19
  rspec-mocks (~> 2.2)
20
- rspec-core (2.2.1)
21
- rspec-expectations (2.2.0)
20
+ rspec-core (2.7.1)
21
+ rspec-expectations (2.7.0)
22
22
  diff-lcs (~> 1.1.2)
23
- rspec-mocks (2.2.0)
23
+ rspec-mocks (2.7.0)
24
+ time_freeze (0.1.1)
24
25
 
25
26
  PLATFORMS
26
27
  ruby
27
28
 
28
29
  DEPENDENCIES
29
- bundler (~> 1.0.0)
30
- json (~> 1.4.6)
30
+ bundler (>= 1.0.0)
31
31
  one_sky!
32
- rest-client (~> 1.6.1)
33
32
  rspec (~> 2.2.0)
33
+ time_freeze
data/README.rdoc CHANGED
@@ -20,23 +20,67 @@ Provide the API key and secret which you can get from the web UI. Also provide t
20
20
 
21
21
  require 'one_sky'
22
22
 
23
- client = OneSky::Project.new("my_api_key", "my_api_secret", "my_project")
23
+ client = OneSky::Client.new("my_api_key", "my_api_secret")
24
+
25
+ == Project
26
+
27
+ Load a specific project by name.
28
+
29
+ project = client.project("my-project-name")
30
+
31
+ Get the details of the project.
32
+
33
+ project.details
34
+
35
+ See what platforms are available.
36
+
37
+ project.platforms
38
+
39
+ == Platform
40
+
41
+ Load a specific platform by id.
42
+
43
+ platform = project.platform(123)
44
+
45
+ Get the details of the platform.
46
+
47
+ platform.details
48
+
49
+ See what locales are assigned.
50
+
51
+ platform.locales
52
+
53
+ == Translation
54
+
55
+ Get the translation proxy for a platform
56
+
57
+ translation = platform.translation
24
58
 
25
59
  == Submit a phrase for translation
26
60
 
27
- Submit a string with no other parameters:
61
+ Submit a single string:
62
+
63
+ translation.input_string("Hello World!")
64
+
65
+ Submit a string with a specified key, context, and page:
66
+
67
+ translation.input_string(:string => "Hello World!", :string_key => "hello_world", :context => "my_context", :page => "my_page")
28
68
 
29
- client.input("Hello World!")
69
+ Submit many strings at once:
30
70
 
31
- You can also provide other parameters:
71
+ translation.input_strings(["Hello World!", "Goodbye Moon"])
72
+
73
+ == Provide a translation
32
74
 
33
- client.input("Hello World!", :string_key => "my_string_key", :context => "my_context", :page => "my_page")
75
+ Submit a translation for a given key, in a given locale.
34
76
 
77
+ translation.translate("hello_world", "zh_CN", "世界你好")
78
+
35
79
  == Get translated phrases
36
80
 
37
81
  So you've submitted your phrases and your translators/users or the general OneSky[link:http://www.oneskyapp.com] community have kindly provided translations for them. It's time now to download those.
38
82
 
39
- translations = client.output
83
+ translations = translation.output
40
84
 
41
85
  => {"Default"=>{"en-us"=>{"Hello World!"=>"Hello World!"}, "zh-cn"=>{"Hello World!"=>"\u4E16\u754C\u60A8\u597D\uFF01"}, "es-es"=>{"Hello World!"=>"Hola Mundo!"}}}
42
86
 
@@ -52,7 +96,7 @@ Let's pretty print that a bit:
52
96
 
53
97
  OneSky[link:http://www.oneskyapp.com] is all about community-powered translations. You can mark your project as public and any OneSky[link:http://www.oneskyapp.com] member translator can help in translating your phrases. Or if you mark it as private, only those you give access to can do so. For instance, you'd like your own website's user base to help you out. You can take a user's unique ID and bind it to OneSky:
54
98
 
55
- client.get_sso_link("myapp/users/123456")
99
+ client.utility.get_sso_link("myapp/users/123456", "fred")
56
100
  => "http://rubyredtomatoes.oneskyapp.com/?time=1294020222&id=myapp/users/123456&data=3d56315499647c0419867283767aa270"
57
101
 
58
102
  That user can then use the above link to automatically sign in to OneSky[link:http://www.oneskyapp.com] and start translating for you.
data/Rakefile CHANGED
@@ -2,7 +2,7 @@ require 'bundler'
2
2
  Bundler::GemHelper.install_tasks
3
3
 
4
4
  # = RDoc
5
- require 'rake/rdoctask'
5
+ require 'rdoc/task'
6
6
 
7
7
  Rake::RDocTask.new do |t|
8
8
  t.rdoc_dir = 'rdoc'
@@ -11,3 +11,19 @@ Rake::RDocTask.new do |t|
11
11
  t.rdoc_files.include('README.rdoc', 'MIT-LICENSE', 'CHANGELOG', 'CREDITS', 'lib/**/*.rb')
12
12
  end
13
13
 
14
+ require 'rspec/core/rake_task'
15
+
16
+ desc 'Default: run specs.'
17
+ task :default => :spec
18
+
19
+ desc "Run specs"
20
+ RSpec::Core::RakeTask.new do |t|
21
+ t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
22
+ t.rspec_opts = %w{--tag ~live}
23
+ end
24
+
25
+ desc "Run live specs"
26
+ RSpec::Core::RakeTask.new("spec:live") do |t|
27
+ t.pattern = "./spec/**/*_spec.rb"
28
+ t.rspec_opts = %w{--tag live}
29
+ end
data/lib/one_sky.rb CHANGED
@@ -1,11 +1,10 @@
1
- require 'json'
2
- require 'rest_client'
3
- require 'digest/md5'
4
-
5
1
  module OneSky
6
- API_ROOT_URL = "https://api.oneskyapp.com/1"
7
-
8
- autoload :Project, 'one_sky/project'
9
-
10
- %w[ApiError].each { |e| const_set(e, Class.new(StandardError)) }
2
+ class ApiError < StandardError; end
11
3
  end
4
+
5
+ require 'one_sky/client'
6
+ require 'one_sky/platform'
7
+ require 'one_sky/project'
8
+ require 'one_sky/translation'
9
+ require 'one_sky/utility'
10
+ require 'one_sky/version'
@@ -0,0 +1,80 @@
1
+ require 'json'
2
+ require 'rest_client'
3
+ require 'digest/md5'
4
+
5
+ module OneSky
6
+
7
+ # Base implemention of an API client
8
+ # based on the one sky api version 2.
9
+ #
10
+ # http://developer.oneskyapp.com/api/list/v/2
11
+ #
12
+ class Client
13
+ attr_accessor :api_key, :api_secret
14
+
15
+ # Provide the name of the project you created on the OneSky website. Also, the API key and secret shown there.
16
+ def initialize(api_key, api_secret)
17
+ raise ArgumentError, "api_key, api_secret cannot be nil." unless [api_key, api_secret].all?
18
+ @api_key, @api_secret = api_key, api_secret
19
+ end
20
+
21
+ # Api version 2
22
+ API_ROOT_URL = "https://api.oneskyapp.com/2/".freeze
23
+
24
+ def get(path, params = {}, options = nil)
25
+ fetch_response :get, path, params, options
26
+ end
27
+
28
+ def post(path, params = {}, options = nil)
29
+ fetch_response :post, path, params, options
30
+ end
31
+
32
+ # Returns an API proxy for the Project Management API
33
+ def project(name)
34
+ Project.new(name, self)
35
+ end
36
+
37
+ # Returns an API proxy for the Utility API
38
+ def utility
39
+ Utility.new(self)
40
+ end
41
+
42
+ protected
43
+
44
+ # dev-hash = MD5( CONCATENATE( timestamp , YOUR_API_SECRET ) )
45
+ def authorization_params
46
+ timestamp = Time.now.to_i.to_s
47
+ {:"api-key" => self.api_key, :timestamp => timestamp, :"dev-hash" => Digest::MD5.hexdigest(timestamp + self.api_secret)}
48
+ end
49
+
50
+ def fetch_response(http_verb, path, params, options)
51
+ options ||= {:content_type => "text/plain; charset=UTF-8"}
52
+ params = authorization_params.merge(params)
53
+ path = api_path(path)
54
+
55
+ response = case http_verb
56
+ when :get
57
+ RestClient.get(path, {:params => params}.merge(options))
58
+ when :post
59
+ RestClient.post(path, params.merge(options))
60
+ else
61
+ raise "bad http verb"
62
+ end
63
+
64
+ parse_response(response)
65
+ end
66
+
67
+ def api_path(path)
68
+ URI.join(API_ROOT_URL, path.gsub(/^\//, "")).to_s
69
+ end
70
+
71
+ def parse_response(response)
72
+ # Do not post-process response if it isn't JSON. (ie. Binary file returned from /output_mo.)
73
+ return response.body unless response.headers[:content_type] =~ /json/
74
+ response_hash = JSON.parse(response.body)
75
+
76
+ raise ApiError, response.body if response_hash.has_key?("response") and response_hash["response"] != "ok"
77
+ response_hash
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,36 @@
1
+ module OneSky
2
+
3
+ # Implements the Platform Management API for a given :platform_id
4
+ class Platform
5
+
6
+ attr_accessor :platform_id, :client
7
+
8
+ # Provide the id of the platform, together with an instance of OneSky::Client.
9
+ def initialize(platform_id, client)
10
+ @platform_id = platform_id
11
+ @client = client
12
+ end
13
+
14
+ # Get the information of the platform.
15
+ def details
16
+ get("platform/details")["platform"]
17
+ end
18
+
19
+ # Get the details of activated locales for a platform.
20
+ def locales
21
+ get("platform/locales")["locales"]
22
+ end
23
+
24
+ # Returns an API proxy for the Translation I/O API for this platform
25
+ def translation
26
+ Translation.new(platform_id, client)
27
+ end
28
+
29
+ protected
30
+
31
+ def get(path, params={})
32
+ client.get(path, params.merge(:"platform-id" => platform_id))
33
+ end
34
+
35
+ end
36
+ end
@@ -1,127 +1,35 @@
1
1
  module OneSky
2
- # This is the main class used to interact with the OneSky API and maps to a project on their web site.
2
+
3
+ # Implements the Project Management API for a given :project_name
3
4
  class Project
4
- attr_accessor :api_key, :api_secret, :name
5
+ attr_accessor :project_name, :client
5
6
 
6
- # Provide the name of the project you created on the OneSky website. Also, the API key and secret shown there.
7
- def initialize(api_key, api_secret, name)
8
- raise ArgumentError, "api_key, api_secret, and name cannot be nil." unless [api_key, api_secret, name].all?
9
- @api_key, @api_secret, @name = api_key, api_secret, name
7
+ # Provide the name of the project, together with an instance of OneSky::Client.
8
+ def initialize(project_name, client)
9
+ @project_name = project_name
10
+ @client = client
10
11
  end
11
12
 
12
- # Returns details about the project.
13
- def details
14
- get("/project/details")["project"]
15
- end
16
-
17
- # Returns available types to be specified when creating a new the project.
18
- def types
19
- get("/project/types")["types"]
20
- end
21
-
22
- # Returns an array of available languages.
23
- def languages
24
- get("/project/languages")["languages"]
25
- end
26
-
27
- # Returns info about your account.
28
- def info
29
- get("/info")["application"]
30
- end
31
-
32
- # Returns the SSO URL for the given unique_id
33
- def get_sso_link(unique_id)
34
- get("/sso/get-link", {:"unique-id" => unique_id})["url"]
35
- end
36
-
37
- # Submits a string for translation.
38
- # Takes an optional hash of parameters, too:
39
- # * :string_key
40
- # * :context
41
- # * :page
42
- def input(string, options = {})
43
- options = {:string => string}.merge(options)
44
- post("/string/input", hash_to_params(options))
45
- true
46
- end
47
-
48
- # Submits a bulk translation request.
49
- # Parameters:
50
- # * hashes - An array of hashes with mandatory key :string and optional keys (:string_key, :context)
51
- # * An optional hash with keys:
52
- # * :page
53
- def input_bulk(hashes, options = {})
54
- arrs = hashes.inject([[],[],[]]) do |o,e|
55
- o[0] << e[:string]; o[1] << e[:string_key]; o[2] << e[:context]; o
56
- end
57
-
58
- post("/string/input-bulk", {:strings => arrs[0], :"string-keys" => arrs[1], :contexts => arrs[2]}.merge(options))
59
- true
60
- end
61
-
62
- # Uploads a PO file for the given language.
63
- # See #languages for a list of supported language codes.
64
- # Takes an optional hash of parameters:
65
- # * :page
66
- def input_po(language, file_name, options = {})
67
- response = post("/string/input-po", {:language => language, :file => File.new(file_name, "rb")}.merge(options), {})
68
- true
13
+ # Return all platforms in a project.
14
+ def platforms
15
+ get("project/platforms")["platforms"]
69
16
  end
70
-
71
- alias_method :upload_po, :input_po
72
-
73
- # Gets the strings with available translations.
74
- # Takes these optional parameters, too:
75
- # * :language
76
- # * :page
77
- # * :md5
78
- #--
79
- # ToDo: Probably need to expose MD5 response values for caching implementations.
80
- #++
81
- def output(options = {})
82
- get("/string/output", hash_to_params(options))["translation"]
17
+
18
+ # Get the information of the project.
19
+ def details
20
+ get("project/details")["project"]
83
21
  end
84
-
85
- # Downloads the compiled MO file for the given language and saves it as file_name.
86
- # See #languages for a list of supported language codes.
87
- # Takes an optional hash of parameters:
88
- # * :page
89
- def output_mo(language, file_name, options = {})
90
- response = get("/string/output-mo", {:language => language}.merge(options))
91
- File.open(file_name, "w") { |f| f.print response }
92
- true
22
+
23
+ # Returns an API proxy for the Platform Management API for the given platform_id.
24
+ def platform(platform_id)
25
+ Platform.new(platform_id, client)
93
26
  end
94
-
95
- alias_method :download_mo, :output_mo
96
-
27
+
97
28
  protected
98
-
99
- def hash_to_params(hash)
100
- hash.inject({}) { |o, (k,v)| o[k.to_s.gsub("_", "-").to_sym] = v; o }
29
+
30
+ def get(path, params={})
31
+ client.get(path, params.merge(:project => project_name))
101
32
  end
102
33
 
103
- def authorization_params
104
- timestamp = Time.now.to_i.to_s
105
- {:project => @name, :"api-key" => @api_key, :timestamp => timestamp, :"dev-hash" => Digest::MD5.hexdigest(timestamp + @api_secret)}
106
- end
107
-
108
- def get(path, params = {}, options = {:content_type => "text/plain; charset=UTF-8"})
109
- params = authorization_params.merge(params)
110
- parse_response(RestClient.get([API_ROOT_URL, path].join, {:params => params}.merge(options)))
111
- end
112
-
113
- def post(path, params = {}, options = {:content_type => "text/plain; charset=UTF-8"})
114
- params = authorization_params.merge(params)
115
- parse_response(RestClient.post([API_ROOT_URL, path].join, params.merge(options)))
116
- end
117
-
118
- def parse_response(response)
119
- # Do not post-process response if it isn't JSON. (ie. Binary file returned from /output_mo.)
120
- return response.body unless response.headers[:content_type] =~ /json/
121
- response_hash = JSON.parse(response)
122
-
123
- raise ApiError, response.body if response_hash.has_key?("response") and response_hash["response"] != "ok"
124
- response_hash
125
- end
126
34
  end
127
35
  end