deepl-rb 2.5.3 → 3.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/add_issues_to_kanban.yml +16 -0
- data/.gitlab-ci.yml +135 -0
- data/.rubocop.yml +27 -0
- data/CHANGELOG.md +39 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/CONTRIBUTING.md +37 -0
- data/Gemfile +3 -1
- data/LICENSE.md +1 -0
- data/README.md +115 -5
- data/Rakefile +7 -5
- data/SECURITY.md +58 -0
- data/VERSION +1 -1
- data/deepl-rb.gemspec +36 -20
- data/lib/deepl/api.rb +11 -1
- data/lib/deepl/configuration.rb +34 -3
- data/lib/deepl/document_api.rb +121 -0
- data/lib/deepl/exceptions/authorization_failed.rb +3 -0
- data/lib/deepl/exceptions/bad_request.rb +3 -0
- data/lib/deepl/exceptions/document_translation_error.rb +15 -0
- data/lib/deepl/exceptions/error.rb +6 -0
- data/lib/deepl/exceptions/limit_exceeded.rb +7 -0
- data/lib/deepl/exceptions/not_found.rb +3 -0
- data/lib/deepl/exceptions/not_supported.rb +3 -0
- data/lib/deepl/exceptions/quota_exceeded.rb +3 -0
- data/lib/deepl/exceptions/request_entity_too_large.rb +3 -0
- data/lib/deepl/exceptions/request_error.rb +4 -2
- data/lib/deepl/exceptions/server_error.rb +18 -0
- data/lib/deepl/glossary_api.rb +3 -0
- data/lib/deepl/requests/base.rb +89 -34
- data/lib/deepl/requests/document/download.rb +44 -0
- data/lib/deepl/requests/document/get_status.rb +44 -0
- data/lib/deepl/requests/document/upload.rb +64 -0
- data/lib/deepl/requests/glossary/create.rb +15 -1
- data/lib/deepl/requests/glossary/destroy.rb +8 -1
- data/lib/deepl/requests/glossary/entries.rb +8 -1
- data/lib/deepl/requests/glossary/find.rb +8 -1
- data/lib/deepl/requests/glossary/language_pairs.rb +9 -2
- data/lib/deepl/requests/glossary/list.rb +9 -2
- data/lib/deepl/requests/languages.rb +9 -2
- data/lib/deepl/requests/translate.rb +33 -11
- data/lib/deepl/requests/usage.rb +9 -2
- data/lib/deepl/resources/base.rb +3 -0
- data/lib/deepl/resources/document_handle.rb +57 -0
- data/lib/deepl/resources/document_translation_status.rb +54 -0
- data/lib/deepl/resources/glossary.rb +3 -0
- data/lib/deepl/resources/language.rb +3 -0
- data/lib/deepl/resources/language_pair.rb +3 -0
- data/lib/deepl/resources/text.rb +3 -0
- data/lib/deepl/resources/usage.rb +3 -0
- data/lib/deepl/utils/backoff_timer.rb +46 -0
- data/lib/deepl/utils/exception_builder.rb +18 -13
- data/lib/deepl.rb +47 -0
- data/lib/http_client_options.rb +22 -0
- data/license_checker.sh +8 -0
- data/spec/api/api_spec.rb +8 -4
- data/spec/api/configuration_spec.rb +92 -18
- data/spec/api/deepl_spec.rb +225 -86
- data/spec/fixtures/vcr_cassettes/deepl_document.yml +95 -0
- data/spec/fixtures/vcr_cassettes/deepl_document_download.yml +1214 -0
- data/spec/fixtures/vcr_cassettes/deepl_glossaries.yml +812 -23
- data/spec/fixtures/vcr_cassettes/deepl_languages.yml +28 -17
- data/spec/fixtures/vcr_cassettes/deepl_translate.yml +161 -53
- data/spec/fixtures/vcr_cassettes/deepl_usage.yml +93 -3
- data/spec/fixtures/vcr_cassettes/glossaries.yml +1237 -15
- data/spec/fixtures/vcr_cassettes/languages.yml +159 -44
- data/spec/fixtures/vcr_cassettes/translate_texts.yml +9742 -12
- data/spec/fixtures/vcr_cassettes/usage.yml +134 -2
- data/spec/integration_tests/document_api_spec.rb +155 -0
- data/spec/integration_tests/integration_test_utils.rb +170 -0
- data/spec/requests/glossary/create_spec.rb +23 -13
- data/spec/requests/glossary/destroy_spec.rb +33 -17
- data/spec/requests/glossary/entries_spec.rb +31 -17
- data/spec/requests/glossary/find_spec.rb +31 -17
- data/spec/requests/glossary/language_pairs_spec.rb +17 -7
- data/spec/requests/glossary/list_spec.rb +21 -11
- data/spec/requests/languages_spec.rb +31 -21
- data/spec/requests/translate_spec.rb +125 -131
- data/spec/requests/usage_spec.rb +17 -7
- data/spec/resources/glossary_spec.rb +15 -12
- data/spec/resources/language_pair_spec.rb +10 -7
- data/spec/resources/language_spec.rb +21 -18
- data/spec/resources/text_spec.rb +10 -7
- data/spec/resources/usage_spec.rb +16 -13
- data/spec/spec_helper.rb +63 -6
- metadata +32 -9
data/lib/deepl/requests/base.rb
CHANGED
@@ -1,19 +1,29 @@
|
|
1
|
+
# Copyright 2018 Daniel Herzog
|
2
|
+
# Use of this source code is governed by an MIT
|
3
|
+
# license that can be found in the LICENSE.md file.
|
1
4
|
# frozen_string_literal: true
|
2
5
|
|
3
6
|
module DeepL
|
4
7
|
module Requests
|
5
|
-
class Base
|
8
|
+
class Base # rubocop:disable Metrics/ClassLength
|
6
9
|
attr_reader :api, :response, :options
|
7
10
|
|
8
|
-
def initialize(api, options = {})
|
11
|
+
def initialize(api, options = {}, additional_headers = {})
|
9
12
|
@api = api
|
10
13
|
@options = options
|
14
|
+
@additional_headers = additional_headers
|
15
|
+
@num_retries = 0
|
16
|
+
@backoff_timer = Utils::BackoffTimer.new
|
11
17
|
end
|
12
18
|
|
13
19
|
def request
|
14
20
|
raise NotImplementedError
|
15
21
|
end
|
16
22
|
|
23
|
+
def details
|
24
|
+
"HTTP Headers #{headers}"
|
25
|
+
end
|
26
|
+
|
17
27
|
private
|
18
28
|
|
19
29
|
def option?(name)
|
@@ -36,43 +46,81 @@ module DeepL
|
|
36
46
|
end
|
37
47
|
end
|
38
48
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
49
|
+
# Files to reset: list of file objects to rewind when retrying the request
|
50
|
+
def execute_request_with_retries(req, files_to_reset = []) # rubocop:disable all
|
51
|
+
api.configuration.logger&.info("Request to the DeepL API: #{self}")
|
52
|
+
api.configuration.logger&.debug("Request details: #{details}")
|
53
|
+
loop do
|
54
|
+
resp = api.http_client.request(req)
|
55
|
+
validate_response!(resp)
|
56
|
+
return [req, resp]
|
57
|
+
rescue DeepL::Exceptions::Error => e
|
58
|
+
raise e unless should_retry?(resp, e, @backoff_timer.num_retries)
|
59
|
+
|
60
|
+
unless e.nil?
|
61
|
+
api.configuration.logger&.info("Encountered a retryable exception: #{e.message}")
|
62
|
+
end
|
63
|
+
api.configuration.logger&.info("Starting retry #{@backoff_timer.num_retries + 1} for " \
|
64
|
+
"request #{request} after sleeping for " \
|
65
|
+
"#{format('%.2f', @backoff_timer.time_until_deadline)}")
|
66
|
+
files_to_reset.each(&:rewind)
|
67
|
+
@backoff_timer.sleep_until_deadline
|
68
|
+
next
|
69
|
+
rescue Net::HTTPBadResponse, Net::HTTPServerError, Net::HTTPFatalError, Timeout::Error,
|
70
|
+
SocketError => e
|
71
|
+
unless e.nil?
|
72
|
+
api.configuration.logger&.info("Encountered a retryable exception: #{e.message}")
|
73
|
+
end
|
74
|
+
api.configuration.logger&.info("Starting retry #{@backoff_timer.num_retries + 1} for " \
|
75
|
+
"request #{request} after sleeping for " \
|
76
|
+
"#{format('%.2f', @backoff_timer.time_until_deadline)}")
|
77
|
+
files_to_reset.each(&:rewind)
|
78
|
+
@backoff_timer.sleep_until_deadline
|
79
|
+
next
|
80
|
+
end
|
46
81
|
end
|
47
82
|
|
48
|
-
def
|
49
|
-
|
50
|
-
|
83
|
+
def should_retry?(response, exception, num_retries)
|
84
|
+
return false if num_retries >= api.configuration.max_network_retries
|
85
|
+
return exception.should_retry? if response.nil?
|
51
86
|
|
52
|
-
|
53
|
-
[request, response]
|
87
|
+
response.is_a?(Net::HTTPTooManyRequests) || response.is_a?(Net::HTTPInternalServerError)
|
54
88
|
end
|
55
89
|
|
56
|
-
def
|
57
|
-
|
58
|
-
|
90
|
+
def post_request(payload)
|
91
|
+
http_headers = add_json_content_type(headers)
|
92
|
+
post_req = Net::HTTP::Post.new(uri.path, http_headers)
|
93
|
+
post_req.body = payload.merge(options).to_json
|
94
|
+
post_req
|
95
|
+
end
|
59
96
|
|
60
|
-
|
61
|
-
|
97
|
+
def post_request_with_file(form_data)
|
98
|
+
http_headers = add_multipart_form_content_type(headers)
|
99
|
+
post_req = Net::HTTP::Post.new(uri.request_uri, http_headers)
|
100
|
+
# options are passed in `form_data`
|
101
|
+
form_data += options.map { |key, value| [key.to_s, value.to_s] }
|
102
|
+
post_req.set_form(form_data, 'multipart/form-data')
|
103
|
+
post_req
|
62
104
|
end
|
63
105
|
|
64
|
-
def
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
end
|
106
|
+
def get_request # rubocop:disable Naming/AccessorMethodName
|
107
|
+
http_headers = add_json_content_type(headers)
|
108
|
+
get_req = Net::HTTP::Get.new(uri.path, http_headers)
|
109
|
+
get_req.body = options.to_json
|
110
|
+
get_req
|
70
111
|
end
|
71
112
|
|
72
|
-
def
|
113
|
+
def delete_request
|
114
|
+
http_headers = add_json_content_type(headers)
|
115
|
+
del_req = Net::HTTP::Delete.new(uri.path, http_headers)
|
116
|
+
del_req.body = options.to_json
|
117
|
+
del_req
|
118
|
+
end
|
119
|
+
|
120
|
+
def validate_response!(response)
|
73
121
|
return if response.is_a?(Net::HTTPSuccess)
|
74
122
|
|
75
|
-
raise Utils::ExceptionBuilder.new(
|
123
|
+
raise Utils::ExceptionBuilder.new(response).build
|
76
124
|
end
|
77
125
|
|
78
126
|
def path
|
@@ -84,12 +132,8 @@ module DeepL
|
|
84
132
|
end
|
85
133
|
|
86
134
|
def uri
|
87
|
-
@uri ||=
|
88
|
-
|
89
|
-
new_query = URI.decode_www_form(uri.query || '') + query_params.to_a
|
90
|
-
uri.query = URI.encode_www_form(new_query)
|
91
|
-
uri
|
92
|
-
end
|
135
|
+
@uri ||= URI(url)
|
136
|
+
@uri
|
93
137
|
end
|
94
138
|
|
95
139
|
def host
|
@@ -101,7 +145,18 @@ module DeepL
|
|
101
145
|
end
|
102
146
|
|
103
147
|
def headers
|
104
|
-
{ 'Authorization' => "DeepL-Auth-Key #{api.configuration.auth_key}"
|
148
|
+
{ 'Authorization' => "DeepL-Auth-Key #{api.configuration.auth_key}",
|
149
|
+
'User-Agent' => api.configuration.user_agent }.merge(@additional_headers)
|
150
|
+
end
|
151
|
+
|
152
|
+
def add_json_content_type(headers_to_add_to)
|
153
|
+
headers_to_add_to['Content-Type'] = 'application/json'
|
154
|
+
headers_to_add_to
|
155
|
+
end
|
156
|
+
|
157
|
+
def add_multipart_form_content_type(headers_to_add_to)
|
158
|
+
headers_to_add_to['Content-Type'] = 'multipart/form-data'
|
159
|
+
headers_to_add_to
|
105
160
|
end
|
106
161
|
end
|
107
162
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Copyright 2024 DeepL SE (https://www.deepl.com)
|
2
|
+
# Use of this source code is governed by an MIT
|
3
|
+
# license that can be found in the LICENSE file.
|
4
|
+
# frozen_string_literal: true
|
5
|
+
|
6
|
+
module DeepL
|
7
|
+
module Requests
|
8
|
+
module Document
|
9
|
+
class Download < Base
|
10
|
+
attr_reader :document_id, :document_key
|
11
|
+
|
12
|
+
def initialize(api, document_id, document_key, output_file)
|
13
|
+
super(api, {})
|
14
|
+
@document_id = document_id
|
15
|
+
@document_key = document_key
|
16
|
+
@output_file = output_file
|
17
|
+
end
|
18
|
+
|
19
|
+
def request
|
20
|
+
payload = { document_key: document_key }
|
21
|
+
extract_file(*execute_request_with_retries(post_request(payload)))
|
22
|
+
end
|
23
|
+
|
24
|
+
def details
|
25
|
+
"HTTP Headers: #{headers}\nPayload #{{ document_key: document_key }}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_s
|
29
|
+
"POST #{uri.request_uri}"
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def extract_file(_request, response)
|
35
|
+
File.write(@output_file, response.body)
|
36
|
+
end
|
37
|
+
|
38
|
+
def path
|
39
|
+
"document/#{document_id}/result"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Copyright 2024 DeepL SE (https://www.deepl.com)
|
2
|
+
# Use of this source code is governed by an MIT
|
3
|
+
# license that can be found in the LICENSE file.
|
4
|
+
# frozen_string_literal: true
|
5
|
+
|
6
|
+
module DeepL
|
7
|
+
module Requests
|
8
|
+
module Document
|
9
|
+
class GetStatus < Base
|
10
|
+
attr_reader :document_id, :document_key
|
11
|
+
|
12
|
+
def initialize(api, document_id, document_key, options = {}, additional_headers = {})
|
13
|
+
super(api, options, additional_headers)
|
14
|
+
@document_id = document_id
|
15
|
+
@document_key = document_key
|
16
|
+
end
|
17
|
+
|
18
|
+
def request
|
19
|
+
payload = { document_key: document_key }
|
20
|
+
build_doc_translation_status(*execute_request_with_retries(post_request(payload)))
|
21
|
+
end
|
22
|
+
|
23
|
+
def details
|
24
|
+
"HTTP Headers: #{headers}\nPayload #{{ document_key: document_key }}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_s
|
28
|
+
"POST #{uri.request_uri}"
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def build_doc_translation_status(request, response)
|
34
|
+
document_translation_status = JSON.parse(response.body)
|
35
|
+
Resources::DocumentTranslationStatus.new(document_translation_status, request, response)
|
36
|
+
end
|
37
|
+
|
38
|
+
def path
|
39
|
+
"document/#{document_id}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# Copyright 2024 DeepL SE (https://www.deepl.com)
|
2
|
+
# Use of this source code is governed by an MIT
|
3
|
+
# license that can be found in the LICENSE file.
|
4
|
+
# frozen_string_literal: true
|
5
|
+
|
6
|
+
module DeepL
|
7
|
+
module Requests
|
8
|
+
module Document
|
9
|
+
class Upload < Base
|
10
|
+
attr_reader :input_file_path, :source_lang, :target_lang, :filename
|
11
|
+
|
12
|
+
SUPPORTED_OPTIONS = %w[formality glossary_id output_format].freeze
|
13
|
+
|
14
|
+
def initialize(api, input_file_path, source_lang, target_lang, filename = nil, # rubocop:disable Metrics/ParameterLists
|
15
|
+
options = {}, additional_headers = {})
|
16
|
+
super(api, options, additional_headers)
|
17
|
+
@input_file_path = input_file_path
|
18
|
+
@source_lang = source_lang
|
19
|
+
@target_lang = target_lang
|
20
|
+
@filename = filename
|
21
|
+
end
|
22
|
+
|
23
|
+
def request # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
24
|
+
input_file = File.open(input_file_path, 'rb')
|
25
|
+
form_data = [
|
26
|
+
['file', input_file], ['source_lang', source_lang],
|
27
|
+
['target_lang', target_lang]
|
28
|
+
]
|
29
|
+
filename_param = filename || File.basename(input_file_path)
|
30
|
+
form_data.push(['filename', filename_param]) unless filename_param.nil?
|
31
|
+
# Manually add options due to multipart/form-data request
|
32
|
+
SUPPORTED_OPTIONS.each do |option|
|
33
|
+
form_data.push([option, options[option]]) unless options[option].nil?
|
34
|
+
end
|
35
|
+
build_doc_handle(*execute_request_with_retries(post_request_with_file(form_data),
|
36
|
+
[input_file]))
|
37
|
+
end
|
38
|
+
|
39
|
+
def details
|
40
|
+
"HTTP Headers: #{headers}\nPayload #{[
|
41
|
+
['file', "File at #{input_file_path} opened in binary mode"],
|
42
|
+
['source_lang', source_lang], ['target_lang', target_lang], ['filename', filename]
|
43
|
+
]}"
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_s
|
47
|
+
"POST #{uri.request_uri}"
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def build_doc_handle(request, response)
|
53
|
+
parsed_response = JSON.parse(response.body)
|
54
|
+
Resources::DocumentHandle.new(parsed_response['document_id'],
|
55
|
+
parsed_response['document_key'], request, response)
|
56
|
+
end
|
57
|
+
|
58
|
+
def path
|
59
|
+
'document'
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -1,3 +1,6 @@
|
|
1
|
+
# Copyright 2022 Daniel Herzog
|
2
|
+
# Use of this source code is governed by an MIT
|
3
|
+
# license that can be found in the LICENSE.md file.
|
1
4
|
# frozen_string_literal: true
|
2
5
|
|
3
6
|
module DeepL
|
@@ -20,7 +23,18 @@ module DeepL
|
|
20
23
|
name: name, source_lang: source_lang, target_lang: target_lang, entries: entries_to_tsv,
|
21
24
|
entries_format: entries_format
|
22
25
|
}
|
23
|
-
build_glossary(*
|
26
|
+
build_glossary(*execute_request_with_retries(post_request(payload)))
|
27
|
+
end
|
28
|
+
|
29
|
+
def details
|
30
|
+
"HTTP Headers: #{headers}\nPayload #{{
|
31
|
+
name: name, source_lang: source_lang, target_lang: target_lang, entries: entries_to_tsv,
|
32
|
+
entries_format: entries_format
|
33
|
+
}}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_s
|
37
|
+
"POST #{uri.request_uri}"
|
24
38
|
end
|
25
39
|
|
26
40
|
private
|
@@ -1,3 +1,6 @@
|
|
1
|
+
# Copyright 2022 Daniel Herzog
|
2
|
+
# Use of this source code is governed by an MIT
|
3
|
+
# license that can be found in the LICENSE.md file.
|
1
4
|
# frozen_string_literal: true
|
2
5
|
|
3
6
|
module DeepL
|
@@ -12,7 +15,11 @@ module DeepL
|
|
12
15
|
end
|
13
16
|
|
14
17
|
def request
|
15
|
-
build_response(*
|
18
|
+
build_response(*execute_request_with_retries(delete_request))
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
"DELETE #{uri.request_uri}"
|
16
23
|
end
|
17
24
|
|
18
25
|
private
|
@@ -1,3 +1,6 @@
|
|
1
|
+
# Copyright 2022 Daniel Herzog
|
2
|
+
# Use of this source code is governed by an MIT
|
3
|
+
# license that can be found in the LICENSE.md file.
|
1
4
|
# frozen_string_literal: true
|
2
5
|
|
3
6
|
module DeepL
|
@@ -12,7 +15,11 @@ module DeepL
|
|
12
15
|
end
|
13
16
|
|
14
17
|
def request
|
15
|
-
build_entries(*
|
18
|
+
build_entries(*execute_request_with_retries(get_request))
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
"GET #{uri.request_uri}"
|
16
23
|
end
|
17
24
|
|
18
25
|
private
|
@@ -1,3 +1,6 @@
|
|
1
|
+
# Copyright 2022 Daniel Herzog
|
2
|
+
# Use of this source code is governed by an MIT
|
3
|
+
# license that can be found in the LICENSE.md file.
|
1
4
|
# frozen_string_literal: true
|
2
5
|
|
3
6
|
module DeepL
|
@@ -12,7 +15,11 @@ module DeepL
|
|
12
15
|
end
|
13
16
|
|
14
17
|
def request
|
15
|
-
build_glossary(*
|
18
|
+
build_glossary(*execute_request_with_retries(get_request))
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
"GET #{uri.request_uri}"
|
16
23
|
end
|
17
24
|
|
18
25
|
private
|
@@ -1,3 +1,6 @@
|
|
1
|
+
# Copyright 2022 Daniel Herzog
|
2
|
+
# Use of this source code is governed by an MIT
|
3
|
+
# license that can be found in the LICENSE.md file.
|
1
4
|
# frozen_string_literal: true
|
2
5
|
|
3
6
|
module DeepL
|
@@ -5,11 +8,15 @@ module DeepL
|
|
5
8
|
module Glossary
|
6
9
|
class LanguagePairs < Base
|
7
10
|
def initialize(api, options = {})
|
8
|
-
super
|
11
|
+
super
|
9
12
|
end
|
10
13
|
|
11
14
|
def request
|
12
|
-
build_language_pair_list(*
|
15
|
+
build_language_pair_list(*execute_request_with_retries(get_request))
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
"GET #{uri.request_uri}"
|
13
20
|
end
|
14
21
|
|
15
22
|
private
|
@@ -1,3 +1,6 @@
|
|
1
|
+
# Copyright 2022 Daniel Herzog
|
2
|
+
# Use of this source code is governed by an MIT
|
3
|
+
# license that can be found in the LICENSE.md file.
|
1
4
|
# frozen_string_literal: true
|
2
5
|
|
3
6
|
module DeepL
|
@@ -5,11 +8,15 @@ module DeepL
|
|
5
8
|
module Glossary
|
6
9
|
class List < Base
|
7
10
|
def initialize(api, options = {})
|
8
|
-
super
|
11
|
+
super
|
9
12
|
end
|
10
13
|
|
11
14
|
def request
|
12
|
-
build_glossary_list(*
|
15
|
+
build_glossary_list(*execute_request_with_retries(get_request))
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
"GET #{uri.request_uri}"
|
13
20
|
end
|
14
21
|
|
15
22
|
private
|
@@ -1,14 +1,21 @@
|
|
1
|
+
# Copyright 2021 Daniel Herzog
|
2
|
+
# Use of this source code is governed by an MIT
|
3
|
+
# license that can be found in the LICENSE.md file.
|
1
4
|
# frozen_string_literal: true
|
2
5
|
|
3
6
|
module DeepL
|
4
7
|
module Requests
|
5
8
|
class Languages < Base
|
6
9
|
def initialize(api, options = {})
|
7
|
-
super
|
10
|
+
super
|
8
11
|
end
|
9
12
|
|
10
13
|
def request
|
11
|
-
build_languages(*
|
14
|
+
build_languages(*execute_request_with_retries(get_request))
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_s
|
18
|
+
"GET #{uri.request_uri}"
|
12
19
|
end
|
13
20
|
|
14
21
|
private
|
@@ -1,17 +1,29 @@
|
|
1
|
+
# Copyright 2018 Daniel Herzog
|
2
|
+
# Use of this source code is governed by an MIT
|
3
|
+
# license that can be found in the LICENSE.md file.
|
1
4
|
# frozen_string_literal: true
|
2
5
|
|
3
6
|
module DeepL
|
4
7
|
module Requests
|
5
8
|
class Translate < Base
|
6
|
-
|
7
|
-
|
9
|
+
STRING_TO_BOOLEAN_MAP = { '1' => true, '0' => false }.freeze
|
10
|
+
BOOLEAN_TO_STRING_MAP = { true => '1', false => '0' }.freeze
|
11
|
+
STRING_TO_BOOLEAN_CONVERSION = ->(value) { STRING_TO_BOOLEAN_MAP[value] }
|
12
|
+
BOOLEAN_TO_STRING_CONVERSION = ->(value) { BOOLEAN_TO_STRING_MAP[value] }
|
13
|
+
STRING_TO_ARRAY_CONVERSION = lambda { |value|
|
14
|
+
if value.nil?
|
15
|
+
nil
|
16
|
+
else
|
17
|
+
(value.is_a?(Array) ? value : value.split(','))
|
18
|
+
end
|
19
|
+
}.freeze
|
8
20
|
OPTIONS_CONVERSIONS = {
|
9
|
-
split_sentences:
|
10
|
-
preserve_formatting:
|
11
|
-
outline_detection:
|
12
|
-
splitting_tags:
|
13
|
-
non_splitting_tags:
|
14
|
-
ignore_tags:
|
21
|
+
split_sentences: BOOLEAN_TO_STRING_CONVERSION,
|
22
|
+
preserve_formatting: STRING_TO_BOOLEAN_CONVERSION,
|
23
|
+
outline_detection: STRING_TO_BOOLEAN_CONVERSION,
|
24
|
+
splitting_tags: STRING_TO_ARRAY_CONVERSION,
|
25
|
+
non_splitting_tags: STRING_TO_ARRAY_CONVERSION,
|
26
|
+
ignore_tags: STRING_TO_ARRAY_CONVERSION
|
15
27
|
}.freeze
|
16
28
|
|
17
29
|
attr_reader :text, :source_lang, :target_lang, :ignore_tags, :splitting_tags,
|
@@ -27,15 +39,25 @@ module DeepL
|
|
27
39
|
end
|
28
40
|
|
29
41
|
def request
|
30
|
-
|
31
|
-
|
42
|
+
text_arrayified = text.is_a?(Array) ? text : [text]
|
43
|
+
payload = { text: text_arrayified, source_lang: source_lang, target_lang: target_lang }
|
44
|
+
build_texts(*execute_request_with_retries(post_request(payload)))
|
45
|
+
end
|
46
|
+
|
47
|
+
def details
|
48
|
+
"HTTP Headers: #{headers}\nPayload #{{ text: text, source_lang: source_lang,
|
49
|
+
target_lang: target_lang }}"
|
50
|
+
end
|
51
|
+
|
52
|
+
def to_s
|
53
|
+
"POST #{uri.request_uri}"
|
32
54
|
end
|
33
55
|
|
34
56
|
private
|
35
57
|
|
36
58
|
def tweak_parameters!
|
37
59
|
OPTIONS_CONVERSIONS.each do |param, converter|
|
38
|
-
next unless option?(param) && converter[option(param)]
|
60
|
+
next unless option?(param) && !converter[option(param)].nil?
|
39
61
|
|
40
62
|
set_option(param, converter[option(param)])
|
41
63
|
end
|
data/lib/deepl/requests/usage.rb
CHANGED
@@ -1,14 +1,21 @@
|
|
1
|
+
# Copyright 2018 Daniel Herzog
|
2
|
+
# Use of this source code is governed by an MIT
|
3
|
+
# license that can be found in the LICENSE.md file.
|
1
4
|
# frozen_string_literal: true
|
2
5
|
|
3
6
|
module DeepL
|
4
7
|
module Requests
|
5
8
|
class Usage < Base
|
6
9
|
def initialize(api, options = {})
|
7
|
-
super
|
10
|
+
super
|
8
11
|
end
|
9
12
|
|
10
13
|
def request
|
11
|
-
build_usage(*
|
14
|
+
build_usage(*execute_request_with_retries(get_request))
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_s
|
18
|
+
"GET #{uri.request_uri}"
|
12
19
|
end
|
13
20
|
|
14
21
|
private
|
data/lib/deepl/resources/base.rb
CHANGED
@@ -0,0 +1,57 @@
|
|
1
|
+
# Copyright 2024 DeepL SE (https://www.deepl.com)
|
2
|
+
# Use of this source code is governed by an MIT
|
3
|
+
# license that can be found in the LICENSE file.
|
4
|
+
# frozen_string_literal: true
|
5
|
+
|
6
|
+
module DeepL
|
7
|
+
module Resources
|
8
|
+
class DocumentHandle < Base
|
9
|
+
attr_reader :document_id, :document_key
|
10
|
+
|
11
|
+
def initialize(document_id, document_key, *args)
|
12
|
+
super(*args)
|
13
|
+
|
14
|
+
@document_id = document_id
|
15
|
+
@document_key = document_key
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
"DocumentHandle: ID: #{document_id} - Key: #{document_key}"
|
20
|
+
end
|
21
|
+
|
22
|
+
##
|
23
|
+
# For this DocumentHandle, waits until the document translation is finished and returns the
|
24
|
+
# final status of the document.
|
25
|
+
#
|
26
|
+
# @return [DeepL::Resources::DocumentTranslationStatus] Final status of the document
|
27
|
+
# translation.
|
28
|
+
|
29
|
+
def wait_until_document_translation_finished
|
30
|
+
doc_status = nil
|
31
|
+
max_tries = max_doc_status_queries
|
32
|
+
num_tries = 0
|
33
|
+
loop do
|
34
|
+
num_tries += 1
|
35
|
+
sleep(calculate_waiting_time(doc_status)) unless doc_status.nil?
|
36
|
+
doc_status = DeepL.document.get_status(self)
|
37
|
+
break if doc_status.finished? || num_tries > max_tries
|
38
|
+
end
|
39
|
+
doc_status
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def calculate_waiting_time(_resp)
|
45
|
+
# ignore _resp.seconds_remaining for now, while it is unreliable
|
46
|
+
5
|
47
|
+
end
|
48
|
+
|
49
|
+
def max_doc_status_queries
|
50
|
+
configured_value = DeepL.configuration.max_doc_status_queries
|
51
|
+
return configured_value unless configured_value.nil?
|
52
|
+
|
53
|
+
10
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|