返回博客
Terminal window showing a Composer install command for the PolyLingo PHP SDK alongside a short PHP translate call and its JSON output.

使用 PolyLingo SDK 翻译来自 PHP 的结构化内容

By Robert M

使用 PolyLingo SDK 翻译 PHP 结构化内容

PolyLingo PHP SDK 现已在 Packagist 上可用。通过 Composer 安装,传入纯文本、Markdown、JSON 或 HTML 字符串,即可获得所需语言的翻译——无需编写原始 HTTP 请求,也不用担心结构在传输过程中被破坏。

本文涵盖安装、认证以及 SDK 的全部功能:同步翻译、批量请求、异步任务和错误处理。


安装

需要 PHP 7.4 或更高版本。通过 Composer 安装:

composer require usepolylingo/polylingo

SDK 依赖 guzzlehttp/guzzle ^7.8psr/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 选项接受 plainmarkdownjsonhtml。如果省略,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 "队列位置: {$queuePosition}\n";
    // },
]);

$translations = $done['translations'];
$usage        = $done['usage'];

onProgress 回调在每次轮询时触发,传入当前队列位置(如果 API 返回),否则为 null。可用于记录进度或更新 UI。


实用端点

三个轻量级端点只需认证,无需其他参数:

$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 /healthGET /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 包含该头时需等待的秒数,否则返回 nullJobFailedException::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

获取你的 API 密钥