deepl-rb 3.2.0 → 3.3.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 47bf797967929a4b7775e21ce7021cdc1871283b3358cbb36d13a8f6f6b5ac6b
4
- data.tar.gz: df4399cc6c552fb5c03b79b0566d2370101b58246bfd5e0b05d27c83e994ae6c
3
+ metadata.gz: ce04c17b4585b9813713f61db8fe35e3a61b777c48ec22011f81b7febe106527
4
+ data.tar.gz: 3c4432516a14b2fb0e8886f2ff3e6d31c5ba5c88590d4e28a9631fc0a233f724
5
5
  SHA512:
6
- metadata.gz: 4639c87e107dfa0a13b1bace938e9a3580fb15bb1e2f280267527e3d5d0c9b8913752b841bd095039f1e4f7d15b13813075131c0767216855bf5e7d28a4b81a1
7
- data.tar.gz: 19743f57e84c550e5fe35b1d6c39f853df1d0d1d357eb8c0f061a0202831af8a557651f34f50dcad10928b45638a3a09b9ab64652fdadab6d6ad62ec3f2a1242
6
+ metadata.gz: 8a736f2b2cc257c26cd47e67bdbdcbc89afbb6de444176f0dab5b0a470fe2c713e3c32396391a05c007ddfbfbbc80953b0f6c6afb1fdf9b138c0eca97ae02a52
7
+ data.tar.gz: 1828bdede7c38bec246302645e39ec7f01950096f3c52fb1b119766bbdf11b6c2b6d3ab881ebdf2875f736ab8f47778e87abcb5f107ca2ef6f4848c66d11d680
data/.gitlab-ci.yml CHANGED
@@ -1,5 +1,6 @@
1
1
  # Note: This GitLab CI configuration is used for internal testing, users can ignore it.
2
2
  include:
3
+ - template: Security/SAST.gitlab-ci.yml
3
4
  - project: '${CI_PROJECT_NAMESPACE}/ci-libs-for-client-libraries'
4
5
  file:
5
6
  - '/${CI_PROJECT_NAME}/.gitlab-ci.yml'
@@ -7,6 +8,7 @@ include:
7
8
  file:
8
9
  - '/templates/.buildkit.yml'
9
10
  - '/templates/.secret-detection.yml'
11
+ - '/templates/.gitlab-release.yml'
10
12
 
11
13
  # Global --------------------------
12
14
 
@@ -16,11 +18,14 @@ workflow:
16
18
  - if: $CI_COMMIT_TAG
17
19
  - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
18
20
 
21
+ variables:
22
+ GITLAB_ADVANCED_SAST_ENABLED: 'true'
23
+
19
24
  stages:
20
25
  - install
21
26
  - check
22
27
  - test
23
- # - publish
28
+ - publish # Only for internal tracking
24
29
 
25
30
 
26
31
  before_script:
@@ -82,6 +87,29 @@ license_check:
82
87
  - ./license_checker.sh '*.rb' | tee license_check_output.txt
83
88
  - '[ ! -s license_check_output.txt ]'
84
89
 
90
+ gitlab-advanced-sast:
91
+ stage: check
92
+ before_script:
93
+ - ''
94
+ rules:
95
+ - when: always
96
+ variables:
97
+ SAST_EXCLUDED_PATHS: '$DEFAULT_SAST_EXCLUDED_PATHS,/spec'
98
+ GIT_STRATEGY: clone
99
+ KUBERNETES_HELPER_MEMORY_LIMIT: 8Gi
100
+ SAST_SCANNER_ALLOWED_CLI_OPTS: --multi-core 8
101
+
102
+ semgrep-sast:
103
+ stage: check
104
+ before_script:
105
+ - ''
106
+ rules:
107
+ - when: always
108
+ variables:
109
+ SAST_EXCLUDED_PATHS: '$DEFAULT_SAST_EXCLUDED_PATHS,/spec'
110
+ GIT_STRATEGY: clone
111
+ KUBERNETES_MEMORY_LIMIT: 8Gi
112
+
85
113
 
86
114
  # stage: test ----------------------
87
115
 
@@ -133,3 +161,12 @@ test_manual:
133
161
  extends: .test_base
134
162
  rules:
135
163
  - if: $CI_PIPELINE_SOURCE != "schedule"
