deepl-rb 3.9.0 → 3.10.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.
Files changed (237) hide show
  1. checksums.yaml +4 -4
  2. data/.gitlab-ci.yml +70 -52
  3. data/.rubocop.yml +26 -0
  4. data/CHANGELOG.md +429 -18
  5. data/Gemfile +4 -0
  6. data/README.md +981 -223
  7. data/Rakefile +18 -5
  8. data/VERSION +1 -1
  9. data/deepl-rb.gemspec +6 -6
  10. data/lib/deepl/admin_client.rb +183 -0
  11. data/lib/deepl/api.rb +30 -6
  12. data/lib/deepl/app_info.rb +20 -0
  13. data/lib/deepl/client.rb +969 -0
  14. data/lib/deepl/configuration.rb +56 -10
  15. data/lib/deepl/constants/admin_usage_group_by.rb +13 -0
  16. data/lib/deepl/constants/custom_tag_usage_aggregate_by.rb +13 -0
  17. data/lib/deepl/constants/document_status_code.rb +17 -0
  18. data/lib/deepl/constants/language_include.rb +17 -0
  19. data/lib/deepl/constants/language_resource_name.rb +21 -0
  20. data/lib/deepl/constants/tag_handling_version.rb +14 -0
  21. data/lib/deepl/deprecation.rb +42 -0
  22. data/lib/deepl/document_api.rb +41 -22
  23. data/lib/deepl/exceptions/bad_request.rb +1 -3
  24. data/lib/deepl/exceptions/connection_error.rb +37 -0
  25. data/lib/deepl/exceptions/document_not_ready_error.rb +17 -0
  26. data/lib/deepl/exceptions/document_translation_error.rb +17 -1
  27. data/lib/deepl/exceptions/error.rb +13 -1
  28. data/lib/deepl/exceptions/not_found.rb +8 -3
  29. data/lib/deepl/exceptions/not_supported.rb +6 -0
  30. data/lib/deepl/exceptions/request_error.rb +19 -2
  31. data/lib/deepl/exceptions/server_error.rb +7 -1
  32. data/lib/deepl/exceptions/validation_error.rb +14 -0
  33. data/lib/deepl/requests/admin/base.rb +94 -0
  34. data/lib/deepl/requests/admin/create_developer_key.rb +38 -0
  35. data/lib/deepl/requests/admin/custom_tag_usage_analytics.rb +38 -0
  36. data/lib/deepl/requests/admin/list_developer_keys.rb +28 -0
  37. data/lib/deepl/requests/admin/update_developer_key.rb +35 -0
  38. data/lib/deepl/requests/admin/usage_analytics.rb +36 -0
  39. data/lib/deepl/requests/base.rb +229 -59
  40. data/lib/deepl/requests/correct.rb +57 -0
  41. data/lib/deepl/requests/document/download.rb +11 -3
  42. data/lib/deepl/requests/document/get_status.rb +2 -2
  43. data/lib/deepl/requests/document/upload.rb +43 -10
  44. data/lib/deepl/requests/glossary/create.rb +6 -2
  45. data/lib/deepl/requests/glossary/language_pairs.rb +20 -4
  46. data/lib/deepl/requests/language_resources.rb +41 -0
  47. data/lib/deepl/requests/languages.rb +28 -4
  48. data/lib/deepl/requests/languages_for_resource.rb +54 -0
  49. data/lib/deepl/requests/multilingual_glossary/create.rb +37 -0
  50. data/lib/deepl/requests/multilingual_glossary/destroy.rb +36 -0
  51. data/lib/deepl/requests/multilingual_glossary/destroy_dictionary.rb +51 -0
  52. data/lib/deepl/requests/multilingual_glossary/entries.rb +66 -0
  53. data/lib/deepl/requests/multilingual_glossary/find.rb +35 -0
  54. data/lib/deepl/requests/multilingual_glossary/helpers.rb +63 -0
  55. data/lib/deepl/requests/multilingual_glossary/list.rb +39 -0
  56. data/lib/deepl/requests/multilingual_glossary/replace_dictionary.rb +41 -0
  57. data/lib/deepl/requests/multilingual_glossary/update.rb +40 -0
  58. data/lib/deepl/requests/rephrase.rb +5 -9
  59. data/lib/deepl/requests/spoken_terms/create.rb +37 -0
  60. data/lib/deepl/requests/spoken_terms/destroy.rb +36 -0
  61. data/lib/deepl/requests/spoken_terms/destroy_term_list.rb +41 -0
  62. data/lib/deepl/requests/spoken_terms/entries.rb +46 -0
  63. data/lib/deepl/requests/spoken_terms/find.rb +35 -0
  64. data/lib/deepl/requests/spoken_terms/helpers.rb +67 -0
  65. data/lib/deepl/requests/spoken_terms/list.rb +35 -0
  66. data/lib/deepl/requests/spoken_terms/replace_term_list.rb +41 -0
  67. data/lib/deepl/requests/spoken_terms/update.rb +40 -0
  68. data/lib/deepl/requests/style_profile/base.rb +83 -0
  69. data/lib/deepl/requests/style_profile/create.rb +35 -0
  70. data/lib/deepl/requests/style_profile/destroy.rb +34 -0
  71. data/lib/deepl/requests/style_profile/find.rb +33 -0
  72. data/lib/deepl/requests/style_profile/list.rb +43 -0
  73. data/lib/deepl/requests/style_profile/update.rb +35 -0
  74. data/lib/deepl/requests/style_rule/create.rb +1 -1
  75. data/lib/deepl/requests/style_rule/create_custom_instruction.rb +4 -2
  76. data/lib/deepl/requests/style_rule/destroy.rb +4 -2
  77. data/lib/deepl/requests/style_rule/destroy_custom_instruction.rb +5 -3
  78. data/lib/deepl/requests/style_rule/find.rb +4 -2
  79. data/lib/deepl/requests/style_rule/find_custom_instruction.rb +5 -3
  80. data/lib/deepl/requests/style_rule/helpers.rb +35 -0
  81. data/lib/deepl/requests/style_rule/list.rb +1 -1
  82. data/lib/deepl/requests/style_rule/update.rb +4 -2
  83. data/lib/deepl/requests/style_rule/update_configured_rules.rb +4 -2
  84. data/lib/deepl/requests/style_rule/update_custom_instruction.rb +5 -3
  85. data/lib/deepl/requests/translate.rb +52 -20
  86. data/lib/deepl/requests/translation_memory/base.rb +1 -4
  87. data/lib/deepl/requests/translation_memory/create_export.rb +1 -1
  88. data/lib/deepl/requests/translation_memory/create_import.rb +1 -1
  89. data/lib/deepl/requests/translation_memory/destroy.rb +1 -1
  90. data/lib/deepl/requests/translation_memory/download_export.rb +4 -0
  91. data/lib/deepl/requests/translation_memory/find.rb +1 -1
  92. data/lib/deepl/requests/translation_memory/find_job.rb +1 -1
  93. data/lib/deepl/requests/translation_memory/list.rb +2 -1
  94. data/lib/deepl/requests/translation_memory/segments.rb +3 -2
  95. data/lib/deepl/requests/translation_memory/storage_base.rb +40 -8
  96. data/lib/deepl/requests/translation_memory/upload_file.rb +1 -1
  97. data/lib/deepl/requests/usage.rb +28 -1
  98. data/lib/deepl/requests/write_improvements.rb +35 -0
  99. data/lib/deepl/resources/admin_usage_report.rb +73 -0
  100. data/lib/deepl/resources/custom_tag_usage_report.rb +59 -0
  101. data/lib/deepl/resources/developer_key.rb +57 -0
  102. data/lib/deepl/resources/document_handle.rb +24 -25
  103. data/lib/deepl/resources/document_translation_status.rb +23 -4
  104. data/lib/deepl/resources/language.rb +10 -2
  105. data/lib/deepl/resources/language_resource.rb +57 -0
  106. data/lib/deepl/resources/language_support.rb +56 -0
  107. data/lib/deepl/resources/multilingual_glossary.rb +112 -0
  108. data/lib/deepl/resources/spoken_terms.rb +61 -0
  109. data/lib/deepl/resources/style_profile.rb +44 -0
  110. data/lib/deepl/resources/style_rule.rb +3 -0
  111. data/lib/deepl/resources/text.rb +18 -2
  112. data/lib/deepl/resources/translation_memory.rb +8 -2
  113. data/lib/deepl/resources/translation_memory_import.rb +1 -1
  114. data/lib/deepl/resources/translation_memory_job.rb +23 -3
  115. data/lib/deepl/resources/translation_memory_segments.rb +8 -6
  116. data/lib/deepl/resources/usage.rb +93 -4
  117. data/lib/deepl/style_rule_api.rb +11 -0
  118. data/lib/deepl/translation_memory_api.rb +104 -24
  119. data/lib/deepl/utils/client_builder.rb +54 -0
  120. data/lib/deepl/utils/document_poller.rb +70 -0
  121. data/lib/deepl/utils/exception_builder.rb +3 -2
  122. data/lib/deepl/utils/http_client_builder.rb +79 -0
  123. data/lib/deepl/utils/number_parser.rb +34 -0
  124. data/lib/deepl/utils/term_validator.rb +33 -0
  125. data/lib/deepl/utils/time_parser.rb +14 -0
  126. data/lib/deepl.rb +166 -41
  127. data/lib/http_client_options.rb +21 -1
  128. data/lib/version.rb +1 -1
  129. data/spec/fixtures.rb +33 -0
  130. data/spec/offline/admin_client_spec.rb +551 -0
  131. data/spec/offline/client_spec.rb +273 -0
  132. data/spec/{api → offline}/configuration_spec.rb +45 -3
  133. data/spec/{constants → offline}/constants_spec.rb +23 -1
  134. data/spec/offline/correct_text_spec.rb +50 -0
  135. data/spec/offline/deprecation_spec.rb +32 -0
  136. data/spec/offline/errors_spec.rb +92 -0
  137. data/spec/offline/glossaries_spec.rb +98 -0
  138. data/spec/offline/http_client_spec.rb +319 -0
  139. data/spec/offline/languages_spec.rb +155 -0
  140. data/spec/offline/module_methods_spec.rb +13 -0
  141. data/spec/offline/multilingual_glossaries_spec.rb +358 -0
  142. data/spec/offline/offline_helper.rb +71 -0
  143. data/spec/offline/rephrase_text_spec.rb +73 -0
  144. data/spec/offline/spoken_terms_spec.rb +215 -0
  145. data/spec/offline/style_profiles_spec.rb +266 -0
  146. data/spec/offline/style_rules_spec.rb +318 -0
  147. data/spec/offline/translate_document_spec.rb +606 -0
  148. data/spec/offline/translate_text_spec.rb +286 -0
  149. data/spec/offline/translation_memories_client_spec.rb +256 -0
  150. data/spec/offline/translation_memories_spec.rb +463 -0
  151. data/spec/offline/usage_spec.rb +151 -0
  152. data/spec/real_api/admin_client_spec.rb +77 -0
  153. data/spec/real_api/correct_text_spec.rb +20 -0
  154. data/spec/real_api/glossaries_spec.rb +28 -0
  155. data/spec/real_api/languages_spec.rb +27 -0
  156. data/spec/real_api/multilingual_glossaries_spec.rb +53 -0
  157. data/spec/real_api/proxy_spec.rb +41 -0
  158. data/spec/real_api/real_api_helper.rb +65 -0
  159. data/spec/real_api/rephrase_text_spec.rb +16 -0
  160. data/spec/real_api/spoken_terms_spec.rb +56 -0
  161. data/spec/real_api/style_profiles_spec.rb +46 -0
  162. data/spec/real_api/style_rules_spec.rb +46 -0
  163. data/spec/real_api/translate_document_spec.rb +18 -0
  164. data/spec/real_api/translate_text_spec.rb +16 -0
  165. data/spec/real_api/translation_memories_spec.rb +56 -0
  166. data/spec/real_api/usage_spec.rb +20 -0
  167. data/spec/spec_helper.rb +1 -50
  168. metadata +116 -76
  169. data/.circleci/config.yml +0 -27
  170. data/.github/workflows/add_issues_to_kanban.yml +0 -16
  171. data/spec/api/api_spec.rb +0 -20
  172. data/spec/api/deepl_spec.rb +0 -262
  173. data/spec/integration_tests/document_api_spec.rb +0 -211
  174. data/spec/integration_tests/document_error_paths_spec.rb +0 -33
  175. data/spec/integration_tests/glossary_api_spec.rb +0 -114
  176. data/spec/integration_tests/glossary_error_paths_spec.rb +0 -107
  177. data/spec/integration_tests/integration_test_utils.rb +0 -178
  178. data/spec/integration_tests/languages_api_spec.rb +0 -54
  179. data/spec/integration_tests/languages_error_paths_spec.rb +0 -25
  180. data/spec/integration_tests/rephrase_api_spec.rb +0 -90
  181. data/spec/integration_tests/rephrase_error_paths_spec.rb +0 -53
  182. data/spec/integration_tests/smoke_test_spec.rb +0 -24
  183. data/spec/integration_tests/style_rule_api_spec.rb +0 -117
  184. data/spec/integration_tests/style_rule_error_paths_spec.rb +0 -45
  185. data/spec/integration_tests/translate_api_spec.rb +0 -117
  186. data/spec/integration_tests/translate_error_paths_spec.rb +0 -48
  187. data/spec/integration_tests/translation_memory_api_spec.rb +0 -244
  188. data/spec/integration_tests/translation_memory_error_paths_spec.rb +0 -87
  189. data/spec/integration_tests/usage_api_spec.rb +0 -29
  190. data/spec/integration_tests/usage_error_paths_spec.rb +0 -18
  191. data/spec/requests/document/upload_spec.rb +0 -130
  192. data/spec/requests/extra_body_parameters_types_spec.rb +0 -82
  193. data/spec/requests/glossary/create_spec.rb +0 -44
  194. data/spec/requests/glossary/destroy_spec.rb +0 -27
  195. data/spec/requests/glossary/entries_spec.rb +0 -27
  196. data/spec/requests/glossary/find_spec.rb +0 -28
  197. data/spec/requests/glossary/language_pairs_spec.rb +0 -27
  198. data/spec/requests/glossary/list_spec.rb +0 -27
  199. data/spec/requests/languages_spec.rb +0 -27
  200. data/spec/requests/rephrase_spec.rb +0 -46
  201. data/spec/requests/style_rule/create_custom_instruction_spec.rb +0 -30
  202. data/spec/requests/style_rule/create_spec.rb +0 -29
  203. data/spec/requests/style_rule/destroy_custom_instruction_spec.rb +0 -28
  204. data/spec/requests/style_rule/destroy_spec.rb +0 -27
  205. data/spec/requests/style_rule/find_custom_instruction_spec.rb +0 -29
  206. data/spec/requests/style_rule/find_spec.rb +0 -28
  207. data/spec/requests/style_rule/list_spec.rb +0 -27
  208. data/spec/requests/style_rule/update_configured_rules_spec.rb +0 -31
  209. data/spec/requests/style_rule/update_custom_instruction_spec.rb +0 -32
  210. data/spec/requests/style_rule/update_spec.rb +0 -29
  211. data/spec/requests/translate_spec.rb +0 -338
  212. data/spec/requests/translation_memory/create_export_spec.rb +0 -37
  213. data/spec/requests/translation_memory/create_import_spec.rb +0 -61
  214. data/spec/requests/translation_memory/destroy_spec.rb +0 -36
  215. data/spec/requests/translation_memory/download_export_spec.rb +0 -54
  216. data/spec/requests/translation_memory/find_job_spec.rb +0 -37
  217. data/spec/requests/translation_memory/find_spec.rb +0 -36
  218. data/spec/requests/translation_memory/list_spec.rb +0 -27
  219. data/spec/requests/translation_memory/segments_spec.rb +0 -58
  220. data/spec/requests/translation_memory/upload_file_spec.rb +0 -55
  221. data/spec/requests/usage_spec.rb +0 -27
  222. data/spec/resources/custom_instruction_spec.rb +0 -32
  223. data/spec/resources/glossary_spec.rb +0 -38
  224. data/spec/resources/language_pair_spec.rb +0 -23
  225. data/spec/resources/language_spec.rb +0 -45
  226. data/spec/resources/style_rule_spec.rb +0 -68
  227. data/spec/resources/text_spec.rb +0 -23
  228. data/spec/resources/translation_memory_export_spec.rb +0 -38
  229. data/spec/resources/translation_memory_import_spec.rb +0 -30
  230. data/spec/resources/translation_memory_job_spec.rb +0 -109
  231. data/spec/resources/translation_memory_segments_spec.rb +0 -78
  232. data/spec/resources/translation_memory_spec.rb +0 -52
  233. data/spec/resources/usage_spec.rb +0 -35
  234. data/spec/support/live_mock_server.rb +0 -12
  235. data/spec/support/managed_glossary.rb +0 -65
  236. data/spec/support/managed_style_rule.rb +0 -17
  237. data/spec/support/managed_translation_memory.rb +0 -55
