Skip to content

Commit d826569

Browse files
committed
feat: Add write API to java CL
1 parent 40997d8 commit d826569

15 files changed

+475
-52
lines changed

Diff for: CHANGELOG.md

+11
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

77

8+
## [Unreleased]
9+
### Added
10+
* Added support for the Write API in the client library, the implementation
11+
can be found in the `DeepLClient` class. Please refer to the README for usage
12+
instructions.
13+
### Changed
14+
* The main functionality of the library is now also exposed via the `DeepLClient`
15+
class. Please change your code to use this over the `Translator` class whenever
16+
convenient.
17+
818
## [1.7.0] - 2024-11-15
919
### Added
1020
* Added `modelType` option to `translateText()` to use models with higher
@@ -125,6 +135,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
125135
Initial version.
126136

127137

138+
[Unreleased]: https://github.com/DeepLcom/deepl-java/compare/v1.7.0...HEAD
128139
[1.7.0]: https://github.com/DeepLcom/deepl-java/compare/v1.6.0...v1.7.0
129140
[1.6.0]: https://github.com/DeepLcom/deepl-java/compare/v1.5.1...v1.6.0
130141
[1.5.1]: https://github.com/DeepLcom/deepl-java/compare/v1.5.0...v1.5.1

Diff for: README.md

