|
ドキュメント
デモを予約プラットフォーム
プラットフォームMCPCLIAPI
ワークフロー
ガイド変更履歴

ようこそ

  • 概要
  • 認証
  • エラーとステータスコード
  • Webhookシグネチャ

ローカライゼーション

  • 概要
  • ジョブを作成
  • 翻訳対象外のキーをロックする
  • ジョブグループを追跡
  • 単一ジョブを取得
  • ジョブ一覧
  • Webhook配信
  • リアルタイム進捗(WebSocket)

パイプライン

  • 概要
  • ローカライズ前のAI編集
  • 人によるレビュー
  • AI評価(ポストエディット)
  • 自然なコピーに言い換える
  • 逆翻訳チェック
  • パイプラインを設定
  • パイプライン実行を確認する

プロビジョニング

  • 概要
  • プロビジョニングジョブを作成
  • ソースの種類
  • AIが抽出するもの
  • Webhook配信
  • ライブ進行状況(WebSocket)

同期

  • Localize
  • Recognize

エンジン管理

  • エンジン提案

Webhook配信

ジョブグループを作成すると、数ミリ秒で 202 が返ります。翻訳はその後バックグラウンドで進み、ロケールごとに1つずつジョブが動きます。完了まで各ジョブをポーリングし続けることもできますが、ドイツ語の準備ができたことを知るためだけにポーリングループを回したくはないはずです。欲しいのは、各ロケールが仕上がった瞬間にサーバーへ通知が飛ぶことです。

それを実現するのが webhook です。ジョブ作成時に callbackUrl を渡すと、Lingo.dev は各ジョブが終端状態に達した時点で、その URL に結果を POST します。ロケールごとに1回、完了したその瞬間に POST されます。 問題なく翻訳できたロケールは、データ付きの translation.completed として届きます。失敗したロケールは、エラー付きの translation.failed として届きます。こちらから取りにいかなくても、言語ごとに必ず通知されます。

このページでは、2種類のペイロードとその扱い方を説明します。配信には署名と再試行があり、その仕組みはプロビジョニングと共通です。詳細は webhook署名の検証 ページにまとまっており、必要な箇所からすぐ辿れるようになっています。

このページの内容

  • 配信の仕組み
  • 完了時のペイロード
  • 失敗時のペイロード
  • webhook の処理
  • 配信が向いていないケース

配信の仕組み#

グループ内の各ロケールは、それぞれ独立したジョブです。どれか1つが終端状態に達した瞬間、その結果だけが個別に callbackUrl へ配信されます。Lingo.dev は最も遅いロケールを待ちませんし、グループ全体をまとめて1回の呼び出しにすることもありません。対象ロケールが14件なら、最大14回の POST が、それぞれの言語の完了に合わせて、完了した順に届きます。

送信先は、ジョブグループを作成するときに callbackUrl でリクエストごとに指定できます。あるいは、ダッシュボードで組織のデフォルトを設定して、すべてのグループに継承させることもできます。リクエスト単位で指定した callbackUrl は、そのグループでは組織のデフォルトより優先されます。

HTTPS のみ

callbackUrl には HTTPS を使う必要があります。HTTP の URL はジョブ作成時に 400 で拒否されます。webhook は署名付きなので、平文通信で送ってしまうと意味がありません。

送られてくるペイロードは2種類で、見分けるキーは type フィールドです。種類は translation.completed と translation.failed。どちらにも、対象のジョブ、所属グループ、対象ロケールが含まれるので、1つのハンドラーで type を見て振り分け、正しいレコードを更新できます。

未知のイベント型も安全に扱う

現時点で送られてくるのは translation.completed と translation.failed です。ただし、この種類は今後増える前提で扱ってください。既知の型だけを分岐し、それ以外は無視するようにしておけば、将来イベント型が追加されても、デプロイ済みのハンドラーが壊れません。

完了時のペイロード#

ジョブが正常に完了すると、ペイロードには翻訳済みの data が入ります。形式は ジョブを取得 したときと同じで、ポーリングで取りにいく代わりにプッシュで届くイメージです。data は、送信した構造をそのまま保っています。すべての文字列は翻訳され、文字列以外の値(数値、真偽値、null)はそのまま保持され、ネストも崩れません。

json
{
  "type": "translation.completed",
  "jobId": "ljb_A1b2C3d4E5f6G7h8",
  "groupId": "ljg_A1b2C3d4E5f6G7h8",
  "sourceLocale": "en",
  "targetLocale": "de",
  "data": {
    "id": "course_101",
    "title": "Einführung in maschinelles Lernen",
    "steps": [
      { "heading": "Was ist ML?", "body": "Maschinelles Lernen ist ein Teilbereich der künstlichen Intelligenz." },
      { "heading": "Überwachtes Lernen", "body": "Trainieren eines Modells mit gelabelten Daten." }
    ],
    "metadata": { "author": "Dr. Smith", "difficulty": "beginner" }
  }
}
フィールド説明
typetranslation.completed
jobId完了したジョブ(ljb_ プレフィックス)
groupId所属するグループ(ljg_ プレフィックス)
sourceLocale送信したソースロケール
targetLocaleこのペイロードの翻訳先ロケール
data送信した data と同じ構造の翻訳済みコンテンツ

