Voltar ao blog
Maven coordinates for the PolyLingo Java SDK alongside a short Java client setup snippet.

Traduzir conteúdo estruturado de Java com o SDK PolyLingo

By Robert

Traduzir conteúdo estruturado de Java com o SDK PolyLingo

O SDK PolyLingo Java está agora disponível no Maven Central. Ele cobre toda a API PolyLingo: tradução síncrona, requisições em lote, trabalhos assíncronos com polling e todos os endpoints utilitários. Requer Java 11 ou superior, usa o cliente HTTP da biblioteca padrão e tem exatamente uma dependência em tempo de execução: Jackson para JSON.


Instalação

Maven

<dependency>
  <groupId>com.usepolylingo</groupId>
  <artifactId>polylingo</artifactId>
  <version>0.1.0</version>
</dependency>

Gradle

implementation 'com.usepolylingo:polylingo:0.1.0'

Nenhuma dependência adicional de cliente HTTP é necessária. O SDK usa java.net.http.HttpClient da biblioteca padrão do Java 11.


Configurando o cliente

import com.usepolylingo.polylingo.PolyLingo;
 
PolyLingo client = PolyLingo.builder()
    .apiKey(System.getenv("POLYLINGO_API_KEY"))
    .build();

Dois parâmetros opcionais do construtor estão disponíveis:

PolyLingo client = PolyLingo.builder()
    .apiKey(System.getenv("POLYLINGO_API_KEY"))
    .baseUrl("https://api.usepolylingo.com/v1") // padrão, sobrescreva para instâncias self-hosted
    .timeout(Duration.ofSeconds(30))            // padrão é 120 segundos
    .build();

Mantenha sua chave API em uma variável de ambiente. Nunca a codifique diretamente ou a comite no controle de versão.

O SDK usa o padrão builder em todo lugar. Sem construtores posicionais, sem ordem obrigatória de campos. Todos os campos opcionais têm valores padrão sensatos para que você configure apenas o que realmente precisa alterar.


Traduzindo conteúdo

Requisição ú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!

O builder TranslateParams aceita content e targets como campos obrigatórios. Parâmetros opcionais incluem format (plain, markdown, json ou html — detectado automaticamente se omitido), source como dica de idioma, e model como standard (padrão) ou advanced.

A preservação do formato funciona igual ao resto da API PolyLingo. Para conteúdo json, apenas valores string são traduzidos e chaves, aninhamentos e tipos não-string permanecem intactos. Para markdown, títulos permanecem títulos e blocos de código são mantidos verbatim. Para html, tags e atributos são preservados e apenas nós de texto são traduzidos.

Traduzindo um arquivo JSON de localidade

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);
    }
});

Uma requisição trata todas as três localidades. As chaves são idênticas à fonte em todos os arquivos de saída.


Requisições em lote

Envie até 100 itens de conteúdo em uma única requisição, cada um com seu próprio id e 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 os itens compartilham a mesma lista targets. O id que você atribui é preservado na resposta para que você possa mapear os resultados de volta aos seus dados fonte sem depender da ordem.


Trabalhos assíncronos

Para documentos longos ou grandes cargas de tradução, a API de jobs aceita uma requisição, retorna imediatamente com um ID de job e permite que você faça polling pelo resultado. O SDK trata isso de duas formas.

Uma chamada que faz polling até terminar

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) + "...")
);

O callback onProgress é chamado a cada polling com a posição atual na fila como um inteiro, ou null se a API não retornar essa informação. Use para registrar progresso ou atualizar uma interface.

Enfileirar e fazer 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()
);
 
// Faça polling você mesmo
Job status = client.jobs().get(job.getJobId());
System.out.println(status.getStatus()); // pending / processing / completed / failed

Endpoints utilitários

// Verificar saúde da API (não requer chave API)
HealthResponse health = client.health();
System.out.println(health.getStatus()); // "ok"
 
// Listar idiomas suportados (não requer chave API)
LanguagesResponse langs = client.languages();
langs.getLanguages().forEach(l ->
    System.out.println(l.getCode() + " — " + l.getName())
);
 
// Verificar uso de tokens para o mês atual de faturamento
UsageResponse usage = client.usage();
System.out.println("Tokens usados: " + usage.getUsage().getTokensUsed());
System.out.println("Tokens restantes: " + usage.getUsage().getTokensRemaining());

Tratamento de erros

Todas as exceções são unchecked. Sem declarações forçadas de throws, sem cadeias de exceções verificadas para desfazer:

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 — chave API inválida, ausente ou revogada
    System.out.println("Falha na autenticação: " + e.getError());
} catch (RateLimitException e) {
    // HTTP 429 — limite por minuto atingido
    e.getRetryAfter().ifPresent(s ->
        System.out.println("Tente novamente após: " + s + "s")
    );
} catch (JobFailedException e) {
    // Job assíncrono atingiu status terminal falhado ou polling expirou
    System.out.println("Job " + e.getJobId() + " falhou: " + e.getError());
} catch (PolyLingoException e) {
    // Todos os outros erros da API
    System.out.println(e.getStatus() + ": " + e.getMessage());
}

RateLimitException.getRetryAfter() retorna um Optional<Integer> — presente com o número de segundos para esperar se a API incluir esse valor, vazio caso contrário. JobFailedException.getJobId() fornece o ID do job falhado para registro ou lógica de nova tentativa.


Notas de design

Algumas decisões importantes para saber se você está avaliando o SDK:

API síncrona. Cada método bloqueia e retorna um resultado diretamente. Sem Future, sem CompletableFuture, sem streams reativos. O polling dos jobs é a história assíncrona do SDK para cargas pesadas — submeta o job, o SDK faz polling na sua thread e chama seu callback onProgress conforme a posição na fila atualiza.

Padrão builder em todo lugar. Cada objeto de parâmetros usa um builder. Sem construtores posicionais significa sem adivinhação na ordem dos argumentos, sem troca acidental de campos e código claro no ponto da chamada.

Uma dependência em tempo de execução. Jackson para serialização JSON. Todo o resto é biblioteca padrão. Sem OkHttp, sem Apache HttpClient, sem Guava.

Java 11+. Usa java.net.http.HttpClient introduzido no Java 11. Se seu projeto mira Java 8 ou anterior, o SDK não é compatível.


Referência rápida

MétodoEndpointRequer autenticação
client.health()GET /healthNão
client.languages()GET /languagesNão
client.translate(...)POST /translateSim
client.batch(...)POST /translate/batchSim
client.usage()GET /usageSim
client.jobs().create(...)POST /jobsSim
client.jobs().get(jobId)GET /jobs/:idSim
client.jobs().translate(...)POST /jobs + pollingSim

Comece agora

O SDK está no Maven Central em central.sonatype.com/artifact/com.usepolylingo/polylingo. Código-fonte e Javadoc estão em github.com/UsePolyLingo/polylingo-Java. Documentação completa da API está em usepolylingo.com/docs/sdk/java.

O plano gratuito inclui 50.000 tokens por mês. Não é necessário cartão de crédito.

<dependency>
  <groupId>com.usepolylingo</groupId>
  <artifactId>polylingo</artifactId>
  <version>0.1.0</version>
</dependency>

Obtenha sua chave API