+100-46
Large diffs are not rendered by default.
+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright 2025 DeepL SE (https://www.deepl.com)
2+
// Use of this source code is governed by an MIT
3+
// license that can be found in the LICENSE file.
4+
5+
package com.deepl.api;
6+
7+
import com.deepl.api.http.HttpResponse;
8+
import com.deepl.api.utils.KeyValuePair;
9+
import java.util.ArrayList;
10+
import java.util.List;
11+
import org.jetbrains.annotations.Nullable;
12+
13+
public class DeepLClient extends Translator {
14+
15+
/** {@inheritDoc} */
16+
public DeepLClient(String authKey, TranslatorOptions options) throws IllegalArgumentException {
17+
super(authKey, options);
18+
}
19+
20+
public WriteResult rephraseText(
21+
String text, @Nullable String targetLang, @Nullable TextRephraseOptions options)
22+
throws InterruptedException, DeepLException {
23+
ArrayList<String> texts = new ArrayList<>();
24+
texts.add(text);
25+
return this.rephraseText(texts, targetLang, options).get(0);
26+
}
27+
28+
public List<WriteResult> rephraseText(
29+
List<String> texts, @Nullable String targetLang, @Nullable TextRephraseOptions options)
30+
throws InterruptedException, DeepLException {
31+
Iterable<KeyValuePair<String, String>> params =
32+
createWriteHttpParams(texts, targetLang, options);
33+
HttpResponse response = httpClientWrapper.sendRequestWithBackoff("/v2/write/rephrase", params);
34+
checkResponse(response, false, false);
35+
return jsonParser.parseWriteResult(response.getBody());
36+
}
37+
38+
protected static ArrayList<KeyValuePair<String, String>> createWriteHttpParams(
39+
List<String> texts, @Nullable String targetLang, @Nullable TextRephraseOptions options) {
40+
targetLang = LanguageCode.standardize(targetLang);
41+
checkValidLanguages(null, targetLang);
42+
43+
ArrayList<KeyValuePair<String, String>> params = new ArrayList<>();
44+
if (targetLang != null) {
45+
params.add(new KeyValuePair<>("target_lang", targetLang));
46+
}
47+
if (options != null && options.getWritingStyle() != null) {
48+
params.add(new KeyValuePair<>("writing_style", options.getWritingStyle()));
49+
}
50+
if (options != null && options.getTone() != null) {
51+
params.add(new KeyValuePair<>("tone", options.getTone()));
52+
}
53+
54+
texts.forEach(
55+
(text) -> {
56+
if (text.isEmpty()) throw new IllegalArgumentException("text must not be empty");
57+
params.add(new KeyValuePair<>("text", text));
58+
});
59+
60+
return params;
61+
}
62+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Copyright 2025 DeepL SE (https://www.deepl.com)
2+
// Use of this source code is governed by an MIT
3+
// license that can be found in the LICENSE file.
4+
package com.deepl.api;
5+
6+
/** {@inheritDoc} */
7+
public class DeepLClientOptions extends TranslatorOptions {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright 2025 DeepL SE (https://www.deepl.com)
2+
// Use of this source code is governed by an MIT
3+
// license that can be found in the LICENSE file.
4+
package com.deepl.api;
5+
6+
/**
7+
* Options to control text rephrasing behaviour. These options may be provided to {@link
8+
* DeepLClient#rephraseText} overloads.
9+
*
10+
* <p>All properties have corresponding setters in fluent-style, so the following is possible:
11+
* <code>
12+
* TextRephraseOptions options = new TextRephraseOptions()
13+
* .WritingStyle(WritingStyle.Business.getValue());
14+
* </code>
15+
*/
16+
public class TextRephraseOptions {
17+
private String writingStyle;
18+
private String tone;
19+
20+
/**
21+
* Sets a style the improved text should be in. Note that only style OR tone can be set.
22+
*
23+
* @see WritingStyle
24+
*/
25+
public TextRephraseOptions setWritingStyle(String style) {
26+
this.writingStyle = style;
27+
return this;
28+
}
29+
30+
/**
31+
* Sets a tone the improved text should be in. Note that only style OR tone can be set.
32+
*
33+
* @see WritingTone
34+
*/
35+
public TextRephraseOptions setTone(String tone) {
36+
this.tone = tone;
37+
return this;
38+
}
39+
40+
/** Gets the current style setting. */
41+
public String getWritingStyle() {
42+
return writingStyle;
43+
}
44+
45+
/** Gets the current tone setting. */
46+
public String getTone() {
47+
return tone;
48+
}
49+
}

Diff for: deepl-java/src/main/java/com/deepl/api/Translator.java

+9-6
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,18 @@
1717
* Client for the DeepL API. To use the DeepL API, initialize an instance of this class using your
1818
* DeepL Authentication Key as found in your <a href="https://www.deepl.com/pro-account/">DeepL
1919
* account</a>.
20+
*
21+
* @deprecated Use {@link DeepLClient} instead.
2022
*/
23+
@Deprecated
2124
public class Translator {
2225
/** Base URL for DeepL API Free accounts. */
2326
private static final String DEEPL_SERVER_URL_FREE = "https://api-free.deepl.com";
2427
/** Base URL for DeepL API Pro accounts */
2528
private static final String DEEPL_SERVER_URL_PRO = "https://api.deepl.com";
2629

27-
private final Parser jsonParser = new Parser();
28-
private final HttpClientWrapper httpClientWrapper;
30+
protected final Parser jsonParser = new Parser();
31+
protected final HttpClientWrapper httpClientWrapper;
2932

3033
/**
3134
* Initializes a new Translator object using your Authentication Key.
@@ -841,7 +844,7 @@ private static ArrayList<KeyValuePair<String, String>> createHttpParams(
841844
* @param options Options influencing translation.
842845
* @return Iterable of parameters for HTTP request.
843846
*/
844-
private static ArrayList<KeyValuePair<String, String>> createHttpParams(
847+
protected static ArrayList<KeyValuePair<String, String>> createHttpParams(
845848
String sourceLang, String targetLang, DocumentTranslationOptions options) {
846849
return createHttpParamsCommon(
847850
sourceLang,
@@ -861,7 +864,7 @@ private static ArrayList<KeyValuePair<String, String>> createHttpParams(
861864
* @param glossaryId ID of glossary to use for translation.
862865
* @return Iterable of parameters for HTTP request.
863866
*/
864-
private static ArrayList<KeyValuePair<String, String>> createHttpParamsCommon(
867+
protected static ArrayList<KeyValuePair<String, String>> createHttpParamsCommon(
865868
@Nullable String sourceLang,
866869
String targetLang,
867870
@Nullable Formality formality,
@@ -920,7 +923,7 @@ private static String joinTags(Iterable<String> tags) {
920923
* @param targetLang Language code of the desired output language.
921924
* @throws IllegalArgumentException If either language code is invalid.
922925
*/
923-
private static void checkValidLanguages(@Nullable String sourceLang, String targetLang)
926+
protected static void checkValidLanguages(@Nullable String sourceLang, String targetLang)
924927
throws IllegalArgumentException {
925928
if (sourceLang != null && sourceLang.isEmpty()) {
926929
throw new IllegalArgumentException("sourceLang must be null or non-empty");
@@ -982,7 +985,7 @@ private void checkResponse(HttpResponseStream response) throws DeepLException {
982985
* @throws DeepLException Throws {@link DeepLException} or a derived exception depending on the
983986
* type of error.
984987
*/
985-
private void checkResponse(
988+
protected void checkResponse(
986989
HttpResponse response, boolean inDocumentDownload, boolean usingGlossary)
987990
throws DeepLException {
988991
if (response.getCode() >= 200 && response.getCode() < 300) {

Diff for: deepl-java/src/main/java/com/deepl/api/TranslatorOptions.java

+3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@
1717
* TranslatorOptions options = new TranslatorOptions()
1818
* .setTimeout(Duration.ofSeconds(1)).setMaxRetries(2);
1919
* </code>
20+
*
21+
* @deprecated Use {@link DeepLClientOptions} instead.
2022
*/
23+
@Deprecated
2124
public class TranslatorOptions {
2225
private int maxRetries = 5;
2326
private Duration timeout = Duration.ofSeconds(10);
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2025 DeepL SE (https://www.deepl.com)
2+
// Use of this source code is governed by an MIT
3+
// license that can be found in the LICENSE file.
4+
package com.deepl.api;
5+
6+
/** The result of a text translation. */
7+
public class WriteResult {
8+
private final String text;
9+
private final String detectedSourceLanguage;
10+
private final String targetLanguage;
11+
12+
/** Constructs a new instance. */
13+
public WriteResult(String text, String detectedSourceLanguage, String targetLanguage) {
14+
this.text = text;
15+
this.detectedSourceLanguage = LanguageCode.standardize(detectedSourceLanguage);
16+
this.targetLanguage = targetLanguage;
17+
}
18+
19+
/** The translated text. */
20+
public String getText() {
21+
return text;
22+
}
23+
24+
/** The language code of the source text detected by DeepL. */
25+
public String getDetectedSourceLanguage() {
26+
return detectedSourceLanguage;
27+
}
28+
29+
/** The language code of the target language set by the request. */
30+
public String getTargetLanguage() {
31+
return targetLanguage;
32+
}
33+
}
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2025 DeepL SE (https://www.deepl.com)
2+
// Use of this source code is governed by an MIT
3+
// license that can be found in the LICENSE file.
4+
package com.deepl.api;
5+
6+
/** Represents the style the improved text should be in in a rephrase request. */
7+
public enum WritingStyle {
8+
Academic("academic"),
9+
Business("business"),
10+
Casual("casual"),
11+
Default("default"),
12+
PreferAcademic("prefer_academic"),
13+
PreferBusiness("prefer_business"),
14+
PreferCasual("prefer_casual"),
15+
PreferSimple("prefer_simple"),
16+
Simple("simple");
17+
18+
private final String value;
19+
20+
WritingStyle(String value) {
21+
this.value = value;
22+
}
23+
24+
public String getValue() {
25+
return value;
26+
}
27+
}
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2025 DeepL SE (https://www.deepl.com)
2+
// Use of this source code is governed by an MIT
3+
// license that can be found in the LICENSE file.
4+
package com.deepl.api;
5+
6+
/** Represents the tone the improved text should be in in a rephrase request. */
7+
public enum WritingTone {
8+
Confident("confident"),
9+
Default("default"),
10+
Diplomatic("diplomatic"),
11+
Enthusiastic("enthusiastic"),
12+
Friendly("friendly"),
13+
PreferConfident("prefer_confident"),
14+
PreferDiplomatic("prefer_diplomatic"),
15+
PreferEnthusiastic("prefer_enthusiastic"),
16+
PreferFriendly("prefer_friendly");
17+
18+
private final String value;
19+
20+
WritingTone(String value) {
21+
this.value = value;
22+
}
23+
24+
public String getValue() {
25+
return value;
26+
}
27+
}

Diff for: deepl-java/src/main/java/com/deepl/api/parsing/Parser.java

+6
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public class Parser {
2121
public Parser() {
2222
GsonBuilder gsonBuilder = new GsonBuilder();
2323
gsonBuilder.registerTypeAdapter(TextResult.class, new TextResultDeserializer());
24+
gsonBuilder.registerTypeAdapter(WriteResult.class, new WriteResultDeserializer());
2425
gsonBuilder.registerTypeAdapter(Language.class, new LanguageDeserializer());
2526
gsonBuilder.registerTypeAdapter(Usage.class, new UsageDeserializer());
2627
gson = gsonBuilder.create();
@@ -31,6 +32,11 @@ public List<TextResult> parseTextResult(String json) {
3132
return result.translations;
3233
}
3334

35+
public List<WriteResult> parseWriteResult(String json) {
36+
WriteResponse result = gson.fromJson(json, WriteResponse.class);
37+
return result.improvements;
38+
}
39+
3440
public Usage parseUsage(String json) {
3541
return gson.fromJson(json, Usage.class);
3642
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2025 DeepL SE (https://www.deepl.com)
2+
// Use of this source code is governed by an MIT
3+
// license that can be found in the LICENSE file.
4+
package com.deepl.api.parsing;
5+
6+
import com.deepl.api.WriteResult;
7+
import java.util.List;
8+
9+
/**
10+
* Class representing text rephrase responses from the DeepL API.
11+
*
12+
* <p>This class is internal; you should not use this class directly.
13+
*/
14+
class WriteResponse {
15+
public List<WriteResult> improvements;
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2025 DeepL SE (https://www.deepl.com)
2+
// Use of this source code is governed by an MIT
3+
// license that can be found in the LICENSE file.
4+
package com.deepl.api.parsing;
5+
6+
import com.deepl.api.WriteResult;
7+
import com.google.gson.*;
8+
import java.lang.reflect.Type;
9+
10+
/**
11+
* Utility class for deserializing text rephrase results returned by the DeepL API.
12+
*
13+
* <p>This class is internal; you should not use this class directly.
14+
*/
15+
class WriteResultDeserializer implements JsonDeserializer<WriteResult> {
16+
public WriteResult deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
17+
throws JsonParseException {
18+
JsonObject jsonObject = json.getAsJsonObject();
19+
return new WriteResult(
20+
jsonObject.get("text").getAsString(),
21+
jsonObject.get("detected_source_language").getAsString(),
22+
jsonObject.get("target_language").getAsString());
23+
}
24+
}

0 commit comments

Comments
 (0)