@@ -1,54 +0,0 @@
1
- # Copyright 2026 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
- require 'spec_helper'
7
-
8
- # Covers GET /v2/languages; the SDK has no v3 languages endpoint.
9
- describe 'DeepL.languages' do # rubocop:disable RSpec/DescribeClass
10
- describe 'source languages' do
11
- it 'returns a non-empty array of Language resources with common codes' do
12
- languages = DeepL.languages
13
-
14
- expect(languages).to be_an(Array)
15
- expect(languages).not_to be_empty
16
- expect(languages).to all(be_a(DeepL::Resources::Language))
17
- expect(languages.first).to respond_to(:code, :name)
18
-
19
- codes = languages.map(&:code)
20
- expect(codes).to include('EN', 'DE')
21
- end
22
- end
23
-
24
- describe 'target languages' do
25
- it 'returns target entries that include both formality-supporting and non-supporting members' do
26
- languages = DeepL.languages(type: :target)
27
-
28
- expect(languages).to be_an(Array)
29
- expect(languages).not_to be_empty
30
- expect(languages).to all(be_a(DeepL::Resources::Language))
31
-
32
- formalities = languages.map(&:supports_formality?)
33
- expect(formalities).to include(true)
34
- expect(formalities).to include(false)
35
- end
36
-
37
- it 'raises NotSupported when supports_formality? is called on a source-language entry' do
38
- source_languages = DeepL.languages
39
-
40
- expect { source_languages.first.supports_formality? }
41
- .to raise_error(DeepL::Exceptions::NotSupported)
42
- end
43
- end
44
-
45
- describe 'source vs target counts' do
46
- it 'returns sensible (>20) counts for both source and target listings' do
47
- source_languages = DeepL.languages
48
- target_languages = DeepL.languages(type: :target)
49
-
50
- expect(source_languages.size).to be > 20
51
- expect(target_languages.size).to be > 20
52
- end
53
- end
54
- end
@@ -1,25 +0,0 @@
1
- # Copyright 2026 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
- require 'spec_helper'
7
-
8
- describe 'DeepL.languages error paths' do # rubocop:disable RSpec/DescribeClass
9
- include_context 'with a live mock server'
10
-
11
- describe 'authorization failures' do
12
- it 'raises AuthorizationFailed when the auth key is invalid' do
13
- request = DeepL::Requests::Languages.new(unauthorized_api)
14
-
15
- expect { request.request }.to raise_error(DeepL::Exceptions::AuthorizationFailed)
16
- end
17
- end
18
-
19
- describe 'bad request errors' do
20
- it 'raises BadRequest for an unsupported languages type' do
21
- expect { DeepL.languages(type: :invalid) }
22
- .to raise_error(DeepL::Exceptions::BadRequest)
23
- end
24
- end
25
- end
@@ -1,90 +0,0 @@
1
- # Copyright 2026 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
- require 'spec_helper'
7
-
8
- describe 'DeepL.rephrase' do # rubocop:disable RSpec/DescribeClass
9
- describe 'happy path' do
10
- it 'rephrases an English sentence into English and returns a Text resource' do
11
- result = DeepL.rephrase('As Gregor Samsa awoke one morning he found himself transformed.',
12
- 'en')
13
-
14
- expect(result).to be_a(DeepL::Resources::Text)
15
- expect(result.text).to be_a(String)
16
- expect(result.text).not_to be_empty
17
- end
18
- end
19
-
20
- describe 'error path' do
21
- it 'raises a bad request error for an invalid writing_style value' do
22
- expect do
23
- DeepL.rephrase('As Gregor Samsa awoke one morning he found himself transformed.',
24
- 'en', 'totally_invalid_style')
25
- end.to raise_error(DeepL::Exceptions::BadRequest)
26
- end
27
- end
28
-
29
- describe 'edge case' do
30
- it 'rephrases with a writing_style option applied' do
31
- result = DeepL.rephrase('As Gregor Samsa awoke one morning he found himself transformed.',
32
- 'en', 'business')
33
-
34
- expect(result).to be_a(DeepL::Resources::Text)
35
- expect(result.text).to be_a(String)
36
- expect(result.text).not_to be_empty
37
- end
38
-
39
- it 'rephrases with a tone option applied' do
40
- result = DeepL.rephrase('As Gregor Samsa awoke one morning he found himself transformed.',
41
- 'en', nil, 'friendly')
42
-
43
- expect(result).to be_a(DeepL::Resources::Text)
44
- expect(result.text).to be_a(String)
45
- expect(result.text).not_to be_empty
46
- end
47
-
48
- it 'rephrases an array of texts with a tone applied' do
49
- texts = [
50
- 'As Gregor Samsa awoke one morning he found himself transformed.',
51
- 'He lay on his armour-like back, and if he lifted his head a little.'
52
- ]
53
-
54
- results = DeepL.rephrase(texts, 'en', nil, 'friendly')
55
-
56
- expect(results).to be_an(Array)
57
- expect(results.size).to eq(2)
58
- expect(results).to all(be_a(DeepL::Resources::Text))
59
- expect(results.map(&:text)).to all(be_a(String).and(satisfy { |t| !t.empty? }))
60
- end
61
-
62
- it 'rephrases an array of texts with a writing_style applied' do
63
- texts = [
64
- 'As Gregor Samsa awoke one morning he found himself transformed.',
65
- 'He lay on his armour-like back, and if he lifted his head a little.'
66
- ]
67
-
68
- results = DeepL.rephrase(texts, 'en', 'business')
69
-
70
- expect(results).to be_an(Array)
71
- expect(results.size).to eq(2)
72
- expect(results).to all(be_a(DeepL::Resources::Text))
73
- expect(results.map(&:text)).to all(be_a(String).and(satisfy { |t| !t.empty? }))
74
- end
75
-
76
- it 'rephrases an array of texts and returns an array of Text resources' do
77
- texts = [
78
- 'As Gregor Samsa awoke one morning he found himself transformed.',
79
- 'He lay on his armour-like back, and if he lifted his head a little.'
80
- ]
81
-
82
- results = DeepL.rephrase(texts, 'en')
83
-
84
- expect(results).to be_an(Array)
85
- expect(results.size).to eq(2)
86
- expect(results).to all(be_a(DeepL::Resources::Text))
87
- expect(results.map(&:text)).to all(be_a(String).and(satisfy { |t| !t.empty? }))
88
- end
89
- end
90
- end
@@ -1,53 +0,0 @@
1
- # Copyright 2026 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
- require 'securerandom'
7
- require 'spec_helper'
8
-
9
- describe 'DeepL.rephrase error paths' do # rubocop:disable RSpec/DescribeClass
10
- include IntegrationTestUtils
11
-
12
- include_context 'with a live mock server'
13
-
14
- let(:sample_text) { 'As Gregor Samsa awoke one morning he found himself transformed.' }
15
-
16
- def rephrase_with_fresh_user(headers)
17
- fresh_auth_key = "rephrase-err-#{SecureRandom.uuid}"
18
- config = DeepL::Configuration.new(auth_key: fresh_auth_key)
19
- config.max_network_retries = 0
20
- api = DeepL::API.new(config)
21
- DeepL::Requests::Rephrase.new(api, sample_text, 'en', nil, nil, {}, headers).request
22
- end
23
-
24
- describe 'authorization failures' do
25
- it 'raises AuthorizationFailed when called with an invalid auth_key' do
26
- request = DeepL::Requests::Rephrase.new(unauthorized_api, sample_text, 'en')
27
-
28
- expect { request.request }.to raise_error(DeepL::Exceptions::AuthorizationFailed)
29
- end
30
- end
31
-
32
- describe 'bad request errors' do
33
- it 'raises BadRequest for an unsupported target_lang code' do
34
- expect do
35
- DeepL.rephrase(sample_text, 'zzz')
36
- end.to raise_error(DeepL::Exceptions::BadRequest)
37
- end
38
-
39
- it 'raises BadRequest when both writing_style and tone are provided' do
40
- expect do
41
- DeepL.rephrase(sample_text, 'en', 'business', 'friendly')
42
- end.to raise_error(DeepL::Exceptions::BadRequest)
43
- end
44
- end
45
-
46
- describe 'rate limiting' do
47
- it 'raises LimitExceeded when the server responds with 429', :mock_server_only do
48
- expect do
49
- rephrase_with_fresh_user(respond_with_429_header(1))
50
- end.to raise_error(DeepL::Exceptions::LimitExceeded)
51
- end
52
- end
53
- end
@@ -1,24 +0,0 @@
1
- # Copyright 2025 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
- require 'spec_helper'
7
-
8
- describe 'SDK smoke test', :integration do # rubocop:disable RSpec/DescribeClass
9
- it 'exercises translate, glossaries.list, and usage end-to-end' do # rubocop:disable RSpec/ExampleLength
10
- source_text = 'Hello, world!'
11
- result = DeepL.translate(source_text, 'EN', 'DE')
12
- expect(result).to be_a(DeepL::Resources::Text)
13
- expect(result.text).to be_a(String)
14
- expect(result.text).not_to be_empty
15
- expect(result.text).not_to eq(source_text)
16
-
17
- glossaries = DeepL.glossaries.list
18
- expect(glossaries).to be_an(Array)
19
-
20
- usage = DeepL.usage
21
- expect(usage).to be_a(DeepL::Resources::Usage)
22
- expect(usage).to respond_to(:character_count, :character_limit)
23
- end
24
- end
@@ -1,117 +0,0 @@
1
- # Copyright 2025 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
- require 'spec_helper'
7
-
8
- describe DeepL::StyleRuleApi, :mock_server_only do
9
- describe '#translate_with_style_rules' do
10
- it 'when performing a request with style_id' do
11
- source_lang = 'DE'
12
- target_lang = 'EN-US'
13
- text = 'Hallo, Welt!'
14
- style_id = 'dca2e053-8ae5-45e6-a0d2-881156e7f4e4'
15
-
16
- result = DeepL.translate(text, source_lang, target_lang, { style_rule: style_id })
17
- expect(result).to be_a(DeepL::Resources::Text)
18
- end
19
-
20
- it 'when performing a request with style_rule object' do
21
- source_lang = 'DE'
22
- target_lang = 'EN-US'
23
- text = 'Hallo, Welt!'
24
- style_rule = build_test_style_rule
25
-
26
- result = DeepL.translate(text, source_lang, target_lang, { style_rule: style_rule })
27
- expect(result).to be_a(DeepL::Resources::Text)
28
- end
29
- end
30
-
31
- describe '#list_style_rules' do
32
- it 'when requesting a list of all style rules' do
33
- style_rules = DeepL.style_rules.list(page: 0, page_size: 10, detailed: true)
34
- expect(style_rules).to be_an(Array)
35
- expect(style_rules.length).to eq(1)
36
- expect(style_rules[0].style_id).to eq('dca2e053-8ae5-45e6-a0d2-881156e7f4e4')
37
- expect(style_rules[0].name).to eq('Default Style Rule')
38
- expect(style_rules[0].configured_rules).to be_a(DeepL::Resources::ConfiguredRules)
39
- expect(style_rules[0].custom_instructions).to be_an(Array)
40
- end
41
-
42
- it 'when requesting a list of all style rules without detailed' do
43
- style_rules = DeepL.style_rules.list
44
- expect(style_rules).to be_an(Array)
45
- expect(style_rules.length).to eq(1)
46
- expect(style_rules[0].style_id).to eq('dca2e053-8ae5-45e6-a0d2-881156e7f4e4')
47
- expect(style_rules[0].configured_rules).to be_nil
48
- expect(style_rules[0].custom_instructions).to be_nil
49
- end
50
- end
51
-
52
- describe 'style rule management operations' do
53
- it 'when performing all management operations on style rules' do # rubocop:disable RSpec/ExampleLength,RSpec/MultipleExpectations
54
- # Create a style rule
55
- style_rule = DeepL.style_rules.create('Test Style Rule', 'en')
56
- expect(style_rule).to be_a(DeepL::Resources::StyleRule)
57
- expect(style_rule.style_id).not_to be_nil
58
- style_id = style_rule.style_id
59
-
60
- # Find the style rule
61
- found_rule = DeepL.style_rules.find(style_id)
62
- expect(found_rule).to be_a(DeepL::Resources::StyleRule)
63
- expect(found_rule.style_id).to eq(style_id)
64
-
65
- # Update the style rule name
66
- updated_rule = DeepL.style_rules.update_name(style_id, 'Updated Style Rule')
67
- expect(updated_rule).to be_a(DeepL::Resources::StyleRule)
68
-
69
- # Update configured rules
70
- configured_rules = {
71
- 'dates_and_times' => { 'calendar_era' => 'use_bc_and_ad' }
72
- }
73
- updated_rule = DeepL.style_rules.update_configured_rules(style_id, configured_rules)
74
- expect(updated_rule).to be_a(DeepL::Resources::StyleRule)
75
-
76
- # Create a custom instruction
77
- custom_instruction = DeepL.style_rules.create_custom_instruction(
78
- style_id, 'Test Instruction', 'Always use formal language'
79
- )
80
- expect(custom_instruction).to be_a(DeepL::Resources::CustomInstruction)
81
- expect(custom_instruction.id).not_to be_nil
82
- instruction_id = custom_instruction.id
83
-
84
- # Find a custom instruction
85
- fetched_instruction = DeepL.style_rules.find_custom_instruction(style_id, instruction_id)
86
- expect(fetched_instruction).to be_a(DeepL::Resources::CustomInstruction)
87
- expect(fetched_instruction.id).to eq(instruction_id)
88
-
89
- # Update a custom instruction
90
- updated_instruction = DeepL.style_rules.update_custom_instruction(
91
- style_id, instruction_id, 'Updated Instruction', 'Use casual language'
92
- )
93
- expect(updated_instruction).to be_a(DeepL::Resources::CustomInstruction)
94
-
95
- # Destroy the custom instruction
96
- deleted_instruction_id = DeepL.style_rules.destroy_custom_instruction(style_id,
97
- instruction_id)
98
- expect(deleted_instruction_id).to eq(instruction_id)
99
-
100
- # Destroy the style rule
101
- deleted_style_id = DeepL.style_rules.destroy(style_id)
102
- expect(deleted_style_id).to eq(style_id)
103
- end
104
- end
105
-
106
- def build_test_style_rule
107
- style_rule_data = {
108
- 'style_id' => 'dca2e053-8ae5-45e6-a0d2-881156e7f4e4',
109
- 'name' => 'Default Style Rule',
110
- 'creation_time' => '2025-01-01T00:00:00Z',
111
- 'updated_time' => '2025-01-01T00:00:00Z',
112
- 'language' => 'en',
113
- 'version' => 1
114
- }
115
- DeepL::Resources::StyleRule.new(style_rule_data, nil, nil)
116
- end
117
- end
@@ -1,45 +0,0 @@
1
- # Copyright 2026 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.md file.
4
- # frozen_string_literal: true
5
-
6
- require 'spec_helper'
7
-
8
- describe DeepL::StyleRuleApi, :mock_server_only do # rubocop:disable RSpec/SpecFilePathFormat
9
- include_context 'with a live mock server'
10
-
11
- let(:missing_uuid) { '00000000-0000-0000-0000-000000000000' }
12
-
13
- describe 'authorization failures' do
14
- let(:unauthorized_style_rules) { described_class.new(unauthorized_api) }
15
-
16
- it 'raises AuthorizationFailed on a read operation (list)' do
17
- expect { unauthorized_style_rules.list }
18
- .to raise_error(DeepL::Exceptions::AuthorizationFailed)
19
- end
20
-
21
- it 'raises AuthorizationFailed on a write operation (create)' do
22
- expect { unauthorized_style_rules.create('Auth Failure Test', 'en') }
23
- .to raise_error(DeepL::Exceptions::AuthorizationFailed)
24
- end
25
- end
26
-
27
- describe 'not-found failures' do
28
- it 'raises NotFound when #find is called with a missing UUID' do
29
- expect { DeepL.style_rules.find(missing_uuid) }
30
- .to raise_error(DeepL::Exceptions::NotFound)
31
- end
32
- end
33
-
34
- describe 'bad-request failures' do
35
- it 'raises BadRequest when create is called with a nil language' do
36
- expect { DeepL.style_rules.create('Nil Lang', nil) }
37
- .to raise_error(DeepL::Exceptions::BadRequest)
38
- end
39
-
40
- it 'raises an error when #destroy is called with a malformed UUID' do
41
- expect { DeepL.style_rules.destroy('invalid-uuid') }
42
- .to raise_error(DeepL::Exceptions::Error)
43
- end
44
- end
45
- end
@@ -1,117 +0,0 @@
1
- # Copyright 2026 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
- require 'spec_helper'
7
-
8
- describe 'DeepL.translate' do # rubocop:disable RSpec/DescribeClass
9
- include_context 'with a live mock server'
10
-
11
- let(:text) { 'proton beam' }
12
-
13
- describe 'happy path' do
14
- it 'translates a single string into a Text resource' do
15
- result = DeepL.translate(text, 'EN', 'DE')
16
-
17
- expect(result).to be_a(DeepL::Resources::Text)
18
- expect(result.text).to be_a(String)
19
- expect(result.text).not_to be_empty
20
- end
21
-
22
- it 'translates an array of strings into an array of Text resources' do
23
- results = DeepL.translate(%w[Sample Word], 'EN', 'ES')
24
-
25
- expect(results).to be_an(Array)
26
- expect(results.size).to eq(2)
27
- expect(results).to all(be_a(DeepL::Resources::Text))
28
- end
29
- end
30
-
31
- describe 'options' do
32
- it 'accepts a formality setting' do
33
- result = DeepL.translate('How are you?', 'EN', 'DE', { formality: 'more' })
34
-
35
- expect(result).to be_a(DeepL::Resources::Text)
36
- end
37
-
38
- it 'translates with XML tag handling and ignored tags' do
39
- result = DeepL.translate('<p>Sample <code>x</code></p>', 'EN', 'ES',
40
- { tag_handling: 'xml', ignore_tags: %w[code] })
41
-
42
- expect(result.text).to be_a(String)
43
- expect(result.text).not_to be_empty
44
- end
45
-
46
- it 'accepts a context option' do
47
- result = DeepL.translate('That is hot!', 'EN', 'ES', { context: 'about the weather' })
48
-
49
- expect(result).to be_a(DeepL::Resources::Text)
50
- end
51
-
52
- it 'accepts an empty context option' do
53
- result = DeepL.translate('That is hot!', 'EN', 'ES', { context: '' })
54
-
55
- expect(result).to be_a(DeepL::Resources::Text)
56
- end
57
-
58
- it 'translates an HTML document with split_sentences, outline_detection and splitting_tags' do
59
- document = '<document><meta><title>Title</title></meta>' \
60
- '<content><par>First sentence. Second one.</par></content></document>'
61
- result = DeepL.translate(document, 'EN', 'ES',
62
- { tag_handling: 'xml', split_sentences: 'nonewlines',
63
- outline_detection: false, splitting_tags: %w[title par] })
64
-
65
- expect(result).to be_a(DeepL::Resources::Text)
66
- expect(result.text).not_to be_empty
67
- end
68
-
69
- it 'translates using a glossary' do
70
- with_managed_glossary(name: 'Translate Glossary', source_lang: 'en', target_lang: 'de',
71
- entries: [%w[Hello Hallo]]) do |glossary|
72
- result = DeepL.translate('Hello', 'EN', 'DE', { glossary_id: glossary.id })
73
-
74
- expect(result).to be_a(DeepL::Resources::Text)
75
- expect(result.text).not_to be_empty
76
- end
77
- end
78
-
79
- it 'translates using multiple glossaries via glossary_ids' do # rubocop:disable RSpec/ExampleLength
80
- with_managed_glossary(name: 'Translate Glossary IDs 1', source_lang: 'en', target_lang: 'de',
81
- entries: [%w[Hello Hallo]]) do |glossary1|
82
- with_managed_glossary(name: 'Translate Glossary IDs 2', source_lang: 'en',
83
- target_lang: 'de', entries: [%w[World Welt]]) do |glossary2|
84
- # Newly created glossaries can lag behind (eventual consistency), so
85
- # ensure they are resolvable before translating and tolerate a
86
- # transient "not found" on the translate call itself.
87
- wait_until_glossaries_ready(glossary1, glossary2)
88
- result = translate_retrying_missing_glossary(
89
- 'Hello', 'EN', 'DE', { glossary_ids: [glossary1.id, glossary2.id] }
90
- )
91
-
92
- expect(result).to be_a(DeepL::Resources::Text)
93
- expect(result.text).not_to be_empty
94
- end
95
- end
96
- end
97
-
98
- %w[quality_optimized latency_optimized prefer_quality_optimized].each do |model_type|
99
- it "returns model_type_used for #{model_type}" do
100
- result = DeepL.translate(text, 'EN', 'DE', { model_type: model_type })
101
-
102
- expect(result).to be_a(DeepL::Resources::Text)
103
- expect(result.model_type_used).not_to be_nil
104
- end
105
- end
106
-
107
- %w[v1 v2].each do |version|
108
- it "translates with tag_handling_version #{version}" do
109
- result = DeepL.translate('<p>Hello world</p>', 'EN', 'DE',
110
- { tag_handling: 'html', tag_handling_version: version })
111
-
112
- expect(result).to be_a(DeepL::Resources::Text)
113
- expect(result.text).not_to be_empty
114
- end
115
- end
116
- end
117
- end
@@ -1,48 +0,0 @@
1
- # Copyright 2026 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
- require 'spec_helper'
7
-
8
- describe 'DeepL.translate error paths' do # rubocop:disable RSpec/DescribeClass
9
- include_context 'with a live mock server'
10
-
11
- let(:text) { 'proton beam' }
12
-
13
- describe 'authorization failures' do
14
- it 'raises AuthorizationFailed when the auth key is invalid' do
15
- request = DeepL::Requests::Translate.new(unauthorized_api, text, 'EN', 'DE')
16
-
17
- expect { request.request }.to raise_error(DeepL::Exceptions::AuthorizationFailed)
18
- end
19
- end
20
-
21
- describe 'bad request errors' do
22
- it 'raises BadRequest for an unsupported target language' do
23
- expect { DeepL.translate(text, 'EN', 'ZZ') }
24
- .to raise_error(DeepL::Exceptions::BadRequest)
25
- end
26
-
27
- it 'raises BadRequest when no target language is given' do
28
- expect { DeepL.translate(text, 'EN', nil) }
29
- .to raise_error(DeepL::Exceptions::BadRequest)
30
- end
31
-
32
- # Real-server only: the mock coerces text:[null] to text:[""] and accepts it,
33
- # so it cannot reproduce this; prod rejects [null] with 400.
34
- it 'raises BadRequest when the text is nil', :real_server_only do
35
- expect { DeepL.translate(nil, 'EN', 'DE') }
36
- .to raise_error(DeepL::Exceptions::BadRequest)
37
- end
38
- end
39
-
40
- describe 'request entity too large errors' do
41
- it 'raises RequestEntityTooLarge when too many texts are sent in a single request' do
42
- texts = Array.new(10_000) { |i| "This is the sentence number #{i}" }
43
-
44
- expect { DeepL.translate(texts, 'EN', 'DE') }
45
- .to raise_error(DeepL::Exceptions::RequestEntityTooLarge)
46
- end
47
- end
48
- end