164
+
165
+
166
+ # stage: publish ----------------------
167
+
168
+ gitlab release:
169
+ stage: publish
170
+ extends: .create_gitlab_release
171
+ rules:
172
+ - if: '$CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+$/'
data/CHANGELOG.md CHANGED
@@ -4,59 +4,69 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
- ## [3.2.0]
7
+ ## [Unreleased]
8
+
9
+ ## [3.3.0] - 2025-11-04
10
+ ### Added
11
+ - Added `extra_body_parameters` option to text and document translation methods to pass arbitrary parameters in the request body. This can be used to access beta features or override built-in parameters (such as `target_lang`, `source_lang`, etc.).
12
+ - Added `rephrase` functionality to the top-level `DeepL` module for convenience.
13
+ * Thanks to [341bms](https://github.com/341bms) in [#14](https://github.com/DeepLcom/deepl-rb/issues/14) for the report!
14
+
15
+ ## [3.2.0] - 2025-01-15
8
16
  ### Added
9
- * Added `rephrase` functionality to get a new version of submitted text with various possible styles or tones applied
10
- * Added `DeepL::Constants` namespace and associated constant values for options possibilities
17
+ - Added `rephrase` functionality to get a new version of submitted text with various possible styles or tones applied
18
+ - Added `DeepL::Constants` namespace and associated constant values for options possibilities
11
19
 
12
- ## [3.1.0]
20
+ ## [3.1.0] - 2024-11-15
13
21
  ### Added
14
- * Added `model_type` option to `translate()` to use models with higher
22
+ - Added `model_type` option to `translate()` to use models with higher
15
23
  translation quality (available for some language pairs), or better latency.
16
24
  Options are `'quality_optimized'`, `'latency_optimized'`, and `'prefer_quality_optimized'`
17
- * Added the `model_type_used` field to the `translate()` response, that
25
+ - Added the `model_type_used` field to the `translate()` response, that
18
26
  indicates the translation model used when the `model_type` option is
19
27
  specified.
20
28
 
21
-
22
29
  ## [3.0.2] - 2024-10-02
23
30
  ### Added
24
- * Added doc example and tests for context parameter
31
+ - Added doc example and tests for context parameter
32
+
25
33
  ### Fixed
26
- * Fix metadata displayed on RubyGems.org for this library.
27
- * Fixed library version sent in the `User-Agent` string.
34
+ - Fix metadata displayed on RubyGems.org for this library.
35
+ - Fixed library version sent in the `User-Agent` string.
28
36
 
29
37
  ## [3.0.1] - 2024-09-23
30
38
  ### Fixed
31
- * `document.translate_document` required a filename, this is now optional. The example in the README now works.
39
+ - `document.translate_document` required a filename, this is now optional. The example in the README now works.
32
40
 
33
41
  ## [3.0.0] - 2024-09-20
34
42
  Beginning with version 3, deepl-rb is officially supported by DeepL, and maintained together with [Daniel Herzog](mailto:info@danielherzog.es) the developer of earlier versions of this library.
35
43
  The change in major version is only due to the change in maintainership, there is no migration necessary from v2 to v3.
44
+
36
45
  ### Added
37
- * Added rubocop-rspec linting for rspec test files
38
- * Added document translation to the ruby CL
39
- * Added possibility to use one HTTP session for multiple calls
40
- * Added platform and ruby version information to the user-agent string that is sent with API calls, along with an opt-out
41
- * Added support for logging of HTTP requests
42
- * Added support for using a proxy and a custom certificate file
43
- * Added a gitlab CI pipeline
46
+ - Added rubocop-rspec linting for rspec test files
47
+ - Added document translation to the ruby CL
48
+ - Added possibility to use one HTTP session for multiple calls
49
+ - Added platform and ruby version information to the user-agent string that is sent with API calls, along with an opt-out
50
+ - Added support for logging of HTTP requests
51
+ - Added support for using a proxy and a custom certificate file
52
+ - Added a gitlab CI pipeline
53
+
44
54
  ### Changed
45
- * HTTP requests to the DeepL API now use `application/json`, rather than `application/www-form-unencoded`
46
- * HTTP requests now automatically retry on transient failures, using exponential backoff
47
- ### Deprecated
55
+ - HTTP requests to the DeepL API now use `application/json`, rather than `application/www-form-unencoded`
56
+ - HTTP requests now automatically retry on transient failures, using exponential backoff
57
+
48
58
  ### Removed
49
- * Removed CircleCI and CodeCov upload
50
- ### Fixed
51
- ### Security
59
+ - Removed CircleCI and CodeCov upload
52
60
 
53
61
  ## [2.5.3] - 2022-09-26
54
62
  ### Fixed
55
- * Make RequestEntityTooLarge error message more clear
63
+ - Make RequestEntityTooLarge error message more clear
56
64
 
57
- [3.2.0]: https://github.com/DeepLcom/deepl-rb/compare/v3.1.0...3.2.0
65
+ [Unreleased]: https://github.com/DeepLcom/deepl-rb/compare/v3.3.0...HEAD
66
+ [3.3.0]: https://github.com/DeepLcom/deepl-rb/compare/v3.2.0...v3.3.0
67
+ [3.2.0]: https://github.com/DeepLcom/deepl-rb/compare/v3.1.0...v3.2.0
58
68
  [3.1.0]: https://github.com/DeepLcom/deepl-rb/compare/v3.0.2...v3.1.0
59
69
  [3.0.2]: https://github.com/DeepLcom/deepl-rb/compare/v3.0.1...v3.0.2
60
70
  [3.0.1]: https://github.com/DeepLcom/deepl-rb/compare/v3.0.0...v3.0.1
61
71
  [3.0.0]: https://github.com/DeepLcom/deepl-rb/compare/v2.5.3...v3.0.0
62
- [2.5.3]: https://github.com/DeepLcom/deepl-rb/compare/v2.5.2...v2.5.3
72
+ [2.5.3]: https://github.com/DeepLcom/deepl-rb/releases/tag/v2.5.3
data/README.md CHANGED
@@ -167,6 +167,7 @@ The following parameters will be automatically converted:
167
167
  | `formality` | No conversion applied
168
168
  | `glossary_id` | No conversion applied
169
169
  | `context` | No conversion applied
170
+ | `extra_body_parameters` | Hash of extra parameters to pass in the body of the HTTP request. Can be used to access beta features, or to override built-in parameters for testing purposes. Extra parameters can override keys explicitly set by the client.
170
171
 
171
172
  ### Rephrase Text
172
173
 
@@ -322,6 +323,18 @@ doc_status = doc_handle.wait_until_document_translation_finished # alternatively
322
323
  DeepL.document.download(doc_handle, '/path/to/translated_document.pdf') unless doc_status.error?
323
324
  ```
324
325
 
326
+ You can also pass additional options to document translation methods, including `extra_body_parameters`:
327
+
328
+ ```rb
329
+ options = {
330
+ formality: 'more',
331
+ extra_body_parameters: { example_param: 'true' }
332
+ }
333
+ doc_handle = DeepL.document.upload('/path/to/spanish_document.pdf', 'ES', 'EN', nil, options)
334
+ ```
335
+
336
+ The `extra_body_parameters` option allows you to pass arbitrary parameters in the request body. This can be used to access beta features by adding new parameters, or to override built-in parameters (such as `target_lang`, `source_lang`, etc.) for testing purposes.
337
+
325
338
  ### Handle exceptions
326
339
 
327
340
  You can capture and process exceptions that may be raised during API calls. These are all the possible exceptions:
data/Rakefile CHANGED
@@ -33,6 +33,7 @@ Juwelier::Tasks.new do |gem|
33
33
  }
34
34
  gem.files.exclude '.github'
35
35
  gem.files.exclude '.circleci'
36
+ gem.files.exclude 'catalog-info.yaml'
36
37
  end
37
38
 
38
39
  Juwelier::RubygemsDotOrgTasks.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.2.0
1
+ 3.3.0
data/deepl-rb.gemspec CHANGED
@@ -2,17 +2,17 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: deepl-rb 3.2.0 ruby lib
5
+ # stub: deepl-rb 3.3.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "deepl-rb".freeze
9
- s.version = "3.2.0".freeze
9
+ s.version = "3.3.0"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
12
  s.metadata = { "bug_tracker_uri" => "https://github.com/DeepLcom/deepl-rb/issues", "changelog_uri" => "https://github.com/DeepLcom/deepl-rb/blob/main/CHANGELOG.md", "documentation_uri" => "https://github.com/DeepLcom/deepl-rb/blob/main/README.md", "homepage_uri" => "https://github.com/DeepLcom/deepl-rb" } if s.respond_to? :metadata=
13
13
  s.require_paths = ["lib".freeze]
14
14
  s.authors = ["DeepL SE".freeze]
15
- s.date = "2025-01-15"
15
+ s.date = "2025-11-04"
16
16
  s.description = "Official Ruby library for the DeepL language translation API (v2). For more information, check this: https://www.deepl.com/docs/api-reference.html".freeze
17
17
  s.email = "open-source@deepl.com".freeze
18
18
  s.extra_rdoc_files = [
@@ -93,6 +93,7 @@ Gem::Specification.new do |s|
93
93
  "spec/fixtures/vcr_cassettes/deepl_document_download.yml",
94
94
  "spec/fixtures/vcr_cassettes/deepl_glossaries.yml",
95
95
  "spec/fixtures/vcr_cassettes/deepl_languages.yml",
96
+ "spec/fixtures/vcr_cassettes/deepl_rephrase.yml",
96
97
  "spec/fixtures/vcr_cassettes/deepl_translate.yml",
97
98
  "spec/fixtures/vcr_cassettes/deepl_usage.yml",
98
99
  "spec/fixtures/vcr_cassettes/glossaries.yml",
@@ -121,12 +122,12 @@ Gem::Specification.new do |s|
121
122
  ]
122
123
  s.homepage = "https://github.com/DeepLcom/deepl-rb".freeze
123
124
  s.licenses = ["MIT".freeze]
124
- s.rubygems_version = "3.5.3".freeze
125
+ s.rubygems_version = "3.4.6".freeze
125
126
  s.summary = "Official Ruby library for the DeepL language translation API.".freeze
126
127
 
127
128
  s.specification_version = 4
128
129
 
129
- s.add_development_dependency(%q<juwelier>.freeze, [">= 0".freeze])
130
- s.add_development_dependency(%q<byebug>.freeze, [">= 0".freeze])
130
+ s.add_development_dependency(%q<juwelier>.freeze, [">= 0"])
131
+ s.add_development_dependency(%q<byebug>.freeze, [">= 0"])
131
132
  end
132
133
 
@@ -6,7 +6,7 @@
6
6
  module DeepL
7
7
  module Exceptions
8
8
  class AuthorizationFailed < RequestError
9
- def message
9
+ def to_s
10
10
  'Authorization failed. Please supply a valid auth_key parameter.'
11
11
  end
12
12
  end
@@ -6,7 +6,7 @@
6
6
  module DeepL
7
7
  module Exceptions
8
8
  class BadRequest < RequestError
9
- def message
9
+ def to_s
10
10
  JSON.parse(response.body)['message']
11
11
  rescue JSON::ParserError
12
12
  response.body
@@ -6,7 +6,7 @@
6
6
  module DeepL
7
7
  module Exceptions
8
8
  class LimitExceeded < RequestError
9
- def message
9
+ def to_s
10
10
  'Limit exceeded. Please wait and send your request once again.'
11
11
  end
12
12
 
@@ -6,7 +6,7 @@
6
6
  module DeepL
7
7
  module Exceptions
8
8
  class NotFound < RequestError
9
- def message
9
+ def to_s
10
10
  JSON.parse(response.body)['message']
11
11
  rescue JSON::ParserError
12
12
  response.body
@@ -6,7 +6,7 @@
6
6
  module DeepL
7
7
  module Exceptions
8
8
  class QuotaExceeded < RequestError
9
- def message
9
+ def to_s
10
10
  'Quota exceeded. The character limit has been reached.'
11
11
  end
12
12
  end
@@ -6,7 +6,7 @@
6
6
  module DeepL
7
7
  module Exceptions
8
8
  class RequestEntityTooLarge < RequestError
9
- def message
9
+ def to_s
10
10
  'The request size has reached the supported limit. ' \
11
11
  "Make sure that you're not sending more than 50 text parts."
12
12
  end
@@ -13,7 +13,7 @@ module DeepL
13
13
  @response = response
14
14
  end
15
15
 
16
- def message
16
+ def to_s
17
17
  'Unknown error.'
18
18
  end
19
19
  end
@@ -6,7 +6,7 @@
6
6
  module DeepL
7
7
  module Exceptions
8
8
  class ServerError < RequestError
9
- def message
9
+ def to_s
10
10
  'An internal server error occured. Try again after waiting a short period.'
11
11
  end
12
12
 
@@ -46,6 +46,40 @@ module DeepL
46
46
  end
47
47
  end
48
48
 
49
+ # Returns options excluding extra_body_parameters
50
+ # extra_body_parameters are applied separately via apply_extra_body_parameters_* methods
51
+ def options_without_extra_params
52
+ options.reject do |k, _|
53
+ k.to_s == 'extra_body_parameters' || k.to_sym == :extra_body_parameters
54
+ end
55
+ end
56
+
57
+ # Apply extra body parameters to a hash payload (for JSON/form-encoded requests)
58
+ # Extra parameters will override existing keys
59
+ def apply_extra_body_parameters_to_json(payload)
60
+ return unless option?(:extra_body_parameters)
61
+
62
+ extra_params = option(:extra_body_parameters)
63
+ extra_params.each do |key, value|
64
+ payload[key] = value.to_s
65
+ end
66
+ end
67
+
68
+ # Apply extra body parameters to multipart form data array
69
+ # Extra parameters will override existing keys
70
+ def apply_extra_body_parameters_to_form(form_data)
71
+ return unless option?(:extra_body_parameters)
72
+
73
+ extra_params = option(:extra_body_parameters)
74
+ extra_params.each do |key, value|
75
+ key_str = key.to_s
76
+ # Remove existing key if present to allow override.
77
+ # Required for form data as it would be duplicated otherwise
78
+ form_data.reject! { |field| field[0].to_s == key_str }
79
+ form_data.push([key_str, value.to_s])
80
+ end
81
+ end
82
+
49
83
  # Files to reset: list of file objects to rewind when retrying the request
50
84
  def execute_request_with_retries(req, files_to_reset = []) # rubocop:disable all
51
85
  api.configuration.logger&.info("Request to the DeepL API: #{self}")
@@ -88,17 +122,16 @@ module DeepL
88
122
  end
89
123
 
90
124
  def post_request(payload)
125
+ apply_extra_body_parameters_to_json(payload)
91
126
  http_headers = add_json_content_type(headers)
92
127
  post_req = Net::HTTP::Post.new(uri.path, http_headers)
93
- post_req.body = payload.merge(options).to_json
128
+ post_req.body = payload.merge(options_without_extra_params).to_json
94
129
  post_req
95
130
  end
96
131
 
97
132
  def post_request_with_file(form_data)
98
133
  http_headers = add_multipart_form_content_type(headers)
99
134
  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
135
  post_req.set_form(form_data, 'multipart/form-data')
103
136
  post_req
104
137
  end
@@ -106,14 +139,14 @@ module DeepL
106
139
  def get_request # rubocop:disable Naming/AccessorMethodName
107
140
  http_headers = add_json_content_type(headers)
108
141
  get_req = Net::HTTP::Get.new(uri.path, http_headers)
109
- get_req.body = options.to_json
142
+ get_req.body = options_without_extra_params.to_json
110
143
  get_req
111
144
  end
112
145
 
113
146
  def delete_request
114
147
  http_headers = add_json_content_type(headers)
115
148
  del_req = Net::HTTP::Delete.new(uri.path, http_headers)
116
- del_req.body = options.to_json
149
+ del_req.body = options_without_extra_params.to_json
117
150
  del_req
118
151
  end
119
152
 
@@ -20,18 +20,10 @@ module DeepL
20
20
  @filename = filename
21
21
  end
22
22
 
23
- def request # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
23
+ def request
24
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
25
+ form_data = build_base_form_data(input_file)
26
+ apply_extra_body_parameters_to_form(form_data)
35
27
  build_doc_handle(*execute_request_with_retries(post_request_with_file(form_data),
36
28
  [input_file]))
37
29
  end
@@ -49,6 +41,24 @@ module DeepL
49
41
 
50
42
  private
51
43
 
44
+ def build_base_form_data(input_file)
45
+ form_data = [
46
+ ['file', input_file], ['source_lang', source_lang],
47
+ ['target_lang', target_lang]
48
+ ]
49
+ filename_param = filename || File.basename(input_file_path)
50
+ form_data.push(['filename', filename_param]) unless filename_param.nil?
51
+ add_supported_options_to_form(form_data)
52
+ form_data
53
+ end
54
+
55
+ def add_supported_options_to_form(form_data)
56
+ SUPPORTED_OPTIONS.each do |option_name|
57
+ option_value = option(option_name)
58
+ form_data.push([option_name, option_value]) unless option_value.nil?
59
+ end
60
+ end
61
+
52
62
  def build_doc_handle(request, response)
53
63
  parsed_response = JSON.parse(response.body)
54
64
  Resources::DocumentHandle.new(parsed_response['document_id'],
@@ -8,7 +8,7 @@ module DeepL
8
8
  class Rephrase < Base
9
9
  attr_reader :text, :target_lang, :writing_style, :tone
10
10
 
11
- def initialize(api, text, target_lang, writing_style = nil, tone = nil, options = {})
11
+ def initialize(api, text, target_lang = nil, writing_style = nil, tone = nil, options = {}) # rubocop:disable Metrics/ParameterLists
12
12
  super(api, options)
13
13
  @text = text
14
14
  @target_lang = target_lang
@@ -16,9 +16,10 @@ module DeepL
16
16
  @tone = tone
17
17
  end
18
18
 
19
- def request
19
+ def request # rubocop:disable Metrics/AbcSize
20
20
  text_arrayified = text.is_a?(Array) ? text : [text]
21
- payload = { text: text_arrayified, target_lang: target_lang }
21
+ payload = { text: text_arrayified }
22
+ payload[:target_lang] = target_lang unless target_lang.nil?
22
23
  payload[:writing_style] = writing_style unless writing_style.nil?
23
24
  payload[:tone] = tone unless tone.nil?
24
25
  build_texts(*execute_request_with_retries(post_request(payload)))
data/lib/deepl.rb CHANGED
@@ -97,6 +97,11 @@ module DeepL
97
97
  GlossaryApi.new(api, options)
98
98
  end
99
99
 
100
+ def rephrase(text, target_lang = nil, writing_style = nil, tone = nil, options = {}) # rubocop:disable Metrics/ParameterLists
101
+ configure if @configuration.nil?
102
+ Requests::Rephrase.new(api, text, target_lang, writing_style, tone, options).request
103
+ end
104
+
100
105
  def usage(options = {})
101
106
  configure if @configuration.nil?
102
107
  Requests::Usage.new(api, options).request
@@ -428,4 +428,33 @@ describe DeepL do
428
428
  end
429
429
  end
430
430
  end
431
+
432
+ describe '#rephrase' do
433
+ let(:text) { 'Ih bin ei beispielsatz.' }
434
+ let(:target_lang) { 'DE' }
435
+ let(:options) { {} }
436
+
437
+ around do |example|
438
+ deepl.configure
439
+ VCR.use_cassette('deepl_rephrase') { example.call }
440
+ end
441
+
442
+ context 'when rephrasing text' do
443
+ it 'creates and call a request object' do
444
+ expect(DeepL::Requests::Rephrase).to receive(:new)
445
+ .with(deepl.api, text, nil, nil, nil, {}).and_call_original
446
+
447
+ rephrased_text = deepl.rephrase(text)
448
+ expect(rephrased_text).to be_a(DeepL::Resources::Text)
449
+ end
450
+
451
+ it 'creates and call a request object when passing options' do
452
+ expect(DeepL::Requests::Rephrase).to receive(:new)
453
+ .with(deepl.api, text, target_lang, nil, nil, options).and_call_original
454
+
455
+ rephrased_text = deepl.rephrase(text, target_lang, nil, nil, options)
456
+ expect(rephrased_text).to be_a(DeepL::Resources::Text)
457
+ end
458
+ end
459
+ end
431
460
  end
@@ -0,0 +1,87 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://api.deepl.com/v2/write/rephrase
6
+ body:
7
+ encoding: UTF-8
8
+ string: '{"text":["Ih bin ei beispielsatz."]}'
9
+ headers:
10
+ Authorization:
11
+ - DeepL-Auth-Key VALID_TOKEN
12
+ User-Agent:
13
+ - deepl-ruby/3.0.2 (darwin22) ruby/3.2.1
14
+ Content-Type:
15
+ - application/json
16
+ Accept-Encoding:
17
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
18
+ Accept:
19
+ - "*/*"
20
+ response:
21
+ status:
22
+ code: 200
23
+ message: OK
24
+ headers:
25
+ Content-Type:
26
+ - application/json; charset=utf-8
27
+ Date:
28
+ - Tue, 04 Nov 2025 09:49:46 GMT
29
+ X-Trace-Id:
30
+ - 55e4d15b3b5f43d5911ddd20e43e4853
31
+ Access-Control-Expose-Headers:
32
+ - Server-Timing, X-Trace-ID
33
+ Server-Timing:
34
+ - l7_lb_tls;dur=39, l7_lb_idle;dur=0, l7_lb_receive;dur=0, l7_lb_total;dur=122
35
+ Strict-Transport-Security:
36
+ - max-age=63072000; includeSubDomains; preload
37
+ Transfer-Encoding:
38
+ - chunked
39
+ Vary:
40
+ - Accept-Encoding
41
+ body:
42
+ encoding: ASCII-8BIT
43
+ string: '{"improvements":[{"text":"Ich bin ein Beispiel.","detected_source_language":"de","target_language":"de"}]}'
44
+ recorded_at: Tue, 04 Nov 2025 09:49:47 GMT
45
+ - request:
46
+ method: post
47
+ uri: https://api.deepl.com/v2/write/rephrase
48
+ body:
49
+ encoding: UTF-8
50
+ string: '{"text":["Ih bin ei beispielsatz."],"target_lang":"DE"}'
51
+ headers:
52
+ Authorization:
53
+ - DeepL-Auth-Key VALID_TOKEN
54
+ User-Agent:
55
+ - deepl-ruby/3.0.2 (darwin22) ruby/3.2.1
56
+ Content-Type:
57
+ - application/json
58
+ Accept-Encoding:
59
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
60
+ Accept:
61
+ - "*/*"
62
+ response:
63
+ status:
64
+ code: 200
65
+ message: OK
66
+ headers:
67
+ Content-Type:
68
+ - application/json; charset=utf-8
69
+ Date:
70
+ - Tue, 04 Nov 2025 09:49:47 GMT
71
+ X-Trace-Id:
72
+ - bdeb8592514b40b8a16068b3cff1a4ed
73
+ Access-Control-Expose-Headers:
74
+ - Server-Timing, X-Trace-ID
75
+ Server-Timing:
76
+ - l7_lb_tls;dur=40, l7_lb_idle;dur=0, l7_lb_receive;dur=0, l7_lb_total;dur=138
77
+ Strict-Transport-Security:
78
+ - max-age=63072000; includeSubDomains; preload
79
+ Transfer-Encoding:
80
+ - chunked
81
+ Vary:
82
+ - Accept-Encoding
83
+ body:
84
+ encoding: ASCII-8BIT
85
+ string: '{"improvements":[{"text":"Ich bin ein Beispiel.","detected_source_language":"de","target_language":"de"}]}'
86
+ recorded_at: Tue, 04 Nov 2025 09:49:47 GMT
87
+ recorded_with: VCR 6.2.0
@@ -10369,4 +10369,47 @@ http_interactions:
10369
10369
  encoding: ASCII-8BIT
10370
10370
  string: '{"translations":[{"detected_source_language":"EN","text":"Beispieltext","model_type_used":"latency_optimized"}]}'
10371
10371
  recorded_at: Fri, 15 Nov 2024 11:35:22 GMT
10372
- recorded_with: VCR 6.2.0
10372
+ - request:
10373
+ method: post
10374
+ uri: https://api-free.deepl.com/v2/translate
10375
+ body:
10376
+ encoding: UTF-8
10377
+ string: '{"text":["Sample text"],"source_lang":"EN","target_lang":"FR","debug":"1"}'
10378
+ headers:
10379
+ Authorization:
10380
+ - DeepL-Auth-Key VALID_TOKEN
10381
+ User-Agent:
10382
+ - deepl-ruby/3.0.2 (darwin24) ruby/3.3.3
10383
+ Content-Type:
10384
+ - application/json
10385
+ Accept-Encoding:
10386
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
10387
+ Accept:
10388
+ - "*/*"
10389
+ response:
10390
+ status:
10391
+ code: 200
10392
+ message: OK
10393
+ headers:
10394
+ Content-Type:
10395
+ - application/json
10396
+ Date:
10397
+ - Tue, 28 Oct 2025 12:50:22 GMT
10398
+ X-Trace-Id:
10399
+ - b146de80d79542e8bd5d8f50c1410e3a
10400
+ Access-Control-Expose-Headers:
10401
+ - Server-Timing, X-Trace-ID
10402
+ Server-Timing:
10403
+ - l7_lb_tls;dur=71, l7_lb_idle;dur=2, l7_lb_receive;dur=0, l7_lb_total;dur=101
10404
+ Strict-Transport-Security:
10405
+ - max-age=63072000; includeSubDomains; preload
10406
+ Transfer-Encoding:
10407
+ - chunked
10408
+ Vary:
10409
+ - Accept-Encoding
10410
+ body:
10411
+ encoding: ASCII-8BIT
10412
+ string: !binary |-
10413
+ eyJ0cmFuc2xhdGlvbnMiOlt7ImRldGVjdGVkX3NvdXJjZV9sYW5ndWFnZSI6IkVOIiwidGV4dCI6IlRleHRlIG1vZMOobGUifV19
10414
+ recorded_at: Tue, 28 Oct 2025 12:50:23 GMT
10415
+ recorded_with: VCR 6.3.1
@@ -152,4 +152,26 @@ describe DeepL::DocumentApi do
152
152
  )
153
153
  expect(doc_status.status).to eq('done')
154
154
  end
155
+
156
+ it 'Translates a document with extra_body_parameters' do # rubocop:disable RSpec/ExampleLength
157
+ File.unlink(output_document_path)
158
+ source_lang = default_lang_args[:source_lang]
159
+ target_lang = default_lang_args[:target_lang]
160
+ example_doc_path = example_document_path(source_lang)
161
+
162
+ handle = DeepL.document.upload(example_doc_path, source_lang, target_lang,
163
+ File.basename(example_doc_path),
164
+ {
165
+ extra_body_parameters: {
166
+ target_lang: 'FR',
167
+ debug: '1'
168
+ }
169
+ })
170
+ doc_status = handle.wait_until_document_translation_finished
171
+ DeepL.document.download(handle, output_document_path) if doc_status.status != 'error'
172
+ output_file_contents = File.read(output_document_path)
173
+
174
+ expect(example_document_translation('FR')).to eq(output_file_contents)
175
+ expect(doc_status.status).to eq('done')
176
+ end
155
177
  end
@@ -366,6 +366,18 @@ describe DeepL::Requests::Translate do
366
366
  end
367
367
  end
368
368
 
369
+ context 'when performing a request with extra_body_parameters' do
370
+ it 'allows extra parameters to override standard parameters' do
371
+ extra_options = { extra_body_parameters: { target_lang: 'FR', debug: '1' } }
372
+ translate = described_class.new(api, text, source_lang, target_lang, extra_options)
373
+ res = translate.request
374
+
375
+ expect(res).to be_a(DeepL::Resources::Text)
376
+ expect(res.text).to eq('Texte modèle')
377
+ expect(res.detected_source_language).to eq('EN')
378
+ end
379
+ end
380
+
369
381
  context 'when performing a bad request' do
370
382
  context 'when using an invalid token' do
371
383
  let(:api) do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deepl-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.0
4
+ version: 3.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - DeepL SE
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-01-15 00:00:00.000000000 Z
11
+ date: 2025-11-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: juwelier
@@ -120,6 +120,7 @@ files:
120
120
  - spec/fixtures/vcr_cassettes/deepl_document_download.yml
121
121
  - spec/fixtures/vcr_cassettes/deepl_glossaries.yml
122
122
  - spec/fixtures/vcr_cassettes/deepl_languages.yml
123
+ - spec/fixtures/vcr_cassettes/deepl_rephrase.yml
123
124
  - spec/fixtures/vcr_cassettes/deepl_translate.yml
124
125
  - spec/fixtures/vcr_cassettes/deepl_usage.yml
125
126
  - spec/fixtures/vcr_cassettes/glossaries.yml
@@ -168,7 +169,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
168
169
  - !ruby/object:Gem::Version
169
170
  version: '0'
170
171
  requirements: []
171
- rubygems_version: 3.5.3
172
+ rubygems_version: 3.4.6
172
173
  signing_key:
173
174
  specification_version: 4
174
175
  summary: Official Ruby library for the DeepL language translation API.