
Tłumaczenie treści strukturalnych z Javy za pomocą PolyLingo SDK
By Robert
Tłumaczenie ustrukturyzowanej zawartości z Java za pomocą PolyLingo SDK
PolyLingo Java SDK jest teraz dostępne w Maven Central. Obejmuje pełne API PolyLingo: tłumaczenie synchroniczne, żądania wsadowe, zadania asynchroniczne z pollingiem oraz wszystkie punkty końcowe narzędziowe. Wymaga Java 11 lub nowszej, używa standardowego klienta HTTP z biblioteki standardowej i ma dokładnie jedną zależność w czasie wykonywania: Jackson do JSON.
Instalacja
Maven
<dependency>
<groupId>com.usepolylingo</groupId>
<artifactId>polylingo</artifactId>
<version>0.1.0</version>
</dependency>
Gradle
implementation 'com.usepolylingo:polylingo:0.1.0'
Nie jest wymagana dodatkowa zależność klienta HTTP. SDK używa java.net.http.HttpClient z biblioteki standardowej Java 11.
Konfiguracja klienta
import com.usepolylingo.polylingo.PolyLingo;
PolyLingo client = PolyLingo.builder()
.apiKey(System.getenv("POLYLINGO_API_KEY"))
.build();
Dostępne są dwa opcjonalne parametry buildera:
PolyLingo client = PolyLingo.builder()
.apiKey(System.getenv("POLYLINGO_API_KEY"))
.baseUrl("https://api.usepolylingo.com/v1") // domyślny, nadpisz dla instancji self-hosted
.timeout(Duration.ofSeconds(30)) // domyślnie 120 sekund
.build();
Przechowuj swój klucz API w zmiennej środowiskowej. Nigdy nie koduj go na stałe ani nie zatwierdzaj do kontroli wersji.
SDK używa wzorca buildera w całym kodzie. Brak konstruktorów pozycyjnych, brak wymaganego porządku pól. Wszystkie pola opcjonalne mają sensowne wartości domyślne, więc konfigurujesz tylko to, co faktycznie chcesz zmienić.
Tłumaczenie zawartości
Pojedyncze żądanie
import com.usepolylingo.polylingo.types.TranslateParams;
import com.usepolylingo.polylingo.types.TranslateResult;
TranslateResult result = client.translate(
TranslateParams.builder()
.content("Hello, world!")
.targets(List.of("es", "fr", "de"))
.build()
);
result.getTranslations().forEach((lang, text) ->
System.out.println(lang + ": " + text)
);
// es: ¡Hola, mundo!
// fr: Bonjour le monde !
// de: Hallo Welt!
Builder TranslateParams akceptuje content i targets jako pola wymagane. Parametry opcjonalne to format (plain, markdown, json lub html — wykrywany automatycznie, jeśli pominięty), source jako wskazówka językowa oraz model jako standard (domyślny) lub advanced.
Zachowanie formatu działa tak samo jak w reszcie API PolyLingo. Dla zawartości json tłumaczone są tylko wartości tekstowe, a klucze, zagnieżdżenia i typy niebędące tekstem pozostają nietknięte. Dla markdown nagłówki pozostają nagłówkami, a bloki kodu są pozostawione dosłownie. Dla html tagi i atrybuty są zachowane, a tłumaczone są tylko węzły tekstowe.
Tłumaczenie pliku locale JSON
import com.fasterxml.jackson.databind.ObjectMapper;
import java.nio.file.Files;
import java.nio.file.Path;
ObjectMapper mapper = new ObjectMapper();
String sourceJson = Files.readString(Path.of("messages/en.json"));
TranslateResult result = client.translate(
TranslateParams.builder()
.content(sourceJson)
.format("json")
.targets(List.of("fr", "de", "ja"))
.build()
);
result.getTranslations().forEach((locale, translated) -> {
try {
Object parsed = mapper.readValue(translated, Object.class);
String pretty = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(parsed);
Files.writeString(Path.of("messages/" + locale + ".json"), pretty);
System.out.println("Wrote messages/" + locale + ".json");
} catch (Exception e) {
throw new RuntimeException(e);
}
});
Jedno żądanie obsługuje wszystkie trzy locale. Klucze są identyczne jak w źródle w każdym pliku wyjściowym.
Żądania wsadowe
Wyślij do 100 elementów zawartości w jednym żądaniu, każdy z własnym id i opcjonalnym format:
import com.usepolylingo.polylingo.types.BatchParams;
import com.usepolylingo.polylingo.types.BatchItem;
import com.usepolylingo.polylingo.types.BatchResult;
BatchResult result = client.batch(
BatchParams.builder()
.targets(List.of("es", "ja"))
.addItem(BatchItem.builder().id("title").content("Welcome").build())
.addItem(BatchItem.builder().id("body").content("Get started today.").build())
.build()
);
for (BatchItemResult item : result.getResults()) {
System.out.println(item.getId() + ": " + item.getTranslations());
}
Wszystkie elementy dzielą tę samą listę targets. Przypisane id jest zachowywane w odpowiedzi, dzięki czemu możesz mapować wyniki z powrotem do swoich danych źródłowych bez polegania na kolejności.
Zadania asynchroniczne
Dla długich dokumentów lub dużych obciążeń tłumaczeniowych API zadań przyjmuje żądanie, zwraca natychmiast identyfikator zadania i pozwala na polling wyniku. SDK obsługuje to na dwa sposoby.
Jedno wywołanie, które polluje aż do zakończenia
import com.usepolylingo.polylingo.types.JobsTranslateParams;
TranslateResult result = client.jobs().translate(
JobsTranslateParams.builder()
.content(longArticleText)
.targets(List.of("fr", "de", "ja", "zh"))
.pollInterval(Duration.ofSeconds(3))
.timeout(Duration.ofMinutes(10))
.onProgress(queuePosition ->
System.out.println("Queue position: " + queuePosition))
.build()
);
result.getTranslations().forEach((lang, text) ->
System.out.println(lang + ": " + text.substring(0, 100) + "...")
);
Callback onProgress wywoływany jest przy każdym pollingu z aktualną pozycją w kolejce jako liczbą całkowitą lub null, jeśli API jej nie zwraca. Użyj go do logowania postępu lub aktualizacji interfejsu użytkownika.
Kolejkowanie i polling ręczny
import com.usepolylingo.polylingo.types.CreateJobParams;
import com.usepolylingo.polylingo.types.Job;
Job job = client.jobs().create(
CreateJobParams.builder()
.content("Translate this.")
.targets(List.of("es"))
.build()
);
// Polluj samodzielnie
Job status = client.jobs().get(job.getJobId());
System.out.println(status.getStatus()); // pending / processing / completed / failed
Punkty końcowe narzędziowe
// Sprawdź stan API (nie wymaga klucza API)
HealthResponse health = client.health();
System.out.println(health.getStatus()); // "ok"
// Lista obsługiwanych języków (nie wymaga klucza API)
LanguagesResponse langs = client.languages();
langs.getLanguages().forEach(l ->
System.out.println(l.getCode() + " — " + l.getName())
);
// Sprawdź użycie tokenów za bieżący miesiąc rozliczeniowy
UsageResponse usage = client.usage();
System.out.println("Tokens used: " + usage.getUsage().getTokensUsed());
System.out.println("Tokens remaining: " + usage.getUsage().getTokensRemaining());
Obsługa błędów
Wszystkie wyjątki są unchecked. Brak wymuszonych deklaracji throws, brak łańcuchów wyjątków do rozwinięcia:
import com.usepolylingo.polylingo.errors.*;
try {
TranslateResult result = client.translate(
TranslateParams.builder()
.content("# Hello")
.targets(List.of("es", "fr"))
.format("markdown")
.build()
);
} catch (AuthException e) {
// HTTP 401 — nieprawidłowy, brakujący lub cofnięty klucz API
System.out.println("Auth failed: " + e.getError());
} catch (RateLimitException e) {
// HTTP 429 — osiągnięto limit na minutę
e.getRetryAfter().ifPresent(s ->
System.out.println("Retry after: " + s + "s")
);
} catch (JobFailedException e) {
// Zadanie async osiągnęło stan końcowy z błędem lub polling przekroczył limit czasu
System.out.println("Job " + e.getJobId() + " failed: " + e.getError());
} catch (PolyLingoException e) {
// Wszystkie inne błędy API
System.out.println(e.getStatus() + ": " + e.getMessage());
}
RateLimitException.getRetryAfter() zwraca Optional<Integer> — obecny z liczbą sekund do odczekania, jeśli API zawiera tę wartość, pusty w przeciwnym razie. JobFailedException.getJobId() zwraca ID nieudanego zadania do logowania lub logiki ponownej próby.
Notatki projektowe
Kilka decyzji wartych poznania, jeśli oceniasz SDK:
Synchroniczne API. Każda metoda blokuje i zwraca wynik bezpośrednio. Brak Future, brak CompletableFuture, brak reaktywnych strumieni. Polling zadań to async historia SDK dla dużych obciążeń — wyślij zadanie, SDK polluje na twoim wątku i wywołuje twój callback onProgress gdy pozycja w kolejce się zmienia.
Wzorzec buildera wszędzie. Każdy obiekt parametrów używa buildera. Brak konstruktorów pozycyjnych oznacza brak zgadywania kolejności argumentów, brak przypadkowej zamiany pól i czytelny kod w miejscu wywołania.
Jedna zależność runtime. Jackson do serializacji JSON. Wszystko inne to biblioteka standardowa. Brak OkHttp, brak Apache HttpClient, brak Guava.
Java 11+. Używa java.net.http.HttpClient wprowadzonego w Java 11. Jeśli twój projekt celuje w Java 8 lub starszą, SDK nie jest kompatybilne.
Szybkie odniesienie
| Metoda | Endpoint | Wymaga autoryzacji |
|---|---|---|
client.health() | GET /health | Nie |
client.languages() | GET /languages | Nie |
client.translate(...) | POST /translate | Tak |
client.batch(...) | POST /translate/batch | Tak |
client.usage() | GET /usage | Tak |
client.jobs().create(...) | POST /jobs | Tak |
client.jobs().get(jobId) | GET /jobs/:id | Tak |
client.jobs().translate(...) | POST /jobs + polling | Tak |
Rozpocznij
SDK jest dostępne w Maven Central pod adresem central.sonatype.com/artifact/com.usepolylingo/polylingo. Kod źródłowy i Javadoc są na github.com/UsePolyLingo/polylingo-Java. Pełna dokumentacja API jest na usepolylingo.com/docs/sdk/java.
Darmowy poziom obejmuje 50 000 tokenów miesięcznie. Nie jest wymagana karta kredytowa.
<dependency>
<groupId>com.usepolylingo</groupId>
<artifactId>polylingo</artifactId>
<version>0.1.0</version>
</dependency>