gengo 0.0.2 → 0.0.3
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.
- data/Gemfile.lock +1 -1
- data/README.md +26 -23
- data/lib/gengo-ruby/api_handler.rb +391 -388
- data/lib/gengo-ruby/gengo_exception.rb +11 -11
- data/lib/gengo.rb +8 -8
- metadata +7 -6
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,41 +1,44 @@
|
|
1
1
|
[](http://travis-ci.org/gengo/gengo-ruby)
|
2
|
+
|
2
3
|
Gengo Ruby Library (for the [Gengo API](http://gengo.com/api/))
|
3
|
-
|
4
|
-
Translating your tools and products helps people all over the world access them; this is, of course, a
|
5
|
-
|
6
|
-
|
7
|
-
jobs. This is a ruby interface to make using the API simpler (some would say incredibly easy).
|
4
|
+
======================================================================================================================================================
|
5
|
+
Translating your tools and products helps people all over the world access them; this is, of course, a somewhat tricky problem to solve.
|
6
|
+
**[Gengo](http://gengo.com/)** is a service that offers human-translation (which is often a higher quality than machine translation), and an API to
|
7
|
+
manage sending in work and watching jobs. This is a Ruby interface to make using the API simpler (some would say incredibly easy).
|
8
8
|
|
9
9
|
|
10
10
|
Installation & Requirements
|
11
|
-
|
11
|
+
------------------------------------------------------------------------------------------------------------------------------------------------------
|
12
12
|
Installing Gengo is fairly simple:
|
13
13
|
|
14
|
-
|
14
|
+
```sh
|
15
|
+
$ gem install gengo
|
16
|
+
```
|
15
17
|
|
16
18
|
|
17
19
|
Tests - Running Them, etc
|
18
|
-
|
19
|
-
Gengo has a full suite of tests, however they're not currently automated. Each script in the
|
20
|
-
|
20
|
+
------------------------------------------------------------------------------------------------------------------------------------------------------
|
21
|
+
Gengo has a full suite of tests, however they're not currently automated. Each script in the `examples` directory tests a different Gengo API
|
22
|
+
endpoint; run against those if you wish to test for now.
|
23
|
+
|
21
24
|
|
22
25
|
Question, Comments, Complaints, Praise?
|
23
|
-
|
24
|
-
If you have questions or comments and would like to reach us directly, please feel free to do
|
25
|
-
|
26
|
+
------------------------------------------------------------------------------------------------------------------------------------------------------
|
27
|
+
If you have questions or comments and would like to reach us directly, please feel free to do so at the following outlets. We love hearing from
|
28
|
+
developers!
|
26
29
|
|
27
|
-
Email: api [at] gengo dot com
|
28
|
-
Twitter:
|
30
|
+
* Email: api [at] gengo dot com
|
31
|
+
* Twitter: [@gengoit](https://twitter.com/gengoit)
|
32
|
+
* IRC: [#gengo](irc://irc.freenode.net/gengo)
|
29
33
|
|
30
|
-
If you come across any issues, please file them on the
|
34
|
+
If you come across any issues, please file them on the [Github project issue tracker](https://github.com/gengo/gengo-ruby/issues). Thanks!
|
31
35
|
|
32
36
|
|
33
37
|
Documentation
|
34
|
-
|
35
|
-
The usage of the API is very simple - the most important part is getting authenticated. To do this is just
|
36
|
-
a few lines of code:
|
38
|
+
------------------------------------------------------------------------------------------------------------------------------------------------------
|
39
|
+
The usage of the API is very simple - the most important part is getting authenticated. To do this is just a few lines of code:
|
37
40
|
|
38
|
-
```
|
41
|
+
```ruby
|
39
42
|
require 'gengo'
|
40
43
|
|
41
44
|
gengo = Gengo::API.new({
|
@@ -48,6 +51,6 @@ gengo = Gengo::API.new({
|
|
48
51
|
puts gengo.getAccountBalance()
|
49
52
|
```
|
50
53
|
|
51
|
-
With that, you can call any number of methods supported by this library. The entire library is rdoc supported,
|
52
|
-
|
53
|
-
|
54
|
+
With that, you can call any number of methods supported by this library. The entire library is rdoc supported, so you can look at more method
|
55
|
+
information there. There's also a full suite of test code/examples, located in the `examples` directory. Be sure to checkout the [Gengo API
|
56
|
+
documentation](http://developers.gengo.com). Enjoy!
|
@@ -12,422 +12,425 @@ require 'mime/types'
|
|
12
12
|
|
13
13
|
module Gengo
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
)
|
72
|
-
}
|
73
|
-
|
74
|
-
query[:api_key] = @opts[:public_key]
|
75
|
-
query[:ts] = Time.now.gmtime.to_i.to_s
|
76
|
-
|
77
|
-
endpoint << "?api_sig=" + signature_of(query[:ts])
|
78
|
-
endpoint << '&' + query.map { |k, v| "#{k}=#{urlencode(v)}" }.join('&')
|
79
|
-
|
80
|
-
uri = "/v#{@opts[:api_version]}/" + endpoint
|
81
|
-
headers = {
|
82
|
-
'Accept' => 'application/json',
|
83
|
-
'User-Agent' => @opts[:user_agent]
|
84
|
-
}
|
85
|
-
|
86
|
-
if is_delete
|
87
|
-
req = Net::HTTP::Delete.new(uri, headers)
|
88
|
-
else
|
89
|
-
req = Net::HTTP::Get.new(uri, headers)
|
90
|
-
end
|
91
|
-
|
92
|
-
http = Net::HTTP.start(@api_host, 80)
|
93
|
-
if @debug
|
94
|
-
http.set_debug_output($stdout)
|
95
|
-
end
|
96
|
-
http.read_timeout = 5*60
|
97
|
-
resp = http.request(req)
|
98
|
-
|
99
|
-
if is_download_file.nil?
|
100
|
-
json = JSON.parse(resp.body)
|
101
|
-
if json['opstat'] != 'ok'
|
102
|
-
raise Gengo::Exception.new(json['opstat'], json['err']['code'].to_i, json['err']['msg'])
|
103
|
-
end
|
104
|
-
|
105
|
-
# Return it if there are no problems, nice...
|
106
|
-
return json
|
107
|
-
else
|
108
|
-
return resp.body
|
109
|
-
end
|
110
|
-
|
111
|
-
end
|
112
|
-
|
113
|
-
# The "POST" method; handles shuttling up encoded job data to Gengo
|
114
|
-
# for translation and such. Somewhat similar to the above methods, but depending on the scenario
|
115
|
-
# can get some strange exceptions, so we're gonna keep them fairly separate for the time being. Consider
|
116
|
-
# for a merger down the road...
|
117
|
-
#
|
118
|
-
# Options:
|
119
|
-
# <tt>endpoint</tt> - String/URL to post data to.
|
120
|
-
# <tt>params</tt> - Data necessary for request (keys, etc). Generally taken care of by the requesting instance.
|
121
|
-
def send_to_gengo(endpoint, params = {})
|
122
|
-
|
123
|
-
# Check if this is a put
|
124
|
-
is_put = params.delete(:is_put)
|
15
|
+
# The only real class that ever needs to be instantiated.
|
16
|
+
class API
|
17
|
+
attr_accessor :api_host
|
18
|
+
attr_accessor :debug
|
19
|
+
attr_accessor :client_info
|
20
|
+
|
21
|
+
# Creates a new API handler to shuttle calls/jobs/etc over to the Gengo translation API.
|
22
|
+
#
|
23
|
+
# Options:
|
24
|
+
# <tt>opts</tt> - A hash containing the api key, the api secret key, the API version (defaults to 1), whether to use
|
25
|
+
# the sandbox API, and an optional custom user agent to send.
|
26
|
+
def initialize(opts)
|
27
|
+
# Consider this an example of the object you need to pass.
|
28
|
+
@opts = {
|
29
|
+
:public_key => '',
|
30
|
+
:private_key => '',
|
31
|
+
:api_version => '2',
|
32
|
+
:sandbox => false,
|
33
|
+
:user_agent => "Gengo Ruby Library; Version #{Gengo::Config::VERSION}; http://gengo.com/;",
|
34
|
+
:debug => false,
|
35
|
+
}.merge(opts)
|
36
|
+
|
37
|
+
# Let's go ahead and separate these out, for clarity...
|
38
|
+
@debug = @opts[:debug]
|
39
|
+
@api_host = (@opts[:sandbox] == true ? Gengo::Config::SANDBOX_API_HOST : Gengo::Config::API_HOST)
|
40
|
+
|
41
|
+
# More of a public "check this" kind of object.
|
42
|
+
@client_info = {"VERSION" => Gengo::Config::VERSION}
|
43
|
+
end
|
44
|
+
|
45
|
+
# Use CGI escape to escape a string
|
46
|
+
def urlencode(string)
|
47
|
+
CGI::escape(string)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Creates an HMAC::SHA1 signature, signing the timestamp with the private key.
|
51
|
+
def signature_of(ts)
|
52
|
+
OpenSSL::HMAC.hexdigest 'sha1', @opts[:private_key], ts
|
53
|
+
end
|
54
|
+
|
55
|
+
# The "GET" method; handles requesting basic data sets from Gengo and converting
|
56
|
+
# the response to a Ruby hash/object.
|
57
|
+
#
|
58
|
+
# Options:
|
59
|
+
# <tt>endpoint</tt> - String/URL to request data from.
|
60
|
+
# <tt>params</tt> - Data necessary for request (keys, etc). Generally taken care of by the requesting instance.
|
61
|
+
def get_from_gengo(endpoint, params = {})
|
62
|
+
# Do this small check here...
|
63
|
+
is_delete = params.delete(:is_delete)
|
64
|
+
is_download_file = params.delete(:is_download)
|
65
|
+
|
66
|
+
# The first part of the object we're going to encode and use in our request to Gengo. The signing process
|
67
|
+
# is a little annoying at the moment, so bear with us...
|
68
|
+
query = params.reduce({}) do |hash_thus_far, (param_key, param_value)|
|
69
|
+
hash_thus_far.merge(param_key.to_sym => param_value.to_s)
|
70
|
+
end
|
125
71
|
|
126
|
-
|
127
|
-
|
128
|
-
:data => params.to_json.gsub('"', '\"'),
|
129
|
-
:ts => Time.now.gmtime.to_i.to_s
|
130
|
-
}
|
131
|
-
|
132
|
-
url = URI.parse("http://#{@api_host}/v#{@opts[:api_version]}/#{endpoint}")
|
133
|
-
http = Net::HTTP.new(url.host, url.port)
|
134
|
-
http.read_timeout = 5*60
|
135
|
-
if is_put
|
136
|
-
request = Net::HTTP::Put.new(url.path)
|
137
|
-
else
|
138
|
-
request = Net::HTTP::Post.new(url.path)
|
139
|
-
end
|
140
|
-
|
141
|
-
request.add_field('Accept', 'application/json')
|
142
|
-
request.add_field('User-Agent', @opts[:user_agent])
|
143
|
-
|
144
|
-
request.content_type = 'application/x-www-form-urlencoded'
|
145
|
-
request.body = {
|
146
|
-
"api_sig" => signature_of(query[:ts]),
|
147
|
-
"api_key" => urlencode(@opts[:public_key]),
|
148
|
-
"data" => urlencode(params.to_json.gsub('\\', '\\\\')),
|
149
|
-
"ts" => query[:ts].to_i.to_s
|
150
|
-
}.map { |k, v| "#{k}=#{v}" }.flatten.join('&')
|
151
|
-
|
152
|
-
if @debug
|
153
|
-
http.set_debug_output($stdout)
|
154
|
-
end
|
155
|
-
|
156
|
-
resp = http.request(request)
|
157
|
-
|
158
|
-
case resp
|
159
|
-
when Net::HTTPSuccess, Net::HTTPRedirection
|
160
|
-
json = JSON.parse(resp.body)
|
161
|
-
|
162
|
-
if json['opstat'] != 'ok'
|
163
|
-
raise Gengo::Exception.new(json['opstat'], json['err']['code'].to_i, json['err']['msg'])
|
164
|
-
end
|
165
|
-
|
166
|
-
# Return it if there are no problems, nice...
|
167
|
-
json
|
168
|
-
else
|
169
|
-
resp.error!
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
# The "UPLOAD" method; handles sending a file to the quote method
|
174
|
-
#
|
175
|
-
# Options:
|
176
|
-
# <tt>endpoint</tt> - String/URL to post data to.
|
177
|
-
# <tt>params</tt> - Data necessary for request (keys, etc). Generally taken care of by the requesting instance.
|
178
|
-
def upload_to_gengo(endpoint, params = {})
|
179
|
-
|
180
|
-
# prepare the file_hash and append file_key to each job payload
|
181
|
-
files_hash = params[:jobs].each_value.reduce({}) do |hash_thus_far, job_values|
|
182
|
-
if job_values[:file_path]
|
183
|
-
job_mime_type = MIME::Types.type_for(job_values[:file_path]).first.content_type
|
184
|
-
file_hash_key = "file_#{hash_thus_far.length.to_s}".to_sym
|
185
|
-
job_values[:file_key] = file_hash_key
|
186
|
-
hash_thus_far[file_hash_key] = UploadIO.new(File.open(job_values[:file_path]), job_mime_type, File.basename(job_values[:file_path]))
|
187
|
-
end
|
188
|
-
hash_thus_far
|
189
|
-
end
|
190
|
-
|
191
|
-
url = URI.parse("http://#{@api_host}/v#{@opts[:api_version]}/#{endpoint}")
|
192
|
-
|
193
|
-
http = Net::HTTP.new(url.host, url.port)
|
194
|
-
http.read_timeout = 5*60
|
195
|
-
|
196
|
-
call_timestamp = Time.now.gmtime.to_i.to_s
|
197
|
-
|
198
|
-
the_hash = files_hash.merge({
|
199
|
-
"api_sig" => signature_of(call_timestamp),
|
200
|
-
"api_key" => @opts[:public_key],
|
201
|
-
"data" =>params.to_json.gsub('\\', '\\\\'),
|
202
|
-
"ts" => call_timestamp
|
203
|
-
})
|
204
|
-
|
205
|
-
request = Net::HTTP::Post::Multipart.new(url.path, the_hash, {'Accept' => 'application/json', 'User-Agent' => @opts[:user_agent] })
|
206
|
-
|
207
|
-
if @debug
|
208
|
-
http.set_debug_output($stdout)
|
209
|
-
end
|
210
|
-
|
211
|
-
resp = http.request(request)
|
212
|
-
|
213
|
-
case resp
|
214
|
-
when Net::HTTPSuccess, Net::HTTPRedirection
|
215
|
-
json = JSON.parse(resp.body)
|
216
|
-
|
217
|
-
if json['opstat'] != 'ok'
|
218
|
-
raise Gengo::Exception.new(json['opstat'], json['err']['code'].to_i, json['err']['msg'])
|
219
|
-
end
|
220
|
-
|
221
|
-
# Return it if there are no problems, nice...
|
222
|
-
json
|
223
|
-
else
|
224
|
-
resp.error!
|
225
|
-
end
|
226
|
-
end
|
227
|
-
|
228
|
-
# Returns a Ruby-hash of the stats for the current account. No arguments required!
|
229
|
-
#
|
230
|
-
# Options:
|
231
|
-
# <tt>None</tt> - N/A
|
232
|
-
def getAccountStats(params = {})
|
233
|
-
self.get_from_gengo('account/stats', params)
|
234
|
-
end
|
72
|
+
query[:api_key] = @opts[:public_key]
|
73
|
+
query[:ts] = Time.now.gmtime.to_i.to_s
|
235
74
|
|
236
|
-
|
237
|
-
|
238
|
-
# Options:
|
239
|
-
# <tt>None</tt> - N/A
|
240
|
-
def getAccountBalance(params = {})
|
241
|
-
self.get_from_gengo('account/balance', params)
|
242
|
-
end
|
75
|
+
endpoint << "?api_sig=" + signature_of(query[:ts])
|
76
|
+
endpoint << '&' + query.map { |k, v| "#{k}=#{urlencode(v)}" }.join('&')
|
243
77
|
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
# more information on what this should be. (type/slug/body_src/lc_src/lc_tgt/tier/auto_approve/comment/callback_url/custom_data)
|
250
|
-
def postTranslationJob(params = {})
|
251
|
-
self.send_to_gengo('translate/job', params)
|
252
|
-
end
|
78
|
+
uri = "/v#{@opts[:api_version]}/" + endpoint
|
79
|
+
headers = {
|
80
|
+
'Accept' => 'application/json',
|
81
|
+
'User-Agent' => @opts[:user_agent]
|
82
|
+
}
|
253
83
|
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
self.send_to_gengo('translate/jobs', params)
|
260
|
-
end
|
84
|
+
if is_delete
|
85
|
+
req = Net::HTTP::Delete.new(uri, headers)
|
86
|
+
else
|
87
|
+
req = Net::HTTP::Get.new(uri, headers)
|
88
|
+
end
|
261
89
|
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
params[:is_put] = true
|
269
|
-
self.send_to_gengo('translate/job/:id'.gsub(':id', params.delete(:id).to_s), params)
|
270
|
-
end
|
90
|
+
http = Net::HTTP.start(@api_host, 80)
|
91
|
+
if @debug
|
92
|
+
http.set_debug_output($stdout)
|
93
|
+
end
|
94
|
+
http.read_timeout = 5*60
|
95
|
+
resp = http.request(req)
|
271
96
|
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
# <tt>action</tt> - A String describing the update to this job. "approved", "rejected", etc - see Gengo docs.
|
277
|
-
def updateTranslationJobs(params = {})
|
278
|
-
params[:is_put] = true
|
279
|
-
self.send_to_gengo('translate/jobs', {:jobs => params[:jobs], :action => params[:action]})
|
97
|
+
if is_download_file.nil?
|
98
|
+
json = JSON.parse(resp.body)
|
99
|
+
if json['opstat'] != 'ok'
|
100
|
+
raise Gengo::Exception.new(json['opstat'], json['err']['code'].to_i, json['err']['msg'])
|
280
101
|
end
|
281
102
|
|
282
|
-
#
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
self.get_from_gengo('translate/job/:id'.gsub(':id', params.delete(:id).to_s), params)
|
288
|
-
end
|
103
|
+
# Return it if there are no problems, nice...
|
104
|
+
return json
|
105
|
+
else
|
106
|
+
return resp.body
|
107
|
+
end
|
289
108
|
|
290
|
-
|
291
|
-
#
|
292
|
-
# <tt>status</tt> - Optional. "unpaid", "available", "pending", "reviewable", "approved", "rejected", or "canceled".
|
293
|
-
# <tt>timestamp_after</tt> - Optional. Epoch timestamp from which to filter submitted jobs.
|
294
|
-
# <tt>count</tt> - Optional. Defaults to 10.
|
295
|
-
def getTranslationJobs(params = {})
|
296
|
-
if params[:ids] and params[:ids].kind_of?(Array)
|
297
|
-
params[:ids] = params[:ids].map { |i| i.to_s() }.join(',')
|
298
|
-
self.get_from_gengo('translate/jobs/:ids'.gsub(':ids', params.delete(:ids)))
|
299
|
-
else
|
300
|
-
self.get_from_gengo('translate/jobs', params)
|
301
|
-
end
|
302
|
-
end
|
109
|
+
end
|
303
110
|
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
111
|
+
# The "POST" method; handles shuttling up encoded job data to Gengo
|
112
|
+
# for translation and such. Somewhat similar to the above methods, but depending on the scenario
|
113
|
+
# can get some strange exceptions, so we're gonna keep them fairly separate for the time being. Consider
|
114
|
+
# for a merger down the road...
|
115
|
+
#
|
116
|
+
# Options:
|
117
|
+
# <tt>endpoint</tt> - String/URL to post data to.
|
118
|
+
# <tt>params</tt> - Data necessary for request (keys, etc). Generally taken care of by the requesting instance.
|
119
|
+
def send_to_gengo(endpoint, params = {})
|
310
120
|
|
311
|
-
|
312
|
-
|
313
|
-
# <tt>id</tt> - Required, the ID of a job that you want the batch/group of.
|
314
|
-
def getTranslationOrderJobs(params = {})
|
315
|
-
self.get_from_gengo('translate/order/:order_id'.gsub(':order_id', params.delete(:order_id).to_s), params)
|
316
|
-
end
|
121
|
+
# Check if this is a put
|
122
|
+
is_put = params.delete(:is_put)
|
317
123
|
|
318
|
-
|
319
|
-
|
320
|
-
|
124
|
+
query = {
|
125
|
+
:api_key => @opts[:public_key],
|
126
|
+
:data => params.to_json.gsub('"', '\"'),
|
127
|
+
:ts => Time.now.gmtime.to_i.to_s
|
128
|
+
}
|
129
|
+
|
130
|
+
url = URI.parse("http://#{@api_host}/v#{@opts[:api_version]}/#{endpoint}")
|
131
|
+
http = Net::HTTP.new(url.host, url.port)
|
132
|
+
http.read_timeout = 5*60
|
133
|
+
if is_put
|
134
|
+
request = Net::HTTP::Put.new(url.path)
|
135
|
+
else
|
136
|
+
request = Net::HTTP::Post.new(url.path)
|
137
|
+
end
|
321
138
|
|
322
|
-
|
323
|
-
|
324
|
-
else
|
325
|
-
self.send_to_gengo('translate/service/quote', params)
|
326
|
-
end
|
327
|
-
end
|
139
|
+
request.add_field('Accept', 'application/json')
|
140
|
+
request.add_field('User-Agent', @opts[:user_agent])
|
328
141
|
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
end
|
142
|
+
request.content_type = 'application/x-www-form-urlencoded'
|
143
|
+
request.body = {
|
144
|
+
"api_sig" => signature_of(query[:ts]),
|
145
|
+
"api_key" => urlencode(@opts[:public_key]),
|
146
|
+
"data" => urlencode(params.to_json.gsub('\\', '\\\\')),
|
147
|
+
"ts" => query[:ts].to_i.to_s
|
148
|
+
}.map { |k, v| "#{k}=#{v}" }.flatten.join('&')
|
337
149
|
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
# <tt>id</tt> - The ID of the job to get comments for.
|
342
|
-
def getTranslationJobComments(params = {})
|
343
|
-
self.get_from_gengo('translate/job/:id/comments'.gsub(':id', params.delete(:id).to_s), params)
|
344
|
-
end
|
150
|
+
if @debug
|
151
|
+
http.set_debug_output($stdout)
|
152
|
+
end
|
345
153
|
|
346
|
-
|
347
|
-
#
|
348
|
-
# Options:
|
349
|
-
# <tt>id</tt> - The ID of the translation job you're retrieving comments from.
|
350
|
-
def getTranslationJobFeedback(params = {})
|
351
|
-
self.get_from_gengo('translate/job/:id/feedback'.gsub(':id', params.delete(:id).to_s), params)
|
352
|
-
end
|
154
|
+
resp = http.request(request)
|
353
155
|
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
# <tt>id</tt> - The ID of the translation job you're getting revisions from.
|
358
|
-
def getTranslationJobRevisions(params = {})
|
359
|
-
self.get_from_gengo('translate/job/:id/revisions'.gsub(':id', params.delete(:id).to_s), params)
|
360
|
-
end
|
156
|
+
case resp
|
157
|
+
when Net::HTTPSuccess, Net::HTTPRedirection
|
158
|
+
json = JSON.parse(resp.body)
|
361
159
|
|
362
|
-
|
363
|
-
|
364
|
-
# Options:
|
365
|
-
# <tt>id</tt> - The ID of the translation job you're getting revisions from.
|
366
|
-
# <tt>rev_id</tt> - The ID of the revision you're looking up.
|
367
|
-
def getTranslationJobRevision(params = {})
|
368
|
-
self.get_from_gengo('translate/job/:id/revisions/:revision_id'.gsub(':id', params.delete(:id).to_s).gsub(':revision_id', params.delete(:rev_id).to_s), params)
|
160
|
+
if json['opstat'] != 'ok'
|
161
|
+
raise Gengo::Exception.new(json['opstat'], json['err']['code'].to_i, json['err']['msg'])
|
369
162
|
end
|
370
163
|
|
371
|
-
#
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
164
|
+
# Return it if there are no problems, nice...
|
165
|
+
json
|
166
|
+
else
|
167
|
+
resp.error!
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# The "UPLOAD" method; handles sending a file to the quote method
|
172
|
+
#
|
173
|
+
# Options:
|
174
|
+
# <tt>endpoint</tt> - String/URL to post data to.
|
175
|
+
# <tt>params</tt> - Data necessary for request (keys, etc). Generally taken care of by the requesting instance.
|
176
|
+
def upload_to_gengo(endpoint, params = {})
|
177
|
+
|
178
|
+
# prepare the file_hash and append file_key to each job payload
|
179
|
+
files_hash = params[:jobs].each_value.reduce({}) do |hash_thus_far, job_values|
|
180
|
+
if job_values[:file_path]
|
181
|
+
job_mime_type = MIME::Types.type_for(job_values[:file_path]).first.content_type
|
182
|
+
file_hash_key = "file_#{hash_thus_far.length.to_s}".to_sym
|
183
|
+
job_values[:file_key] = file_hash_key
|
184
|
+
hash_thus_far[file_hash_key] = UploadIO.new(File.open(job_values[:file_path]), job_mime_type, File.basename(job_values[:file_path]))
|
185
|
+
end
|
186
|
+
hash_thus_far
|
187
|
+
end
|
379
188
|
|
380
|
-
|
381
|
-
#
|
382
|
-
# Options:
|
383
|
-
# <tt>id</tt> - The ID of the job you want to delete.
|
384
|
-
def deleteTranslationJob(params = {})
|
385
|
-
params[:is_delete] = true
|
386
|
-
self.get_from_gengo('translate/job/:id'.gsub(':id', params.delete(:id).to_s), params)
|
387
|
-
end
|
189
|
+
url = URI.parse("http://#{@api_host}/v#{@opts[:api_version]}/#{endpoint}")
|
388
190
|
|
389
|
-
|
390
|
-
|
391
|
-
# Options:
|
392
|
-
# <tt>ids</tt> - An Array of job IDs you want to delete.
|
393
|
-
def deleteTranslationJobs(params = {})
|
394
|
-
if params[:ids] and params[:ids].kind_of?(Array)
|
395
|
-
params[:job_ids] = params[:ids].map { |i| i.to_s() }.join(',')
|
396
|
-
params.delete(:ids)
|
397
|
-
end
|
398
|
-
|
399
|
-
params[:is_delete] = true
|
400
|
-
self.get_from_gengo('translate/jobs', params)
|
401
|
-
end
|
191
|
+
http = Net::HTTP.new(url.host, url.port)
|
192
|
+
http.read_timeout = 5*60
|
402
193
|
|
403
|
-
|
404
|
-
#
|
405
|
-
# Options:
|
406
|
-
# <tt>lc_src</tt> - Optional language code to filter on.
|
407
|
-
def getServiceLanguagePairs(params = {})
|
408
|
-
self.get_from_gengo('translate/service/language_pairs', params)
|
409
|
-
end
|
194
|
+
call_timestamp = Time.now.gmtime.to_i.to_s
|
410
195
|
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
196
|
+
the_hash = files_hash.merge({
|
197
|
+
"api_sig" => signature_of(call_timestamp),
|
198
|
+
"api_key" => @opts[:public_key],
|
199
|
+
"data" =>params.to_json.gsub('\\', '\\\\'),
|
200
|
+
"ts" => call_timestamp
|
201
|
+
})
|
415
202
|
|
416
|
-
|
417
|
-
def getGlossaryList(params = {})
|
418
|
-
self.get_from_gengo('translate/glossary', params)
|
419
|
-
end
|
203
|
+
request = Net::HTTP::Post::Multipart.new(url.path, the_hash, {'Accept' => 'application/json', 'User-Agent' => @opts[:user_agent] })
|
420
204
|
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
205
|
+
if @debug
|
206
|
+
http.set_debug_output($stdout)
|
207
|
+
end
|
208
|
+
|
209
|
+
resp = http.request(request)
|
210
|
+
|
211
|
+
case resp
|
212
|
+
when Net::HTTPSuccess, Net::HTTPRedirection
|
213
|
+
json = JSON.parse(resp.body)
|
425
214
|
|
426
|
-
|
427
|
-
|
428
|
-
params[:is_download] = true
|
429
|
-
self.get_from_gengo('translate/glossary/download/:id'.gsub(':id', params.delete(:id).to_s), params)
|
215
|
+
if json['opstat'] != 'ok'
|
216
|
+
raise Gengo::Exception.new(json['opstat'], json['err']['code'].to_i, json['err']['msg'])
|
430
217
|
end
|
218
|
+
|
219
|
+
# Return it if there are no problems, nice...
|
220
|
+
json
|
221
|
+
else
|
222
|
+
resp.error!
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
# Returns a Ruby-hash of the stats for the current account. No arguments required!
|
227
|
+
#
|
228
|
+
# Options:
|
229
|
+
# <tt>None</tt> - N/A
|
230
|
+
def getAccountStats(params = {})
|
231
|
+
self.get_from_gengo('account/stats', params)
|
232
|
+
end
|
233
|
+
|
234
|
+
# Returns a Ruby-hash of the balance for the authenticated account. No args required!
|
235
|
+
#
|
236
|
+
# Options:
|
237
|
+
# <tt>None</tt> - N/A
|
238
|
+
def getAccountBalance(params = {})
|
239
|
+
self.get_from_gengo('account/balance', params)
|
240
|
+
end
|
241
|
+
|
242
|
+
# Much like the above, but takes a hash titled "jobs" that is multiple jobs, each with their own unique key.
|
243
|
+
#
|
244
|
+
# Options:
|
245
|
+
# <tt>jobs</tt> - "Jobs" is a hash containing further hashes; each further hash is a job. This is best seen in the example code.
|
246
|
+
def postTranslationJobs(params = {})
|
247
|
+
self.send_to_gengo('translate/jobs', params)
|
248
|
+
end
|
249
|
+
|
250
|
+
# Updates an already submitted job.
|
251
|
+
#
|
252
|
+
# Options:
|
253
|
+
# <tt>id</tt> - The ID of a job to update.
|
254
|
+
# <tt>action</tt> - A hash describing the update to this job. See the examples for further documentation.
|
255
|
+
def updateTranslationJob(params = {})
|
256
|
+
params[:is_put] = true
|
257
|
+
self.send_to_gengo('translate/job/:id'.gsub(':id', params.delete(:id).to_s), params)
|
258
|
+
end
|
259
|
+
|
260
|
+
# Updates a group of already submitted jobs.
|
261
|
+
#
|
262
|
+
# Options:
|
263
|
+
# <tt>jobs</tt> - An Array of job objects to update (job objects or ids)
|
264
|
+
# <tt>action</tt> - A String describing the update to this job. "approved", "rejected", etc - see Gengo docs.
|
265
|
+
def updateTranslationJobs(params = {})
|
266
|
+
params[:is_put] = true
|
267
|
+
self.send_to_gengo('translate/jobs', {:jobs => params[:jobs], :action => params[:action]})
|
268
|
+
end
|
269
|
+
|
270
|
+
# Given an ID, pulls down information concerning that job from Gengo.
|
271
|
+
#
|
272
|
+
# <tt>id</tt> - The ID of a job to check.
|
273
|
+
# <tt>pre_mt</tt> - Optional, get a machine translation if the human translation is not done.
|
274
|
+
def getTranslationJob(params = {})
|
275
|
+
self.get_from_gengo('translate/job/:id'.gsub(':id', params.delete(:id).to_s), params)
|
276
|
+
end
|
277
|
+
|
278
|
+
# Pulls down a list of recently submitted jobs, allows some filters.
|
279
|
+
#
|
280
|
+
# <tt>status</tt> - Optional. "unpaid", "available", "pending", "reviewable", "approved", "rejected", or "canceled".
|
281
|
+
# <tt>timestamp_after</tt> - Optional. Epoch timestamp from which to filter submitted jobs.
|
282
|
+
# <tt>count</tt> - Optional. Defaults to 10.
|
283
|
+
def getTranslationJobs(params = {})
|
284
|
+
if params[:ids] and params[:ids].kind_of?(Array)
|
285
|
+
params[:ids] = params[:ids].map { |i| i.to_s() }.join(',')
|
286
|
+
self.get_from_gengo('translate/jobs/:ids'.gsub(':ids', params.delete(:ids)))
|
287
|
+
else
|
288
|
+
self.get_from_gengo('translate/jobs', params)
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
# Pulls a group of jobs that were previously submitted together.
|
293
|
+
#
|
294
|
+
# <tt>id</tt> - Required, the ID of a job that you want the batch/group of.
|
295
|
+
def getTranslationJobBatch(params = {})
|
296
|
+
self.get_from_gengo('translate/jobs/group/:group_id'.gsub(':group_id', params.delete(:group_id).to_s), params)
|
297
|
+
end
|
298
|
+
|
299
|
+
# Pulls a group of jobs that were previously submitted together.
|
300
|
+
#
|
301
|
+
# <tt>id</tt> - Required, the ID of a job that you want the batch/group of.
|
302
|
+
def getTranslationOrderJobs(params = {})
|
303
|
+
self.get_from_gengo('translate/order/:order_id'.gsub(':order_id', params.delete(:order_id).to_s), params)
|
304
|
+
end
|
305
|
+
|
306
|
+
# Mirrors the bulk Translation call, but just returns an estimated cost.
|
307
|
+
def determineTranslationCost(params = {})
|
308
|
+
is_upload = params.delete(:is_upload)
|
309
|
+
if is_upload
|
310
|
+
self.upload_to_gengo('translate/service/quote/file', params)
|
311
|
+
else
|
312
|
+
self.send_to_gengo('translate/service/quote', params)
|
431
313
|
end
|
314
|
+
end
|
315
|
+
|
316
|
+
# Mirrors the bulk Translation call, but just returns an estimated cost.
|
317
|
+
def getTranslationQuote(params = {})
|
318
|
+
determineTranslationCost(params)
|
319
|
+
end
|
320
|
+
|
321
|
+
# Post a comment for a translator or Gengo on a job.
|
322
|
+
#
|
323
|
+
# Options:
|
324
|
+
# <tt>id</tt> - The ID of the job you're commenting on.
|
325
|
+
# <tt>comment</tt> - The comment to put on the job.
|
326
|
+
def postTranslationJobComment(params = {})
|
327
|
+
self.send_to_gengo('translate/job/:id/comment'.gsub(':id', params.delete(:id).to_s), params)
|
328
|
+
end
|
329
|
+
|
330
|
+
# Get all comments (the history) from a given job.
|
331
|
+
#
|
332
|
+
# Options:
|
333
|
+
# <tt>id</tt> - The ID of the job to get comments for.
|
334
|
+
def getTranslationJobComments(params = {})
|
335
|
+
self.get_from_gengo('translate/job/:id/comments'.gsub(':id', params.delete(:id).to_s), params)
|
336
|
+
end
|
337
|
+
|
338
|
+
# Returns the feedback you've submitted for a given job.
|
339
|
+
#
|
340
|
+
# Options:
|
341
|
+
# <tt>id</tt> - The ID of the translation job you're retrieving comments from.
|
342
|
+
def getTranslationJobFeedback(params = {})
|
343
|
+
self.get_from_gengo('translate/job/:id/feedback'.gsub(':id', params.delete(:id).to_s), params)
|
344
|
+
end
|
345
|
+
|
346
|
+
# Gets a list of the revision resources for a job. Revisions are created each time a translator updates the text.
|
347
|
+
#
|
348
|
+
# Options:
|
349
|
+
# <tt>id</tt> - The ID of the translation job you're getting revisions from.
|
350
|
+
def getTranslationJobRevisions(params = {})
|
351
|
+
self.get_from_gengo('translate/job/:id/revisions'.gsub(':id', params.delete(:id).to_s), params)
|
352
|
+
end
|
353
|
+
|
354
|
+
# Get a specific revision to a job.
|
355
|
+
#
|
356
|
+
# Options:
|
357
|
+
# <tt>id</tt> - The ID of the translation job you're getting revisions from.
|
358
|
+
# <tt>rev_id</tt> - The ID of the revision you're looking up.
|
359
|
+
def getTranslationJobRevision(params = {})
|
360
|
+
self.get_from_gengo('translate/job/:id/revisions/:revision_id'.gsub(':id', params.delete(:id).to_s).gsub(':revision_id', params.delete(:rev_id).to_s), params)
|
361
|
+
end
|
362
|
+
|
363
|
+
# Returns a preview image for a job.
|
364
|
+
#
|
365
|
+
# Options:
|
366
|
+
# <tt>id</tt> - The ID of the job you want a preview image of.
|
367
|
+
def getTranslationJobPreviewImage(params = {})
|
368
|
+
params[:is_download] = true
|
369
|
+
self.get_from_gengo('translate/job/:id/preview'.gsub(':id', params.delete(:id).to_s), params)
|
370
|
+
end
|
371
|
+
|
372
|
+
# Deletes an order, cancelling all available jobs.
|
373
|
+
#
|
374
|
+
# This method is EXPERIMENTAL
|
375
|
+
#
|
376
|
+
# Options:
|
377
|
+
# <tt>id</tt> - The ID of the order you want to delete.
|
378
|
+
def deleteTranslationOrder(params = {})
|
379
|
+
params[:is_delete] = true
|
380
|
+
self.get_from_gengo('translate/order/:id'.gsub(':id', params.delete(:id).to_s), params)
|
381
|
+
end
|
382
|
+
|
383
|
+
# Deletes a job.
|
384
|
+
#
|
385
|
+
# Options:
|
386
|
+
# <tt>id</tt> - The ID of the job you want to delete.
|
387
|
+
def deleteTranslationJob(params = {})
|
388
|
+
params[:is_delete] = true
|
389
|
+
self.get_from_gengo('translate/job/:id'.gsub(':id', params.delete(:id).to_s), params)
|
390
|
+
end
|
391
|
+
|
392
|
+
# Deletes multiple jobs.
|
393
|
+
#
|
394
|
+
# Options:
|
395
|
+
# <tt>ids</tt> - An Array of job IDs you want to delete.
|
396
|
+
def deleteTranslationJobs(params = {})
|
397
|
+
if params[:ids] and params[:ids].kind_of?(Array)
|
398
|
+
params[:job_ids] = params[:ids].map { |i| i.to_s() }.join(',')
|
399
|
+
params.delete(:ids)
|
400
|
+
end
|
401
|
+
|
402
|
+
params[:is_delete] = true
|
403
|
+
self.get_from_gengo('translate/jobs', params)
|
404
|
+
end
|
405
|
+
|
406
|
+
# Gets information about currently supported language pairs.
|
407
|
+
#
|
408
|
+
# Options:
|
409
|
+
# <tt>lc_src</tt> - Optional language code to filter on.
|
410
|
+
def getServiceLanguagePairs(params = {})
|
411
|
+
self.get_from_gengo('translate/service/language_pairs', params)
|
412
|
+
end
|
413
|
+
|
414
|
+
# Pulls down currently supported languages.
|
415
|
+
def getServiceLanguages(params = {})
|
416
|
+
self.get_from_gengo('translate/service/languages', params)
|
417
|
+
end
|
418
|
+
|
419
|
+
# Gets list of glossaries that belongs to the authenticated user
|
420
|
+
def getGlossaryList(params = {})
|
421
|
+
self.get_from_gengo('translate/glossary', params)
|
422
|
+
end
|
423
|
+
|
424
|
+
# Gets one glossary that belongs to the authenticated user
|
425
|
+
def getGlossary(params = {})
|
426
|
+
self.get_from_gengo('translate/glossary/:id'.gsub(':id', params.delete(:id).to_s), params)
|
427
|
+
end
|
428
|
+
|
429
|
+
# Downloads one glossary that belongs to the authenticated user
|
430
|
+
def getGlossaryFile(params = {})
|
431
|
+
params[:is_download] = true
|
432
|
+
self.get_from_gengo('translate/glossary/download/:id'.gsub(':id', params.delete(:id).to_s), params)
|
433
|
+
end
|
434
|
+
end
|
432
435
|
|
433
436
|
end
|
@@ -1,15 +1,15 @@
|
|
1
1
|
module Gengo
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
# Base Exception class and such.
|
3
|
+
class Gengo::Exception < ::StandardError
|
4
|
+
attr_accessor :opstat, :code, :msg
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
# Pretty self explanatory stuff here...
|
7
|
+
def initialize(opstat, code, msg)
|
8
|
+
@opstat = opstat
|
9
|
+
@code = code
|
10
|
+
@msg = msg
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
puts msg
|
13
|
+
end
|
14
|
+
end
|
15
15
|
end
|
data/lib/gengo.rb
CHANGED
@@ -3,13 +3,13 @@ require 'gengo-ruby/api_handler'
|
|
3
3
|
require 'gengo-ruby/gengo_exception'
|
4
4
|
|
5
5
|
module Gengo
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
# Store global config objects here - e.g, urls, etc.
|
7
|
+
module Config
|
8
|
+
# API url endpoints; replace the version at function call time to
|
9
|
+
# allow for function-by-function differences in versioning.
|
10
|
+
API_HOST = 'api.gengo.com'
|
11
|
+
SANDBOX_API_HOST = 'api.sandbox.gengo.com'
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
VERSION = '0.0.0'
|
14
|
+
end
|
15
15
|
end
|
metadata
CHANGED
@@ -1,22 +1,23 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gengo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 3
|
10
|
+
version: 0.0.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Matthew Romaine
|
14
14
|
- Shawn Smith
|
15
|
+
- Issam Zeibak
|
15
16
|
autorequire:
|
16
17
|
bindir: bin
|
17
18
|
cert_chain: []
|
18
19
|
|
19
|
-
date:
|
20
|
+
date: 2013-04-17 00:00:00 Z
|
20
21
|
dependencies:
|
21
22
|
- !ruby/object:Gem::Dependency
|
22
23
|
name: json
|
@@ -135,8 +136,8 @@ files:
|
|
135
136
|
- Rakefile
|
136
137
|
- README.md
|
137
138
|
homepage: http://developers.gengo.com
|
138
|
-
licenses:
|
139
|
-
|
139
|
+
licenses:
|
140
|
+
- New BSD
|
140
141
|
post_install_message:
|
141
142
|
rdoc_options: []
|
142
143
|
|