
Traducir contenido estructurado desde Java con el SDK de PolyLingo
By Robert
Traducir contenido estructurado desde Java con el SDK PolyLingo
El SDK PolyLingo para Java ya está disponible en Maven Central. Cubre toda la API de PolyLingo: traducción síncrona, solicitudes por lotes, trabajos asíncronos con sondeo y todos los endpoints de utilidad. Requiere Java 11 o superior, usa el cliente HTTP de la biblioteca estándar y tiene exactamente una dependencia en tiempo de ejecución: Jackson para JSON.
Instalación
Maven
<dependency>
<groupId>com.usepolylingo</groupId>
<artifactId>polylingo</artifactId>
<version>0.1.0</version>
</dependency>
Gradle
implementation 'com.usepolylingo:polylingo:0.1.0'
No se requiere dependencia adicional para el cliente HTTP. El SDK usa java.net.http.HttpClient de la biblioteca estándar de Java 11.
Configuración del cliente
import com.usepolylingo.polylingo.PolyLingo;
PolyLingo client = PolyLingo.builder()
.apiKey(System.getenv("POLYLINGO_API_KEY"))
.build();
Hay dos parámetros opcionales en el builder:
PolyLingo client = PolyLingo.builder()
.apiKey(System.getenv("POLYLINGO_API_KEY"))
.baseUrl("https://api.usepolylingo.com/v1") // por defecto, sobrescribir para instancias autoalojadas
.timeout(Duration.ofSeconds(30)) // por defecto es 120 segundos
.build();
Guarda tu clave API en una variable de entorno. Nunca la codifiques directamente ni la subas al control de versiones.
El SDK usa el patrón builder en todo momento. No hay constructores posicionales ni orden obligatorio de campos. Todos los campos opcionales tienen valores predeterminados sensatos para que solo configures lo que realmente necesitas cambiar.
Traducción de contenido
Solicitud única
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!
El builder TranslateParams acepta content y targets como campos obligatorios. Los parámetros opcionales incluyen format (plain, markdown, json o html — se detecta automáticamente si se omite), source como pista de idioma y model como standard (predeterminado) o advanced.
La preservación del formato funciona igual que en el resto de la API de PolyLingo. Para contenido json, solo se traducen los valores de cadena y las claves, anidamientos y tipos no cadena permanecen intactos. Para markdown, los encabezados permanecen encabezados y los bloques de código se mantienen tal cual. Para html, las etiquetas y atributos se preservan y solo se traducen los nodos de texto.
Traducción de un archivo JSON de localización
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);
}
});
Una sola solicitud maneja los tres locales. Las claves son idénticas a la fuente en cada archivo de salida.
Solicitudes por lotes
Envía hasta 100 elementos de contenido en una sola solicitud, cada uno con su propio id y format opcional:
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());
}
Todos los elementos comparten la misma lista targets. El id que asignas se conserva en la respuesta para que puedas mapear los resultados a tus datos fuente sin depender del orden.
Trabajos asíncronos
Para documentos largos o grandes cargas de traducción, la API de trabajos acepta una solicitud, devuelve inmediatamente un ID de trabajo y te permite hacer polling para obtener el resultado. El SDK lo maneja de dos maneras.
Una llamada que hace polling hasta que termina
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) + "...")
);
El callback onProgress se dispara en cada polling con la posición actual en la cola como entero, o null si la API no devuelve uno. Úsalo para registrar el progreso o actualizar una interfaz de usuario.
Encolar y hacer polling manualmente
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()
);
// Haz polling tú mismo
Job status = client.jobs().get(job.getJobId());
System.out.println(status.getStatus()); // pending / processing / completed / failed
Endpoints de utilidad
// Comprobar salud de la API (no requiere clave API)
HealthResponse health = client.health();
System.out.println(health.getStatus()); // "ok"
// Listar idiomas soportados (no requiere clave API)
LanguagesResponse langs = client.languages();
langs.getLanguages().forEach(l ->
System.out.println(l.getCode() + " — " + l.getName())
);
// Comprobar uso de tokens para el mes de facturación actual
UsageResponse usage = client.usage();
System.out.println("Tokens usados: " + usage.getUsage().getTokensUsed());
System.out.println("Tokens restantes: " + usage.getUsage().getTokensRemaining());
Manejo de errores
Todas las excepciones son unchecked. Sin declaraciones forzadas de throws, sin cadenas de excepciones checked para desenrollar:
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 — clave API inválida, ausente o revocada
System.out.println("Auth failed: " + e.getError());
} catch (RateLimitException e) {
// HTTP 429 — límite por minuto alcanzado
e.getRetryAfter().ifPresent(s ->
System.out.println("Retry after: " + s + "s")
);
} catch (JobFailedException e) {
// Trabajo asíncrono alcanzó estado terminal fallido o el polling expiró
System.out.println("Job " + e.getJobId() + " failed: " + e.getError());
} catch (PolyLingoException e) {
// Todos los demás errores de API
System.out.println(e.getStatus() + ": " + e.getMessage());
}
RateLimitException.getRetryAfter() devuelve un Optional<Integer> — presente con el número de segundos a esperar si la API incluye ese valor, vacío de lo contrario. JobFailedException.getJobId() te da el ID del trabajo fallido para registro o lógica de reintento.
Notas de diseño
Algunas decisiones que vale la pena conocer si evalúas el SDK:
API síncrona. Cada método bloquea y devuelve un resultado directamente. Sin Future, sin CompletableFuture, sin streams reactivos. El polling de trabajos es la solución asíncrona del SDK para cargas pesadas — envía el trabajo, el SDK hace polling en tu hilo y llama a tu callback onProgress conforme se actualiza la posición en la cola.
Patrón builder en todo. Cada objeto de parámetros usa un builder. Sin constructores posicionales significa sin adivinar el orden de argumentos, sin intercambios accidentales de campos y código claro en el sitio de llamada.
Una dependencia en tiempo de ejecución. Jackson para serialización JSON. Todo lo demás es biblioteca estándar. Sin OkHttp, sin Apache HttpClient, sin Guava.
Java 11+. Usa java.net.http.HttpClient introducido en Java 11. Si tu proyecto apunta a Java 8 o anterior, el SDK no es compatible.
Referencia rápida
| Método | Endpoint | Requiere Auth |
|---|---|---|
client.health() | GET /health | No |
client.languages() | GET /languages | No |
client.translate(...) | POST /translate | Sí |
client.batch(...) | POST /translate/batch | Sí |
client.usage() | GET /usage | Sí |
client.jobs().create(...) | POST /jobs | Sí |
client.jobs().get(jobId) | GET /jobs/:id | Sí |
client.jobs().translate(...) | POST /jobs + polling | Sí |
Comenzar
El SDK está en Maven Central en central.sonatype.com/artifact/com.usepolylingo/polylingo. El código fuente y Javadoc están en github.com/UsePolyLingo/polylingo-Java. La documentación completa del API está en usepolylingo.com/docs/sdk/java.
El nivel gratuito incluye 50,000 tokens por mes. No se requiere tarjeta de crédito.
<dependency>
<groupId>com.usepolylingo</groupId>
<artifactId>polylingo</artifactId>
<version>0.1.0</version>
</dependency>