API経由で文字列カタログをローカライズする
UIテキストやゲーム内の文字列、メールテンプレートはキー付きカタログとして管理されます。キーがあるからこそ、ローカライズの自動化が可能になります。Transeptはキーをもとにカタログの差分を検出し、実際に変更された部分だけを翻訳して、同じキー構造のまま全言語を返します。そのため、1件の文字列を変更したときのコストは、その1件分だけで済みます。
目次
文字列カタログとは?
Transeptのキー付きフォーマットは.tstrings.jsonです。ユニットのリストで、各ユニットは固定のidとsourceを持ち、任意でcontext(どんな文字列か、どこに表示されるか)、max_length、placeholdersを指定できます。要になるのはidです。再インポートしても訳文が同じ文字列に結び付いたままになるのも、レビューの状態が引き継がれるのも、エクスポートで全言語がキー付きで返るのも、idがあるからです。任意の項目も形だけではありません。コンテキストは翻訳者向けの指示としてモデルに渡され、文字数制限は自動の短縮と再試行で守られます。
CSV、gettext PO、XLIFFのファイルも、アプリまたはアップロード用エンドポイントから、同じキー付きユニットとしてインポートできます。各フォーマットがどう対応付けられるかは、文字列ファイルをご覧ください。この記事では、この一連の処理をコードから動かす方法を説明します。その場合の標準の形式が.tstrings.jsonです。APIの利用にはキーが必要で、キーはStarterプランとProプランで利用できます。
API経由でカタログをインポートするには?
カタログのJSONを指定してPOST /documents/import-stringsを実行します。翻訳先の言語は決まった順序で判定されます。リクエスト内で明示されたtarget_languageまたはtarget_languagesが最優先され、指定がなければカタログヘッダーのtarget_localesが使用されます。どちらも指定されていない場合は、翻訳先のないドキュメントがインポートされるのを防ぐため、直ちにno_target_languagesエラーで失敗します。この呼び出しはprocessing_job_idを返すため、インポートが完了してドキュメントIDを取得できるまでGET /document-jobs/{id}をポーリングしてください。
ファイルにすでに含まれている訳文(targets: {de: "…"})は、モデルの実行を必要とせず、無料で各文字列の現在の訳文として登録されます。また、アプリから既存の翻訳を取り込む場合と同様に、すぐに翻訳メモリにも反映されます。
# BASE="https://app.transept.ai/api/public/v1"; KEY from Settings → Developer
curl -s -X POST $BASE/documents/import-strings \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"document": {
"format": "transept-strings", "version": 1, "source_locale": "en",
"target_locales": ["de", "fr", "uk"],
"metadata": {"name": "App UI"},
"units": [
{"id": "app.save", "source": "Save", "context": "Toolbar button"},
{"id": "app.greeting", "source": "Welcome, {name}", "context": "Dashboard header"}
]}}'
# → { processing_job_id }; poll GET /document-jobs/{id}変更された箇所だけを再翻訳するには?
一部を削ったファイルではなく、現在のカタログ全体をPOST /documents/{id}/import-stringsに再送信します。サーバーはユニットIDで差分を取り、検出結果(added、changed、unchanged、removed)に加えて、言語バージョンごとに処理が必要なブロックを正確に示すdelta_block_idsを返します。このオブジェクトをそのままグループ実行のblock_idsに渡すと、該当するブロックだけが翻訳されます。再インポートの際にrunをインラインで渡して、同じ呼び出しで差分の実行を開始することもできます。
変更のないユニットは、訳文だけでなく、完了済みのレビューもそのまま残ります。これは変更箇所のみを実行のAPI版です。数百件あるカタログのうち1件の文字列を修正した場合のコストは、その1件分だけです。
# 1. Re-submit the whole current catalog; the server diffs it by unit id
curl -s -X POST $BASE/documents/<master>/import-strings \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d @app-ui.tstrings.json
# → { units: {added, changed, unchanged, removed}, delta_block_ids: {<doc_id>: [block ids]} }
# 2. Feed delta_block_ids VERBATIM into a group run; only those blocks translate
curl -s -X POST $BASE/group-runs \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"document_id": "<master>", "template_id": "end_to_end",
"target_languages": "all", "block_ids": { "<doc_id>": ["<block id>", "…"] }}'キー付きで結果を取得するには?
マスタードキュメントに対してGET /documents/{id}/content?format=stringsを実行すると、全言語の訳文がユニットIDごとにキー付けされた1つの.tstrings.jsonが返されます。1回の呼び出しで、そのままコミットしたりビルドパイプラインに戻したりできます。パイプラインで特定の形式が必要な場合は、同じエンドポイントで言語ごとの出力(markdown、html、csv、xliff、tmx)も取得できます。形式の一覧はAPIでTranseptを自動化するにあります。
CSV、PO、XLIFFとして取り込んだカタログの場合は、元のファイル形式でエクスポートすると、アップロードしたファイル自体のセルやエントリに訳文が入ります(アップロードしたものとバイト単位で同じファイルに、訳文が加わった状態です)。そのため、そのファイルを元のシステムにそのまま読み込めます。
curl -s "$BASE/documents/<master>/content?format=strings" \
-H "Authorization: Bearer $KEY"
# → one .tstrings.json with every language keyed by unit id変更のない文字列に対して再度請求されますか?
いいえ、請求されません。再インポートのたびに、Transeptは送信されたカタログと保存済みのカタログをユニットIDで比較し、新規または変更されたユニットだけを実行の対象にします。変更のない文字列は、訳文も完了済みのレビューもそのまま残ります。ファイル全体を再送信すること自体に費用はかかりません。
{name}などのプレースホルダーはどうなりますか?
翻訳されることなく保護されます。プレースホルダーはテキストがモデルに渡される前にマスクされ、AIの出力ごとに原文と照合されます。プレースホルダーが欠落したり崩れたりした訳文は修復または再試行され、気づかないうちにそのまま出力されることはありません。プレースホルダー自体の文字列は、元の状態のまま復元されます。
再インポートする前に自分で差分を計算する必要がありますか?
いいえ、その必要はありません。差分の検出こそがこの処理フローの役割です。常に現在のカタログ全体を送信してください。差分はサーバー側で検出され、どのブロックが変わったかが正確に返されます。手作業で一部を削ったファイルを送ると、かえって誤った結果になります。送信に含まれていないユニットは、削除されたものとして扱われます。
解決しない場合は、アプリ内のLiteressに質問するか、[email protected]までご連絡ください。