Skip to content

Commit 9f28661

Browse files
feat: add support for the translation memory management APIs
1 parent 07c1d10 commit 9f28661

20 files changed

Lines changed: 2045 additions & 60 deletions

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414
- Added support for translation memories in document translation via
1515
`setTranslationMemory()`/`setTranslationMemoryId()`/`setTranslationMemoryThreshold()`
1616
in `DocumentTranslationOptions`.
17+
- Added support for the translation memory management endpoints in the
18+
`DeepLClient` class: `getTranslationMemory()`,
19+
`listTranslationMemorySegments()`, `deleteTranslationMemory()`,
20+
`createTranslationMemoryImport()`, `uploadTranslationMemoryFile()`,
21+
`createTranslationMemoryExport()`, `getTranslationMemoryJob()`,
22+
`waitUntilTranslationMemoryJobDone()`, `downloadTranslationMemoryExport()`,
23+
`importTranslationMemoryFromFilepath()` and
24+
`exportTranslationMemoryToFilepath()`.
25+
- Added `creationTime` and `updatedTime` to `TranslationMemoryInfo`.
26+
- Added optional timeouts to `waitUntilTranslationMemoryJobDone()`,
27+
`importTranslationMemoryFromFilepath()` and
28+
`exportTranslationMemoryToFilepath()`.
1729

1830
### Fixed
31+
- Fixed `waitUntilTranslationMemoryJobDone()` throwing when a translation memory
32+
job reports `AwaitingInput`. An import job keeps reporting that status for a
33+
while after its file has been uploaded, because the API detects the upload
34+
asynchronously, so it is now polled through like any other non-terminal
35+
status.
1936
- Fixed incorrect example texts in the test suite for several languages (Danish,
2037
Indonesian, Japanese, Portuguese, and Russian) to match the mock server.
2138

README.md

