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,244 +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::TranslationMemoryApi, :mock_server_only do
9
- include_context 'with temp dir'
10
-
11
- let(:default_tm_id) { 'a74d88fb-ed2a-4943-a664-a4512398b994' }
12
- let(:tmx_file_path) { write_example_tmx(File.join(temp_dir, 'example.tmx')) }
13
- let(:translation_memories) { DeepL.translation_memories }
14
-
15
- describe '#translate_with_translation_memory' do
16
- it 'when performing a request with translation_memory_id' do
17
- source_lang = 'DE'
18
- target_lang = 'EN'
19
- text = 'Protonenstrahl'
20
-
21
- result = DeepL.translate(text, source_lang, target_lang,
22
- { translation_memory: default_tm_id })
23
- expect(result).to be_a(DeepL::Resources::Text)
24
- end
25
-
26
- it 'when performing a request with translation_memory resource object' do
27
- source_lang = 'DE'
28
- target_lang = 'EN'
29
- text = 'Protonenstrahl'
30
- translation_memory = build_test_translation_memory
31
-
32
- result = DeepL.translate(text, source_lang, target_lang,
33
- { translation_memory: translation_memory })
34
- expect(result).to be_a(DeepL::Resources::Text)
35
- end
36
- end
37
-
38
- describe '#list_translation_memories' do
39
- it 'when requesting a list of all translation memories' do
40
- translation_memories = DeepL.translation_memories.list
41
- expect(translation_memories).to be_an(Array)
42
- expect(translation_memories).not_to be_empty
43
- expect(translation_memories.first).to be_a(DeepL::Resources::TranslationMemory)
44
- expect(translation_memories.first.translation_memory_id).not_to be_nil
45
- expect(translation_memories.first.name).not_to be_nil
46
- end
47
- end
48
-
49
- describe '#find' do
50
- it 'when requesting a single translation memory by ID' do
51
- translation_memory = DeepL.translation_memories.find(default_tm_id)
52
- expect(translation_memory).to be_a(DeepL::Resources::TranslationMemory)
53
- expect(translation_memory.translation_memory_id).to eq(default_tm_id)
54
- expect(translation_memory.name).to eq('Default Translation Memory')
55
- expect(translation_memory.source_language).to eq('de')
56
- expect(translation_memory.target_languages).to eq(%w[en es fr])
57
- expect(translation_memory.segment_count).to eq(12)
58
- end
59
-
60
- it 'when requesting a single translation memory by resource object' do
61
- translation_memory = DeepL.translation_memories.find(build_test_translation_memory)
62
- expect(translation_memory.translation_memory_id).to eq(default_tm_id)
63
- expect(translation_memory.creation_time).to be_a(Time)
64
- expect(translation_memory.updated_time).to be_a(Time)
65
- end
66
- end
67
-
68
- describe '#segments' do
69
- it 'when requesting the segments of a translation memory' do
70
- page = DeepL.translation_memories.segments(default_tm_id)
71
- expect(page).to be_a(DeepL::Resources::TranslationMemorySegments)
72
- expect(page.segments.length).to eq(12)
73
- expect(page.segment_count).to eq(12)
74
- expect(page.next_page?).to be(false)
75
- expect(page.segments.first.source_text).to eq('Quelltext Nummer 0')
76
- end
77
-
78
- it 'when reading segment timestamps' do
79
- # The API does not return creation_time/updated_time on segments at all, and returns
80
- # last_used_time only for segments that have been used.
81
- page = DeepL.translation_memories.segments(default_tm_id)
82
- expect(page.segments.first.creation_time).to be_nil
83
- expect(page.segments.first.updated_time).to be_nil
84
- expect(page.segments.first.last_used_time).to be_a(Time)
85
- expect(page.segments[1].last_used_time).to be_nil
86
- end
87
-
88
- it 'when reading the target segments of a source segment' do
89
- page = DeepL.translation_memories.segments(default_tm_id, page_size: 1)
90
- segment = page.segments.first
91
- expect(segment.targets.map(&:target_language)).to eq(%w[en es fr])
92
- expect(segment.targets.first.target_text).to eq('Target text number 0 (de->en)')
93
- expect(segment.targets.first.target_segment_id).not_to be_nil
94
- expect(segment.targets.first.last_used_time).to be_a(Time)
95
- end
96
-
97
- it 'when paginating through the segments with the page cursor' do
98
- first_page = DeepL.translation_memories.segments(default_tm_id, page_size: 5)
99
- second_page = next_segments_page(first_page)
100
- last_page = next_segments_page(second_page)
101
-
102
- expect(first_page.segments.length).to eq(5)
103
- expect(first_page.next_page?).to be(true)
104
- expect(second_page.segments.first.source_text).to eq('Quelltext Nummer 5')
105
- expect(last_page.segments.length).to eq(2)
106
- expect(last_page.next_page?).to be(false)
107
- end
108
-
109
- it 'when filtering the segments by a text containing a space' do
110
- page = DeepL.translation_memories.segments(default_tm_id, filter_text: 'Nummer 1')
111
- expect(page.segments.map(&:source_text))
112
- .to eq(['Quelltext Nummer 1', 'Quelltext Nummer 10', 'Quelltext Nummer 11'])
113
- # segment_count is the number of segments stored in the translation memory, a text filter
114
- # does not reduce it.
115
- expect(page.segment_count).to eq(12)
116
- end
117
-
118
- it 'when filtering the segments case-sensitively' do
119
- page = DeepL.translation_memories.segments(default_tm_id, filter_text: 'quelltext',
120
- filter_case_sensitive: true)
121
- expect(page.segments).to be_empty
122
- expect(page.segment_count).to eq(12)
123
- end
124
- end
125
-
126
- describe '#import_from_filepath' do
127
- it 'when importing a translation memory from a TMX file' do
128
- with_managed_translation_memory(tmx_file_path, display_name: 'Imported TM') do |job|
129
- expect(job).to be_a(DeepL::Resources::TranslationMemoryJob)
130
- expect(job.operation).to eq('import')
131
- expect(job.display_name).to eq('Imported TM')
132
- expect(job.status).to eq('completed')
133
- expect(job.finished?).to be(true)
134
- expect(job.result.translation_memory_id).not_to be_nil
135
- expect(job.result.skipped_segment_count).to eq(0)
136
- end
137
- end
138
-
139
- it 'when the imported translation memory can be retrieved afterwards' do
140
- with_managed_translation_memory(tmx_file_path) do |job|
141
- translation_memory = DeepL.translation_memories.find(job.result.translation_memory_id)
142
- expect(translation_memory.name).to eq('example.tmx')
143
- expect(translation_memory.source_language).to eq('de')
144
- expect(job.source_content_type).to eq('application/xml')
145
- expect(job.source_content_length).to eq(File.size(tmx_file_path))
146
- end
147
- end
148
- end
149
-
150
- describe '#create_import' do
151
- it 'when the import job is still awaiting the file upload' do
152
- created = DeepL.translation_memories.create_import('awaiting.tmx', 128,
153
- display_name: 'Awaiting Upload')
154
- expect(created).to be_a(DeepL::Resources::TranslationMemoryImport)
155
- expect(created.upload_url).to start_with('http')
156
- expect(created.expires_at).to be_a(Time)
157
-
158
- job = DeepL.translation_memories.find_job(created.job_id)
159
- expect(job.awaiting_input?).to be(true)
160
- expect(job.status).to eq('awaiting_input')
161
- expect(job.result.required_action).not_to be_nil
162
- end
163
-
164
- # The API detects the upload asynchronously, so an uploaded job keeps reporting
165
- # `awaiting_input` for a while. The wait loop must poll through that status.
166
- it 'when waiting on an uploaded job it polls through the awaiting_input status' do
167
- created = create_uploaded_import(translation_memories, tmx_file_path, processing_polls: 1)
168
- polled_statuses = []
169
- allow(translation_memories).to receive(:find_job).and_wrap_original do |original, *args|
170
- original.call(*args).tap { |status| polled_statuses << status.status }
171
- end
172
- expect(translation_memories).to receive(:sleep).once
173
-
174
- job = translation_memories.wait_until_job_done(created.job_id)
175
-
176
- expect(polled_statuses).to eq(%w[awaiting_input completed])
177
- expect(job.status).to eq('completed')
178
- DeepL.translation_memories.destroy(job.result.translation_memory_id)
179
- end
180
-
181
- it 'when the file is never uploaded it waits until the timeout of the caller' do
182
- created = translation_memories.create_import('never-uploaded.tmx', 128)
183
- # Such a job does not finish on its own, only the timeout ends the wait.
184
- expect(translation_memories).not_to receive(:sleep)
185
-
186
- expect { translation_memories.wait_until_job_done(created.job_id, timeout_s: 0) }
187
- .to raise_error(DeepL::Exceptions::Error, /Manual timeout of 0s exceeded/)
188
- end
189
- end
190
-
191
- describe '#export_to_filepath' do
192
- let(:output_path) { File.join(temp_dir, 'export.tmx') }
193
-
194
- it 'when exporting a translation memory to a TMX file' do
195
- job = DeepL.translation_memories.export_to_filepath(default_tm_id, output_path)
196
- expect(job).to be_a(DeepL::Resources::TranslationMemoryJob)
197
- expect(job.operation).to eq('export')
198
- expect(job.status).to eq('completed')
199
- expect(job.result.download_url).to start_with('http')
200
-
201
- contents = File.read(output_path)
202
- expect(contents).to include('<tmx version="1.4">')
203
- expect(contents).to include('<seg>Quelltext Nummer 0</seg>')
204
- expect(contents).to include('<tuv xml:lang="en"><seg>Target text number 0 (de->en)</seg>')
205
- end
206
-
207
- it 'when re-exporting an unchanged translation memory it reuses the completed job' do
208
- job = DeepL.translation_memories.export_to_filepath(default_tm_id, output_path)
209
- reused = DeepL.translation_memories.create_export(default_tm_id)
210
- expect(reused).to be_a(DeepL::Resources::TranslationMemoryExport)
211
- expect(reused.reused_existing?).to be(true)
212
- expect(reused.job_id).to eq(job.job_id)
213
- expect(reused.translation_memory_id).to eq(default_tm_id)
214
- end
215
- end
216
-
217
- describe '#destroy' do
218
- it 'when deleting a translation memory it can no longer be found' do
219
- job = DeepL.translation_memories.import_from_filepath(tmx_file_path)
220
- translation_memory_id = job.result.translation_memory_id
221
-
222
- expect(DeepL.translation_memories.destroy(translation_memory_id))
223
- .to eq(translation_memory_id)
224
- expect { DeepL.translation_memories.find(translation_memory_id) }
225
- .to raise_error(DeepL::Exceptions::NotFound)
226
- end
227
- end
228
-
229
- def next_segments_page(page)
230
- DeepL.translation_memories.segments(default_tm_id, page_size: 5,
231
- page_cursor: page.next_page_cursor)
232
- end
233
-
234
- def build_test_translation_memory
235
- tm_data = {
236
- 'translation_memory_id' => 'a74d88fb-ed2a-4943-a664-a4512398b994',
237
- 'name' => 'Default Translation Memory',
238
- 'source_language' => 'DE',
239
- 'target_languages' => %w[EN ES FR],
240
- 'segment_count' => 3542
241
- }
242
- DeepL::Resources::TranslationMemory.new(tm_data, nil, nil)
243
- end
244
- end
@@ -1,87 +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::TranslationMemoryApi, :mock_server_only do # rubocop:disable RSpec/SpecFilePathFormat
9
- include_context 'with a live mock server'
10
-
11
- let(:default_tm_id) { 'a74d88fb-ed2a-4943-a664-a4512398b994' }
12
- let(:missing_uuid) { '00000000-0000-0000-0000-000000000000' }
13
-
14
- describe 'authorization failures' do
15
- let(:unauthorized_translation_memories) { described_class.new(unauthorized_api) }
16
-
17
- it 'raises AuthorizationFailed when listing with an invalid auth key' do
18
- expect { unauthorized_translation_memories.list }
19
- .to raise_error(DeepL::Exceptions::AuthorizationFailed)
20
- end
21
-
22
- it 'raises AuthorizationFailed on a read operation (find)' do
23
- expect { unauthorized_translation_memories.find(default_tm_id) }
24
- .to raise_error(DeepL::Exceptions::AuthorizationFailed)
25
- end
26
-
27
- it 'raises AuthorizationFailed on a write operation (create_export)' do
28
- expect { unauthorized_translation_memories.create_export(default_tm_id) }
29
- .to raise_error(DeepL::Exceptions::AuthorizationFailed)
30
- end
31
- end
32
-
33
- describe 'not-found failures' do
34
- it 'raises NotFound when #find is called with a missing UUID' do
35
- expect { DeepL.translation_memories.find(missing_uuid) }
36
- .to raise_error(DeepL::Exceptions::NotFound)
37
- end
38
-
39
- it 'raises NotFound when #segments is called with a missing UUID' do
40
- expect { DeepL.translation_memories.segments(missing_uuid) }
41
- .to raise_error(DeepL::Exceptions::NotFound)
42
- end
43
-
44
- it 'raises NotFound when #find_job is called with a missing UUID' do
45
- expect { DeepL.translation_memories.find_job(missing_uuid) }
46
- .to raise_error(DeepL::Exceptions::NotFound)
47
- end
48
- end
49
-
50
- describe 'bad-request failures' do
51
- it 'raises BadRequest when #segments is called with a too short text filter' do
52
- expect { DeepL.translation_memories.segments(default_tm_id, filter_text: 'a') }
53
- .to raise_error(DeepL::Exceptions::BadRequest)
54
- end
55
-
56
- it 'raises an error when #destroy is called with a malformed UUID' do
57
- expect { DeepL.translation_memories.destroy('invalid-uuid') }
58
- .to raise_error(DeepL::Exceptions::Error)
59
- end
60
- end
61
-
62
- describe 'client-side validation failures' do
63
- it 'raises an error when #find is called with an empty ID' do
64
- expect { DeepL.translation_memories.find('') }
65
- .to raise_error(DeepL::Exceptions::Error, /must not be empty/)
66
- end
67
-
68
- it 'raises an error when #find_job is called with an empty job ID' do
69
- expect { DeepL.translation_memories.find_job(nil) }
70
- .to raise_error(DeepL::Exceptions::Error, /must not be empty/)
71
- end
72
-
73
- it 'raises an error when #import_from_filepath is given a missing file' do
74
- expect { DeepL.translation_memories.import_from_filepath('/no/such/file.tmx') }
75
- .to raise_error(DeepL::Exceptions::Error, /No file found/)
76
- end
77
-
78
- it 'raises an error when #download_export is given an unfinished job' do
79
- created = DeepL.translation_memories.create_export(default_tm_id)
80
- job = DeepL::Resources::TranslationMemoryJob.new(
81
- { 'job_id' => created.job_id, 'results' => [{ 'status' => 'processing' }] }, nil, nil
82
- )
83
- expect { DeepL.translation_memories.download_export(job, '/tmp/unused.tmx') }
84
- .to raise_error(DeepL::Exceptions::Error, /no download URL/)
85
- end
86
- end
87
- end
@@ -1,29 +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.usage' do # rubocop:disable RSpec/DescribeClass
9
- describe 'happy path' do
10
- it 'returns a Usage resource with integer counters where count does not exceed limit' do
11
- usage = DeepL.usage
12
-
13
- expect(usage).to be_a(DeepL::Resources::Usage)
14
- expect(usage).to respond_to(:character_count, :character_limit)
15
- expect(usage.character_count).to be_an(Integer)
16
- expect(usage.character_limit).to be_an(Integer)
17
- expect(usage.character_count).to be <= usage.character_limit
18
- end
19
- end
20
-
21
- describe 'resource shape' do
22
- it 'exposes quota_exceeded? consistent with character_count vs character_limit' do
23
- usage = DeepL.usage
24
-
25
- expect(usage).to respond_to(:quota_exceeded?)
26
- expect(usage.quota_exceeded?).to eq(usage.character_count >= usage.character_limit)
27
- end
28
- end
29
- end
@@ -1,18 +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.usage 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::Usage.new(unauthorized_api)
14
-
15
- expect { request.request }.to raise_error(DeepL::Exceptions::AuthorizationFailed)
16
- end
17
- end
18
- end
@@ -1,130 +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::Requests::Document::Upload do
9
- subject(:upload) do
10
- described_class.new(api, input_file_path, source_lang, target_lang, filename, options)
11
- end
12
-
13
- around do |tests|
14
- tmp_env = replace_env_preserving_deepl_vars_except_mock_server
15
- tests.call
16
- ENV.replace(tmp_env)
17
- end
18
-
19
- let(:api) { build_deepl_api }
20
- let(:input_file_path) { '/tmp/example.txt' }
21
- let(:source_lang) { 'EN' }
22
- let(:target_lang) { 'DE' }
23
- let(:filename) { 'example.txt' }
24
- let(:options) { {} }
25
- let(:input_file) { instance_double(File) }
26
-
27
- # Builds the multipart form data without performing any network or filesystem IO.
28
- def form_data
29
- upload.send(:build_base_form_data, input_file)
30
- end
31
-
32
- def form_value(form, key)
33
- field = form.find { |name, _| name == key }
34
- field&.last
35
- end
36
-
37
- describe '#initialize' do
38
- it 'creates a request object' do
39
- expect(upload).to be_a(described_class)
40
- end
41
- end
42
-
43
- describe 'building the upload form data' do
44
- context 'when using the `style_rule` option' do
45
- it 'does not append a `style_id` field when not provided' do
46
- expect(form_value(form_data, 'style_id')).to be_nil
47
- end
48
-
49
- it 'appends a `style_id` field from a style rule ID string' do
50
- options[:style_rule] = 'style-123'
51
- expect(form_value(form_data, 'style_id')).to eq('style-123')
52
- end
53
-
54
- it 'appends a `style_id` field from a StyleRule object' do
55
- options[:style_rule] =
56
- DeepL::Resources::StyleRule.new({ 'style_id' => 'style-obj' }, nil, nil)
57
- expect(form_value(form_data, 'style_id')).to eq('style-obj')
58
- end
59
- end
60
-
61
- context 'when using the `translation_memory` option' do
62
- it 'does not append a `translation_memory_id` field when not provided' do
63
- expect(form_value(form_data, 'translation_memory_id')).to be_nil
64
- end
65
-
66
- it 'appends a `translation_memory_id` field from a translation memory ID string' do
67
- options[:translation_memory] = 'tm-123'
68
- expect(form_value(form_data, 'translation_memory_id')).to eq('tm-123')
69
- end
70
-
71
- it 'appends a `translation_memory_id` field from a TranslationMemory object' do
72
- options[:translation_memory] =
73
- DeepL::Resources::TranslationMemory.new({ 'translation_memory_id' => 'tm-obj' }, nil, nil)
74
- expect(form_value(form_data, 'translation_memory_id')).to eq('tm-obj')
75
- end
76
-
77
- it 'appends a `translation_memory_threshold` field serialized to a string' do
78
- options[:translation_memory] = 'tm-123'
79
- options[:translation_memory_threshold] = 80
80
- form = form_data
81
- expect(form_value(form, 'translation_memory_id')).to eq('tm-123')
82
- expect(form_value(form, 'translation_memory_threshold')).to eq('80')
83
- end
84
-
85
- it 'does not append a `translation_memory_threshold` field when not provided' do
86
- options[:translation_memory] = 'tm-123'
87
- expect(form_value(form_data, 'translation_memory_threshold')).to be_nil
88
- end
89
- end
90
-
91
- context 'when using the `glossary_ids` option' do
92
- it 'does not append a `glossary_ids` field when not provided' do
93
- expect(form_value(form_data, 'glossary_ids')).to be_nil
94
- end
95
-
96
- it 'appends a comma-separated `glossary_ids` field from an array of IDs' do
97
- options[:glossary_ids] = %w[gid1 gid2 gid3]
98
- expect(form_value(form_data, 'glossary_ids')).to eq('gid1,gid2,gid3')
99
- end
100
-
101
- it 'appends `glossary_ids` from Glossary objects using their IDs' do
102
- options[:glossary_ids] = [
103
- DeepL::Resources::Glossary.new({ 'glossary_id' => 'gid-obj' }, nil, nil),
104
- 'gid-str'
105
- ]
106
- expect(form_value(form_data, 'glossary_ids')).to eq('gid-obj,gid-str')
107
- end
108
-
109
- it 'raises when combined with the singular `glossary_id` option' do
110
- options[:glossary_id] = 'single'
111
- options[:glossary_ids] = %w[gid1]
112
- expect { form_data }.to raise_error(ArgumentError, /cannot be used together/)
113
- end
114
-
115
- it 'raises when more than 5 glossary IDs are provided' do
116
- options[:glossary_ids] = %w[a b c d e f]
117
- expect { form_data }.to raise_error(ArgumentError, /maximum of 5 glossary IDs/)
118
- end
119
-
120
- context 'when `source_lang` is not set' do
121
- let(:source_lang) { nil }
122
-
123
- it 'raises because `glossary_ids` requires `source_lang`' do
124
- options[:glossary_ids] = %w[gid1]
125
- expect { form_data }.to raise_error(ArgumentError, /requires `source_lang`/)
126
- end
127
- end
128
- end
129
- end
130
- end
@@ -1,82 +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.md file.
4
- # frozen_string_literal: true
5
-
6
- require 'spec_helper'
7
-
8
- describe 'DeepL::Requests::Base extra_body_parameters type preservation' do
9
- let(:api) { build_deepl_api }
10
-
11
- around do |tests|
12
- tmp_env = replace_env_preserving_deepl_vars_except_mock_server
13
- tests.call
14
- ENV.replace(tmp_env)
15
- end
16
-
17
- describe 'apply_extra_body_parameters_to_json' do
18
- it 'preserves boolean true' do
19
- request = DeepL::Requests::Translate.new(
20
- api, 'test', 'EN', 'ES',
21
- extra_body_parameters: { enable_beta_languages: true }
22
- )
23
-
24
- payload = {}
25
- request.send(:apply_extra_body_parameters_to_json, payload)
26
-
27
- expect(payload[:enable_beta_languages]).to be(true)
28
- expect(payload[:enable_beta_languages]).to be_a(TrueClass)
29
- end
30
-
31
- it 'preserves boolean false' do
32
- request = DeepL::Requests::Translate.new(
33
- api, 'test', 'EN', 'ES',
34
- extra_body_parameters: { some_flag: false }
35
- )
36
-
37
- payload = {}
38
- request.send(:apply_extra_body_parameters_to_json, payload)
39
-
40
- expect(payload[:some_flag]).to be(false)
41
- expect(payload[:some_flag]).to be_a(FalseClass)
42
- end
43
-
44
- it 'preserves integers' do
45
- request = DeepL::Requests::Translate.new(
46
- api, 'test', 'EN', 'ES',
47
- extra_body_parameters: { some_number: 42 }
48
- )
49
-
50
- payload = {}
51
- request.send(:apply_extra_body_parameters_to_json, payload)
52
-
53
- expect(payload[:some_number]).to eq(42)
54
- expect(payload[:some_number]).to be_a(Integer)
55
- end
56
-
57
- it 'preserves strings' do
58
- request = DeepL::Requests::Translate.new(
59
- api, 'test', 'EN', 'ES',
60
- extra_body_parameters: { some_string: 'hello' }
61
- )
62
-
63
- payload = {}
64
- request.send(:apply_extra_body_parameters_to_json, payload)
65
-
66
- expect(payload[:some_string]).to eq('hello')
67
- expect(payload[:some_string]).to be_a(String)
68
- end
69
-
70
- it 'allows overriding standard parameters' do
71
- request = DeepL::Requests::Translate.new(
72
- api, 'test', 'EN', 'ES',
73
- extra_body_parameters: { target_lang: 'FR' }
74
- )
75
-
76
- payload = { target_lang: 'ES' }
77
- request.send(:apply_extra_body_parameters_to_json, payload)
78
-
79
- expect(payload[:target_lang]).to eq('FR')
80
- end
81
- end
82
- end
@@ -1,44 +0,0 @@
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.
4
- # frozen_string_literal: true
5
-
6
- require 'spec_helper'
7
-
8
- describe DeepL::Requests::Glossary::Create do
9
- subject(:create) do
10
- described_class.new(api, name, source_lang, target_lang, entries, options)
11
- end
12
-
13
- around do |tests|
14
- tmp_env = replace_env_preserving_deepl_vars_except_mock_server
15
- tests.call
16
- ENV.replace(tmp_env)
17
- end
18
-
19
- let(:api) { build_deepl_api }
20
- let(:name) { 'Mi Glosario' }
21
- let(:source_lang) { 'EN' }
22
- let(:target_lang) { 'ES' }
23
- let(:entries) do
24
- [
25
- %w[Hello Hola],
26
- %w[World Mundo]
27
- ]
28
- end
29
- let(:options) { {} }
30
-
31
- describe '#initialize' do
32
- context 'when building a request' do
33
- it 'creates a request object' do
34
- expect(create).to be_a(described_class)
35
- end
36
-
37
- it 'sets the default value for the entries format if not specified' do
38
- request = described_class.new(api, name, source_lang, target_lang,
39
- entries, options)
40
- expect(request.entries_format).to eq('tsv')
41
- end
42
- end
43
- end
44
- end
@@ -1,27 +0,0 @@
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.
4
- # frozen_string_literal: true
5
-
6
- require 'spec_helper'
7
-
8
- describe DeepL::Requests::Glossary::Destroy do
9
- subject(:destroy) { described_class.new(api, id) }
10
-
11
- around do |tests|
12
- tmp_env = replace_env_preserving_deepl_vars_except_mock_server
13
- tests.call
14
- ENV.replace(tmp_env)
15
- end
16
-
17
- let(:api) { build_deepl_api }
18
- let(:id) { '9ab5dac2-b7b2-4b4a-808a-e8e305df5ecb' }
19
-
20
- describe '#initialize' do
21
- context 'when building a request' do
22
- it 'creates a request object' do
23
- expect(destroy).to be_a(described_class)
24
- end
25
- end
26
- end
27
- end