
Перевод структурированного контента из Java с помощью PolyLingo SDK
By Robert
Перевод структурированного контента из Java с помощью PolyLingo SDK
PolyLingo Java SDK теперь доступен на Maven Central. Он охватывает полный API PolyLingo: синхронный перевод, пакетные запросы, асинхронные задания с опросом и все вспомогательные конечные точки. Требуется Java 11 или новее, используется стандартный HTTP-клиент библиотеки, и есть ровно одна зависимость во время выполнения: Jackson для JSON.
Установка
Maven
<dependency>
<groupId>com.usepolylingo</groupId>
<artifactId>polylingo</artifactId>
<version>0.1.0</version>
</dependency>
Gradle
implementation 'com.usepolylingo:polylingo:0.1.0'
Дополнительная зависимость HTTP-клиента не требуется. SDK использует java.net.http.HttpClient из стандартной библиотеки Java 11.
Настройка клиента
import com.usepolylingo.polylingo.PolyLingo;
PolyLingo client = PolyLingo.builder()
.apiKey(System.getenv("POLYLINGO_API_KEY"))
.build();
Доступны два необязательных параметра билдера:
PolyLingo client = PolyLingo.builder()
.apiKey(System.getenv("POLYLINGO_API_KEY"))
.baseUrl("https://api.usepolylingo.com/v1") // по умолчанию, переопределите для самостоятельных инстансов
.timeout(Duration.ofSeconds(30)) // по умолчанию 120 секунд
.build();
Храните ваш API-ключ в переменной окружения. Никогда не прописывайте его в коде и не коммитьте в систему контроля версий.
SDK использует паттерн билдера повсеместно. Нет позиционных конструкторов, нет обязательного порядка полей. Все опциональные поля имеют разумные значения по умолчанию, так что вы настраиваете только то, что действительно нужно изменить.
Перевод контента
Один запрос
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!
Билдер TranslateParams принимает content и targets как обязательные поля. Опциональные параметры включают format (plain, markdown, json или html — определяется автоматически, если опущено), source как подсказку языка и model как standard (по умолчанию) или advanced.
Сохранение формата работает так же, как и в остальной части API PolyLingo. Для json контента переводятся только строковые значения, ключи, вложенность и нестроковые типы остаются без изменений. Для markdown заголовки остаются заголовками, а блоки кода сохраняются без изменений. Для html теги и атрибуты сохраняются, переводятся только текстовые узлы.
Перевод 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);
}
});
Один запрос обрабатывает все три локали. Ключи идентичны исходным во всех выходных файлах.
Пакетные запросы
Отправляйте до 100 элементов контента в одном запросе, каждый с собственным id и опциональным 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());
}
Все элементы используют один и тот же список targets. Присвоенный вами id сохраняется в ответе, чтобы вы могли сопоставить результаты с исходными данными без зависимости от порядка.
Асинхронные задания
Для длинных документов или больших объемов перевода API заданий принимает запрос, сразу возвращает ID задания и позволяет опрашивать результат. SDK поддерживает это двумя способами.
Один вызов с опросом до завершения
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) + "...")
);
Обратный вызов onProgress вызывается при каждом опросе с текущей позицией в очереди как целым числом или null, если API не возвращает эту информацию. Используйте для логирования прогресса или обновления UI.
Добавление в очередь и опрос вручную
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()
);
// Опрос самостоятельно
Job status = client.jobs().get(job.getJobId());
System.out.println(status.getStatus()); // pending / processing / completed / failed
Вспомогательные конечные точки
// Проверка состояния API (ключ API не требуется)
HealthResponse health = client.health();
System.out.println(health.getStatus()); // "ok"
// Список поддерживаемых языков (ключ API не требуется)
LanguagesResponse langs = client.languages();
langs.getLanguages().forEach(l ->
System.out.println(l.getCode() + " — " + l.getName())
);
// Проверка использования токенов за текущий расчетный месяц
UsageResponse usage = client.usage();
System.out.println("Использовано токенов: " + usage.getUsage().getTokensUsed());
System.out.println("Остаток токенов: " + usage.getUsage().getTokensRemaining());
Обработка ошибок
Все исключения unchecked. Нет обязательных объявлений throws, нет цепочек проверяемых исключений для обработки:
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 — неверный, отсутствующий или отозванный ключ API
System.out.println("Ошибка аутентификации: " + e.getError());
} catch (RateLimitException e) {
// HTTP 429 — достигнут лимит запросов в минуту
e.getRetryAfter().ifPresent(s ->
System.out.println("Повторить через: " + s + "с")
);
} catch (JobFailedException e) {
// Асинхронное задание завершилось с ошибкой или время опроса истекло
System.out.println("Задание " + e.getJobId() + " не выполнено: " + e.getError());
} catch (PolyLingoException e) {
// Все остальные ошибки API
System.out.println(e.getStatus() + ": " + e.getMessage());
}
RateLimitException.getRetryAfter() возвращает Optional<Integer> — присутствует с числом секунд ожидания, если API включает это значение, иначе пустой. JobFailedException.getJobId() возвращает ID неудавшегося задания для логирования или логики повторной попытки.
Заметки по дизайну
Несколько решений, которые стоит знать при оценке SDK:
Синхронный API. Каждый метод блокирует и возвращает результат напрямую. Нет Future, нет CompletableFuture, нет реактивных потоков. Опрос заданий — это асинхронная история SDK для больших нагрузок — отправьте задание, SDK опрашивает в вашем потоке и вызывает ваш callback onProgress при обновлении позиции в очереди.
Паттерн билдера повсеместно. Каждый объект параметров использует билдер. Отсутствие позиционных конструкторов исключает угадывание порядка аргументов, случайную замену полей и обеспечивает понятный код в месте вызова.
Одна зависимость во время выполнения. Jackson для сериализации JSON. Всё остальное — стандартная библиотека. Нет OkHttp, нет Apache HttpClient, нет Guava.
Java 11+. Использует java.net.http.HttpClient, появившийся в Java 11. Если ваш проект нацелен на Java 8 или ниже, SDK несовместим.
Быстрая справка
| Метод | Endpoint | Требуется аутентификация |
|---|---|---|
client.health() | GET /health | Нет |
client.languages() | GET /languages | Нет |
client.translate(...) | POST /translate | Да |
client.batch(...) | POST /translate/batch | Да |
client.usage() | GET /usage | Да |
client.jobs().create(...) | POST /jobs | Да |
client.jobs().get(jobId) | GET /jobs/:id | Да |
client.jobs().translate(...) | POST /jobs + опрос | Да |
Начало работы
SDK доступен на Maven Central по адресу central.sonatype.com/artifact/com.usepolylingo/polylingo. Исходный код и Javadoc находятся на github.com/UsePolyLingo/polylingo-Java. Полная документация API доступна на usepolylingo.com/docs/sdk/java.
Бесплатный тариф включает 50 000 токенов в месяц. Кредитная карта не требуется.
<dependency>
<groupId>com.usepolylingo</groupId>
<artifactId>polylingo</artifactId>
<version>0.1.0</version>
</dependency>