Lines changed: 153 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -823,16 +823,12 @@ class Example { // Continuing class Example from above
823823
Translation memories store and reuse previously created translations, helping to
824824
ensure consistency and reduce effort when translating similar or repeated content.
825825

826-
#### Uploading and managing translation memories
827-
828-
Currently translation memories must be uploaded and managed in the DeepL UI via
829-
https://www.deepl.com/translation-memory. Full CRUD functionality via the APIs will
830-
come shortly.
831-
832826
#### Listing translation memories
833827

834828
Use `listTranslationMemories()` to retrieve translation memories associated
835-
with your account:
829+
with your account. The number of translation memories returned is controlled by
830+
`pageSize` (max 25). The method accepts optional parameters: `page` (page number
831+
for pagination, 0-indexed) and `pageSize` (number of items per page).
836832

837833
```java
838834
class Example { // Continuing class Example from above
@@ -847,6 +843,156 @@ class Example { // Continuing class Example from above
847843
}
848844
```
849845

846+
#### Retrieving a translation memory
847+
848+
Use `getTranslationMemory()` to retrieve a single translation memory. It accepts
849+
either a translation memory ID or a `TranslationMemoryInfo` object:
850+
851+
```java
852+
class Example { // Continuing class Example from above
853+
public void getTranslationMemoryExample() throws Exception {
854+
TranslationMemoryInfo tm = client.getTranslationMemory("YOUR_TM_ID");
855+
System.out.println(String.format("%s: %d segments, updated %s",
856+
tm.getName(), tm.getSegmentCount(), tm.getUpdatedTime()));
857+
}
858+
}
859+
```
860+
861+
#### Listing the segments of a translation memory
862+
863+
`listTranslationMemorySegments()` returns one page of segments as a
864+
`TranslationMemorySegments` object. Pagination is cursor-based: omit the page
865+
cursor on the first call, then pass the previous response's
866+
`getNextPageCursor()` until it is `null`. Optionally filter with `setFilterText()`
867+
(at least 2 characters, matched against both source and target text) and
868+
`setFilterCaseSensitive()`. Note that `getSegmentCount()` is the
869+
translation-memory total and is not reduced by the filter. The API may omit the
870+
segment timestamps, in which case `getCreationTime()`, `getUpdatedTime()` and
871+
`getLastUsedTime()` are `null` on both segments and their targets.
872+
873+
```java
874+
class Example { // Continuing class Example from above
875+
public void listTranslationMemorySegmentsExample() throws Exception {
876+
String pageCursor = null;
877+
do {
878+
TranslationMemorySegments page = client.listTranslationMemorySegments(
879+
"YOUR_TM_ID",
880+
new TranslationMemorySegmentsOptions()
881+
.setPageSize(50)
882+
.setPageCursor(pageCursor));
883+
for (TranslationMemorySegment segment : page.getSegments()) {
884+
System.out.println(segment.getSourceText());
885+
for (TranslationMemoryTargetSegment target : segment.getTargets()) {
886+
System.out.println(String.format(" %s: %s",
887+
target.getTargetLanguage(), target.getTargetText()));
888+
}
889+
}
890+
pageCursor = page.getNextPageCursor();
891+
} while (pageCursor != null);
892+
}
893+
}
894+
```
895+
896+
#### Importing a translation memory
897+
898+
`importTranslationMemoryFromFilepath()` imports a TMX file as a new translation
899+
memory: it creates the import job, uploads the file, and waits for processing to
900+
finish. The returned `TranslationMemoryJob` carries the ID of the new translation
901+
memory:
902+
903+
```java
904+
class Example { // Continuing class Example from above
905+
public void importTranslationMemoryExample() throws Exception {
906+
TranslationMemoryJob job = client.importTranslationMemoryFromFilepath(
907+
new File("/path/to/legal.tmx"), "Legal TM", Duration.ofSeconds(300));
908+
System.out.println(String.format("Created translation memory %s",
909+
job.getResult().getTranslationMemoryId()));
910+
System.out.println(String.format("Skipped segments: %s",
911+
job.getResult().getSkippedSegmentCount()));
912+
}
913+
}
914+
```
915+
916+
The optional timeout is the maximum time to wait for the import to finish; omit
917+
it to wait indefinitely. The job status is polled every 5 seconds, so the
918+
timeout is not accurate to the millisecond.
919+
920+
The three steps are also available separately, for example to upload the file
921+
yourself or to poll for progress. `createTranslationMemoryImport()` returns an
922+
upload URL that the file must be uploaded to before processing starts, then
923+
`getTranslationMemoryJob()` reports the status:
924+
925+
```java
926+
class Example { // Continuing class Example from above
927+
public void importTranslationMemoryStepsExample() throws Exception {
928+
File inputFile = new File("/path/to/legal.tmx");
929+
byte[] fileContent = Files.readAllBytes(inputFile.toPath());
930+
931+
TranslationMemoryImport created = client.createTranslationMemoryImport(
932+
inputFile.getName(), fileContent.length, null, "Legal TM");
933+
// Until the file is uploaded, the job status is AwaitingInput
934+
client.uploadTranslationMemoryFile(created, fileContent);
935+
936+
TranslationMemoryJob job = client.waitUntilTranslationMemoryJobDone(
937+
created.getJobId(), Duration.ofSeconds(300));
938+
}
939+
}
940+
```
941+
942+
Note that an import job keeps reporting `AwaitingInput` for a while after its
943+
file has been uploaded, because the API detects the upload asynchronously.
944+
`waitUntilTranslationMemoryJobDone()` polls through that status like any other
945+
non-terminal one. A job whose file is never uploaded does not finish on its own,
946+
so pass a timeout when that is a possibility.
947+
948+
#### Exporting a translation memory
949+
950+
`exportTranslationMemoryToFilepath()` exports a translation memory to a TMX file:
951+
it creates the export job, waits for it to finish, and writes the result. It
952+
accepts either a translation memory ID or a `TranslationMemoryInfo` object:
953+
954+
```java
955+
class Example { // Continuing class Example from above
956+
public void exportTranslationMemoryExample() throws Exception {
957+
TranslationMemoryJob job = client.exportTranslationMemoryToFilepath(
958+
"YOUR_TM_ID", new File("/path/to/exported.tmx"), Duration.ofSeconds(300));
959+
}
960+
}
961+
```
962+
963+
As with import, the timeout is optional; omit it to wait indefinitely.
964+
965+
As with import, the individual steps are available separately. Note that the API
966+
may reuse a previously completed export of an unchanged translation memory,
967+
indicated by `isReusedExisting()`:
968+
969+
```java
970+
class Example { // Continuing class Example from above
971+
public void exportTranslationMemoryStepsExample() throws Exception {
972+
TranslationMemoryExport created =
973+
client.createTranslationMemoryExport("YOUR_TM_ID");
974+
TranslationMemoryJob job =
975+
client.waitUntilTranslationMemoryJobDone(created.getJobId());
976+
client.downloadTranslationMemoryExport(
977+
job, new File("/path/to/exported.tmx"));
978+
}
979+
}
980+
```
981+
982+
#### Deleting a translation memory
983+
984+
Use `deleteTranslationMemory()` to permanently remove a translation memory from
985+
your account. It accepts either a translation memory ID or a
986+
`TranslationMemoryInfo` object:
987+
988+
```java
989+
class Example { // Continuing class Example from above
990+
public void deleteTranslationMemoryExample() throws Exception {
991+
client.deleteTranslationMemory("YOUR_TM_ID");
992+
}
993+
}
994+
```
995+
850996
#### Using a translation memory in translations
851997

852998
You can use a translation memory for text translation by setting the translation

0 commit comments

Comments
 (0)