bing_translator 5.2.0 → 6.0.0.beta.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.
- checksums.yaml +4 -4
- data/lib/bing_translator.rb +165 -192
- metadata +7 -102
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9106de975569bef3303a4940318a78b536beaf10
|
4
|
+
data.tar.gz: e40c556e6f474d185b74f6753635a448720600f6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8b84d0f6c1b4a405ee631221a961f8e5462c7de1b0ca3eb26b0f0b2dc105e3b0e8ac19c085c8de320191a66895af313fc1b1f718f81b13505a6b31ab8a20108c
|
7
|
+
data.tar.gz: c22b944db83f5b437b9fa56e8df83da1bd69f7b81f9ef65dedb51a66d82c79714fba29701da46a6bd1b027e56ff69e54f3e5c21bddfccacddfadd3daa252e3a4
|
data/lib/bing_translator.rb
CHANGED
@@ -1,192 +1,165 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
# (c) 2011-present. Ricky Elrod <ricky@elrod.me>
|
4
|
-
# Released under the MIT license.
|
5
|
-
require 'rubygems'
|
6
|
-
require 'cgi'
|
7
|
-
require 'uri'
|
8
|
-
require 'net/http'
|
9
|
-
require 'net/https'
|
10
|
-
require '
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
'
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
# Construct and store new client when token have been expired.
|
167
|
-
def soap_client
|
168
|
-
return @client if @client and @access_token and @access_token['expires_at'] and
|
169
|
-
Time.now < @access_token['expires_at']
|
170
|
-
|
171
|
-
@client = Savon.client(
|
172
|
-
wsdl: WSDL_URI,
|
173
|
-
namespace: NAMESPACE_URI,
|
174
|
-
namespace_identifier: :v2,
|
175
|
-
namespaces: {
|
176
|
-
'xmlns:arr' => 'http://schemas.microsoft.com/2003/10/Serialization/Arrays'
|
177
|
-
},
|
178
|
-
headers: {'Authorization' => "Bearer #{get_access_token['access_token']}"},
|
179
|
-
)
|
180
|
-
end
|
181
|
-
|
182
|
-
# Private: Array#wrap based on ActiveSupport extension
|
183
|
-
def array_wrap(object)
|
184
|
-
if object.nil?
|
185
|
-
[]
|
186
|
-
elsif object.respond_to?(:to_ary)
|
187
|
-
object.to_ary || [object]
|
188
|
-
else
|
189
|
-
[object]
|
190
|
-
end
|
191
|
-
end
|
192
|
-
end
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# (c) 2011-present. Ricky Elrod <ricky@elrod.me>
|
4
|
+
# Released under the MIT license.
|
5
|
+
require 'rubygems'
|
6
|
+
require 'cgi'
|
7
|
+
require 'uri'
|
8
|
+
require 'net/http'
|
9
|
+
require 'net/https'
|
10
|
+
require 'json'
|
11
|
+
|
12
|
+
class BingTranslator
|
13
|
+
class Exception < StandardError; end
|
14
|
+
|
15
|
+
class ApiClient
|
16
|
+
API_HOST = 'https://api.cognitive.microsofttranslator.com'.freeze
|
17
|
+
COGNITIVE_ACCESS_TOKEN_URI =
|
18
|
+
URI.parse('https://api.cognitive.microsoft.com/sts/v1.0/issueToken').freeze
|
19
|
+
|
20
|
+
def initialize(subscription_key, skip_ssl_verify)
|
21
|
+
@subscription_key = subscription_key
|
22
|
+
@skip_ssl_verify = skip_ssl_verify
|
23
|
+
end
|
24
|
+
|
25
|
+
def get(path, params: {}, headers: {}, authorization: false)
|
26
|
+
uri = request_uri(path, params)
|
27
|
+
request = Net::HTTP::Get.new(uri.request_uri, default_headers(authorization).merge(headers))
|
28
|
+
|
29
|
+
json_response(uri, request)
|
30
|
+
end
|
31
|
+
|
32
|
+
def post(path, params: {}, headers: {}, data: {}, authorization: true)
|
33
|
+
uri = request_uri(path, params)
|
34
|
+
|
35
|
+
request = Net::HTTP::Post.new(uri.request_uri, default_headers(authorization).merge(headers))
|
36
|
+
request.body = data
|
37
|
+
|
38
|
+
json_response(uri, request)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def default_headers(authorization = true)
|
44
|
+
headers = { 'Content-Type' => 'application/json' }
|
45
|
+
headers['Authorization'] = "Bearer #{access_token}" if authorization
|
46
|
+
headers
|
47
|
+
end
|
48
|
+
|
49
|
+
def json_response(uri, request)
|
50
|
+
http = http_client(uri)
|
51
|
+
|
52
|
+
response = http.request(request)
|
53
|
+
|
54
|
+
raise Exception.new("Unsuccessful API call: Code: #{response.code}") unless response.code == '200'
|
55
|
+
JSON.parse(response.body)
|
56
|
+
end
|
57
|
+
|
58
|
+
def http_client(uri)
|
59
|
+
http = Net::HTTP.new(uri.host, 443)
|
60
|
+
http.use_ssl = true
|
61
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if @skip_ssl_verify
|
62
|
+
http
|
63
|
+
end
|
64
|
+
|
65
|
+
def request_uri(path, params)
|
66
|
+
encoded_params = URI.encode_www_form(params.merge('api-version' => '3.0'))
|
67
|
+
uri = URI.parse("#{API_HOST}#{path}")
|
68
|
+
uri.query = encoded_params
|
69
|
+
uri
|
70
|
+
end
|
71
|
+
|
72
|
+
def access_token
|
73
|
+
if @access_token.nil? || Time.now < @access_token_expiration_time
|
74
|
+
@access_token = request_new_access_token
|
75
|
+
end
|
76
|
+
@access_token
|
77
|
+
end
|
78
|
+
|
79
|
+
def request_new_access_token
|
80
|
+
headers = {
|
81
|
+
'Ocp-Apim-Subscription-Key' => @subscription_key
|
82
|
+
}
|
83
|
+
|
84
|
+
http = Net::HTTP.new(COGNITIVE_ACCESS_TOKEN_URI.host, COGNITIVE_ACCESS_TOKEN_URI.port)
|
85
|
+
http.use_ssl = true
|
86
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if @skip_ssl_verify
|
87
|
+
|
88
|
+
response = http.post(COGNITIVE_ACCESS_TOKEN_URI.path, '', headers)
|
89
|
+
if response.code != '200'
|
90
|
+
raise Exception.new('Invalid credentials')
|
91
|
+
else
|
92
|
+
@access_token_expiration_time = Time.now + 480
|
93
|
+
response.body
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def initialize(subscription_key, options = {})
|
99
|
+
skip_ssl_verify = options.fetch(:skip_ssl_verify, false)
|
100
|
+
@api_client = ApiClient.new(subscription_key, skip_ssl_verify)
|
101
|
+
end
|
102
|
+
|
103
|
+
def translate(text, params)
|
104
|
+
translate_array([text], params).first
|
105
|
+
end
|
106
|
+
|
107
|
+
def translate_array(texts, params = {})
|
108
|
+
translations = translation_request(texts, params)
|
109
|
+
translations.map do |translation|
|
110
|
+
translation['text'] if translation.is_a?(Hash)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def translate_array2(texts, params = {})
|
115
|
+
translations = translation_request(texts, params.merge('includeAlignment' => true))
|
116
|
+
translations.map do |translation|
|
117
|
+
[translation['text'], translation['alignment']['proj']] if translation.is_a?(Hash)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def detect(text)
|
122
|
+
data = [{ 'Text' => text }].to_json
|
123
|
+
|
124
|
+
response_json = api_client.post('/detect', data: data)
|
125
|
+
best_detection = response_json.sort_by { |detection| -detection['score'] }.first
|
126
|
+
best_detection['language'].to_sym
|
127
|
+
end
|
128
|
+
|
129
|
+
def speak(text, params = {})
|
130
|
+
raise Exception.new('Not supported since 3.0.0')
|
131
|
+
end
|
132
|
+
|
133
|
+
def supported_language_codes
|
134
|
+
response_json = api_client.get('/languages',
|
135
|
+
params: { scope: 'translation' },
|
136
|
+
authorization: false)
|
137
|
+
response_json['translation'].keys
|
138
|
+
end
|
139
|
+
|
140
|
+
def language_names(codes, locale = 'en')
|
141
|
+
response_json = api_client.get('/languages',
|
142
|
+
params: { scope: 'translation' },
|
143
|
+
headers: { 'Accept-Language' => locale },
|
144
|
+
authorization: false)
|
145
|
+
codes.map do |code|
|
146
|
+
response = response_json['translation'][code.to_s]
|
147
|
+
response['name'] unless response.nil?
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
private
|
152
|
+
|
153
|
+
attr_reader :api_client
|
154
|
+
|
155
|
+
def translation_request(texts, params)
|
156
|
+
raise Exception.new('Must provide :to.') if params[:to].nil?
|
157
|
+
|
158
|
+
data = texts.map { |text| { 'Text' => text } }.to_json
|
159
|
+
response_json = api_client.post('/translate', params: params, data: data)
|
160
|
+
response_json.map do |translation|
|
161
|
+
# There should be just one translation, but who knows...
|
162
|
+
translation['translations'].find { |result| result['to'] == params[:to].to_s }
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
metadata
CHANGED
@@ -1,119 +1,23 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bing_translator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 6.0.0.beta.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ricky Elrod
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-03-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: nokogiri
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 1.6.0
|
20
|
-
- - "<"
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: 1.9.0
|
23
|
-
type: :runtime
|
24
|
-
prerelease: false
|
25
|
-
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
requirements:
|
27
|
-
- - ">="
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: 1.6.0
|
30
|
-
- - "<"
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: 1.9.0
|
33
13
|
- !ruby/object:Gem::Dependency
|
34
14
|
name: json
|
35
|
-
requirement: !ruby/object:Gem::Requirement
|
36
|
-
requirements:
|
37
|
-
- - "~>"
|
38
|
-
- !ruby/object:Gem::Version
|
39
|
-
version: 1.8.0
|
40
|
-
type: :runtime
|
41
|
-
prerelease: false
|
42
|
-
version_requirements: !ruby/object:Gem::Requirement
|
43
|
-
requirements:
|
44
|
-
- - "~>"
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
version: 1.8.0
|
47
|
-
- !ruby/object:Gem::Dependency
|
48
|
-
name: savon
|
49
|
-
requirement: !ruby/object:Gem::Requirement
|
50
|
-
requirements:
|
51
|
-
- - "~>"
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: 2.10.0
|
54
|
-
type: :runtime
|
55
|
-
prerelease: false
|
56
|
-
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
requirements:
|
58
|
-
- - "~>"
|
59
|
-
- !ruby/object:Gem::Version
|
60
|
-
version: 2.10.0
|
61
|
-
- !ruby/object:Gem::Dependency
|
62
|
-
name: rake
|
63
|
-
requirement: !ruby/object:Gem::Requirement
|
64
|
-
requirements:
|
65
|
-
- - "~>"
|
66
|
-
- !ruby/object:Gem::Version
|
67
|
-
version: '10.0'
|
68
|
-
type: :development
|
69
|
-
prerelease: false
|
70
|
-
version_requirements: !ruby/object:Gem::Requirement
|
71
|
-
requirements:
|
72
|
-
- - "~>"
|
73
|
-
- !ruby/object:Gem::Version
|
74
|
-
version: '10.0'
|
75
|
-
- !ruby/object:Gem::Dependency
|
76
|
-
name: rspec
|
77
|
-
requirement: !ruby/object:Gem::Requirement
|
78
|
-
requirements:
|
79
|
-
- - "~>"
|
80
|
-
- !ruby/object:Gem::Version
|
81
|
-
version: '3.0'
|
82
|
-
type: :development
|
83
|
-
prerelease: false
|
84
|
-
version_requirements: !ruby/object:Gem::Requirement
|
85
|
-
requirements:
|
86
|
-
- - "~>"
|
87
|
-
- !ruby/object:Gem::Version
|
88
|
-
version: '3.0'
|
89
|
-
- !ruby/object:Gem::Dependency
|
90
|
-
name: rspec-html-matchers
|
91
|
-
requirement: !ruby/object:Gem::Requirement
|
92
|
-
requirements:
|
93
|
-
- - ">="
|
94
|
-
- !ruby/object:Gem::Version
|
95
|
-
version: 0.9.1
|
96
|
-
- - "<"
|
97
|
-
- !ruby/object:Gem::Version
|
98
|
-
version: 0.10.0
|
99
|
-
type: :development
|
100
|
-
prerelease: false
|
101
|
-
version_requirements: !ruby/object:Gem::Requirement
|
102
|
-
requirements:
|
103
|
-
- - ">="
|
104
|
-
- !ruby/object:Gem::Version
|
105
|
-
version: 0.9.1
|
106
|
-
- - "<"
|
107
|
-
- !ruby/object:Gem::Version
|
108
|
-
version: 0.10.0
|
109
|
-
- !ruby/object:Gem::Dependency
|
110
|
-
name: dotenv
|
111
15
|
requirement: !ruby/object:Gem::Requirement
|
112
16
|
requirements:
|
113
17
|
- - ">="
|
114
18
|
- !ruby/object:Gem::Version
|
115
19
|
version: '0'
|
116
|
-
type: :
|
20
|
+
type: :runtime
|
117
21
|
prerelease: false
|
118
22
|
version_requirements: !ruby/object:Gem::Requirement
|
119
23
|
requirements:
|
@@ -143,13 +47,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
143
47
|
version: '0'
|
144
48
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
49
|
requirements:
|
146
|
-
- - "
|
50
|
+
- - ">"
|
147
51
|
- !ruby/object:Gem::Version
|
148
|
-
version:
|
52
|
+
version: 1.3.1
|
149
53
|
requirements: []
|
150
54
|
rubyforge_project:
|
151
|
-
rubygems_version: 2.
|
55
|
+
rubygems_version: 2.4.5.1
|
152
56
|
signing_key:
|
153
57
|
specification_version: 4
|
154
58
|
summary: Translate using the Bing HTTP API
|
155
59
|
test_files: []
|
60
|
+
has_rdoc:
|