ブログに戻る
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キーは環境変数に保存してください。ハードコードしたりバージョン管理にコミットしないでください。

知っておくべきオプション設定が2つあります:

$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オプションはplainmarkdownjson、またはhtmlを受け入れます。省略するとAPIがコンテンツから自動検出します。source言語のヒントやmodelstandard(デフォルト)または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"
    );
}

1つのリクエストで3つのロケールすべてを処理します。すべての出力ファイルでキーは変更されません。


バッチリクエスト

複数の別々のコンテンツアイテムを翻訳する場合はbatch()を使います。1回のリクエストで最大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はこれを2つの方法で処理します。

手動でキューに入れてポーリング

$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'];
}

完了までポーリングする1回の呼び出し

手動制御が不要な場合、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の更新に使えます。


ユーティリティエンドポイント

3つの軽量エンドポイントは認証以外のパラメータを必要としません:

$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 — 1分あたりの制限に達した
    $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

APIキーを取得する