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.
- checksums.yaml +4 -4
- data/.gitlab-ci.yml +70 -52
- data/.rubocop.yml +26 -0
- data/CHANGELOG.md +429 -18
- data/Gemfile +4 -0
- data/README.md +981 -223
- data/Rakefile +18 -5
- data/VERSION +1 -1
- data/deepl-rb.gemspec +6 -6
- data/lib/deepl/admin_client.rb +183 -0
- data/lib/deepl/api.rb +30 -6
- data/lib/deepl/app_info.rb +20 -0
- data/lib/deepl/client.rb +969 -0
- data/lib/deepl/configuration.rb +56 -10
- data/lib/deepl/constants/admin_usage_group_by.rb +13 -0
- data/lib/deepl/constants/custom_tag_usage_aggregate_by.rb +13 -0
- data/lib/deepl/constants/document_status_code.rb +17 -0
- data/lib/deepl/constants/language_include.rb +17 -0
- data/lib/deepl/constants/language_resource_name.rb +21 -0
- data/lib/deepl/constants/tag_handling_version.rb +14 -0
- data/lib/deepl/deprecation.rb +42 -0
- data/lib/deepl/document_api.rb +41 -22
- data/lib/deepl/exceptions/bad_request.rb +1 -3
- data/lib/deepl/exceptions/connection_error.rb +37 -0
- data/lib/deepl/exceptions/document_not_ready_error.rb +17 -0
- data/lib/deepl/exceptions/document_translation_error.rb +17 -1
- data/lib/deepl/exceptions/error.rb +13 -1
- data/lib/deepl/exceptions/not_found.rb +8 -3
- data/lib/deepl/exceptions/not_supported.rb +6 -0
- data/lib/deepl/exceptions/request_error.rb +19 -2
- data/lib/deepl/exceptions/server_error.rb +7 -1
- data/lib/deepl/exceptions/validation_error.rb +14 -0
- data/lib/deepl/requests/admin/base.rb +94 -0
- data/lib/deepl/requests/admin/create_developer_key.rb +38 -0
- data/lib/deepl/requests/admin/custom_tag_usage_analytics.rb +38 -0
- data/lib/deepl/requests/admin/list_developer_keys.rb +28 -0
- data/lib/deepl/requests/admin/update_developer_key.rb +35 -0
- data/lib/deepl/requests/admin/usage_analytics.rb +36 -0
- data/lib/deepl/requests/base.rb +229 -59
- data/lib/deepl/requests/correct.rb +57 -0
- data/lib/deepl/requests/document/download.rb +11 -3
- data/lib/deepl/requests/document/get_status.rb +2 -2
- data/lib/deepl/requests/document/upload.rb +43 -10
- data/lib/deepl/requests/glossary/create.rb +6 -2
- data/lib/deepl/requests/glossary/language_pairs.rb +20 -4
- data/lib/deepl/requests/language_resources.rb +41 -0
- data/lib/deepl/requests/languages.rb +28 -4
- data/lib/deepl/requests/languages_for_resource.rb +54 -0
- data/lib/deepl/requests/multilingual_glossary/create.rb +37 -0
- data/lib/deepl/requests/multilingual_glossary/destroy.rb +36 -0
- data/lib/deepl/requests/multilingual_glossary/destroy_dictionary.rb +51 -0
- data/lib/deepl/requests/multilingual_glossary/entries.rb +66 -0
- data/lib/deepl/requests/multilingual_glossary/find.rb +35 -0
- data/lib/deepl/requests/multilingual_glossary/helpers.rb +63 -0
- data/lib/deepl/requests/multilingual_glossary/list.rb +39 -0
- data/lib/deepl/requests/multilingual_glossary/replace_dictionary.rb +41 -0
- data/lib/deepl/requests/multilingual_glossary/update.rb +40 -0
- data/lib/deepl/requests/rephrase.rb +5 -9
- data/lib/deepl/requests/spoken_terms/create.rb +37 -0
- data/lib/deepl/requests/spoken_terms/destroy.rb +36 -0
- data/lib/deepl/requests/spoken_terms/destroy_term_list.rb +41 -0
- data/lib/deepl/requests/spoken_terms/entries.rb +46 -0
- data/lib/deepl/requests/spoken_terms/find.rb +35 -0
- data/lib/deepl/requests/spoken_terms/helpers.rb +67 -0
- data/lib/deepl/requests/spoken_terms/list.rb +35 -0
- data/lib/deepl/requests/spoken_terms/replace_term_list.rb +41 -0
- data/lib/deepl/requests/spoken_terms/update.rb +40 -0
- data/lib/deepl/requests/style_profile/base.rb +83 -0
- data/lib/deepl/requests/style_profile/create.rb +35 -0
- data/lib/deepl/requests/style_profile/destroy.rb +34 -0
- data/lib/deepl/requests/style_profile/find.rb +33 -0
- data/lib/deepl/requests/style_profile/list.rb +43 -0
- data/lib/deepl/requests/style_profile/update.rb +35 -0
- data/lib/deepl/requests/style_rule/create.rb +1 -1
- data/lib/deepl/requests/style_rule/create_custom_instruction.rb +4 -2
- data/lib/deepl/requests/style_rule/destroy.rb +4 -2
- data/lib/deepl/requests/style_rule/destroy_custom_instruction.rb +5 -3
- data/lib/deepl/requests/style_rule/find.rb +4 -2
- data/lib/deepl/requests/style_rule/find_custom_instruction.rb +5 -3
- data/lib/deepl/requests/style_rule/helpers.rb +35 -0
- data/lib/deepl/requests/style_rule/list.rb +1 -1
- data/lib/deepl/requests/style_rule/update.rb +4 -2
- data/lib/deepl/requests/style_rule/update_configured_rules.rb +4 -2
- data/lib/deepl/requests/style_rule/update_custom_instruction.rb +5 -3
- data/lib/deepl/requests/translate.rb +52 -20
- data/lib/deepl/requests/translation_memory/base.rb +1 -4
- data/lib/deepl/requests/translation_memory/create_export.rb +1 -1
- data/lib/deepl/requests/translation_memory/create_import.rb +1 -1
- data/lib/deepl/requests/translation_memory/destroy.rb +1 -1
- data/lib/deepl/requests/translation_memory/download_export.rb +4 -0
- data/lib/deepl/requests/translation_memory/find.rb +1 -1
- data/lib/deepl/requests/translation_memory/find_job.rb +1 -1
- data/lib/deepl/requests/translation_memory/list.rb +2 -1
- data/lib/deepl/requests/translation_memory/segments.rb +3 -2
- data/lib/deepl/requests/translation_memory/storage_base.rb +40 -8
- data/lib/deepl/requests/translation_memory/upload_file.rb +1 -1
- data/lib/deepl/requests/usage.rb +28 -1
- data/lib/deepl/requests/write_improvements.rb +35 -0
- data/lib/deepl/resources/admin_usage_report.rb +73 -0
- data/lib/deepl/resources/custom_tag_usage_report.rb +59 -0
- data/lib/deepl/resources/developer_key.rb +57 -0
- data/lib/deepl/resources/document_handle.rb +24 -25
- data/lib/deepl/resources/document_translation_status.rb +23 -4
- data/lib/deepl/resources/language.rb +10 -2
- data/lib/deepl/resources/language_resource.rb +57 -0
- data/lib/deepl/resources/language_support.rb +56 -0
- data/lib/deepl/resources/multilingual_glossary.rb +112 -0
- data/lib/deepl/resources/spoken_terms.rb +61 -0
- data/lib/deepl/resources/style_profile.rb +44 -0
- data/lib/deepl/resources/style_rule.rb +3 -0
- data/lib/deepl/resources/text.rb +18 -2
- data/lib/deepl/resources/translation_memory.rb +8 -2
- data/lib/deepl/resources/translation_memory_import.rb +1 -1
- data/lib/deepl/resources/translation_memory_job.rb +23 -3
- data/lib/deepl/resources/translation_memory_segments.rb +8 -6
- data/lib/deepl/resources/usage.rb +93 -4
- data/lib/deepl/style_rule_api.rb +11 -0
- data/lib/deepl/translation_memory_api.rb +104 -24
- data/lib/deepl/utils/client_builder.rb +54 -0
- data/lib/deepl/utils/document_poller.rb +70 -0
- data/lib/deepl/utils/exception_builder.rb +3 -2
- data/lib/deepl/utils/http_client_builder.rb +79 -0
- data/lib/deepl/utils/number_parser.rb +34 -0
- data/lib/deepl/utils/term_validator.rb +33 -0
- data/lib/deepl/utils/time_parser.rb +14 -0
- data/lib/deepl.rb +166 -41
- data/lib/http_client_options.rb +21 -1
- data/lib/version.rb +1 -1
- data/spec/fixtures.rb +33 -0
- data/spec/offline/admin_client_spec.rb +551 -0
- data/spec/offline/client_spec.rb +273 -0
- data/spec/{api → offline}/configuration_spec.rb +45 -3
- data/spec/{constants → offline}/constants_spec.rb +23 -1
- data/spec/offline/correct_text_spec.rb +50 -0
- data/spec/offline/deprecation_spec.rb +32 -0
- data/spec/offline/errors_spec.rb +92 -0
- data/spec/offline/glossaries_spec.rb +98 -0
- data/spec/offline/http_client_spec.rb +319 -0
- data/spec/offline/languages_spec.rb +155 -0
- data/spec/offline/module_methods_spec.rb +13 -0
- data/spec/offline/multilingual_glossaries_spec.rb +358 -0
- data/spec/offline/offline_helper.rb +71 -0
- data/spec/offline/rephrase_text_spec.rb +73 -0
- data/spec/offline/spoken_terms_spec.rb +215 -0
- data/spec/offline/style_profiles_spec.rb +266 -0
- data/spec/offline/style_rules_spec.rb +318 -0
- data/spec/offline/translate_document_spec.rb +606 -0
- data/spec/offline/translate_text_spec.rb +286 -0
- data/spec/offline/translation_memories_client_spec.rb +256 -0
- data/spec/offline/translation_memories_spec.rb +463 -0
- data/spec/offline/usage_spec.rb +151 -0
- data/spec/real_api/admin_client_spec.rb +77 -0
- data/spec/real_api/correct_text_spec.rb +20 -0
- data/spec/real_api/glossaries_spec.rb +28 -0
- data/spec/real_api/languages_spec.rb +27 -0
- data/spec/real_api/multilingual_glossaries_spec.rb +53 -0
- data/spec/real_api/proxy_spec.rb +41 -0
- data/spec/real_api/real_api_helper.rb +65 -0
- data/spec/real_api/rephrase_text_spec.rb +16 -0
- data/spec/real_api/spoken_terms_spec.rb +56 -0
- data/spec/real_api/style_profiles_spec.rb +46 -0
- data/spec/real_api/style_rules_spec.rb +46 -0
- data/spec/real_api/translate_document_spec.rb +18 -0
- data/spec/real_api/translate_text_spec.rb +16 -0
- data/spec/real_api/translation_memories_spec.rb +56 -0
- data/spec/real_api/usage_spec.rb +20 -0
- data/spec/spec_helper.rb +1 -50
- metadata +116 -76
- data/.circleci/config.yml +0 -27
- data/.github/workflows/add_issues_to_kanban.yml +0 -16
- data/spec/api/api_spec.rb +0 -20
- data/spec/api/deepl_spec.rb +0 -262
- data/spec/integration_tests/document_api_spec.rb +0 -211
- data/spec/integration_tests/document_error_paths_spec.rb +0 -33
- data/spec/integration_tests/glossary_api_spec.rb +0 -114
- data/spec/integration_tests/glossary_error_paths_spec.rb +0 -107
- data/spec/integration_tests/integration_test_utils.rb +0 -178
- data/spec/integration_tests/languages_api_spec.rb +0 -54
- data/spec/integration_tests/languages_error_paths_spec.rb +0 -25
- data/spec/integration_tests/rephrase_api_spec.rb +0 -90
- data/spec/integration_tests/rephrase_error_paths_spec.rb +0 -53
- data/spec/integration_tests/smoke_test_spec.rb +0 -24
- data/spec/integration_tests/style_rule_api_spec.rb +0 -117
- data/spec/integration_tests/style_rule_error_paths_spec.rb +0 -45
- data/spec/integration_tests/translate_api_spec.rb +0 -117
- data/spec/integration_tests/translate_error_paths_spec.rb +0 -48
- data/spec/integration_tests/translation_memory_api_spec.rb +0 -244
- data/spec/integration_tests/translation_memory_error_paths_spec.rb +0 -87
- data/spec/integration_tests/usage_api_spec.rb +0 -29
- data/spec/integration_tests/usage_error_paths_spec.rb +0 -18
- data/spec/requests/document/upload_spec.rb +0 -130
- data/spec/requests/extra_body_parameters_types_spec.rb +0 -82
- data/spec/requests/glossary/create_spec.rb +0 -44
- data/spec/requests/glossary/destroy_spec.rb +0 -27
- data/spec/requests/glossary/entries_spec.rb +0 -27
- data/spec/requests/glossary/find_spec.rb +0 -28
- data/spec/requests/glossary/language_pairs_spec.rb +0 -27
- data/spec/requests/glossary/list_spec.rb +0 -27
- data/spec/requests/languages_spec.rb +0 -27
- data/spec/requests/rephrase_spec.rb +0 -46
- data/spec/requests/style_rule/create_custom_instruction_spec.rb +0 -30
- data/spec/requests/style_rule/create_spec.rb +0 -29
- data/spec/requests/style_rule/destroy_custom_instruction_spec.rb +0 -28
- data/spec/requests/style_rule/destroy_spec.rb +0 -27
- data/spec/requests/style_rule/find_custom_instruction_spec.rb +0 -29
- data/spec/requests/style_rule/find_spec.rb +0 -28
- data/spec/requests/style_rule/list_spec.rb +0 -27
- data/spec/requests/style_rule/update_configured_rules_spec.rb +0 -31
- data/spec/requests/style_rule/update_custom_instruction_spec.rb +0 -32
- data/spec/requests/style_rule/update_spec.rb +0 -29
- data/spec/requests/translate_spec.rb +0 -338
- data/spec/requests/translation_memory/create_export_spec.rb +0 -37
- data/spec/requests/translation_memory/create_import_spec.rb +0 -61
- data/spec/requests/translation_memory/destroy_spec.rb +0 -36
- data/spec/requests/translation_memory/download_export_spec.rb +0 -54
- data/spec/requests/translation_memory/find_job_spec.rb +0 -37
- data/spec/requests/translation_memory/find_spec.rb +0 -36
- data/spec/requests/translation_memory/list_spec.rb +0 -27
- data/spec/requests/translation_memory/segments_spec.rb +0 -58
- data/spec/requests/translation_memory/upload_file_spec.rb +0 -55
- data/spec/requests/usage_spec.rb +0 -27
- data/spec/resources/custom_instruction_spec.rb +0 -32
- data/spec/resources/glossary_spec.rb +0 -38
- data/spec/resources/language_pair_spec.rb +0 -23
- data/spec/resources/language_spec.rb +0 -45
- data/spec/resources/style_rule_spec.rb +0 -68
- data/spec/resources/text_spec.rb +0 -23
- data/spec/resources/translation_memory_export_spec.rb +0 -38
- data/spec/resources/translation_memory_import_spec.rb +0 -30
- data/spec/resources/translation_memory_job_spec.rb +0 -109
- data/spec/resources/translation_memory_segments_spec.rb +0 -78
- data/spec/resources/translation_memory_spec.rb +0 -52
- data/spec/resources/usage_spec.rb +0 -35
- data/spec/support/live_mock_server.rb +0 -12
- data/spec/support/managed_glossary.rb +0 -65
- data/spec/support/managed_style_rule.rb +0 -17
- data/spec/support/managed_translation_memory.rb +0 -55
data/README.md
CHANGED
|
@@ -27,6 +27,46 @@ gem 'deepl-rb', require: 'deepl'
|
|
|
27
27
|
|
|
28
28
|
## Usage
|
|
29
29
|
|
|
30
|
+
### Creating a client
|
|
31
|
+
|
|
32
|
+
Create a `DeepL::Client` with your authentication key. Each client owns its configuration and
|
|
33
|
+
HTTP connection, so several clients with different keys or options can be used side by side.
|
|
34
|
+
The client reads no environment variables:
|
|
35
|
+
|
|
36
|
+
```rb
|
|
37
|
+
client = DeepL::Client.new(ENV.fetch('DEEPL_AUTH_KEY'))
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
`DeepL::Client.new` accepts these keyword arguments:
|
|
41
|
+
|
|
42
|
+
| Option | Default | Description |
|
|
43
|
+
| ------ | ------- | ----------- |
|
|
44
|
+
| `server_url:` | `https://api-free.deepl.com` for Free keys (ending in `:fx`), else `https://api.deepl.com` | Base URL of the DeepL API. A path prefix is kept. |
|
|
45
|
+
| `headers:` | `{}` | HTTP headers sent with every DeepL API request. A header of the same name, in any casing, replaces the library's, `Authorization` and `User-Agent` included, except `Content-Type`, `Content-Length`, `Transfer-Encoding` and `Host`. Pre-signed storage URLs get only the `User-Agent`. |
|
|
46
|
+
| `max_retries:` | `5` | Retries after the first attempt, for HTTP 429, any 5xx and transient network failures. |
|
|
47
|
+
| `timeout:` | `10` | Timeout of each attempt in seconds. A longer backoff interval takes precedence. |
|
|
48
|
+
| `proxy:` | none | Proxy URL, e.g. `http://user:password@proxy.example:8080`. |
|
|
49
|
+
| `send_platform_info:` | `true` | Adds the OS and Ruby versions to the `User-Agent`. |
|
|
50
|
+
| `app_info:` | none | A `DeepL::AppInfo` or a hash with `app_name` and `app_version`, added to the `User-Agent`. |
|
|
51
|
+
| `http_client_options:` | none | A `DeepL::HTTPClientOptions` with proxy, certificate, SSL verification and per-phase timeouts. Its timeouts take precedence over `timeout:`. |
|
|
52
|
+
| `logger:` | none | Logger for requests and retries, see [Logging](#logging). |
|
|
53
|
+
|
|
54
|
+
The authentication key is trimmed; an empty key raises `ArgumentError`.
|
|
55
|
+
`DeepL::Client.free_account_auth_key?(key)` returns whether a key is a DeepL API Free key.
|
|
56
|
+
|
|
57
|
+
`DeepL::Client` offers text translation (`translate_text`, see [Translate](#translate)),
|
|
58
|
+
document translation (`translate_document` and its steps, see
|
|
59
|
+
[Translate documents](#translate-documents)), rephrasing and correction (`rephrase_text` and
|
|
60
|
+
`correct_text`, see [Rephrase Text](#rephrase-text) and [Correct Text](#correct-text)),
|
|
61
|
+
multilingual glossaries (see [Multilingual glossaries](#multilingual-glossaries)),
|
|
62
|
+
spoken terms (see
|
|
63
|
+
[Spoken terms](#spoken-terms)) and usage (`get_usage`, see [Monitor usage](#monitor-usage)); for the other operations, use the module-level API shown in the following sections. The module-level API (`DeepL.configure`, `DeepL.translate`, `DeepL.glossaries`, ...)
|
|
64
|
+
is deprecated and will be removed in the next major version: each method prints a deprecation
|
|
65
|
+
warning once per process when Ruby's deprecation warnings are enabled (`ruby -W:deprecated` or
|
|
66
|
+
`Warning[:deprecated] = true`). See [Migrating to DeepL::Client](#migrating-to-deeplclient).
|
|
67
|
+
|
|
68
|
+
### Module-level configuration (deprecated)
|
|
69
|
+
|
|
30
70
|
Setup an environment variable named `DEEPL_AUTH_KEY` with your authentication key:
|
|
31
71
|
|
|
32
72
|
```sh
|
|
@@ -47,68 +87,144 @@ You can also configure the API host and the API version:
|
|
|
47
87
|
DeepL.configure do |config|
|
|
48
88
|
config.auth_key = 'your-api-token'
|
|
49
89
|
config.host = 'https://api-free.deepl.com' # Default value is 'https://api.deepl.com'
|
|
50
|
-
config.version = 'v1' # Default value is 'v2'
|
|
51
90
|
end
|
|
52
91
|
```
|
|
53
92
|
|
|
93
|
+
Without a host, keys ending in `:fx` use `https://api-free.deepl.com`. The `version` setting
|
|
94
|
+
is deprecated.
|
|
95
|
+
|
|
96
|
+
### Migrating to DeepL::Client
|
|
97
|
+
|
|
98
|
+
The module-level API keeps working until the next major version. Its deprecation warnings
|
|
99
|
+
appear only with Ruby's deprecation warnings on (`ruby -W:deprecated` or
|
|
100
|
+
`Warning[:deprecated] = true`). The `DeepL::Client` methods replacing it:
|
|
101
|
+
|
|
102
|
+
| Module-level API | `DeepL::Client` |
|
|
103
|
+
| ---------------- | --------------- |
|
|
104
|
+
| `DeepL.configure` | `DeepL::Client.new(ENV.fetch('DEEPL_AUTH_KEY'), ...)` |
|
|
105
|
+
| `DeepL.translate` | `translate_text` |
|
|
106
|
+
| `DeepL.rephrase` | `rephrase_text` |
|
|
107
|
+
| `DeepL.usage` | `get_usage` |
|
|
108
|
+
| `DeepL.languages(type:)` | `get_source_languages` / `get_target_languages` |
|
|
109
|
+
| `DeepL.document.*` | `translate_document`, `translate_document_upload`, `translate_document_get_status`, `translate_document_wait_until_done`, `translate_document_download` |
|
|
110
|
+
| `DeepL.glossaries` | the `*_multilingual_glossary*` methods |
|
|
111
|
+
| `DeepL.style_rules` | the style rule methods (`get_all_style_rules`, `create_style_rule`, ...) |
|
|
112
|
+
| `DeepL.translation_memories` | the translation memory methods (`list_translation_memories`, ...) |
|
|
113
|
+
| `DeepL.with_session` / `DeepL.http_client` | the `http_client_options:` and `proxy:` options |
|
|
114
|
+
| per-call `additional_headers` | the `headers:` option |
|
|
115
|
+
|
|
116
|
+
`DeepL::Client` behaves differently from the module-level API in these points:
|
|
117
|
+
|
|
118
|
+
- Network failures raise `DeepL::Exceptions::ConnectionError` (the module-level API raises the
|
|
119
|
+
original network error).
|
|
120
|
+
- The timeout of each attempt defaults to 10 seconds (60 for the module-level API).
|
|
121
|
+
- `translate_document` returns the final `DeepL::Resources::DocumentTranslationStatus` (the
|
|
122
|
+
module-level `DeepL.document.translate_document` returns the number of bytes written).
|
|
123
|
+
- The translation memory file helpers raise `ArgumentError` for a missing input file and
|
|
124
|
+
`DeepL::Exceptions::Error` for other local file failures (the module-level API raises
|
|
125
|
+
`DeepL::Exceptions::Error` and the raw `Errno::*`).
|
|
126
|
+
|
|
54
127
|
### Available languages
|
|
55
128
|
|
|
56
|
-
|
|
129
|
+
`get_source_languages` and `get_target_languages` of `DeepL::Client` return the languages that
|
|
130
|
+
can be translated from and into, as `DeepL::Resources::Language` objects with upper-case codes:
|
|
57
131
|
|
|
58
132
|
```rb
|
|
59
|
-
languages =
|
|
133
|
+
languages = client.get_source_languages
|
|
60
134
|
|
|
61
|
-
puts languages.class
|
|
62
|
-
# => Array
|
|
63
135
|
puts languages.first.class
|
|
64
136
|
# => DeepL::Resources::Language
|
|
65
137
|
puts "#{languages.first.code} -> #{languages.first.name}"
|
|
66
138
|
# => "ES -> Spanish"
|
|
139
|
+
|
|
140
|
+
german = client.get_target_languages.find { |language| language.code == 'DE' }
|
|
141
|
+
puts german.supports_formality?
|
|
142
|
+
# => true
|
|
67
143
|
```
|
|
68
144
|
|
|
69
|
-
|
|
70
|
-
|
|
145
|
+
`supports_formality?` is `true` or `false` for target languages and `nil` for source languages.
|
|
146
|
+
For a source language of the module-level `DeepL.languages`, it raises
|
|
147
|
+
`DeepL::Exceptions::NotSupported`, as in version 3.9.0.
|
|
148
|
+
|
|
149
|
+
All languages are also defined on the
|
|
150
|
+
[official API documentation](https://developers.deepl.com/docs/api-reference/translate).
|
|
151
|
+
|
|
152
|
+
The module-level `DeepL.languages(type: :source)` and `DeepL.languages(type: :target)` are
|
|
153
|
+
deprecated.
|
|
154
|
+
|
|
155
|
+
#### Languages per resource
|
|
156
|
+
|
|
157
|
+
`get_languages_for_resource` returns the languages supported by a given API resource, with
|
|
158
|
+
source/target usability and per-feature support. The language codes are returned as the API sends
|
|
159
|
+
them (`de`, `en-GB`). The resources are defined in `DeepL::Constants::LanguageResourceName`
|
|
160
|
+
(`TRANSLATE_TEXT`, `TRANSLATE_DOCUMENT`, `GLOSSARY`, `VOICE`, `WRITE`, `STYLE_RULES`,
|
|
161
|
+
`TRANSLATION_MEMORY`). Pass `include:` with one value or an array of values from
|
|
162
|
+
`DeepL::Constants::LanguageInclude` (`BETA`, `EXTERNAL`) to also list beta languages and features
|
|
163
|
+
or features that rely on third-party providers. Other strings are sent unchanged, for both the
|
|
164
|
+
resource and `include:`.
|
|
71
165
|
|
|
72
166
|
```rb
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
167
|
+
languages = client.get_languages_for_resource(
|
|
168
|
+
DeepL::Constants::LanguageResourceName::TRANSLATE_TEXT,
|
|
169
|
+
include: [DeepL::Constants::LanguageInclude::BETA]
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
german = languages.find { |language| language.code == 'de' }
|
|
173
|
+
puts german.usable_as_target?
|
|
174
|
+
# => true
|
|
175
|
+
puts german.supports?(:formality)
|
|
176
|
+
# => true
|
|
177
|
+
puts german.features['formality'].status
|
|
178
|
+
# => "stable"
|
|
77
179
|
```
|
|
78
180
|
|
|
79
|
-
|
|
80
|
-
|
|
181
|
+
`get_language_resources` lists every resource with its `name` and features, and whether a
|
|
182
|
+
feature must be supported by the source language, the target language, or both:
|
|
81
183
|
|
|
82
|
-
|
|
83
|
-
|
|
184
|
+
```rb
|
|
185
|
+
translate_text = client.get_language_resources.find { |resource| resource.name == 'translate_text' }
|
|
186
|
+
formality = translate_text.features['formality']
|
|
187
|
+
puts formality.needs_source_support?
|
|
188
|
+
# => false
|
|
189
|
+
puts formality.needs_target_support?
|
|
190
|
+
# => true
|
|
191
|
+
```
|
|
84
192
|
|
|
85
193
|
### Translate
|
|
86
194
|
|
|
87
|
-
To translate a simple text, use the `
|
|
195
|
+
To translate a simple text, use the `translate_text` method of `DeepL::Client`:
|
|
88
196
|
|
|
89
197
|
```rb
|
|
90
|
-
translation =
|
|
198
|
+
translation = client.translate_text 'This is my text', 'EN', 'ES'
|
|
91
199
|
|
|
92
200
|
puts translation.class
|
|
93
201
|
# => DeepL::Resources::Text
|
|
94
202
|
puts translation.text
|
|
95
203
|
# => 'Este es mi texto'
|
|
204
|
+
puts translation.billed_characters
|
|
205
|
+
# => 15
|
|
96
206
|
```
|
|
97
207
|
|
|
208
|
+
Each result has `text`, `detected_source_language`, `billed_characters` (the characters
|
|
209
|
+
billed for the text; the library always asks the API for it), `model_type_used` and
|
|
210
|
+
`tag_handling_version` (the tag handling version the API used, when tag handling was
|
|
211
|
+
requested). A field the response does not contain is `nil`.
|
|
212
|
+
|
|
98
213
|
Enable auto-detect source language by skipping the source language with `nil`:
|
|
99
214
|
|
|
100
215
|
```rb
|
|
101
|
-
translation =
|
|
216
|
+
translation = client.translate_text 'This is my text', nil, 'ES'
|
|
102
217
|
|
|
103
218
|
puts translation.detected_source_language
|
|
104
219
|
# => 'EN'
|
|
105
220
|
```
|
|
106
221
|
|
|
107
|
-
Translate a list of texts by passing an array as an argument
|
|
222
|
+
Translate a list of texts by passing an array as an argument. An array, also one with a
|
|
223
|
+
single text, returns an array of results:
|
|
108
224
|
|
|
109
225
|
```rb
|
|
110
226
|
texts = ['Sample text', 'Another text']
|
|
111
|
-
translations =
|
|
227
|
+
translations = client.translate_text texts, 'EN', 'ES'
|
|
112
228
|
|
|
113
229
|
puts translations.class
|
|
114
230
|
# => Array
|
|
@@ -116,12 +232,13 @@ puts translations.first.class
|
|
|
116
232
|
# => DeepL::Resources::Text
|
|
117
233
|
```
|
|
118
234
|
|
|
119
|
-
|
|
235
|
+
Options are passed as keyword arguments; an option set to `nil` is not sent. You can use
|
|
236
|
+
options like `tag_handling`, `split_sentences`, `non_splitting_tags` or `ignore_tags`:
|
|
120
237
|
|
|
121
238
|
```rb
|
|
122
|
-
translation =
|
|
123
|
-
|
|
124
|
-
|
|
239
|
+
translation = client.translate_text '<p>A sample</p>', 'EN', 'ES',
|
|
240
|
+
tag_handling: 'xml', split_sentences: false,
|
|
241
|
+
non_splitting_tags: 'h1', ignore_tags: %w[code pre]
|
|
125
242
|
|
|
126
243
|
puts translation.text
|
|
127
244
|
# => "<p>Una muestra</p>"
|
|
@@ -130,20 +247,24 @@ puts translation.text
|
|
|
130
247
|
To specify which version of the tag handling algorithm to use, you can use the `tag_handling_version` parameter:
|
|
131
248
|
|
|
132
249
|
```rb
|
|
133
|
-
translation =
|
|
134
|
-
|
|
250
|
+
translation = client.translate_text '<p>A sample</p>', 'EN', 'ES',
|
|
251
|
+
tag_handling: 'xml',
|
|
252
|
+
tag_handling_version: DeepL::Constants::TagHandlingVersion::V2
|
|
135
253
|
|
|
136
254
|
puts translation.text
|
|
137
255
|
# => "<p>Una muestra</p>"
|
|
256
|
+
puts translation.tag_handling_version
|
|
257
|
+
# => "v2"
|
|
138
258
|
```
|
|
139
259
|
|
|
140
|
-
The available values are `'v1'` and `'v2'
|
|
260
|
+
The available values are `'v1'` and `'v2'` (`DeepL::Constants::TagHandlingVersion::V1` and
|
|
261
|
+
`V2`); other strings are sent as given.
|
|
141
262
|
|
|
142
263
|
To translate with context, simply supply the `context` parameter:
|
|
143
264
|
|
|
144
265
|
```rb
|
|
145
|
-
translation =
|
|
146
|
-
|
|
266
|
+
translation = client.translate_text 'That is hot!', 'EN', 'ES',
|
|
267
|
+
context: 'He did not like the jalapenos in his meal.'
|
|
147
268
|
|
|
148
269
|
puts translation.text
|
|
149
270
|
# => "¡Eso es picante!"
|
|
@@ -152,8 +273,8 @@ puts translation.text
|
|
|
152
273
|
To specify a type of translation model to use, you can use the `model_type` option:
|
|
153
274
|
|
|
154
275
|
```rb
|
|
155
|
-
translation =
|
|
156
|
-
|
|
276
|
+
translation = client.translate_text 'That is hot!', 'EN', 'DE',
|
|
277
|
+
model_type: 'quality_optimized'
|
|
157
278
|
```
|
|
158
279
|
|
|
159
280
|
This would use next-gen translation models for the translation. The available values are
|
|
@@ -165,11 +286,12 @@ This would use next-gen translation models for the translation. The available va
|
|
|
165
286
|
- `'latency_optimized'`: use a translation model that minimizes response time, at the cost
|
|
166
287
|
of translation quality.
|
|
167
288
|
|
|
168
|
-
To translate with custom instructions, supply the `custom_instructions` parameter
|
|
289
|
+
To translate with custom instructions, supply the `custom_instructions` parameter, an array
|
|
290
|
+
of instructions. A single string is sent as one instruction, commas included:
|
|
169
291
|
|
|
170
292
|
```rb
|
|
171
|
-
translation =
|
|
172
|
-
|
|
293
|
+
translation = client.translate_text 'Hello, world!', 'EN', 'DE',
|
|
294
|
+
custom_instructions: ['Use informal language', 'Be concise']
|
|
173
295
|
|
|
174
296
|
puts translation.text
|
|
175
297
|
```
|
|
@@ -190,46 +312,89 @@ The following parameters will be automatically converted:
|
|
|
190
312
|
| `non_splitting_tags` | Converts arrays to strings joining by commas
|
|
191
313
|
| `ignore_tags` | Converts arrays to strings joining by commas
|
|
192
314
|
| `formality` | No conversion applied
|
|
193
|
-
| `
|
|
315
|
+
| `glossary` | A glossary ID string, a `Glossary` or a `MultilingualGlossary` object, sent as `glossary_id` (see [Glossaries](#glossaries))
|
|
316
|
+
| `glossary_id` | Deprecated, use `glossary`. No conversion applied
|
|
194
317
|
| `style_rule` | No conversion applied (can be a string ID or a StyleRule object)
|
|
318
|
+
| `style_profile` | No conversion applied (can be a string ID or a StyleProfile object, see [Style profiles](#style-profiles))
|
|
195
319
|
| `translation_memory` | No conversion applied (can be a string ID or a TranslationMemory object)
|
|
196
320
|
| `translation_memory_threshold` | No conversion applied (integer 0-100, recommended minimum 75)
|
|
197
321
|
| `context` | No conversion applied
|
|
198
|
-
| `custom_instructions` |
|
|
199
|
-
| `tag_handling_version` | No conversion applied
|
|
322
|
+
| `custom_instructions` | An array of strings; a string is sent as a one-element array
|
|
323
|
+
| `tag_handling_version` | No conversion applied (`DeepL::Constants::TagHandlingVersion`)
|
|
200
324
|
| `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.
|
|
201
325
|
|
|
326
|
+
`show_billed_characters: true` is always sent.
|
|
327
|
+
|
|
328
|
+
The deprecated module-level `DeepL.translate(text, source_lang, target_lang, options = {},
|
|
329
|
+
additional_headers = {})` takes the same options. Unlike `translate_text`, it returns a single
|
|
330
|
+
result for a one-element array.
|
|
331
|
+
|
|
202
332
|
### Rephrase Text
|
|
203
333
|
|
|
204
|
-
To rephrase or improve text, including changing the writing style or tone of the text, use
|
|
334
|
+
To rephrase or improve text, including changing the writing style or tone of the text, use
|
|
335
|
+
the `rephrase_text` method of `DeepL::Client`:
|
|
205
336
|
|
|
206
337
|
```rb
|
|
207
|
-
rephrased_text =
|
|
338
|
+
rephrased_text = client.rephrase_text 'you will acquire new rephrased text', 'EN'
|
|
208
339
|
|
|
209
340
|
puts rephrased_text.class
|
|
210
341
|
# => DeepL::Resources::Text
|
|
211
342
|
puts rephrased_text.text
|
|
212
343
|
# => 'You get new rephrased text.'
|
|
344
|
+
puts rephrased_text.detected_source_language
|
|
345
|
+
# => 'en'
|
|
346
|
+
puts rephrased_text.target_language
|
|
347
|
+
# => 'en-US'
|
|
213
348
|
```
|
|
214
349
|
|
|
215
|
-
As with
|
|
350
|
+
As with `translate_text`, the text can be a string or an array of strings: a string returns a
|
|
351
|
+
`DeepL::Resources::Text`, an array returns an array of them (also for an array with one
|
|
352
|
+
element). The target language is optional.
|
|
216
353
|
|
|
217
|
-
|
|
354
|
+
Use the `writing_style:` or `tone:` keyword to choose the writing style or tone of the
|
|
355
|
+
rephrased text (`DeepL::Constants::WritingStyle` and `DeepL::Constants::Tone` list the values;
|
|
356
|
+
any string is sent as given). `extra_body_parameters:` is a hash added to the request body
|
|
357
|
+
last; it replaces fields of the same name.
|
|
218
358
|
|
|
219
359
|
```rb
|
|
220
|
-
rephrased_text =
|
|
360
|
+
rephrased_text = client.rephrase_text 'you will acquire new rephrased text', 'EN',
|
|
361
|
+
writing_style: 'casual'
|
|
221
362
|
|
|
222
363
|
puts rephrased_text.text
|
|
223
364
|
# => 'You'll get new, rephrased text.'
|
|
224
365
|
```
|
|
225
366
|
|
|
226
367
|
```rb
|
|
227
|
-
rephrased_text =
|
|
368
|
+
rephrased_text = client.rephrase_text 'you will acquire new rephrased text', 'EN',
|
|
369
|
+
tone: DeepL::Constants::Tone::FRIENDLY
|
|
228
370
|
|
|
229
371
|
puts rephrased_text.text
|
|
230
372
|
# => 'You'll get to enjoy new, rephrased text!'
|
|
231
373
|
```
|
|
232
374
|
|
|
375
|
+
The deprecated module-level `DeepL.rephrase(text, target_lang = nil, writing_style = nil,
|
|
376
|
+
tone = nil, options = {}, additional_headers = {})` takes the writing style and tone as
|
|
377
|
+
positional arguments. Unlike `rephrase_text`, it returns a single result for a one-element
|
|
378
|
+
array.
|
|
379
|
+
|
|
380
|
+
### Correct Text
|
|
381
|
+
|
|
382
|
+
To fix grammar, spelling and punctuation, use the `correct_text` method of `DeepL::Client`.
|
|
383
|
+
It accepts a string or an array of strings, plus an optional target language and
|
|
384
|
+
`extra_body_parameters:`:
|
|
385
|
+
|
|
386
|
+
```ruby
|
|
387
|
+
corrected = client.correct_text 'I has a apple.', 'en-US'
|
|
388
|
+
puts corrected.text
|
|
389
|
+
# => 'It has an apple.'
|
|
390
|
+
puts corrected.target_language
|
|
391
|
+
# => 'en-US'
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
A string returns a `DeepL::Resources::Text`; an array returns an array of them (also for an
|
|
395
|
+
array with one element). Empty text raises `ArgumentError`. It raises
|
|
396
|
+
`DeepL::Exceptions::Error` if the response contains fewer improvements than texts were sent.
|
|
397
|
+
|
|
233
398
|
### Glossaries
|
|
234
399
|
|
|
235
400
|
To create a glossary, use the `glossaries.create` method. The glossary `entries` argument should be an array of text pairs. Each pair includes the source and the target translations.
|
|
@@ -249,17 +414,19 @@ puts glossary.entry_count
|
|
|
249
414
|
# => 2
|
|
250
415
|
```
|
|
251
416
|
|
|
252
|
-
Created glossaries can be used in
|
|
417
|
+
Created glossaries can be used in text and document translation by specifying the
|
|
418
|
+
`glossary` option, a glossary ID or a `Glossary` / `MultilingualGlossary` object. It is sent
|
|
419
|
+
as `glossary_id` and replaces the deprecated `glossary_id` option:
|
|
253
420
|
|
|
254
421
|
```rb
|
|
255
|
-
translation =
|
|
422
|
+
translation = client.translate_text 'Hello World', 'EN', 'ES', glossary: 'aa48c7f0-0d02-413e-8a06-d5bbf0ca7a6e'
|
|
256
423
|
|
|
257
424
|
puts translation.class
|
|
258
425
|
# => DeepL::Resources::Text
|
|
259
426
|
puts translation.text
|
|
260
427
|
# => 'Hola Tierra'
|
|
261
428
|
|
|
262
|
-
translation =
|
|
429
|
+
translation = client.translate_text "I wish we had a car.", 'EN', 'ES', glossary: glossary
|
|
263
430
|
|
|
264
431
|
puts translation.class
|
|
265
432
|
# => DeepL::Resources::Text
|
|
@@ -269,16 +436,19 @@ puts translation.text
|
|
|
269
436
|
|
|
270
437
|
To use more than one glossary at once, specify the `glossary_ids` option with an
|
|
271
438
|
array of up to 5 glossary IDs (as strings or `DeepL::Resources::Glossary`
|
|
272
|
-
objects) instead of `
|
|
273
|
-
translation. `glossary_ids`
|
|
274
|
-
|
|
275
|
-
|
|
439
|
+
objects) instead of `glossary`. This works for both text and document
|
|
440
|
+
translation. `glossary_ids` cannot be combined with `glossary` or `glossary_id`,
|
|
441
|
+
and raises `ArgumentError` if this rule is violated or more than 5 IDs are
|
|
442
|
+
provided. For text translation, a glossary (`glossary` or `glossary_ids`) can be
|
|
443
|
+
used without `source_lang`: the API detects the source language and uses the
|
|
444
|
+
glossary's dictionary for the detected language pair. Document translation with
|
|
445
|
+
`glossary_ids` requires `source_lang` and raises `ArgumentError` without it:
|
|
276
446
|
|
|
277
447
|
```rb
|
|
278
448
|
# Text translation with multiple glossaries
|
|
279
|
-
translation =
|
|
280
|
-
|
|
281
|
-
|
|
449
|
+
translation = client.translate_text 'Hello World', 'EN', 'ES',
|
|
450
|
+
glossary_ids: ['aa48c7f0-0d02-413e-8a06-d5bbf0ca7a6e',
|
|
451
|
+
'bb59d8g1-1e13-524f-9b17-e6ccg1db8b7f']
|
|
282
452
|
|
|
283
453
|
# Document translation with multiple glossaries
|
|
284
454
|
handle = DeepL.document.upload 'my_document.docx', 'EN', 'ES', 'my_document.docx',
|
|
@@ -343,60 +513,248 @@ puts language_pairs.first.target_lang
|
|
|
343
513
|
# => de
|
|
344
514
|
```
|
|
345
515
|
|
|
516
|
+
### Multilingual glossaries
|
|
517
|
+
|
|
518
|
+
Multilingual glossaries (v3) group several language-pair dictionaries under one
|
|
519
|
+
glossary and are managed through `DeepL::Client`. Every method that takes a
|
|
520
|
+
glossary accepts its ID or a `DeepL::Resources::MultilingualGlossary` object; the
|
|
521
|
+
ID is URL-encoded in the request path. A dictionary's `entries` is a hash of
|
|
522
|
+
source term to target term.
|
|
523
|
+
|
|
524
|
+
To create a multilingual glossary, pass a name and one
|
|
525
|
+
`DeepL::Resources::MultilingualGlossaryDictionaryEntries` (or a hash with
|
|
526
|
+
`:source_lang`, `:target_lang` and `:entries`) per language pair. Entries are given
|
|
527
|
+
as a hash (`{ 'Hello' => 'Hallo' }`), as source/target pairs or as a TSV string (one
|
|
528
|
+
source/target pair per line, separated by a tab); a hash dictionary may also give
|
|
529
|
+
them as a CSV string with `entries_format: 'csv'`. Entries given as a hash or as pairs are
|
|
530
|
+
always sent as TSV, whatever `entries_format` says. Terms not given as CSV are checked like v2
|
|
531
|
+
glossary terms: each term is stripped of surrounding whitespace, and an empty term,
|
|
532
|
+
one with a control character, a pair or TSV line that is not exactly two terms, or a
|
|
533
|
+
source term that appears twice raises
|
|
534
|
+
`DeepL::Exceptions::ValidationError` before anything is sent. CSV content is sent as
|
|
535
|
+
given. Further options, such as
|
|
536
|
+
`extra_body_parameters`, are given as additional keywords:
|
|
537
|
+
|
|
538
|
+
```rb
|
|
539
|
+
glossary = client.create_multilingual_glossary(
|
|
540
|
+
'My Glossary',
|
|
541
|
+
[
|
|
542
|
+
DeepL::Resources::MultilingualGlossaryDictionaryEntries.new(
|
|
543
|
+
'EN', 'DE', { 'Hello' => 'Hallo', 'World' => 'Welt' }
|
|
544
|
+
),
|
|
545
|
+
{ source_lang: 'EN', target_lang: 'FR', entries: [['Hello', 'Bonjour']] }
|
|
546
|
+
]
|
|
547
|
+
)
|
|
548
|
+
|
|
549
|
+
puts glossary.class
|
|
550
|
+
# => DeepL::Resources::MultilingualGlossary
|
|
551
|
+
puts glossary.id
|
|
552
|
+
# => 'aa48c7f0-0d02-413e-8a06-d5bbf0ca7a6e'
|
|
553
|
+
puts glossary.creation_time.class
|
|
554
|
+
# => Time
|
|
555
|
+
puts glossary.dictionaries.first.entry_count
|
|
556
|
+
# => 2
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
To create a multilingual glossary with one dictionary from CSV content (a string
|
|
560
|
+
or an IO), use `create_multilingual_glossary_from_csv`:
|
|
561
|
+
|
|
562
|
+
```rb
|
|
563
|
+
glossary = client.create_multilingual_glossary_from_csv(
|
|
564
|
+
'My Glossary', 'EN', 'DE', File.read('entries.csv')
|
|
565
|
+
)
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
List or fetch multilingual glossaries with `list_multilingual_glossaries` and
|
|
569
|
+
`get_multilingual_glossary`. The glossary does not include the entries; fetch the
|
|
570
|
+
entries of one language pair with `get_multilingual_glossary_dictionary_entries`,
|
|
571
|
+
which raises `DeepL::Exceptions::NotFound` if the glossary has no dictionary for
|
|
572
|
+
that pair. The returned object can be passed to the create, update and replace
|
|
573
|
+
methods:
|
|
574
|
+
|
|
575
|
+
```rb
|
|
576
|
+
glossaries = client.list_multilingual_glossaries
|
|
577
|
+
glossary = client.get_multilingual_glossary 'aa48c7f0-0d02-413e-8a06-d5bbf0ca7a6e'
|
|
578
|
+
|
|
579
|
+
dictionary = client.get_multilingual_glossary_dictionary_entries(glossary, 'EN', 'DE')
|
|
580
|
+
puts dictionary.entries.inspect
|
|
581
|
+
# => {"Hello"=>"Hallo", "World"=>"Welt"}
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
`update_multilingual_glossary` renames the glossary and/or merges entries into
|
|
585
|
+
its dictionaries (a new language pair adds a dictionary). Keywords left `nil` are
|
|
586
|
+
not sent. `update_multilingual_glossary_name`,
|
|
587
|
+
`update_multilingual_glossary_dictionary` and
|
|
588
|
+
`update_multilingual_glossary_dictionary_from_csv` do one of these at a time. To
|
|
589
|
+
replace the entries of a dictionary instead, use
|
|
590
|
+
`replace_multilingual_glossary_dictionary` (or
|
|
591
|
+
`replace_multilingual_glossary_dictionary_from_csv`):
|
|
592
|
+
|
|
593
|
+
```rb
|
|
594
|
+
client.update_multilingual_glossary(
|
|
595
|
+
glossary, name: 'Renamed Glossary',
|
|
596
|
+
dictionaries: [{ source_lang: 'EN', target_lang: 'FR', entries: [['World', 'Monde']] }]
|
|
597
|
+
)
|
|
598
|
+
client.update_multilingual_glossary_name(glossary, 'Renamed Glossary')
|
|
599
|
+
client.update_multilingual_glossary_dictionary(
|
|
600
|
+
glossary, { source_lang: 'EN', target_lang: 'FR', entries: [['World', 'Monde']] }
|
|
601
|
+
)
|
|
602
|
+
client.replace_multilingual_glossary_dictionary(
|
|
603
|
+
glossary, { source_lang: 'EN', target_lang: 'DE', entries: [['Hello', 'Hallo'], ['car', 'Auto']] }
|
|
604
|
+
)
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
To delete one dictionary or the entire glossary (both return `nil`):
|
|
608
|
+
|
|
609
|
+
```rb
|
|
610
|
+
client.delete_multilingual_glossary_dictionary(glossary, 'EN', 'FR')
|
|
611
|
+
client.delete_multilingual_glossary(glossary)
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
### Spoken terms
|
|
615
|
+
|
|
616
|
+
Spoken terms collections improve the transcription of terms such as product
|
|
617
|
+
names. A collection holds one list of terms per language and is managed through
|
|
618
|
+
`DeepL::Client`. Every method that takes a collection accepts its ID or a
|
|
619
|
+
`DeepL::Resources::SpokenTerms` object. Terms are passed and returned as arrays
|
|
620
|
+
of strings.
|
|
621
|
+
|
|
622
|
+
To create a collection, pass a name and one `DeepL::Resources::SpokenTermsEntries`
|
|
623
|
+
(or a hash with `:lang` and `:entries`) per language. Terms are checked like
|
|
624
|
+
glossary terms: each term is stripped of surrounding whitespace and sent stripped,
|
|
625
|
+
and `create_spoken_terms`, `update_spoken_terms` and `replace_spoken_terms_list`
|
|
626
|
+
raise `DeepL::Exceptions::ValidationError` before sending anything if a term is then empty or contains
|
|
627
|
+
a C0 or C1 control character (such as a tab or newline), U+2028 or U+2029.
|
|
628
|
+
Further options, such as `extra_body_parameters`, are given as additional
|
|
629
|
+
keywords:
|
|
630
|
+
|
|
631
|
+
```rb
|
|
632
|
+
spoken_terms = client.create_spoken_terms(
|
|
633
|
+
'Product names',
|
|
634
|
+
[DeepL::Resources::SpokenTermsEntries.new('en', ['DeepL', 'webhook'])]
|
|
635
|
+
)
|
|
636
|
+
|
|
637
|
+
puts spoken_terms.class
|
|
638
|
+
# => DeepL::Resources::SpokenTerms
|
|
639
|
+
puts spoken_terms.spoken_terms_id
|
|
640
|
+
# => 'a74d88fb-ed2a-4943-a664-a4512398b994'
|
|
641
|
+
puts spoken_terms.creation_time.class
|
|
642
|
+
# => Time
|
|
643
|
+
puts spoken_terms.term_lists.first.entry_count
|
|
644
|
+
# => 2
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
`creation_time` is `nil` if the API returns a malformed timestamp. List all
|
|
648
|
+
collections or fetch one with `list_spoken_terms` and `get_spoken_terms`:
|
|
649
|
+
|
|
650
|
+
```rb
|
|
651
|
+
collections = client.list_spoken_terms
|
|
652
|
+
spoken_terms = client.get_spoken_terms 'a74d88fb-ed2a-4943-a664-a4512398b994'
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
`update_spoken_terms` renames a collection and/or merges terms into the list of
|
|
656
|
+
each given language. Arguments that are not given are not sent:
|
|
657
|
+
|
|
658
|
+
```rb
|
|
659
|
+
client.update_spoken_terms(spoken_terms, name: 'Renamed')
|
|
660
|
+
client.update_spoken_terms(spoken_terms, name: 'Renamed',
|
|
661
|
+
extra_body_parameters: { example_param: 'value' })
|
|
662
|
+
updated = client.update_spoken_terms(
|
|
663
|
+
spoken_terms, term_lists: [{ lang: 'en', entries: ['authentication'] }]
|
|
664
|
+
)
|
|
665
|
+
puts updated.term_lists.first.entry_count
|
|
666
|
+
# => 3
|
|
667
|
+
```
|
|
668
|
+
|
|
669
|
+
To read the terms of one language, use `get_spoken_terms_entries`:
|
|
670
|
+
|
|
671
|
+
```rb
|
|
672
|
+
entries = client.get_spoken_terms_entries(spoken_terms, 'en')
|
|
673
|
+
puts entries.entries.inspect
|
|
674
|
+
# => ["DeepL", "authentication", "webhook"]
|
|
675
|
+
```
|
|
676
|
+
|
|
677
|
+
`replace_spoken_terms_list` replaces the terms of one language, or adds the list
|
|
678
|
+
if the language is new. It takes one `DeepL::Resources::SpokenTermsEntries` or a
|
|
679
|
+
hash with `:lang` and `:entries`:
|
|
680
|
+
|
|
681
|
+
```rb
|
|
682
|
+
term_list = client.replace_spoken_terms_list(
|
|
683
|
+
spoken_terms, DeepL::Resources::SpokenTermsEntries.new('en', ['API'])
|
|
684
|
+
)
|
|
685
|
+
puts term_list.class
|
|
686
|
+
# => DeepL::Resources::SpokenTermsList
|
|
687
|
+
puts term_list.entry_count
|
|
688
|
+
# => 1
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
To delete the list of one language or the entire collection (both return `nil`):
|
|
692
|
+
|
|
693
|
+
```rb
|
|
694
|
+
client.delete_spoken_terms_list(spoken_terms, 'de')
|
|
695
|
+
client.delete_spoken_terms(spoken_terms)
|
|
696
|
+
```
|
|
697
|
+
|
|
346
698
|
### Style Rules
|
|
347
699
|
|
|
348
700
|
Style rules allow you to customize your translations using a managed, shared list
|
|
349
|
-
of rules for style, formatting, and more. Multiple style
|
|
350
|
-
your account, each with a user-specified name and a uniquely-assigned ID
|
|
701
|
+
of rules for style, formatting, and more. Multiple style rule lists can be stored
|
|
702
|
+
with your account, each with a user-specified name and a uniquely-assigned ID
|
|
703
|
+
(`style_id`). `DeepL::Client` manages them with `get_all_style_rules`,
|
|
704
|
+
`create_style_rule`, `get_style_rule`, `update_style_rule_name`,
|
|
705
|
+
`update_style_rule_configured_rules` and `delete_style_rule`. Every method that
|
|
706
|
+
takes a style rule list accepts its ID string or a `DeepL::Resources::StyleRule`
|
|
707
|
+
object.
|
|
351
708
|
|
|
352
709
|
#### Creating a style rule
|
|
353
710
|
|
|
354
|
-
Use `
|
|
355
|
-
|
|
711
|
+
Use `create_style_rule` with a name and language code. The optional keywords
|
|
712
|
+
`configured_rules` (category -> rule -> value) and `custom_instructions` (hashes
|
|
713
|
+
with `label`, `prompt` and optionally `source_language`) are sent as given;
|
|
714
|
+
keywords left `nil` are not sent. `extra_body_parameters` adds fields to the
|
|
715
|
+
request body.
|
|
356
716
|
|
|
357
717
|
```rb
|
|
718
|
+
client = DeepL::Client.new(ENV.fetch('DEEPL_AUTH_KEY'))
|
|
719
|
+
|
|
358
720
|
# Simple creation with just a name and language
|
|
359
|
-
style_rule =
|
|
721
|
+
style_rule = client.create_style_rule('My Style Rule', 'en')
|
|
360
722
|
puts "Created: #{style_rule.name} (#{style_rule.style_id})"
|
|
361
723
|
|
|
362
724
|
# Creation with configured rules and custom instructions
|
|
363
|
-
style_rule =
|
|
725
|
+
style_rule = client.create_style_rule(
|
|
364
726
|
'Formal English',
|
|
365
727
|
'en',
|
|
366
|
-
configured_rules: {
|
|
728
|
+
configured_rules: { dates_and_times: { calendar_era: 'use_bc_and_ad' } },
|
|
367
729
|
custom_instructions: [{ label: 'Tone', prompt: 'Always use formal language' }]
|
|
368
730
|
)
|
|
369
731
|
```
|
|
370
732
|
|
|
371
733
|
#### Retrieving and listing style rules
|
|
372
734
|
|
|
373
|
-
Use `
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
`
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
for each style rule. When `false` (default), these fields are omitted for faster
|
|
381
|
-
responses.
|
|
735
|
+
Use `get_style_rule` to retrieve a single style rule list, or `get_all_style_rules`
|
|
736
|
+
to list them one page at a time. `get_all_style_rules` returns a list of
|
|
737
|
+
`StyleRule` objects and accepts the optional keywords `page` (page number,
|
|
738
|
+
0-indexed), `page_size` (number of items per page) and `detailed`. When `true`,
|
|
739
|
+
the response includes `configured_rules` and `custom_instructions` for each style
|
|
740
|
+
rule list; when `false` (default), these fields are omitted for faster responses.
|
|
741
|
+
Keywords left `nil` are not sent.
|
|
382
742
|
|
|
383
743
|
```rb
|
|
384
|
-
# Get a single style rule by ID
|
|
385
|
-
style_rule =
|
|
744
|
+
# Get a single style rule list by ID
|
|
745
|
+
style_rule = client.get_style_rule('YOUR_STYLE_ID')
|
|
386
746
|
puts "#{style_rule.name} (#{style_rule.language})"
|
|
387
747
|
|
|
388
|
-
# List
|
|
389
|
-
|
|
390
|
-
style_rules.each do |rule|
|
|
748
|
+
# List the first page of style rule lists
|
|
749
|
+
client.get_all_style_rules.each do |rule|
|
|
391
750
|
puts "#{rule.name} (#{rule.style_id})"
|
|
392
751
|
end
|
|
393
752
|
|
|
394
753
|
# List with pagination
|
|
395
|
-
style_rules =
|
|
754
|
+
style_rules = client.get_all_style_rules(page: 0, page_size: 10)
|
|
396
755
|
|
|
397
756
|
# List with detailed configuration
|
|
398
|
-
|
|
399
|
-
style_rules.each do |rule|
|
|
757
|
+
client.get_all_style_rules(detailed: true).each do |rule|
|
|
400
758
|
if rule.configured_rules
|
|
401
759
|
puts " Number formatting: #{rule.configured_rules.numbers.keys.join(', ')}"
|
|
402
760
|
end
|
|
@@ -405,17 +763,18 @@ end
|
|
|
405
763
|
|
|
406
764
|
#### Updating a style rule
|
|
407
765
|
|
|
408
|
-
Use `
|
|
409
|
-
|
|
766
|
+
Use `update_style_rule_name` to rename a style rule list, and
|
|
767
|
+
`update_style_rule_configured_rules` to replace its configured rules. Both accept
|
|
768
|
+
`extra_body_parameters`.
|
|
410
769
|
|
|
411
770
|
```rb
|
|
412
771
|
# Update the name
|
|
413
|
-
updated =
|
|
772
|
+
updated = client.update_style_rule_name(style_rule, 'New Name')
|
|
414
773
|
|
|
415
774
|
# Update configured rules
|
|
416
|
-
updated =
|
|
417
|
-
|
|
418
|
-
{
|
|
775
|
+
updated = client.update_style_rule_configured_rules(
|
|
776
|
+
style_rule,
|
|
777
|
+
{ dates_and_times: { calendar_era: 'use_bc_and_ad' } }
|
|
419
778
|
)
|
|
420
779
|
```
|
|
421
780
|
|
|
@@ -425,66 +784,183 @@ and `vocabulary`.
|
|
|
425
784
|
|
|
426
785
|
#### Managing custom instructions
|
|
427
786
|
|
|
428
|
-
Custom instructions allow you to add free-text prompts to a style rule. Each
|
|
787
|
+
Custom instructions allow you to add free-text prompts to a style rule list. Each
|
|
429
788
|
instruction has an `id`, `label`, `prompt`, and `source_language`. Use
|
|
430
|
-
`
|
|
431
|
-
`
|
|
789
|
+
`create_style_rule_custom_instruction`, `get_style_rule_custom_instruction`,
|
|
790
|
+
`update_style_rule_custom_instruction`, and `delete_style_rule_custom_instruction`
|
|
791
|
+
to manage them. An instruction is given as its ID or a
|
|
792
|
+
`DeepL::Resources::CustomInstruction` object; `source_language` is optional and
|
|
793
|
+
not sent if `nil`.
|
|
432
794
|
|
|
433
795
|
```rb
|
|
434
796
|
# Create a custom instruction
|
|
435
|
-
instruction =
|
|
436
|
-
|
|
797
|
+
instruction = client.create_style_rule_custom_instruction(
|
|
798
|
+
style_rule, 'Formal tone', 'Always use formal language'
|
|
437
799
|
)
|
|
438
800
|
puts "Created instruction: #{instruction.id}"
|
|
439
801
|
|
|
440
802
|
# Create with an optional source language
|
|
441
|
-
instruction =
|
|
442
|
-
|
|
803
|
+
instruction = client.create_style_rule_custom_instruction(
|
|
804
|
+
style_rule, 'Formal tone', 'Always use formal language', source_language: 'en'
|
|
443
805
|
)
|
|
444
806
|
|
|
445
807
|
# Get a custom instruction
|
|
446
|
-
instruction =
|
|
808
|
+
instruction = client.get_style_rule_custom_instruction(style_rule, instruction)
|
|
447
809
|
|
|
448
810
|
# Update a custom instruction
|
|
449
|
-
updated =
|
|
450
|
-
|
|
811
|
+
updated = client.update_style_rule_custom_instruction(
|
|
812
|
+
style_rule, instruction, 'Updated label', 'Use very formal language'
|
|
451
813
|
)
|
|
452
814
|
|
|
453
|
-
# Delete a custom instruction
|
|
454
|
-
|
|
815
|
+
# Delete a custom instruction (returns nil)
|
|
816
|
+
client.delete_style_rule_custom_instruction(style_rule, instruction)
|
|
455
817
|
```
|
|
456
818
|
|
|
457
819
|
#### Deleting a style rule
|
|
458
820
|
|
|
459
|
-
Use `
|
|
821
|
+
Use `delete_style_rule` to delete a style rule list. It returns `nil`.
|
|
460
822
|
|
|
461
823
|
```rb
|
|
462
|
-
|
|
824
|
+
client.delete_style_rule('YOUR_STYLE_ID')
|
|
463
825
|
```
|
|
464
826
|
|
|
827
|
+
The deprecated module-level `DeepL.style_rules` (`list`, `create`, `find`,
|
|
828
|
+
`update_name`, `update_configured_rules`, `destroy`, `create_custom_instruction`,
|
|
829
|
+
`find_custom_instruction`, `update_custom_instruction`,
|
|
830
|
+
`destroy_custom_instruction`) keeps working unchanged.
|
|
831
|
+
|
|
465
832
|
#### Using style rules in translations
|
|
466
833
|
|
|
467
|
-
Style rules can be used in
|
|
834
|
+
Style rules can be used in `translate_text` by specifying the `style_rule` option
|
|
468
835
|
with either a style rule ID string or a `StyleRule` object:
|
|
469
836
|
|
|
470
837
|
```rb
|
|
471
838
|
# Using a style rule ID
|
|
472
|
-
translation =
|
|
839
|
+
translation = client.translate_text('Hello World', 'EN', 'ES',
|
|
840
|
+
style_rule: 'dca2e053-8ae5-45e6-a0d2-881156e7f4e4')
|
|
473
841
|
|
|
474
842
|
# Or using a StyleRule object
|
|
475
|
-
|
|
476
|
-
translation =
|
|
843
|
+
style_rule = client.get_all_style_rules.first
|
|
844
|
+
translation = client.translate_text('Hello World', 'EN', 'ES', style_rule: style_rule)
|
|
477
845
|
```
|
|
478
846
|
|
|
479
|
-
The same `style_rule` option can be passed to document translation
|
|
480
|
-
`
|
|
481
|
-
|
|
847
|
+
The same `style_rule` option can be passed to document translation
|
|
848
|
+
(`translate_document` or `translate_document_upload`), accepting either a style
|
|
849
|
+
rule ID string or a `StyleRule` object:
|
|
482
850
|
|
|
483
851
|
```rb
|
|
484
|
-
|
|
485
|
-
|
|
852
|
+
client.translate_document('my_document.docx', 'my_document_es.docx', 'EN', 'ES',
|
|
853
|
+
style_rule: 'dca2e053-8ae5-45e6-a0d2-881156e7f4e4')
|
|
486
854
|
```
|
|
487
855
|
|
|
856
|
+
### Style profiles
|
|
857
|
+
|
|
858
|
+
A style profile bundles glossaries, style rule lists and translation memories under one
|
|
859
|
+
name. `DeepL::Client` manages them with `create_style_profile`, `get_style_profile`,
|
|
860
|
+
`list_style_profiles`, `update_style_profile` and `delete_style_profile`. The last three
|
|
861
|
+
take a style profile ID string or a `DeepL::Resources::StyleProfile` object; the ID of a
|
|
862
|
+
profile is `style_profile_id`.
|
|
863
|
+
|
|
864
|
+
#### Creating a style profile
|
|
865
|
+
|
|
866
|
+
Only the name is required. The optional keywords are `description`, `industry`,
|
|
867
|
+
`glossary_ids`, `style_rule_ids`, `translation_memory_ids` and
|
|
868
|
+
`glossary_priority_order_enabled` (when `true`, the order of `glossary_ids` sets priority).
|
|
869
|
+
The component lists take IDs or the resource objects (`Glossary`, `MultilingualGlossary`,
|
|
870
|
+
`StyleRule`, `TranslationMemory`), which are sent as their IDs. If any component cannot be
|
|
871
|
+
used, the request fails and no style profile is created. `extra_body_parameters` adds
|
|
872
|
+
fields to the request body.
|
|
873
|
+
|
|
874
|
+
```rb
|
|
875
|
+
client = DeepL::Client.new(ENV.fetch('DEEPL_AUTH_KEY'))
|
|
876
|
+
|
|
877
|
+
# Only a name
|
|
878
|
+
profile = client.create_style_profile('Legal, German')
|
|
879
|
+
|
|
880
|
+
# With components
|
|
881
|
+
profile = client.create_style_profile(
|
|
882
|
+
'Legal, German',
|
|
883
|
+
description: 'Contract wording for the German market.',
|
|
884
|
+
industry: 'Legal',
|
|
885
|
+
glossary_ids: ['YOUR_GLOSSARY_ID'],
|
|
886
|
+
style_rule_ids: [style_rule], # a DeepL::Resources::StyleRule
|
|
887
|
+
translation_memory_ids: ['YOUR_TM_ID'],
|
|
888
|
+
glossary_priority_order_enabled: true
|
|
889
|
+
)
|
|
890
|
+
profile.class
|
|
891
|
+
# => DeepL::Resources::StyleProfile
|
|
892
|
+
profile.style_profile_id
|
|
893
|
+
# => "3f1c9d0e-7a24-4b58-9c31-8f0e5d2a1b47"
|
|
894
|
+
profile.style_rule_ids
|
|
895
|
+
# => ["YOUR_STYLE_ID"]
|
|
896
|
+
profile.creation_time.class
|
|
897
|
+
# => Time
|
|
898
|
+
```
|
|
899
|
+
|
|
900
|
+
`description` and `industry` are `nil` when the style profile has none.
|
|
901
|
+
|
|
902
|
+
#### Retrieving and listing style profiles
|
|
903
|
+
|
|
904
|
+
`list_style_profiles` returns an array of style profiles, one page at a time. It accepts
|
|
905
|
+
`page:` (0-indexed, default 0) and `page_size:` (default 10; values above 100 are reduced to
|
|
906
|
+
100).
|
|
907
|
+
|
|
908
|
+
```rb
|
|
909
|
+
profile = client.get_style_profile('YOUR_STYLE_PROFILE_ID')
|
|
910
|
+
|
|
911
|
+
profiles = client.list_style_profiles
|
|
912
|
+
profiles = client.list_style_profiles(page: 1, page_size: 100)
|
|
913
|
+
```
|
|
914
|
+
|
|
915
|
+
#### Updating a style profile
|
|
916
|
+
|
|
917
|
+
`update_style_profile` takes the same keywords as `create_style_profile`, plus `name`.
|
|
918
|
+
Keywords you leave out (or set to `nil`) are not sent and leave the field unchanged. An
|
|
919
|
+
empty string clears `description` or `industry`. A component list you send replaces the
|
|
920
|
+
linked list in full; an empty array unlinks all components of that kind.
|
|
921
|
+
|
|
922
|
+
```rb
|
|
923
|
+
updated = client.update_style_profile(
|
|
924
|
+
'YOUR_STYLE_PROFILE_ID',
|
|
925
|
+
name: 'Legal, German (2026)',
|
|
926
|
+
industry: 'Legal',
|
|
927
|
+
description: '', # clears the description
|
|
928
|
+
style_rule_ids: [] # unlinks all style rule lists
|
|
929
|
+
)
|
|
930
|
+
updated.description
|
|
931
|
+
# => nil
|
|
932
|
+
```
|
|
933
|
+
|
|
934
|
+
#### Deleting a style profile
|
|
935
|
+
|
|
936
|
+
`delete_style_profile` returns `nil`.
|
|
937
|
+
|
|
938
|
+
```rb
|
|
939
|
+
client.delete_style_profile('YOUR_STYLE_PROFILE_ID')
|
|
940
|
+
```
|
|
941
|
+
|
|
942
|
+
#### Using style profiles in translations
|
|
943
|
+
|
|
944
|
+
Pass the `style_profile` option, a style profile ID string or a `StyleProfile` object, to
|
|
945
|
+
`translate_text`, `translate_document` or `translate_document_upload` to apply the
|
|
946
|
+
profile's glossaries, style rule lists and translation memories. A component that does not
|
|
947
|
+
fit the language pair is left out. The option cannot be combined with `glossary`,
|
|
948
|
+
`glossary_id`, `glossary_ids`, `style_rule`, `translation_memory`,
|
|
949
|
+
`translation_memory_threshold` or `custom_instructions`; the API rejects such requests.
|
|
950
|
+
|
|
951
|
+
```rb
|
|
952
|
+
translation = client.translate_text('The artist is here.', nil, 'DE', style_profile: profile)
|
|
953
|
+
puts translation.text
|
|
954
|
+
# => Der Maler ist hier.
|
|
955
|
+
|
|
956
|
+
client.translate_document('/path/to/document.docx', '/path/to/translated.docx', 'EN', 'DE',
|
|
957
|
+
style_profile: 'YOUR_STYLE_PROFILE_ID')
|
|
958
|
+
```
|
|
959
|
+
|
|
960
|
+
With documents, an unknown style profile is not rejected at upload: the translation fails
|
|
961
|
+
with a `DeepL::Exceptions::DocumentTranslationError` whose message contains
|
|
962
|
+
`Style profile not found.`
|
|
963
|
+
|
|
488
964
|
### Translation Memories
|
|
489
965
|
|
|
490
966
|
Translation memories allow you to store and reuse previously created translations.
|
|
@@ -495,37 +971,44 @@ account, each with a source language and one or more target languages.
|
|
|
495
971
|
Translation memories can also be managed in the DeepL UI via
|
|
496
972
|
https://www.deepl.com/translation-memory.
|
|
497
973
|
|
|
498
|
-
|
|
499
|
-
|
|
974
|
+
`DeepL::Client` manages them with `list_translation_memories`,
|
|
975
|
+
`get_translation_memory`, `list_translation_memory_segments`,
|
|
976
|
+
`import_translation_memory_from_filepath`, `export_translation_memory_to_filepath`
|
|
977
|
+
and `delete_translation_memory`, plus the single steps of an import or export
|
|
978
|
+
described below. Every method that takes a translation memory accepts either a
|
|
979
|
+
string containing the translation memory ID or a `TranslationMemory` object, and
|
|
980
|
+
every method that takes a job accepts its ID or a `TranslationMemoryJob`.
|
|
500
981
|
|
|
501
982
|
#### Listing translation memories
|
|
502
983
|
|
|
503
|
-
`
|
|
504
|
-
|
|
505
|
-
`page` (page number for pagination, 0-indexed) and `page_size` (number
|
|
506
|
-
per page, max 25).
|
|
984
|
+
`list_translation_memories` returns a list of `TranslationMemory` objects for
|
|
985
|
+
your stored translation memories, one page at a time. It accepts the optional
|
|
986
|
+
keywords `page` (page number for pagination, 0-indexed) and `page_size` (number
|
|
987
|
+
of items per page, max 25). Keywords left `nil` are not sent.
|
|
507
988
|
|
|
508
989
|
```rb
|
|
990
|
+
client = DeepL::Client.new(ENV.fetch('DEEPL_AUTH_KEY'))
|
|
991
|
+
|
|
509
992
|
# List translation memories
|
|
510
|
-
|
|
511
|
-
translation_memories.each do |tm|
|
|
993
|
+
client.list_translation_memories.each do |tm|
|
|
512
994
|
puts "#{tm.name} (#{tm.translation_memory_id})"
|
|
513
995
|
puts " Source: #{tm.source_language}, Targets: #{tm.target_languages.join(', ')}"
|
|
514
996
|
puts " Segments: #{tm.segment_count}"
|
|
515
997
|
end
|
|
516
998
|
|
|
517
999
|
# List with pagination
|
|
518
|
-
translation_memories =
|
|
1000
|
+
translation_memories = client.list_translation_memories(page: 0, page_size: 10)
|
|
519
1001
|
```
|
|
520
1002
|
|
|
521
1003
|
#### Retrieving a single translation memory
|
|
522
1004
|
|
|
523
|
-
`
|
|
524
|
-
|
|
525
|
-
`updated_time` timestamps
|
|
1005
|
+
`get_translation_memory` retrieves one translation memory. In addition to the
|
|
1006
|
+
fields returned by `list_translation_memories`, the resource carries the
|
|
1007
|
+
`creation_time` and `updated_time` timestamps (`nil` if the API sends none or a
|
|
1008
|
+
malformed one).
|
|
526
1009
|
|
|
527
1010
|
```rb
|
|
528
|
-
tm =
|
|
1011
|
+
tm = client.get_translation_memory('YOUR_TM_ID')
|
|
529
1012
|
|
|
530
1013
|
puts tm.class
|
|
531
1014
|
# => DeepL::Resources::TranslationMemory
|
|
@@ -539,7 +1022,7 @@ puts tm.creation_time.class
|
|
|
539
1022
|
|
|
540
1023
|
#### Listing the segments of a translation memory
|
|
541
1024
|
|
|
542
|
-
`
|
|
1025
|
+
`list_translation_memory_segments` returns one page of the segments of a
|
|
543
1026
|
translation memory as a `TranslationMemorySegments` object. Each segment holds
|
|
544
1027
|
the source text and one target per target language of the translation memory.
|
|
545
1028
|
|
|
@@ -547,13 +1030,14 @@ Pagination is cursor-based: omit `page_cursor` on the first call, then pass the
|
|
|
547
1030
|
`next_page_cursor` of the previous response until `next_page?` is `false`. The
|
|
548
1031
|
method also accepts `page_size` (1-100, defaults to 50), `filter_text` (a
|
|
549
1032
|
substring matched against the source and target texts, at least 2 characters)
|
|
550
|
-
and `filter_case_sensitive` (defaults to `false`).
|
|
1033
|
+
and `filter_case_sensitive` (defaults to `false`). Keywords left `nil` are not
|
|
1034
|
+
sent.
|
|
551
1035
|
|
|
552
1036
|
Note that `segment_count` is the number of segments stored in the translation
|
|
553
1037
|
memory; a text filter does not reduce it.
|
|
554
1038
|
|
|
555
1039
|
```rb
|
|
556
|
-
page =
|
|
1040
|
+
page = client.list_translation_memory_segments('YOUR_TM_ID', page_size: 50)
|
|
557
1041
|
|
|
558
1042
|
puts page.class
|
|
559
1043
|
# => DeepL::Resources::TranslationMemorySegments
|
|
@@ -566,28 +1050,35 @@ puts page.segments.first.targets.first.target_text
|
|
|
566
1050
|
|
|
567
1051
|
# Walk through every page of segments
|
|
568
1052
|
while page.next_page?
|
|
569
|
-
page =
|
|
570
|
-
|
|
571
|
-
|
|
1053
|
+
page = client.list_translation_memory_segments('YOUR_TM_ID',
|
|
1054
|
+
page_size: 50,
|
|
1055
|
+
page_cursor: page.next_page_cursor)
|
|
572
1056
|
end
|
|
573
1057
|
|
|
574
1058
|
# Only the segments matching a text
|
|
575
|
-
page =
|
|
576
|
-
|
|
577
|
-
|
|
1059
|
+
page = client.list_translation_memory_segments('YOUR_TM_ID',
|
|
1060
|
+
filter_text: 'Nummer 1',
|
|
1061
|
+
filter_case_sensitive: true)
|
|
578
1062
|
```
|
|
579
1063
|
|
|
580
1064
|
#### Importing a translation memory
|
|
581
1065
|
|
|
582
|
-
`
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
1066
|
+
`import_translation_memory_from_filepath` creates a new translation memory from
|
|
1067
|
+
a TMX file. It creates the import job, uploads the file and waits until the job
|
|
1068
|
+
is completed, and returns the `TranslationMemoryJob`. Its result carries the ID
|
|
1069
|
+
of the newly created translation memory. The optional keywords are
|
|
1070
|
+
`display_name` (the name of the translation memory, defaults to the file name),
|
|
1071
|
+
`content_type` (the MIME type of the file, declared in the job and sent with the
|
|
1072
|
+
upload, defaults to `application/xml`), `timeout_s` and `extra_body_parameters`
|
|
1073
|
+
(fields added to the body of the import job request). It raises an
|
|
1074
|
+
`ArgumentError` before any request if the file does not exist, and a
|
|
1075
|
+
`DeepL::Exceptions::Error` if the file cannot be read, with the API's error
|
|
1076
|
+
message if the job fails or expires, and when `timeout_s` expires.
|
|
586
1077
|
|
|
587
1078
|
```rb
|
|
588
|
-
job =
|
|
589
|
-
|
|
590
|
-
|
|
1079
|
+
job = client.import_translation_memory_from_filepath('legal.tmx',
|
|
1080
|
+
display_name: 'Legal',
|
|
1081
|
+
timeout_s: 300)
|
|
591
1082
|
|
|
592
1083
|
puts job.class
|
|
593
1084
|
# => DeepL::Resources::TranslationMemoryJob
|
|
@@ -599,81 +1090,100 @@ puts job.result.skipped_segment_count
|
|
|
599
1090
|
# => 0
|
|
600
1091
|
```
|
|
601
1092
|
|
|
602
|
-
The three steps can also be performed separately
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
the
|
|
1093
|
+
The three steps can also be performed separately with
|
|
1094
|
+
`create_translation_memory_import`, `upload_translation_memory_file` and
|
|
1095
|
+
`wait_until_translation_memory_job_done`, for example to upload a file that is
|
|
1096
|
+
not available on the local file system. `create_translation_memory_import`
|
|
1097
|
+
accepts `content_type`, `display_name` and `extra_body_parameters`; keywords left
|
|
1098
|
+
`nil` are not sent. The upload URL is a pre-signed storage URL outside of the
|
|
1099
|
+
DeepL API, so no authorization header and, of the configured `headers`, only a
|
|
1100
|
+
`User-Agent` is sent with the upload; the proxy, SSL and timeout settings of the client apply. A non-2xx
|
|
1101
|
+
reply of a storage URL (for example 403 for an expired URL) raises a plain
|
|
1102
|
+
`DeepL::Exceptions::Error` carrying `http_status_code`; its `should_retry?` is
|
|
1103
|
+
`true` for 429 and 5xx.
|
|
606
1104
|
|
|
607
1105
|
```rb
|
|
608
|
-
content = File.binread
|
|
609
|
-
created =
|
|
610
|
-
|
|
611
|
-
|
|
1106
|
+
content = File.binread('legal.tmx')
|
|
1107
|
+
created = client.create_translation_memory_import('legal.tmx', content.bytesize,
|
|
1108
|
+
content_type: 'application/xml',
|
|
1109
|
+
display_name: 'Legal')
|
|
612
1110
|
|
|
613
1111
|
puts created.upload_url
|
|
614
1112
|
# => 'https://...'
|
|
615
1113
|
|
|
616
|
-
|
|
617
|
-
job =
|
|
1114
|
+
client.upload_translation_memory_file(created, content, content_type: 'application/xml')
|
|
1115
|
+
job = client.wait_until_translation_memory_job_done(created.job_id)
|
|
618
1116
|
```
|
|
619
1117
|
|
|
620
1118
|
Until the file is uploaded the job stays in the `awaiting_input` status and
|
|
621
1119
|
`result.required_action` describes what is missing. The API detects the upload
|
|
622
1120
|
asynchronously, so the job keeps reporting `awaiting_input` for a while
|
|
623
1121
|
afterwards, typically around half a minute, before it completes.
|
|
624
|
-
`
|
|
625
|
-
non-terminal one. A job whose file is never uploaded does not
|
|
626
|
-
|
|
1122
|
+
`wait_until_translation_memory_job_done` therefore polls through that status
|
|
1123
|
+
like any other non-terminal one. A job whose file is never uploaded does not
|
|
1124
|
+
finish on its own, and a status the library does not know keeps it polling too, so pass
|
|
1125
|
+
`timeout_s` to bound the wait.
|
|
627
1126
|
|
|
628
1127
|
#### Exporting a translation memory
|
|
629
1128
|
|
|
630
|
-
`
|
|
631
|
-
file. It creates the export job, waits
|
|
632
|
-
result, overwriting the output file if it already exists.
|
|
1129
|
+
`export_translation_memory_to_filepath` writes a translation memory to a TMX
|
|
1130
|
+
file. It creates the export job, waits until it is completed and downloads the
|
|
1131
|
+
result, overwriting the output file if it already exists. It accepts
|
|
1132
|
+
`timeout_s` and raises a `DeepL::Exceptions::Error` if the job fails or expires,
|
|
1133
|
+
if the output directory does not exist (checked before the job is created), and
|
|
1134
|
+
if the file cannot be written.
|
|
633
1135
|
|
|
634
1136
|
```rb
|
|
635
|
-
job =
|
|
1137
|
+
job = client.export_translation_memory_to_filepath('YOUR_TM_ID', 'export.tmx')
|
|
636
1138
|
|
|
637
1139
|
puts job.status
|
|
638
1140
|
# => 'completed'
|
|
639
1141
|
```
|
|
640
1142
|
|
|
641
|
-
The steps can be performed separately as well
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
1143
|
+
The steps can be performed separately as well, with
|
|
1144
|
+
`create_translation_memory_export`, `wait_until_translation_memory_job_done` and
|
|
1145
|
+
`download_translation_memory_export`. Repeating the export of an unchanged
|
|
1146
|
+
translation memory reuses the previously completed job instead of starting a new
|
|
1147
|
+
one, which `reused_existing?` reports. Just like the upload URL, the download URL
|
|
1148
|
+
is a pre-signed storage URL and is requested without an authorization header.
|
|
646
1149
|
|
|
647
1150
|
```rb
|
|
648
|
-
created =
|
|
1151
|
+
created = client.create_translation_memory_export('YOUR_TM_ID')
|
|
649
1152
|
|
|
650
1153
|
puts created.reused_existing?
|
|
651
1154
|
# => false
|
|
652
1155
|
|
|
653
|
-
job =
|
|
1156
|
+
job = client.wait_until_translation_memory_job_done(created.job_id)
|
|
654
1157
|
|
|
655
1158
|
puts job.result.download_url
|
|
656
1159
|
# => 'https://...'
|
|
657
1160
|
|
|
658
|
-
|
|
1161
|
+
client.download_translation_memory_export(job, 'export.tmx')
|
|
659
1162
|
```
|
|
660
1163
|
|
|
661
1164
|
#### Tracking import and export jobs
|
|
662
1165
|
|
|
663
|
-
`
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
1166
|
+
`get_translation_memory_job` returns the current status of an import or export
|
|
1167
|
+
job, and `wait_until_translation_memory_job_done` polls it every five seconds
|
|
1168
|
+
until it is completed, raising a `DeepL::Exceptions::Error` with the API's error
|
|
1169
|
+
message if the job failed or expired. A status the library does not know keeps it
|
|
1170
|
+
polling. Pass `timeout_s` to give up after a number of seconds instead of
|
|
1171
|
+
waiting forever; the last wait is cut so that the call never waits longer than
|
|
1172
|
+
`timeout_s`.
|
|
1173
|
+
|
|
1174
|
+
`done?` is `true` once the job is completed, `ok?` is `false` once it failed or
|
|
1175
|
+
expired (and `true` while it runs), and `finished?` is `true` for any terminal
|
|
1176
|
+
status.
|
|
667
1177
|
|
|
668
1178
|
```rb
|
|
669
|
-
job =
|
|
1179
|
+
job = client.get_translation_memory_job('YOUR_JOB_ID')
|
|
670
1180
|
|
|
671
1181
|
puts job.operation
|
|
672
1182
|
# => 'import'
|
|
673
1183
|
puts job.status
|
|
674
1184
|
# => 'processing'
|
|
675
|
-
puts job.finished?
|
|
676
|
-
# => false
|
|
1185
|
+
puts [job.done?, job.ok?, job.finished?].inspect
|
|
1186
|
+
# => [false, true, false]
|
|
677
1187
|
```
|
|
678
1188
|
|
|
679
1189
|
The status is one of `awaiting_input`, `processing`, `completed`, `downloaded`,
|
|
@@ -681,16 +1191,25 @@ The status is one of `awaiting_input`, `processing`, `completed`, `downloaded`,
|
|
|
681
1191
|
|
|
682
1192
|
#### Deleting a translation memory
|
|
683
1193
|
|
|
684
|
-
`
|
|
1194
|
+
`delete_translation_memory` deletes a translation memory. It returns `nil`.
|
|
685
1195
|
|
|
686
1196
|
```rb
|
|
687
|
-
|
|
688
|
-
# => 'YOUR_TM_ID'
|
|
1197
|
+
client.delete_translation_memory('YOUR_TM_ID')
|
|
689
1198
|
```
|
|
690
1199
|
|
|
1200
|
+
The deprecated module-level `DeepL.translation_memories` (`list`, `find`,
|
|
1201
|
+
`segments`, `destroy`, `create_import`, `upload_file`, `import_from_filepath`,
|
|
1202
|
+
`create_export`, `download_export`, `export_to_filepath`, `find_job`,
|
|
1203
|
+
`wait_until_job_done`) keeps working unchanged. Its `import_from_filepath` also
|
|
1204
|
+
accepts `content_type` and `extra_body_parameters`, and `create_import` accepts
|
|
1205
|
+
`extra_body_parameters`. Its file helpers raise `DeepL::Exceptions::Error` for a
|
|
1206
|
+
missing input file and the raw `Errno::*` error for other local file failures,
|
|
1207
|
+
such as an unreadable input file or a missing output directory (checked before
|
|
1208
|
+
the export job is created).
|
|
1209
|
+
|
|
691
1210
|
#### Using a translation memory in translations
|
|
692
1211
|
|
|
693
|
-
Pass the `translation_memory`
|
|
1212
|
+
Pass the `translation_memory` option to `translate_text` to use a translation
|
|
694
1213
|
memory. You can pass either a string containing the translation memory ID, or a
|
|
695
1214
|
`TranslationMemory` object. Use `translation_memory_threshold` to control the
|
|
696
1215
|
minimum matching percentage for fuzzy matches (0-100, recommended minimum of
|
|
@@ -698,71 +1217,248 @@ minimum matching percentage for fuzzy matches (0-100, recommended minimum of
|
|
|
698
1217
|
|
|
699
1218
|
```rb
|
|
700
1219
|
# Using a translation memory ID
|
|
701
|
-
translation =
|
|
702
|
-
|
|
703
|
-
|
|
1220
|
+
translation = client.translate_text('Hello, world!', 'EN', 'DE',
|
|
1221
|
+
translation_memory: 'YOUR_TM_ID',
|
|
1222
|
+
translation_memory_threshold: 80)
|
|
704
1223
|
|
|
705
1224
|
# Or using a TranslationMemory object
|
|
706
|
-
translation_memories =
|
|
707
|
-
translation =
|
|
708
|
-
|
|
1225
|
+
translation_memories = client.list_translation_memories
|
|
1226
|
+
translation = client.translate_text('Hello, world!', 'EN', 'DE',
|
|
1227
|
+
translation_memory: translation_memories.first)
|
|
709
1228
|
```
|
|
710
1229
|
|
|
711
1230
|
The same `translation_memory` and `translation_memory_threshold` options can be
|
|
712
|
-
passed to document translation via `
|
|
713
|
-
`
|
|
714
|
-
|
|
1231
|
+
passed to document translation via `translate_document_upload` (or
|
|
1232
|
+
`translate_document`). The `translation_memory` option accepts either a
|
|
1233
|
+
translation memory ID string or a `TranslationMemory` object:
|
|
715
1234
|
|
|
716
1235
|
```rb
|
|
717
|
-
handle =
|
|
718
|
-
|
|
719
|
-
|
|
1236
|
+
handle = client.translate_document_upload('my_document.docx', 'EN', 'DE',
|
|
1237
|
+
translation_memory: 'YOUR_TM_ID',
|
|
1238
|
+
translation_memory_threshold: 80)
|
|
720
1239
|
```
|
|
721
1240
|
|
|
722
1241
|
### Monitor usage
|
|
723
1242
|
|
|
724
|
-
To check current API usage,
|
|
1243
|
+
To check current API usage, call `get_usage`. It returns a `DeepL::Resources::Usage`. Each
|
|
1244
|
+
usage type is a `DeepL::Resources::Usage::Detail` with `count`, `limit` and `limit_reached?`:
|
|
1245
|
+
`character`, plus `document` and `team_document` for accounts with a document limit.
|
|
1246
|
+
`any_limit_reached?` checks `character`, `document` and `team_document`:
|
|
725
1247
|
|
|
726
1248
|
```rb
|
|
727
|
-
usage =
|
|
1249
|
+
usage = client.get_usage
|
|
728
1250
|
|
|
729
|
-
puts usage.
|
|
1251
|
+
puts usage.character.count
|
|
730
1252
|
# => 180118
|
|
731
|
-
puts usage.
|
|
1253
|
+
puts usage.character.limit
|
|
732
1254
|
# => 1250000
|
|
1255
|
+
puts 'Translation limit reached.' if usage.any_limit_reached?
|
|
1256
|
+
puts "Document usage: #{usage.document}" if usage.document
|
|
1257
|
+
# => Document usage: 5 of 10
|
|
1258
|
+
```
|
|
1259
|
+
|
|
1260
|
+
`DeepL.usage` and the `Usage` readers `character_count`, `character_limit` and
|
|
1261
|
+
`quota_exceeded?` are deprecated. Use `client.get_usage`, `character.count`,
|
|
1262
|
+
`character.limit` and `character.limit_reached?` (or `any_limit_reached?`) instead.
|
|
1263
|
+
|
|
1264
|
+
For API Pro users, the response also contains this API key's usage, speech usage, the billing
|
|
1265
|
+
period and a per-product breakdown. These fields are `nil` when the response does not contain
|
|
1266
|
+
them (e.g. for API Free users). `any_limit_reached?` does not consider them; call
|
|
1267
|
+
`limit_reached?` on them directly, e.g. `usage.api_key_character.limit_reached?`:
|
|
1268
|
+
|
|
1269
|
+
```rb
|
|
1270
|
+
usage = client.get_usage
|
|
1271
|
+
|
|
1272
|
+
# Characters used by the whole account vs. by this API key
|
|
1273
|
+
puts "account: #{usage.character}"
|
|
1274
|
+
# => account: 5947223 of 1000000000000
|
|
1275
|
+
puts "this key: #{usage.api_key_character}"
|
|
1276
|
+
# => this key: 636 of 1000000000000
|
|
1277
|
+
|
|
1278
|
+
puts usage.speech_to_text_minutes # => 30 of 600
|
|
1279
|
+
puts usage.speech_to_speech_minutes # => 12 of 600
|
|
1280
|
+
puts usage.start_time # => 2025-05-13 09:18:42 UTC (Time)
|
|
1281
|
+
puts usage.end_time # => 2025-06-13 09:18:42 UTC (Time)
|
|
1282
|
+
|
|
1283
|
+
usage.products&.each do |product|
|
|
1284
|
+
# product_type and billing_unit are plain strings, e.g. 'translate' and 'characters'
|
|
1285
|
+
puts "#{product.product_type}: key #{product.api_key_unit_count}, " \
|
|
1286
|
+
"account #{product.account_unit_count} #{product.billing_unit}"
|
|
1287
|
+
end
|
|
1288
|
+
# => translate: key 636, account 5941580 characters
|
|
733
1289
|
```
|
|
734
1290
|
|
|
735
1291
|
### Translate documents
|
|
736
1292
|
|
|
737
|
-
To translate a document, use the `
|
|
1293
|
+
To translate a document, use the `translate_document` method of `DeepL::Client`. It uploads
|
|
1294
|
+
the document, waits until the translation is done and writes the translated document to the
|
|
1295
|
+
output path, which must not exist yet. It returns the final
|
|
1296
|
+
`DeepL::Resources::DocumentTranslationStatus`:
|
|
738
1297
|
|
|
739
1298
|
```rb
|
|
740
|
-
|
|
1299
|
+
status = client.translate_document('/path/to/spanish_document.pdf',
|
|
1300
|
+
'/path/to/translated_document.pdf', 'ES', 'EN')
|
|
1301
|
+
puts status.billed_characters
|
|
1302
|
+
# => 2045
|
|
741
1303
|
```
|
|
742
1304
|
|
|
743
|
-
|
|
1305
|
+
A missing input file raises `ArgumentError` before anything is sent. Every other failure (also
|
|
1306
|
+
an existing output file, which is kept, and a failed translation) raises
|
|
1307
|
+
`DeepL::Exceptions::DocumentTranslationError`. Once the upload succeeded, its `document_handle`
|
|
1308
|
+
is set, so you can still query the status and download the document. If a DeepL error caused
|
|
1309
|
+
it, its `http_status_code` and `should_retry?` are copied from that error. `timeout_s:` limits the wait after the upload in seconds; by default
|
|
1310
|
+
`translate_document` waits until the translation is done or failed:
|
|
1311
|
+
|
|
1312
|
+
```rb
|
|
1313
|
+
begin
|
|
1314
|
+
client.translate_document('/path/to/document.docx', '/path/to/translated.docx', 'EN', 'DE',
|
|
1315
|
+
timeout_s: 600, formality: 'more')
|
|
1316
|
+
rescue DeepL::Exceptions::DocumentTranslationError => e
|
|
1317
|
+
puts "Translation failed: #{e.message}, document: #{e.document_handle&.document_id}"
|
|
1318
|
+
end
|
|
1319
|
+
```
|
|
1320
|
+
|
|
1321
|
+
The steps are also exposed. `translate_document_upload` returns a
|
|
1322
|
+
`DeepL::Resources::DocumentHandle` (`document_id`, `document_key`). To resume from a stored ID
|
|
1323
|
+
and key, create the handle with `DeepL::Resources::DocumentHandle.new(document_id, document_key)`.
|
|
1324
|
+
`translate_document_wait_until_done(handle, timeout_s: nil)` queries the status every 5 seconds
|
|
1325
|
+
until the translation is done and returns that status; it raises `DeepL::Exceptions::Error`
|
|
1326
|
+
with the API's error message if the translation fails, and when `timeout_s` expires. A status
|
|
1327
|
+
the library does not know keeps it polling, so pass `timeout_s` to bound the wait.
|
|
1328
|
+
`translate_document_get_status` queries the status once, and `translate_document_download`
|
|
1329
|
+
writes the translated document, overwriting an existing file; it raises
|
|
1330
|
+
`DeepL::Exceptions::DocumentNotReadyError` if the translation is not done yet.
|
|
1331
|
+
|
|
1332
|
+
```rb
|
|
1333
|
+
handle = client.translate_document_upload('/path/to/spanish_document.pdf', 'ES', 'EN',
|
|
1334
|
+
filename: 'report.pdf')
|
|
1335
|
+
status = client.translate_document_get_status(handle)
|
|
1336
|
+
puts "#{status.status}, ok: #{status.ok?}, done: #{status.done?}"
|
|
1337
|
+
# => translating, ok: true, done: false
|
|
1338
|
+
client.translate_document_wait_until_done(handle)
|
|
1339
|
+
client.translate_document_download(handle, '/path/to/translated_document.pdf')
|
|
1340
|
+
```
|
|
1341
|
+
|
|
1342
|
+
A `DeepL::Resources::DocumentTranslationStatus` has `document_id`, `status` (a string;
|
|
1343
|
+
`DeepL::Constants::DocumentStatusCode` has the values `QUEUED`, `TRANSLATING`, `DONE` and
|
|
1344
|
+
`ERROR`), `seconds_remaining`, `billed_characters` and `error_message`, and the predicates
|
|
1345
|
+
`done?` (done), `error?` (failed), `ok?` (not failed, also while queued or translating)
|
|
1346
|
+
and `finished?` (done or failed). `successful?` is a deprecated alias of `done?`.
|
|
1347
|
+
|
|
1348
|
+
With the deprecated module-level API, the same methods are `DeepL.document.translate_document`,
|
|
1349
|
+
`upload`, `get_status` and `download`, which take the filename as a positional parameter and
|
|
1350
|
+
optional additional headers. `DeepL.document.translate_document` waits until the translation is
|
|
1351
|
+
done or failed and returns the number of bytes written; the deprecated configuration setting
|
|
1352
|
+
`max_doc_status_queries` limits the number of status requests. The deprecated
|
|
1353
|
+
`DocumentHandle#wait_until_document_translation_finished` returns the final status also when
|
|
1354
|
+
the translation failed. `DeepL.document.translate_document` raises
|
|
1355
|
+
`DeepL::Exceptions::DocumentTranslationError` if the output file already exists.
|
|
1356
|
+
|
|
744
1357
|
```rb
|
|
745
1358
|
doc_handle = DeepL.document.upload('/path/to/spanish_document.pdf', 'ES', 'EN')
|
|
746
|
-
doc_status = doc_handle.wait_until_document_translation_finished
|
|
747
|
-
# until the `doc_status.successful?`
|
|
1359
|
+
doc_status = doc_handle.wait_until_document_translation_finished
|
|
748
1360
|
DeepL.document.download(doc_handle, '/path/to/translated_document.pdf') unless doc_status.error?
|
|
749
1361
|
```
|
|
750
1362
|
|
|
751
1363
|
You can also pass additional options to document translation methods, including `extra_body_parameters`:
|
|
752
1364
|
|
|
753
1365
|
```rb
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
1366
|
+
doc_handle = client.translate_document_upload('/path/to/spanish_document.pdf', 'ES', 'DE',
|
|
1367
|
+
formality: 'more',
|
|
1368
|
+
extra_body_parameters: { example_param: 'true' })
|
|
1369
|
+
```
|
|
1370
|
+
|
|
1371
|
+
Document translation options include:
|
|
1372
|
+
|
|
1373
|
+
- `filename` (`DeepL::Client` only): the file name sent with the upload, including its
|
|
1374
|
+
extension. Defaults to the base name of the input path.
|
|
1375
|
+
- `formality`: same as for text translation.
|
|
1376
|
+
- `glossary` / `glossary_ids`: see the glossary sections above. `glossary_id` is deprecated,
|
|
1377
|
+
use `glossary`.
|
|
1378
|
+
- `output_format`: file extension of the desired output format, e.g. `'pdf'` to translate
|
|
1379
|
+
a `docx` into a PDF.
|
|
1380
|
+
- `enable_watermark`: `true` adds a "Translated by DeepL" watermark to the translated
|
|
1381
|
+
document. The API supports it only for `docx` and `pdf` output and ignores it for other
|
|
1382
|
+
formats. When not set, the parameter is not sent.
|
|
1383
|
+
- `style_rule`, `style_profile`, `translation_memory`, `translation_memory_threshold`:
|
|
1384
|
+
same as in text translation; see the style rules, style profiles and translation memory
|
|
1385
|
+
sections above.
|
|
1386
|
+
|
|
1387
|
+
```rb
|
|
1388
|
+
client.translate_document('/path/to/document.docx', '/path/to/translated.pdf', 'EN', 'DE',
|
|
1389
|
+
output_format: 'pdf', enable_watermark: true)
|
|
759
1390
|
```
|
|
760
1391
|
|
|
761
1392
|
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.
|
|
762
1393
|
|
|
1394
|
+
### Admin API
|
|
1395
|
+
|
|
1396
|
+
The Admin API lets you manage the developer keys of your organization and retrieve usage analytics. It requires an admin API key, which you can create in the "Admin API Keys" tab of your DeepL account. Admin keys cannot be used for translation, and developer keys cannot access the Admin API: the API rejects a wrong key with `DeepL::Exceptions::AuthorizationFailed`.
|
|
1397
|
+
|
|
1398
|
+
Create a `DeepL::AdminClient` with your admin key. It is independent of `DeepL.configure`, does not read the `DEEPL_AUTH_KEY` and `DEEPL_SERVER_URL` environment variables, and uses the `https://api.deepl.com` server by default. The admin key is trimmed. It also accepts the `server_url:`, `headers:`, `max_retries:`, `timeout:`, `proxy:`, `send_platform_info:`, `app_info:`, `http_client_options:` and `logger:` keyword arguments of [`DeepL::Client`](#creating-a-client); without `server_url:` it uses `https://api.deepl.com`, also for keys ending in `:fx`.
|
|
1399
|
+
|
|
1400
|
+
```rb
|
|
1401
|
+
admin_client = DeepL::AdminClient.new('YOUR_ADMIN_KEY')
|
|
1402
|
+
```
|
|
1403
|
+
|
|
1404
|
+
#### Managing developer keys
|
|
1405
|
+
|
|
1406
|
+
```rb
|
|
1407
|
+
key = admin_client.create_developer_key(label: 'Staging Team Key')
|
|
1408
|
+
puts "Created #{key.label} (#{key.key_id})"
|
|
1409
|
+
|
|
1410
|
+
admin_client.list_developer_keys.each do |developer_key|
|
|
1411
|
+
puts "#{developer_key.label}: deactivated=#{developer_key.deactivated?}"
|
|
1412
|
+
end
|
|
1413
|
+
|
|
1414
|
+
key = admin_client.rename_developer_key(key, 'Production Team Key')
|
|
1415
|
+
|
|
1416
|
+
# Changes only the given limits; the others keep their current value.
|
|
1417
|
+
# nil removes a limit (unlimited) and 0 blocks that usage.
|
|
1418
|
+
key = admin_client.set_developer_key_usage_limits(key, characters: 500_000,
|
|
1419
|
+
speech_to_text_milliseconds: 60_000)
|
|
1420
|
+
key = admin_client.set_developer_key_usage_limits(key, speech_to_speech_milliseconds: nil)
|
|
1421
|
+
|
|
1422
|
+
# Deactivation is permanent.
|
|
1423
|
+
admin_client.deactivate_developer_key(key)
|
|
1424
|
+
```
|
|
1425
|
+
|
|
1426
|
+
`rename_developer_key`, `set_developer_key_usage_limits` and `deactivate_developer_key` accept either a key ID or a `DeepL::Resources::DeveloperKey` object and return the updated `DeepL::Resources::DeveloperKey`. `set_developer_key_usage_limits` accepts `characters:`, `speech_to_text_milliseconds:` and `speech_to_speech_milliseconds:`. `create_developer_key` takes the label as the `label:` keyword argument; without it the API labels the key "DeepL API Key". Labels and limits are sent as given and validated by the API. `create_developer_key`, `deactivate_developer_key`, `rename_developer_key` and `set_developer_key_usage_limits` also accept `extra_body_parameters:`, a hash added to the request body last that replaces fields of the same name. A response without a `key_id` raises `DeepL::Exceptions::Error`. `label` and `usage_limits` are `nil` when the response does not contain them.
|
|
1427
|
+
|
|
1428
|
+
A failed `create_developer_key` request is retried only after HTTP 429, a DNS resolution error or a connection timeout, when the API cannot have created the key. Other requests are retried like all other requests of the library.
|
|
1429
|
+
|
|
1430
|
+
#### Retrieving usage analytics
|
|
1431
|
+
|
|
1432
|
+
`get_usage_analytics` returns a `DeepL::Resources::AdminUsageReport` for a date range. Dates are UTC calendar days, and both the start day and the end day are included. They can be `Date`, `Time` or `DateTime` objects or `YYYY-MM-DD` strings. For `Time` and `DateTime` values the SDK sends the UTC date of that moment, so `Time.new(2026, 10, 20, 0, 0, 0, '+02:00')` is sent as `2026-10-19`. An invalid date raises `ArgumentError` without sending a request. The API requires the end date to be after the start date, so a report covers at least two days, and at most 366 days after it; otherwise both analytics methods raise `DeepL::Exceptions::BadRequest`. Use `group_by:` to break the usage down by key (`DeepL::Constants::AdminUsageGroupBy::KEY`, see `key_usages`) or by key and day (`DeepL::Constants::AdminUsageGroupBy::KEY_AND_DAY`, see `key_and_day_usages`). The `group_by` of the report is the raw string the API returns. The usage breakdowns include `speech_to_text_minutes` and `speech_to_speech_minutes`. `speech_to_speech_minutes` of a usage breakdown, and `total_usage`, `start_date` and `end_date` of a report, are `nil` when the response does not contain them.
|
|
1433
|
+
|
|
1434
|
+
```rb
|
|
1435
|
+
report = admin_client.get_usage_analytics('2026-06-01', '2026-07-01',
|
|
1436
|
+
group_by: DeepL::Constants::AdminUsageGroupBy::KEY)
|
|
1437
|
+
puts "Total characters: #{report.total_usage&.total_characters}"
|
|
1438
|
+
report.key_usages.each do |key_usage|
|
|
1439
|
+
puts "#{key_usage.api_key_label}: #{key_usage.usage.total_characters}"
|
|
1440
|
+
end
|
|
1441
|
+
```
|
|
1442
|
+
|
|
1443
|
+
`get_custom_tag_usage_analytics` returns a `DeepL::Resources::CustomTagUsageReport` with the usage per custom tag, for a date range with the same limits. Use `aggregate_by:` to choose between the whole period (`DeepL::Constants::CustomTagUsageAggregateBy::PERIOD`, the default) and per-day usage (`DeepL::Constants::CustomTagUsageAggregateBy::DAY`). The results are paginated: pass the `next_page` value of a report as `page:` to get the next page. The `aggregate_by` of a custom tag report is the raw string the API returns. `speech_to_speech_minutes` of a custom tag breakdown is `nil` when the response does not contain it.
|
|
1444
|
+
|
|
1445
|
+
```rb
|
|
1446
|
+
page = nil
|
|
1447
|
+
loop do
|
|
1448
|
+
report = admin_client.get_custom_tag_usage_analytics('2026-06-01', '2026-07-01', page: page)
|
|
1449
|
+
report.usage.each do |tag_usage|
|
|
1450
|
+
puts "#{tag_usage.custom_tag}: #{tag_usage.breakdown.total_characters}"
|
|
1451
|
+
end
|
|
1452
|
+
break if report.next_page.nil?
|
|
1453
|
+
|
|
1454
|
+
page = report.next_page
|
|
1455
|
+
end
|
|
1456
|
+
```
|
|
1457
|
+
|
|
763
1458
|
### Sending additional HTTP headers
|
|
764
1459
|
|
|
765
|
-
|
|
1460
|
+
`DeepL::Client.new(key, headers: { 'X-DeepL-Reporting-Tag' => 'my-tag' })` sends the headers
|
|
1461
|
+
with every DeepL API request of that client. With the module-level API, you can pass additional HTTP headers to `translate`, `rephrase` and the
|
|
766
1462
|
`document` methods. For example, to send the `X-DeepL-Reporting-Tag` header
|
|
767
1463
|
for usage reporting (see the [cookbook entry](https://developers.deepl.com/docs/learning-how-tos/cookbook/sending-custom-reporting-tags-from-client-libraries)):
|
|
768
1464
|
|
|
@@ -772,6 +1468,12 @@ translation = DeepL.translate 'Hello, world!', 'EN', 'DE', {}, additional_header
|
|
|
772
1468
|
rephrased = DeepL.rephrase 'Hello, world!', 'EN', nil, nil, {}, additional_headers
|
|
773
1469
|
```
|
|
774
1470
|
|
|
1471
|
+
A header in `headers:` (or `config.headers`) or in the additional headers replaces a library
|
|
1472
|
+
header of the same name, in any casing, `Authorization` and `User-Agent` included, except
|
|
1473
|
+
`Content-Type`, `Content-Length`, `Transfer-Encoding` and `Host`, which the library always sets.
|
|
1474
|
+
Pre-signed translation memory storage URLs get only the `User-Agent`, the caller's if one is
|
|
1475
|
+
set.
|
|
1476
|
+
|
|
775
1477
|
### Handle exceptions
|
|
776
1478
|
|
|
777
1479
|
You can capture and process exceptions that may be raised during API calls. These are all the possible exceptions:
|
|
@@ -780,13 +1482,20 @@ You can capture and process exceptions that may be raised during API calls. Thes
|
|
|
780
1482
|
| --------------- | ----------- |
|
|
781
1483
|
| `DeepL::Exceptions::AuthorizationFailed` | The authorization process has failed. Check your `auth_key` value. |
|
|
782
1484
|
| `DeepL::Exceptions::BadRequest` | Something is wrong in your request. Check `exception.message` for more information. |
|
|
783
|
-
| `DeepL::Exceptions::
|
|
1485
|
+
| `DeepL::Exceptions::ConnectionError` | Raised by `DeepL::Client` and `DeepL::AdminClient` (the module-level API raises the original network error). No complete HTTP response from the API: a DNS, connection or timeout failure, or a response body cut off before its `Content-Length`, after all retries (`should_retry?` is true), or a TLS failure, a proxy failure (the proxy refuses `CONNECT`) or a malformed response, raised without retrying (`should_retry?` is false). The original exception is `exception.cause`. |
|
|
1486
|
+
| `DeepL::Exceptions::DocumentNotReadyError` | A subclass of `ServerError`: HTTP 503 on a document download, the translated document is not ready yet. |
|
|
1487
|
+
| `DeepL::Exceptions::DocumentTranslationError` | An error occured during document translation. Check `exception.message` for more information; `exception.document_handle` is the handle of the uploaded document, `nil` if the upload failed; `http_status_code` and `should_retry?` are those of the DeepL error that caused it, if any. |
|
|
784
1488
|
| `DeepL::Exceptions::LimitExceeded` | You've reached the API's call limit. |
|
|
785
1489
|
| `DeepL::Exceptions::QuotaExceeded` | You've reached the API's character limit. |
|
|
786
|
-
| `DeepL::Exceptions::RequestError` |
|
|
787
|
-
| `DeepL::Exceptions::NotSupported` |
|
|
1490
|
+
| `DeepL::Exceptions::RequestError` | Any other HTTP error status. Its message contains the status and the API's message; check `exception.response` and `exception.request` for more information. |
|
|
1491
|
+
| `DeepL::Exceptions::NotSupported` | Deprecated. Raised only by the module-level API: `supports_formality?` of a source language from `DeepL.languages`. |
|
|
788
1492
|
| `DeepL::Exceptions::RequestEntityTooLarge` | Your request is too large, reduce the amount of data you are sending. The API has a request size limit of 128 KiB. |
|
|
789
|
-
| `DeepL::Exceptions::ServerError` | An error occured in the DeepL API
|
|
1493
|
+
| `DeepL::Exceptions::ServerError` | An error occured in the DeepL API (HTTP 5xx), raised after all retries. |
|
|
1494
|
+
| `DeepL::Exceptions::ValidationError` | An invalid argument detected before any request: an invalid glossary or spoken terms term, or an unsupported `DeepL.languages` type. |
|
|
1495
|
+
|
|
1496
|
+
All of them are subclasses of `DeepL::Exceptions::Error`, which is also raised for a response
|
|
1497
|
+
that cannot be parsed. Errors of an HTTP response carry the status as an `Integer` in
|
|
1498
|
+
`exception.http_status_code` (`nil` otherwise).
|
|
790
1499
|
|
|
791
1500
|
An exampling of handling a generic exception:
|
|
792
1501
|
|
|
@@ -811,37 +1520,61 @@ require 'logger'
|
|
|
811
1520
|
logger = Logger.new(STDOUT)
|
|
812
1521
|
logger.level = Logger::INFO
|
|
813
1522
|
|
|
814
|
-
|
|
815
|
-
config.auth_key =
|
|
1523
|
+
DeepL.configure do |config|
|
|
1524
|
+
config.auth_key = ENV.fetch('DEEPL_AUTH_KEY')
|
|
816
1525
|
config.logger = logger
|
|
817
1526
|
end
|
|
818
1527
|
```
|
|
819
1528
|
|
|
1529
|
+
### Retries and timeouts
|
|
1530
|
+
|
|
1531
|
+
Requests that fail with HTTP 429, any 5xx status or a transient network failure (DNS, refused
|
|
1532
|
+
or reset connection, broken pipe, unreachable host, timeout, response body cut off before its
|
|
1533
|
+
`Content-Length`) are retried up to `max_retries:`
|
|
1534
|
+
times (default 5) with exponential backoff; a request is sent at most `max_retries:` + 1 times.
|
|
1535
|
+
Each attempt has a timeout of `timeout:` seconds (default 10; the module-level
|
|
1536
|
+
`config.timeout` defaults to 60). After the last retry, network failures raise
|
|
1537
|
+
`DeepL::Exceptions::ConnectionError` in `DeepL::Client` and `DeepL::AdminClient`; the
|
|
1538
|
+
module-level API raises the original network error. TLS failures (including certificate
|
|
1539
|
+
verification), proxy failures (the proxy refuses `CONNECT`, e.g. with 407) and malformed
|
|
1540
|
+
responses are not retried and are raised the same way at once.
|
|
1541
|
+
`AdminClient#create_developer_key` is only retried when the request was not sent (HTTP 429,
|
|
1542
|
+
DNS failure, refused connection or connection timeout). With the module-level API, set
|
|
1543
|
+
`config.max_network_retries` and `config.timeout`.
|
|
1544
|
+
|
|
820
1545
|
### Proxy configuration
|
|
821
1546
|
|
|
822
|
-
|
|
1547
|
+
Pass a proxy URL to the client:
|
|
1548
|
+
|
|
1549
|
+
```rb
|
|
1550
|
+
client = DeepL::Client.new(auth_key, proxy: 'http://user:password@localhost:3128')
|
|
1551
|
+
```
|
|
1552
|
+
|
|
1553
|
+
`DeepL::HTTPClientOptions` also takes the proxy as a URL or as a hash with `proxy_addr` and
|
|
1554
|
+
`proxy_port`, together with certificate, SSL verification and timeout options. With the
|
|
1555
|
+
module-level API, a session needs to be used; the proxy is configured as part of the HTTP client options:
|
|
823
1556
|
|
|
824
1557
|
```rb
|
|
825
|
-
client_options = HTTPClientOptions.new({ 'proxy_addr' => 'http://localhost', 'proxy_port' => 80 })
|
|
826
|
-
|
|
1558
|
+
client_options = DeepL::HTTPClientOptions.new({ 'proxy_addr' => 'http://localhost', 'proxy_port' => 80 })
|
|
1559
|
+
DeepL.with_session(client_options) do |session|
|
|
827
1560
|
# ...
|
|
828
1561
|
end
|
|
829
1562
|
```
|
|
830
1563
|
|
|
831
1564
|
### Anonymous platform information
|
|
832
1565
|
|
|
833
|
-
By default, we send some basic information about the platform the client library is running on with each request, see [here for an explanation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent). This data is completely anonymous and only used to improve our product, not track any individual users. If you do not wish to send this data,
|
|
1566
|
+
By default, we send some basic information about the platform the client library is running on with each request, see [here for an explanation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent). This data is completely anonymous and only used to improve our product, not track any individual users. If you do not wish to send this data, create the client with `send_platform_info: false`, or with the module-level API set the `User-Agent` to the library name and version only:
|
|
834
1567
|
|
|
835
1568
|
```rb
|
|
836
|
-
|
|
837
|
-
|
|
1569
|
+
DeepL.configure do |config|
|
|
1570
|
+
config.user_agent = "deepl-ruby/#{DeepL::VERSION}"
|
|
838
1571
|
end
|
|
839
1572
|
```
|
|
840
1573
|
|
|
841
|
-
You can also
|
|
1574
|
+
You can also completely replace the `User-Agent` header with `headers: { 'User-Agent' => 'myCustomUserAgent' }`, or with the module-level API like so:
|
|
842
1575
|
|
|
843
1576
|
```rb
|
|
844
|
-
|
|
1577
|
+
DeepL.configure do |config|
|
|
845
1578
|
config.user_agent = 'myCustomUserAgent'
|
|
846
1579
|
end
|
|
847
1580
|
```
|
|
@@ -851,10 +1584,10 @@ end
|
|
|
851
1584
|
When writing an application that send multiple requests, using a HTTP session will give better performance through [HTTP Keep-Alive](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Keep-Alive). You can use it by simply wrapping your requests in a `with_session` block:
|
|
852
1585
|
|
|
853
1586
|
```rb
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
1587
|
+
DeepL.with_session do |session|
|
|
1588
|
+
DeepL.translate(sentence1, 'DE', 'EN-GB')
|
|
1589
|
+
DeepL.translate(sentence2, 'DE', 'EN-GB')
|
|
1590
|
+
DeepL.translate(sentence3, 'DE', 'EN-GB')
|
|
858
1591
|
end
|
|
859
1592
|
```
|
|
860
1593
|
|
|
@@ -863,12 +1596,19 @@ end
|
|
|
863
1596
|
If you use this library in an application, please identify the application by setting the name and version of the plugin:
|
|
864
1597
|
|
|
865
1598
|
```rb
|
|
866
|
-
|
|
867
|
-
|
|
1599
|
+
client = DeepL::Client.new(auth_key, app_info: { app_name: 'MyTranslationPlugin',
|
|
1600
|
+
app_version: '1.0.1' })
|
|
1601
|
+
```
|
|
1602
|
+
|
|
1603
|
+
With the module-level API, append them to the `User-Agent`:
|
|
1604
|
+
|
|
1605
|
+
```rb
|
|
1606
|
+
DeepL.configure do |config|
|
|
1607
|
+
config.user_agent = "#{config.user_agent} MyTranslationPlugin/1.0.1"
|
|
868
1608
|
end
|
|
869
1609
|
```
|
|
870
1610
|
|
|
871
|
-
This information is passed along when the library makes calls to the DeepL API. Both name and version are required. Please note that setting the `User-Agent` header via `
|
|
1611
|
+
This information is passed along when the library makes calls to the DeepL API. Both name and version are required. Please note that setting the `User-Agent` header via `DeepL.configure` will override this setting, if you need to use this, please manually identify your Application in the `User-Agent` header.
|
|
872
1612
|
|
|
873
1613
|
## Options Constants
|
|
874
1614
|
|
|
@@ -884,14 +1624,14 @@ The available values for various possible options are provided under the `DeepL:
|
|
|
884
1624
|
To view all the possible options for a given constant, call `options`:
|
|
885
1625
|
|
|
886
1626
|
```rb
|
|
887
|
-
all_available_tones = DeepL::Constants::
|
|
1627
|
+
all_available_tones = DeepL::Constants::Tone.options
|
|
888
1628
|
```
|
|
889
1629
|
|
|
890
1630
|
To check if a given string is a possible option for a given constant, call `valid?`:
|
|
891
1631
|
|
|
892
1632
|
```rb
|
|
893
|
-
DeepL::Constants::
|
|
894
|
-
DeepL::Constants::
|
|
1633
|
+
DeepL::Constants::Tone.valid?('friendly') # true
|
|
1634
|
+
DeepL::Constants::Tone.valid?('rude') # false
|
|
895
1635
|
```
|
|
896
1636
|
|
|
897
1637
|
## Integrations
|
|
@@ -927,7 +1667,25 @@ cd deepl-rb
|
|
|
927
1667
|
bundle install
|
|
928
1668
|
```
|
|
929
1669
|
|
|
930
|
-
|
|
1670
|
+
There are two suites of specs, which must run in separate processes:
|
|
1671
|
+
|
|
1672
|
+
- `spec/offline` tests options, validation, errors, retries and polling against intercepted
|
|
1673
|
+
requests (WebMock). It needs no key and no network:
|
|
1674
|
+
|
|
1675
|
+
```
|
|
1676
|
+
bundle exec rspec spec/offline
|
|
1677
|
+
```
|
|
1678
|
+
|
|
1679
|
+
- `spec/real_api` sends every endpoint once to the real API. Set `DEEPL_AUTH_KEY` to a test key,
|
|
1680
|
+
`DEEPL_ADMIN_KEY` to an admin key for the Admin API specs, and `DEEPL_SERVER_URL` if the keys
|
|
1681
|
+
are not for the default server. The specs create resources named `sdktest-ruby-...` and delete
|
|
1682
|
+
them again; developer keys cannot be deleted and are deactivated instead. The Admin API spec creates a key, renames it, sets its limits and deactivates it:
|
|
1683
|
+
|
|
1684
|
+
```
|
|
1685
|
+
DEEPL_AUTH_KEY=... DEEPL_ADMIN_KEY=... bundle exec rspec spec/real_api
|
|
1686
|
+
```
|
|
1687
|
+
|
|
1688
|
+
To run the offline specs and rubocop, use
|
|
931
1689
|
|
|
932
1690
|
```
|
|
933
1691
|
bundle exec rake test
|