From 864f9826ccaf3269de7168dc0e88edf109eaeea0 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Mon, 20 Oct 2025 14:48:16 +0300 Subject: [PATCH 1/8] Translator: add missing imports --- src/main/java/space/dynomake/libretranslate/Translator.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/space/dynomake/libretranslate/Translator.java b/src/main/java/space/dynomake/libretranslate/Translator.java index 5ed1521..b48e584 100644 --- a/src/main/java/space/dynomake/libretranslate/Translator.java +++ b/src/main/java/space/dynomake/libretranslate/Translator.java @@ -7,8 +7,10 @@ import space.dynomake.libretranslate.type.TranslateResponse; import space.dynomake.libretranslate.util.JsonUtil; import java.io.InputStream; +import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.*; +import java.nio.charset.StandardCharsets; import java.util.Scanner; @UtilityClass From 343c3bcf804f482032b10dbe22ffef12ca362ad4 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Mon, 20 Oct 2025 14:49:33 +0300 Subject: [PATCH 2/8] Translator: add User-Agent header --- src/main/java/space/dynomake/libretranslate/Translator.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/space/dynomake/libretranslate/Translator.java b/src/main/java/space/dynomake/libretranslate/Translator.java index b48e584..64a497c 100644 --- a/src/main/java/space/dynomake/libretranslate/Translator.java +++ b/src/main/java/space/dynomake/libretranslate/Translator.java @@ -35,6 +35,7 @@ public TranslateResponse translateDetect(@NonNull String from, @NonNull String t httpConn.setRequestProperty("accept", "application/json"); httpConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + httpConn.setRequestProperty("User-Agent", "Mozilla/5.0"); httpConn.setDoOutput(true); From efb4638cb042f0f808410c05ed9d578301c185dd Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Mon, 20 Oct 2025 14:56:16 +0300 Subject: [PATCH 3/8] Add .gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..abc78ba --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/.gradle/ +/build/ From 2a26f04f367ff3a69d215bfd481393c16e225d29 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Mon, 20 Oct 2025 14:55:37 +0300 Subject: [PATCH 4/8] JsonUtil: add from(Reader) --- .../java/space/dynomake/libretranslate/Translator.java | 9 ++------- .../space/dynomake/libretranslate/util/JsonUtil.java | 6 ++++++ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/java/space/dynomake/libretranslate/Translator.java b/src/main/java/space/dynomake/libretranslate/Translator.java index 64a497c..b788edf 100644 --- a/src/main/java/space/dynomake/libretranslate/Translator.java +++ b/src/main/java/space/dynomake/libretranslate/Translator.java @@ -11,7 +11,6 @@ import java.io.OutputStreamWriter; import java.net.*; import java.nio.charset.StandardCharsets; -import java.util.Scanner; @UtilityClass public class Translator { @@ -33,7 +32,7 @@ public TranslateResponse translateDetect(@NonNull String from, @NonNull String t HttpURLConnection httpConn = (HttpURLConnection) url.openConnection(); httpConn.setRequestMethod("POST"); - httpConn.setRequestProperty("accept", "application/json"); + httpConn.setRequestProperty("Accept", "application/json"); httpConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); httpConn.setRequestProperty("User-Agent", "Mozilla/5.0"); @@ -52,11 +51,7 @@ public TranslateResponse translateDetect(@NonNull String from, @NonNull String t InputStream responseStream = httpConn.getInputStream(); InputStreamReader reader = new InputStreamReader(responseStream, StandardCharsets.UTF_8); - - Scanner s = new Scanner(reader).useDelimiter("\\A"); - String response = s.hasNext() ? s.next() : ""; - - return JsonUtil.from(response, TranslateResponse.class); + return JsonUtil.from(reader, TranslateResponse.class); } catch (Exception e) { if (e instanceof RuntimeException) throw (RuntimeException) e; diff --git a/src/main/java/space/dynomake/libretranslate/util/JsonUtil.java b/src/main/java/space/dynomake/libretranslate/util/JsonUtil.java index 662de44..e6f9d61 100644 --- a/src/main/java/space/dynomake/libretranslate/util/JsonUtil.java +++ b/src/main/java/space/dynomake/libretranslate/util/JsonUtil.java @@ -4,6 +4,8 @@ import lombok.NonNull; import lombok.experimental.UtilityClass; +import java.io.Reader; + @UtilityClass public class JsonUtil { @@ -17,4 +19,8 @@ public String to(@NonNull Object object) { public T from(@NonNull String s, Class tClass) { return gson.fromJson(s, tClass); } + + public T from(@NonNull Reader reader, Class tClass) { + return gson.fromJson(reader, tClass); + } } From d73ab3bb4af53a422eaad260fe011f735d499f98 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Mon, 20 Oct 2025 15:10:22 +0300 Subject: [PATCH 5/8] Translator: don't print stack trace --- src/main/java/space/dynomake/libretranslate/Translator.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/space/dynomake/libretranslate/Translator.java b/src/main/java/space/dynomake/libretranslate/Translator.java index b788edf..c4671c2 100644 --- a/src/main/java/space/dynomake/libretranslate/Translator.java +++ b/src/main/java/space/dynomake/libretranslate/Translator.java @@ -55,8 +55,6 @@ public TranslateResponse translateDetect(@NonNull String from, @NonNull String t } catch (Exception e) { if (e instanceof RuntimeException) throw (RuntimeException) e; - - e.printStackTrace(); throw new RuntimeException(e); } } From db4e49bae7dc7ab2b3897c1efa89fb947220786a Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Mon, 20 Oct 2025 15:17:23 +0300 Subject: [PATCH 6/8] Translator: improve error handling --- .../dynomake/libretranslate/Translator.java | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/main/java/space/dynomake/libretranslate/Translator.java b/src/main/java/space/dynomake/libretranslate/Translator.java index c4671c2..ccfb6bb 100644 --- a/src/main/java/space/dynomake/libretranslate/Translator.java +++ b/src/main/java/space/dynomake/libretranslate/Translator.java @@ -6,6 +6,8 @@ import space.dynomake.libretranslate.exception.BadTranslatorResponseException; import space.dynomake.libretranslate.type.TranslateResponse; import space.dynomake.libretranslate.util.JsonUtil; + +import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; @@ -26,10 +28,10 @@ public String translate(@NonNull String from, @NonNull String to, @NonNull Strin } public TranslateResponse translateDetect(@NonNull String from, @NonNull String to, @NonNull String request) { + HttpURLConnection httpConn = null; try { - URL url = new URL(urlApi); - HttpURLConnection httpConn = (HttpURLConnection) url.openConnection(); + httpConn = (HttpURLConnection) url.openConnection(); httpConn.setRequestMethod("POST"); httpConn.setRequestProperty("Accept", "application/json"); @@ -45,17 +47,26 @@ public TranslateResponse translateDetect(@NonNull String from, @NonNull String t writer.close(); httpConn.getOutputStream().close(); - if (!(httpConn.getResponseCode() / 100 == 2)) - throw new BadTranslatorResponseException(httpConn.getResponseCode(), urlApi); + // Check response code before reading + int responseCode = httpConn.getResponseCode(); + if (responseCode != HttpURLConnection.HTTP_OK) { + throw new BadTranslatorResponseException(responseCode, urlApi); + } InputStream responseStream = httpConn.getInputStream(); InputStreamReader reader = new InputStreamReader(responseStream, StandardCharsets.UTF_8); return JsonUtil.from(reader, TranslateResponse.class); + } catch (IOException e) { + throw new RuntimeException("Network error during translation", e); + } catch (RuntimeException e) { + throw e; } catch (Exception e) { - if (e instanceof RuntimeException) - throw (RuntimeException) e; - throw new RuntimeException(e); + throw new RuntimeException("Translation failed", e); + } finally { + if (httpConn != null) { + httpConn.disconnect(); + } } } From c054d8126b22c1108eaefecac3edb8115e8cd207 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Mon, 20 Oct 2025 15:21:50 +0300 Subject: [PATCH 7/8] Translator: use try with close --- .../dynomake/libretranslate/Translator.java | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/main/java/space/dynomake/libretranslate/Translator.java b/src/main/java/space/dynomake/libretranslate/Translator.java index ccfb6bb..9061946 100644 --- a/src/main/java/space/dynomake/libretranslate/Translator.java +++ b/src/main/java/space/dynomake/libretranslate/Translator.java @@ -7,12 +7,15 @@ import space.dynomake.libretranslate.type.TranslateResponse; import space.dynomake.libretranslate.util.JsonUtil; +import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.*; -import java.nio.charset.StandardCharsets; + +import static java.nio.charset.StandardCharsets.UTF_8; @UtilityClass public class Translator { @@ -40,12 +43,14 @@ public TranslateResponse translateDetect(@NonNull String from, @NonNull String t httpConn.setDoOutput(true); - OutputStreamWriter writer = new OutputStreamWriter(httpConn.getOutputStream()); - - writer.write("q=" + URLEncoder.encode(request, "UTF-8") + "&source=" + from + "&api_key=" + apiKey + "&target=" + to + "&format=text"); - writer.flush(); - writer.close(); - httpConn.getOutputStream().close(); + // Build request body + String requestBody = "q=" + URLEncoder.encode(request, "UTF-8") + "&source=" + from + "&target=" + to + "&format=text"; + // Write request + try (OutputStream outputStream = httpConn.getOutputStream(); + OutputStreamWriter writer = new OutputStreamWriter(outputStream, UTF_8)) { + writer.write(requestBody); + writer.flush(); + } // Check response code before reading int responseCode = httpConn.getResponseCode(); @@ -53,10 +58,10 @@ public TranslateResponse translateDetect(@NonNull String from, @NonNull String t throw new BadTranslatorResponseException(responseCode, urlApi); } - InputStream responseStream = httpConn.getInputStream(); - - InputStreamReader reader = new InputStreamReader(responseStream, StandardCharsets.UTF_8); - return JsonUtil.from(reader, TranslateResponse.class); + try (InputStream responseStream = httpConn.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(responseStream, UTF_8))) { + return JsonUtil.from(reader, TranslateResponse.class); + } } catch (IOException e) { throw new RuntimeException("Network error during translation", e); } catch (RuntimeException e) { From 4c734bc99675cc69b67ee933db8316bf6d60e12d Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Mon, 20 Oct 2025 15:30:35 +0300 Subject: [PATCH 8/8] Translator: disable cache and add timeouts By default, the HTTP client has a zero timeout, which means wait forever. --- .../java/space/dynomake/libretranslate/Translator.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/space/dynomake/libretranslate/Translator.java b/src/main/java/space/dynomake/libretranslate/Translator.java index 9061946..33deef8 100644 --- a/src/main/java/space/dynomake/libretranslate/Translator.java +++ b/src/main/java/space/dynomake/libretranslate/Translator.java @@ -26,6 +26,12 @@ public class Translator { @Setter private String apiKey = "unknown"; + @Setter + private static int connectTimeout = 5000; // 5 seconds + + @Setter + private static int readTimeout = 5000; + public String translate(@NonNull String from, @NonNull String to, @NonNull String request) { return translateDetect(from, to, request).getTranslatedText(); } @@ -35,6 +41,9 @@ public TranslateResponse translateDetect(@NonNull String from, @NonNull String t try { URL url = new URL(urlApi); httpConn = (HttpURLConnection) url.openConnection(); + httpConn.setConnectTimeout(connectTimeout); + httpConn.setReadTimeout(readTimeout); + httpConn.setUseCaches(false); httpConn.setRequestMethod("POST"); httpConn.setRequestProperty("Accept", "application/json");