
Переклад структурованого контенту з PHP за допомогою PolyLingo SDK
By Robert M
Переклад структурованого контенту з PHP за допомогою PolyLingo SDK
PolyLingo PHP SDK тепер доступний на Packagist. Встановіть його через Composer, передайте рядок простого тексту, Markdown, JSON або HTML і отримайте переклади на всі потрібні вам мови — без написання сирого HTTP або турбот про те, що ваша структура буде пошкоджена під час передачі.
У цьому дописі розглядаються встановлення, автентифікація та повний функціонал SDK: синхронний переклад, пакетні запити, асинхронні завдання та обробка помилок.
Встановлення
Потрібен PHP 7.4 або новіший. Встановіть через Composer:
composer require usepolylingo/polylingo
SDK залежить від guzzlehttp/guzzle ^7.8 та psr/http-client ^1.0. Обидва підтягуються автоматично.
Налаштування клієнта
Створіть один екземпляр PolyLingo і використовуйте його у всьому додатку. Єдина обов’язкова опція — ваш API ключ:
<?php
use PolyLingo\PolyLingo;
$client = new PolyLingo([
'apiKey' => getenv('POLYLINGO_API_KEY'),
]);
Зберігайте API ключ у змінній середовища. Ніколи не хардкодьте його і не комітьте у систему контролю версій.
Дві додаткові опції, які варто знати:
$client = new PolyLingo([
'apiKey' => getenv('POLYLINGO_API_KEY'),
'baseURL' => 'https://api.usepolylingo.com/v1', // за замовчуванням, змінюйте для власних інстансів
'timeout' => 120_000, // мілісекунди, за замовчуванням 120000 (2 хвилини)
]);
Переклад контенту
Простий текст, Markdown, JSON або HTML
Передайте ваш контент і масив кодів цільових мов у translate(). Поле format повідомляє SDK, з яким типом контенту він працює:
$result = $client->translate([
'content' => '# Hello',
'targets' => ['es', 'fr', 'de'],
'format' => 'markdown',
]);
$es = $result['translations']['es'];
$tokens = $result['usage']['total_tokens'];
Опція format приймає plain, markdown, json або html. Якщо її опустити, API автоматично визначить формат за контентом. Також можна передати підказку мови джерела source і значення model — standard (за замовчуванням) або advanced.
Збереження формату — ключова поведінка. Для json перекладаються лише рядкові значення. Ключі, вкладені структури, масиви та не рядкові типи повертаються точно так, як ви їх надіслали. Для markdown заголовки залишаються заголовками, блоки коду залишаються без змін, URL посилань не змінюються. Для html теги та атрибути зберігаються, перекладаються лише текстові вузли.
Переклад JSON-файлу локалі
Поширений випадок — переклад файлу локалі. Надішліть весь об’єкт як 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"
);
}
Один запит обробляє всі три локалі. Ключі не змінюються у жодному вихідному файлі.
Пакетні запити
Використовуйте batch(), коли у вас є кілька окремих елементів контенту для перекладу. Ви можете надіслати до 100 елементів в одному запиті, кожен зі своїм id та необов’язковим 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";
}
Всі елементи використовують один і той же масив targets. Відповідь зберігає id, який ви передали для кожного елемента, щоб ви могли зіставити результати з оригінальними даними без залежності від порядку.
Асинхронні завдання
Для тривалих перекладів (великі документи, багато цілей або і те, і інше) API завдань приймає запит, одразу повертає job_id і дозволяє опитувати результат. SDK обробляє це двома способами.
Додати в чергу і опитувати вручну
$accepted = $client->jobs->create([
'content' => file_get_contents('long-article.md'),
'targets' => ['es', 'fr', 'de', 'ja', 'zh'],
'format' => 'markdown',
]);
$jobId = $accepted['job_id'];
// Опитуйте, доки завдання не досягне кінцевого статусу
do {
sleep(5);
$state = $client->jobs->get($jobId);
} while ($state['status'] === 'pending' || $state['status'] === 'processing');
if ($state['status'] === 'complete') {
$translations = $state['translations'];
}
Один виклик, що опитує доки не завершиться
Якщо вам не потрібен ручний контроль, jobs->translate() керує циклом опитування за вас:
$done = $client->jobs->translate([
'content' => file_get_contents('long-article.md'),
'targets' => ['es', 'fr', 'de'],
'format' => 'markdown',
// Необов’язкові перевизначення (показані за замовчуванням):
// 'pollInterval' => 5000, // мс між опитуваннями, за замовчуванням 5000
// 'timeout' => 1_200_000, // загальний час очікування, за замовчуванням 20 хвилин
// 'onProgress' => function (?int $queuePosition) {
// echo "Queue position: {$queuePosition}\n";
// },
]);
$translations = $done['translations'];
$usage = $done['usage'];
Зворотний виклик onProgress виконується при кожному опитуванні з поточною позицією в черзі, якщо API її повертає, або null, якщо ні. Використовуйте для логування прогресу або оновлення інтерфейсу.
Утилітарні кінцеві точки
Три легкі кінцеві точки не потребують параметрів, окрім автентифікації:
$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 та GET /languages не потребують API ключа. GET /usage повертає споживання токенів за поточний календарний місяць для автентифікованого облікового запису.
Обробка помилок
Всі помилки SDK розширюють PolyLingo\Errors\PolyLingoException. Ловіть конкретні підтипи, які хочете обробляти по-іншому:
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 — недійсний, відсутній або відкликаний API ключ
} catch (RateLimitException $e) {
// HTTP 429 — досягнуто ліміт за хвилину
$retryAfter = $e->getRetryAfter(); // int|null секунди
} catch (JobFailedException $e) {
// Асинхронне завдання досягло статусу помилки
$jobId = $e->getJobId();
} catch (PolyLingoException $e) {
// Всі інші помилки API
$httpStatus = $e->getHttpStatus();
$errorCode = $e->getErrorCode(); // напр. "invalid_request", "translation_error"
}
RateLimitException::getRetryAfter() повертає кількість секунд, які потрібно почекати перед повторною спробою, якщо API включає цей заголовок, або null, якщо ні. JobFailedException::getJobId() дає ID невдалого завдання, щоб ви могли його залогувати або показати користувачу.
Швидка довідка
| Метод | Кінцева точка | Потрібна автентифікація |
|---|---|---|
$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($id) | GET /jobs/:id | Так |
$client->jobs->translate() | POST /jobs + опитування | Так |
Початок роботи
SDK доступний на Packagist за адресою usepolylingo/polylingo. Повна документація API — на usepolylingo.com/docs.
Безкоштовний рівень включає 50 000 токенів на місяць. Кредитна картка не потрібна.
composer require usepolylingo/polylingo