Powrót do bloga
Terminal window showing a Composer install command for the PolyLingo PHP SDK alongside a short PHP translate call and its JSON output.

Tłumaczenie treści strukturalnych z PHP za pomocą PolyLingo SDK

By Robert M

Tłumacz ustrukturyzowaną zawartość z PHP za pomocą SDK PolyLingo

SDK PolyLingo PHP jest teraz dostępne na Packagist. Zainstaluj je za pomocą Composera, przekaż mu ciąg zwykłego tekstu, Markdown, JSON lub HTML i otrzymaj tłumaczenia na każdy potrzebny język — bez pisania surowych zapytań HTTP i bez obaw o uszkodzenie struktury podczas przesyłania.

Ten wpis obejmuje instalację, uwierzytelnianie oraz pełen zakres SDK: tłumaczenia synchroniczne, żądania wsadowe, zadania asynchroniczne i obsługę błędów.


Instalacja

Wymaga PHP 7.4 lub nowszego. Zainstaluj przez Composera:

composer require usepolylingo/polylingo

SDK zależy od guzzlehttp/guzzle ^7.8 oraz psr/http-client ^1.0. Oba są instalowane automatycznie.


Konfiguracja klienta

Utwórz pojedynczą instancję PolyLingo i używaj jej w całej aplikacji. Jedyną wymaganą opcją jest Twój klucz API:

<?php
use PolyLingo\PolyLingo;
 
$client = new PolyLingo([
    'apiKey' => getenv('POLYLINGO_API_KEY'),
]);

Przechowuj swój klucz API w zmiennej środowiskowej. Nigdy nie wpisuj go na stałe ani nie dodawaj do kontroli wersji.

Dwie opcjonalne ustawienia warte poznania:

$client = new PolyLingo([
    'apiKey'  => getenv('POLYLINGO_API_KEY'),
    'baseURL' => 'https://api.usepolylingo.com/v1', // domyślny, nadpisz dla instancji hostowanych samodzielnie
    'timeout' => 120_000,                           // milisekundy, domyślnie 120000 (2 minuty)
]);

Tłumaczenie zawartości

Zwykły tekst, Markdown, JSON lub HTML

Przekaż zawartość i tablicę kodów języków docelowych do translate(). Pole format informuje SDK, z jakim typem zawartości ma do czynienia:

$result = $client->translate([
    'content' => '# Hello',
    'targets' => ['es', 'fr', 'de'],
    'format'  => 'markdown',
]);
 
$es     = $result['translations']['es'];
$tokens = $result['usage']['total_tokens'];

Opcja format akceptuje wartości plain, markdown, json lub html. Jeśli ją pominiesz, API automatycznie wykryje format na podstawie zawartości. Możesz też podać wskazówkę języka źródłowego source oraz wartość model standard (domyślny) lub advanced.

Zachowanie formatu jest tutaj kluczowe. Dla zawartości json tłumaczone są tylko wartości tekstowe. Klucze, zagnieżdżenia, tablice i typy niebędące tekstem są zwracane dokładnie tak, jak je wysłałeś. Dla markdown nagłówki pozostają nagłówkami, bloki kodu są pozostawione dosłownie, a adresy URL linków nie są zmieniane. Dla html tagi i atrybuty są zachowane, a tłumaczone są tylko węzły tekstowe.

Tłumaczenie pliku locale JSON

Typowym przypadkiem użycia jest tłumaczenie pliku locale. Wyślij cały obiekt jako ciąg 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"
    );
}

Jedno żądanie obsługuje wszystkie trzy locale. Klucze pozostają niezmienione w każdym pliku wyjściowym.


Żądania wsadowe

Użyj batch(), gdy masz wiele oddzielnych elementów zawartości do przetłumaczenia. Możesz wysłać do 100 elementów w jednym żądaniu, każdy z własnym id i opcjonalnym format:

$batch = $client->batch([
    'items' => [
        ['id' => 'hero_title',    'content' => 'Welcome back',              'format' => 'plain'],
        ['id' => 'hero_subtitle', 'content' => 'Here is what is new today', 'format' => 'plain'],
        ['id' => 'cta',           'content' => 'Get started',               'format' => 'plain'],
    ],
    'targets' => ['es', 'fr'],
]);
 
foreach ($batch['results'] as $row) {
    echo $row['id'] . ': ' . $row['translations']['es'] . "\n";
}

Wszystkie elementy dzielą tę samą tablicę targets. Odpowiedź zachowuje id, które podałeś dla każdego elementu, dzięki czemu możesz powiązać wyniki z oryginalnymi danymi bez polegania na kolejności.


