
Traduzir conteúdo estruturado de PHP com o PolyLingo SDK
By Robert M
Traduzir conteúdo estruturado do PHP com o SDK PolyLingo
O SDK PolyLingo PHP está agora disponível no Packagist. Instale-o com o Composer, forneça uma string de texto simples, Markdown, JSON ou HTML, e receba traduções em todos os idiomas que precisar — sem escrever HTTP bruto ou se preocupar com a estrutura sendo corrompida durante o trânsito.
Este post cobre instalação, autenticação e toda a superfície do SDK: tradução síncrona, requisições em lote, trabalhos assíncronos e tratamento de erros.
Instalação
Requer PHP 7.4 ou superior. Instale via Composer:
composer require usepolylingo/polylingo
O SDK depende de guzzlehttp/guzzle ^7.8 e psr/http-client ^1.0. Ambos são instalados automaticamente.
Configurando o cliente
Crie uma única instância PolyLingo e reutilize-a em toda sua aplicação. A única opção obrigatória é sua chave de API:
<?php
use PolyLingo\PolyLingo;
$client = new PolyLingo([
'apiKey' => getenv('POLYLINGO_API_KEY'),
]);
Armazene sua chave de API em uma variável de ambiente. Nunca a codifique diretamente ou a envie para controle de versão.
Duas configurações opcionais que vale a pena conhecer:
$client = new PolyLingo([
'apiKey' => getenv('POLYLINGO_API_KEY'),
'baseURL' => 'https://api.usepolylingo.com/v1', // padrão, sobrescreva para instâncias auto-hospedadas
'timeout' => 120_000, // milissegundos, padrão é 120000 (2 minutos)
]);
Traduzindo conteúdo
Texto simples, Markdown, JSON ou HTML
Passe seu conteúdo e um array de códigos de idiomas alvo para translate(). O campo format informa ao SDK qual tipo de conteúdo está lidando:
$result = $client->translate([
'content' => '# Olá',
'targets' => ['es', 'fr', 'de'],
'format' => 'markdown',
]);
$es = $result['translations']['es'];
$tokens = $result['usage']['total_tokens'];
A opção format aceita plain, markdown, json ou html. Se omitida, a API detecta automaticamente o formato a partir do conteúdo. Você também pode passar uma dica de idioma source e um valor model de standard (padrão) ou advanced.
A preservação do formato é o comportamento chave aqui. Para conteúdo json, apenas valores string são traduzidos. Chaves, aninhamentos, arrays e tipos não string retornam exatamente como enviados. Para markdown, títulos permanecem títulos, blocos de código são mantidos verbatim, e URLs de links não são alterados. Para html, tags e atributos são preservados e apenas nós de texto são traduzidos.
Traduzindo um arquivo de localidade JSON
Um caso comum é traduzir um arquivo de localidade. Envie o objeto inteiro como uma string JSON:
$source = json_decode(file_get_contents('messages/en.json'), true);
$result = $client->translate([
'content' => json_encode($source),
'format' => 'json',
'targets' => ['de', 'fr', 'ja'],
]);
foreach (['de', 'fr', 'ja'] as $locale) {
$translated = json_decode($result['translations'][$locale], true);
file_put_contents(
"messages/{$locale}.json",
json_encode($translated, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n"
);
}
Uma requisição trata todos os três locais. As chaves não são alteradas em nenhum arquivo de saída.
Requisições em lote
Use batch() quando tiver múltiplos itens de conteúdo separados para traduzir. Você pode enviar até 100 itens em uma única requisição, cada um com seu próprio id e format opcional:
$batch = $client->batch([
'items' => [
['id' => 'hero_title', 'content' => 'Bem-vindo de volta', 'format' => 'plain'],
['id' => 'hero_subtitle', 'content' => 'Aqui está o que há de novo hoje', 'format' => 'plain'],
['id' => 'cta', 'content' => 'Comece agora', 'format' => 'plain'],
],
'targets' => ['es', 'fr'],
]);
foreach ($batch['results'] as $row) {
echo $row['id'] . ': ' . $row['translations']['es'] . "\n";
}
Todos os itens compartilham o mesmo array targets. A resposta preserva o id que você passou para cada item, para que possa mapear os resultados de volta aos seus dados originais sem depender da ordem.
Trabalhos assíncronos
Para traduções de longa duração (documentos grandes, muitos alvos, ou ambos) a API de jobs aceita uma requisição, retorna imediatamente com um job_id, e permite que você consulte o resultado. O SDK lida com isso de duas formas.
Enfileirar e consultar manualmente
$accepted = $client->jobs->create([
'content' => file_get_contents('long-article.md'),
'targets' => ['es', 'fr', 'de', 'ja', 'zh'],
'format' => 'markdown',
]);
$jobId = $accepted['job_id'];
// Consulte até o trabalho atingir um status terminal
do {
sleep(5);
$state = $client->jobs->get($jobId);
} while ($state['status'] === 'pending' || $state['status'] === 'processing');
if ($state['status'] === 'complete') {
$translations = $state['translations'];
}
Uma chamada que consulta até terminar
Se não precisar de controle manual, jobs->translate() gerencia o loop de consulta para você:
$done = $client->jobs->translate([
'content' => file_get_contents('long-article.md'),
'targets' => ['es', 'fr', 'de'],
'format' => 'markdown',
// Sobrescritas opcionais (padrões mostrados):
// 'pollInterval' => 5000, // ms entre consultas, padrão 5000
// 'timeout' => 1_200_000, // orçamento total de espera, padrão 20 minutos
// 'onProgress' => function (?int $queuePosition) {
// echo "Posição na fila: {$queuePosition}\n";
// },
]);
$translations = $done['translations'];
$usage = $done['usage'];
O callback onProgress é chamado a cada consulta com a posição atual na fila se a API retornar uma, ou null se não disponível. Use para registrar progresso ou atualizar uma interface.
Endpoints utilitários
Três endpoints leves não precisam de parâmetros além da autenticação:
$health = $client->health();
// ['status' => 'ok', 'timestamp' => '...']
$langs = $client->languages();
// ['languages' => [['code' => 'en', 'name' => 'English', 'rtl' => false], ...]]
$usage = $client->usage();
// ['usage' => ['tokens_used' => 12000, 'tokens_remaining' => 88000, ...]]
GET /health e GET /languages não requerem chave de API. GET /usage retorna o consumo de tokens do mês corrente para a conta autenticada.
Tratamento de erros
Todos os erros do SDK estendem PolyLingo\Errors\PolyLingoException. Capture os subtipos específicos que deseja tratar de forma diferente:
use PolyLingo\Errors\AuthException;
use PolyLingo\Errors\JobFailedException;
use PolyLingo\Errors\PolyLingoException;
use PolyLingo\Errors\RateLimitException;
try {
$result = $client->translate([
'content' => '# Olá',
'targets' => ['es'],
'format' => 'markdown',
]);
} catch (AuthException $e) {
// HTTP 401 — chave de API inválida, ausente ou revogada
} catch (RateLimitException $e) {
// HTTP 429 — limite por minuto atingido
$retryAfter = $e->getRetryAfter(); // int|null segundos
} catch (JobFailedException $e) {
// Trabalho assíncrono atingiu status terminal falho
$jobId = $e->getJobId();
} catch (PolyLingoException $e) {
// Todos os outros erros da API
$httpStatus = $e->getHttpStatus();
$errorCode = $e->getErrorCode(); // ex: "invalid_request", "translation_error"
}
RateLimitException::getRetryAfter() retorna o número de segundos para esperar antes de tentar novamente se o cabeçalho estiver presente, ou null se não. JobFailedException::getJobId() fornece o ID do trabalho falho para que você possa registrá-lo ou exibi-lo ao usuário.
Referência rápida
| Método | Endpoint | Requer autenticação |
|---|---|---|
$client->health() | GET /health | Não |
$client->languages() | GET /languages | Não |
$client->translate() | POST /translate | Sim |
$client->batch() | POST /translate/batch | Sim |
$client->usage() | GET /usage | Sim |
$client->jobs->create() | POST /jobs | Sim |
$client->jobs->get($id) | GET /jobs/:id | Sim |
$client->jobs->translate() | POST /jobs + polling | Sim |
Comece agora
O SDK está no Packagist em usepolylingo/polylingo. A documentação completa da API está em usepolylingo.com/docs.
O plano gratuito inclui 50.000 tokens por mês. Não é necessário cartão de crédito.
composer require usepolylingo/polylingo