出力が生成されているジョブは失敗扱いではありません。つまり、completed_with_warnings で完了したジョブ(出力は生成されたものの、任意の pipeline ステージを通り切らなかったケース)も、利用可能な data を含む translation.completed として配信されます。webhook が伝えるのは、そのロケールが使える状態になったということです。どのステップで何が起きたかという警告は 単一ジョブ 側にあり、必要になったときに jobId で取得します。

失敗時のペイロード#

ロケール単位では失敗することもあります。たとえばモデルがタイムアウトしたり、設定したすべてのモデルが利用できなかったりする場合です。ジョブが failed に達した場合でも、通知は届きます。ペイロードの型は translation.failed で、data の代わりに error 文字列が入ります。

json
{
  "type": "translation.failed",
  "jobId": "ljb_C3d4E5f6G7h8I9j0",
  "groupId": "ljg_A1b2C3d4E5f6G7h8",
  "sourceLocale": "en",
  "targetLocale": "ja",
  "error": "Model timeout after 30 seconds"
}
フィールド説明
typetranslation.failed
jobId失敗したジョブ
groupId所属するグループ
sourceLocale送信したソースロケール
targetLocale失敗したロケール
error人が読んで分かる失敗内容の説明

失敗は1つのロケールに閉じます。たとえば de、fr、ja を送っていた場合、ja の失敗は、それ単体の translation.failed POST として配信される一方、de と fr は translation.completed として届きます。つまり、ドイツ語とフランス語の翻訳はそのまま配信されます。グループの partial-failure status には、この混在した状態が反映されます。失敗したロケールをやり直すには、新しい冪等キーを使って、そのロケールだけの新しいジョブを送信してください。

webhook の処理#

ここでまず気になるのはもっともです。ハンドラー側では、DB への書き込みやキャッシュの削除、接続中クライアントへのファンアウトなど、実処理が走る。となると、そのせいで接続を開きっぱなしにして webhook をタイムアウトさせてしまわないか?

そのとおりです。だからこそ、Lingo.dev を待たせてはいけません。まず 200 を返し、そのあとで処理する。 受信確認はすぐ返し、実際の処理はレスポンス送信後に行ってください。すぐ応答を返すハンドラーは配信の健全性を保てますが、下流処理でブロックすると、本来不要な再試行を招きます。

javascript
app.post("/webhooks/translations", verifyWebhook, async (req, res) => {
  // Acknowledge first - one POST per locale, the moment it lands.
  res.status(200).send("ok");

  const { type, jobId, groupId, targetLocale, data } = req.body;

  if (type === "translation.completed") {
    await db.content.update({
      where: { groupId },
      data: { [`content_${targetLocale}`]: data },
    });

    // Advance your own progress model - your UI can poll this or receive it over SSE.
    await db.translationProgress.increment({
      where: { groupId },
      data: { completedLanguages: { increment: 1 } },
    });
  }

  if (type === "translation.failed") {
    console.error(`Translation failed: ${jobId} (${targetLocale})`, req.body.error);
  }
});

このページで扱っていない唯一の要素が verifyWebhook ミドルウェアです。すべての配信は Standard Webhooks 仕様に従って署名されているため、独自仕様を読み解く必要はありません。検証方法や、2xx 以外を返した場合の再試行スケジュールについては、プロビジョニングと共通の webhook署名の検証 にまとまっています。ペイロードを信頼する前に、まずこのミドルウェアを組み込んでください。検証していないボディは、認証されていないボディです。

ボディを信頼する前に検証する

エンドポイントは公開 URL なので、誰でも POST できます。どんなペイロードでも処理する前に、必ず生のリクエストボディに対して署名を検証してください。手順、ヘッダー、HMAC、そして whsec_ シークレットについては、署名の検証 ページで説明しています。

配信が向いていないケース#

webhook は便利なプッシュ手段であって、システムの記録元ではありません。別の手段を使うべきケースが2つあり、どちらもリンク先ですぐ確認できます。

結果配信のタイミングでエンドポイントが落ちていても、プラットフォームは再試行します。さらに、すべての再試行を使い切っても、結果が失われることはありません。結果は引き続き jobId で取得可能 で、ジョブの callbackStatus には最終的にプッシュが成功したかどうかも記録されます。再試行スケジュール自体は 署名と配信 ページにあります。通常時には webhook がポーリングループを省いてくれますが、例外時にも、その下には常にジョブレコードがあります。

一方、欲しいのが UI 上でのリアルタイム進捗表示、つまりロケールが完了するたびに 14 件中 3 件から 4 件へとカウンターが進むような体験であって、サーバーへのロケール単位のコールバックではないなら、使うべきなのは webhook ではなくジョブグループ WebSocket です。

ライブ進捗(WebSocket)
サーバーへのロケール単位のコールバックではなく、完全な状態スナップショットを使ってグループの進捗を UI にストリーミングします。
Webhook署名の検証
署名の検証、ヘッダーの確認、再試行スケジュールの処理まで。すべての webhook 配信で共通です。
単一ジョブを取得
warnings を含め、あらゆる結果を jobId で取得できます。すべての配信の裏側にある信頼できる情報源です。

このページは役に立ちましたか?

Max PrilutskiyMax Prilutskiy·更新済み 約2か月前·2分で読めます