
PolyLingo SDK로 Java에서 구조화된 콘텐츠 번역하기
By Robert
PolyLingo SDK로 Java에서 구조화된 콘텐츠 번역하기
PolyLingo Java SDK가 이제 Maven Central에서 제공됩니다. 동기 번역, 배치 요청, 폴링이 포함된 비동기 작업 및 모든 유틸리티 엔드포인트를 포함한 전체 PolyLingo API를 지원합니다. Java 11 이상이 필요하며, 표준 라이브러리 HTTP 클라이언트를 사용하고, 런타임 의존성은 JSON용 Jackson 하나뿐입니다.
설치
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 11 표준 라이브러리의 java.net.http.HttpClient를 사용합니다.
클라이언트 설정
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, standard(기본값) 또는 advanced인 model이 있습니다.
형식 보존은 PolyLingo API의 다른 부분과 동일하게 작동합니다. 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 콜백은 각 폴링 시 현재 대기열 위치(정수)로 호출되며, API가 반환하지 않으면 null입니다. 진행 상황을 기록하거나 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("Tokens used: " + usage.getUsage().getTokensUsed());
System.out.println("Tokens remaining: " + usage.getUsage().getTokensRemaining());
오류 처리
모든 예외는 체크되지 않습니다. 강제 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("Auth failed: " + e.getError());
} catch (RateLimitException e) {
// HTTP 429 — 분당 제한 도달
e.getRetryAfter().ifPresent(s ->
System.out.println("Retry after: " + s + "s")
);
} catch (JobFailedException e) {
// 비동기 작업이 실패 상태에 도달했거나 폴링이 시간 초과됨
System.out.println("Job " + e.getJobId() + " failed: " + 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가 스레드에서 폴링하며 대기열 위치가 업데이트될 때 onProgress 콜백을 호출합니다.
전면 빌더 패턴. 모든 파라미터 객체는 빌더를 사용합니다. 위치 기반 생성자가 없으므로 인수 순서를 추측할 필요 없고, 필드 교환 실수도 없으며 호출 지점의 코드가 명확합니다.
런타임 의존성 1개. JSON 직렬화를 위한 Jackson. 나머지는 표준 라이브러리입니다. OkHttp, Apache HttpClient, Guava는 사용하지 않습니다.
Java 11 이상. Java 11에서 도입된 java.net.http.HttpClient를 사용합니다. 프로젝트가 Java 8 이하를 대상으로 하면 SDK는 호환되지 않습니다.
빠른 참조
| 메서드 | 엔드포인트 | 인증 필요 |
|---|---|---|
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>