Zadania asynchroniczne

Dla długotrwałych tłumaczeń (duże dokumenty, wiele celów lub oba) API zadań przyjmuje żądanie, zwraca natychmiast job_id i pozwala na odpytywanie o wynik. SDK obsługuje to na dwa sposoby.

Kolejkowanie i ręczne odpytywanie

$accepted = $client->jobs->create([
    'content' => file_get_contents('long-article.md'),
    'targets' => ['es', 'fr', 'de', 'ja', 'zh'],
    'format'  => 'markdown',
]);
 
$jobId = $accepted['job_id'];
 
// Odpytywanie aż zadanie osiągnie status końcowy
do {
    sleep(5);
    $state = $client->jobs->get($jobId);
} while ($state['status'] === 'pending' || $state['status'] === 'processing');
 
if ($state['status'] === 'complete') {
    $translations = $state['translations'];
}

Jedno wywołanie, które odpytywa aż do zakończenia

Jeśli nie potrzebujesz ręcznej kontroli, jobs->translate() obsługuje pętlę odpytywania za Ciebie:

$done = $client->jobs->translate([
    'content' => file_get_contents('long-article.md'),
    'targets' => ['es', 'fr', 'de'],
    'format'  => 'markdown',
 
    // Opcjonalne nadpisania (pokazane wartości domyślne):
    // 'pollInterval' => 5000,       // ms między odpytywaniem, domyślnie 5000
    // 'timeout'      => 1_200_000,  // całkowity czas oczekiwania, domyślnie 20 minut
    // 'onProgress'   => function (?int $queuePosition) {
    //     echo "Queue position: {$queuePosition}\n";
    // },
]);
 
$translations = $done['translations'];
$usage        = $done['usage'];

Funkcja zwrotna onProgress jest wywoływana przy każdym odpytywaniu z aktualną pozycją w kolejce, jeśli API ją zwraca, lub null, jeśli nie jest dostępna. Użyj jej do logowania postępu lub aktualizacji interfejsu użytkownika.


Punkty końcowe narzędziowe

Trzy lekkie punkty końcowe nie wymagają parametrów poza uwierzytelnianiem:

$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 i GET /languages nie wymagają klucza API. GET /usage zwraca zużycie tokenów za bieżący miesiąc kalendarzowy dla uwierzytelnionego konta.


Obsługa błędów

Wszystkie błędy SDK rozszerzają PolyLingo\Errors\PolyLingoException. Przechwytuj konkretne podtypy, które chcesz obsłużyć inaczej:

use PolyLingo\Errors\AuthException;
use PolyLingo\Errors\JobFailedException;
use PolyLingo\Errors\PolyLingoException;
use PolyLingo\Errors\RateLimitException;
 
try {
    $result = $client->translate([
        'content' => '# Hello',
        'targets' => ['es'],
        'format'  => 'markdown',
    ]);
} catch (AuthException $e) {
    // HTTP 401 — nieprawidłowy, brakujący lub cofnięty klucz API
} catch (RateLimitException $e) {
    // HTTP 429 — osiągnięto limit na minutę
    $retryAfter = $e->getRetryAfter(); // int|null sekund
} catch (JobFailedException $e) {
    // Zadanie asynchroniczne osiągnęło stan końcowy z błędem
    $jobId = $e->getJobId();
} catch (PolyLingoException $e) {
    // Wszystkie inne błędy API
    $httpStatus = $e->getHttpStatus();
    $errorCode  = $e->getErrorCode(); // np. "invalid_request", "translation_error"
}

RateLimitException::getRetryAfter() zwraca liczbę sekund do odczekania przed ponowną próbą, jeśli API zawiera ten nagłówek, lub null, jeśli go nie ma. JobFailedException::getJobId() zwraca ID nieudanego zadania, abyś mógł je zalogować lub pokazać użytkownikowi.


Szybkie odniesienie

MetodaPunkt końcowyWymaga uwierzytelnienia
$client->health()GET /healthNie
$client->languages()GET /languagesNie
$client->translate()POST /translateTak
$client->batch()POST /translate/batchTak
$client->usage()GET /usageTak
$client->jobs->create()POST /jobsTak
$client->jobs->get($id)GET /jobs/:idTak
$client->jobs->translate()POST /jobs + pollingTak

Zacznij

SDK jest dostępne na Packagist pod usepolylingo/polylingo. Pełna dokumentacja API jest dostępna na usepolylingo.com/docs.

Darmowy poziom obejmuje 50 000 tokenów miesięcznie. Nie jest wymagana karta kredytowa.

composer require usepolylingo/polylingo

Pobierz swój klucz API