
PolyLingo gemを使ってRubyから構造化コンテンツを翻訳する
By Robert M
PolyLingo gemでRubyから構造化コンテンツを翻訳する
PolyLingo Ruby gemは現在RubyGemsで利用可能です。同期翻訳、バッチリクエスト、ポーリング付き非同期ジョブ、すべてのユーティリティエンドポイントをカバーしています。ランタイム依存関係はなく、Ruby 2.7以降が必要です。
この記事ではインストール、クライアント設定、gemで利用可能なすべてのメソッドを説明します。
インストール
Gemfileに追加します:
gem "polylingo"
次に実行します:
bundle install
または直接インストール:
gem install polylingo
ランタイム依存関係はありません。gemはRubyの標準ライブラリのみをHTTPに使用します。
クライアントの設定
require "polylingo"
client = PolyLingo.new(api_key: ENV.fetch("POLYLINGO_API_KEY"))
2つのオプション設定があります:
client = PolyLingo.new(
api_key: ENV.fetch("POLYLINGO_API_KEY"),
base_url: "https://api.usepolylingo.com/v1", # デフォルト、自ホストインスタンス用に上書き可能
timeout: 120, # 秒(オープン+読み取り)、デフォルト120
)
APIキーは環境変数に保持してください。絶対にハードコードせず、バージョン管理にコミットしないでください。
コンテンツの翻訳
単一リクエスト
コンテンツ、ターゲット言語コードの配列、オプションのフォーマットを渡します:
result = client.translate(
content: "# Hello\n\nThis is **structured** content.",
targets: %w[es fr de],
format: "markdown"
)
puts result["translations"]["es"]
puts result["usage"]["total_tokens"]
formatパラメータはplain、markdown、json、またはhtmlを受け入れます。省略するとAPIが自動検出します。sourceを言語ヒントとして、modelを"standard"(デフォルト)または"advanced"として渡すこともできます。
フォーマットの保持は他のPolyLingo APIと同様に動作します。jsonでは文字列値のみ翻訳され、キー、ネスト、非文字列型はそのままです。markdownでは見出しは見出しのままでコードブロックはそのままです。htmlではタグと属性が保持され、テキストノードのみ翻訳されます。
JSONロケールファイルの翻訳
require "json"
source = JSON.parse(File.read("config/locales/en.yml"))
result = client.translate(
content: source.to_json,
format: "json",
targets: %w[fr de ja]
)
%w[fr de ja].each do |locale|
translated = JSON.parse(result["translations"][locale])
File.write(
"config/locales/#{locale}.json",
JSON.pretty_generate(translated)
)
puts "Wrote config/locales/#{locale}.json"
end
1つのリクエストで3つのロケールすべてを処理します。すべての出力ファイルでキーはソースと同一です。
バッチリクエスト
最大100件のコンテンツアイテムを1つのリクエストで送信できます。各アイテムは独自のidとオプションのformatを持ちます:
result = client.batch(
items: [
{ id: "hero_title", content: "Welcome back", format: "plain" },
{ id: "hero_subtitle", content: "Here is what changed today", format: "plain" },
{ id: "cta", content: "Get started", format: "plain" },
],
targets: %w[es fr de]
)
result["results"].each do |row|
puts "#{row["id"]}: #{row["translations"]["es"]}"
end
すべてのアイテムは同じtargets配列を共有します。渡したidはレスポンスで保持されるため、順序に依存せずに結果をソースデータにマッピングできます。
非同期ジョブ
長時間かかる翻訳の場合、ジョブAPIはリクエストを受け入れ、即座にjob_idを返し、結果をポーリングできます。gemはこれを2つの方法で処理します。
手動でキューに入れてポーリング
accepted = client.jobs.create(
content: File.read("content/long-article.md"),
targets: %w[es fr de ja zh],
format: "markdown"
)
job_id = accepted["job_id"]
loop do
sleep 5
state = client.jobs.get(job_id)
break if %w[complete failed].include?(state["status"])
end
if state["status"] == "complete"
translations = state["translations"]
end
完了までポーリングする1回の呼び出し
done = client.jobs.translate(
content: File.read("content/long-article.md"),
targets: %w[es fr de],
format: "markdown",
# オプションのオーバーライド(デフォルト表示):
poll_interval: 5, # ポーリング間隔(秒)、デフォルト5
timeout: 1200, # 合計待機時間(秒)、デフォルト1200(20分)
on_progress: ->(queue_position) { puts "Queue position: #{queue_position.inspect}" }
)
translations = done["translations"]
usage = done["usage"]
Ruby gem内のすべての時間値は秒単位で、Rubyの慣習に沿っています。on_progressラムダは各ポーリング時に呼ばれ、現在のキュー位置を整数で受け取ります。APIが返さない場合はnilです。
ユーティリティエンドポイント
health = client.health
# => { "status" => "ok", "timestamp" => "..." }
languages = client.languages
# => { "languages" => [{ "code" => "en", "name" => "English", "rtl" => false }, ...] }
usage = client.usage
# => { "usage" => { "tokens_used" => 12000, "tokens_remaining" => 38000, ... } }
healthとlanguagesはAPIキー不要です。usageは認証済みアカウントの当月カレンダー月のトークン使用量を返します。
エラーハンドリング
すべてのエラーはPolyLingo::PolyLingoErrorを継承します。処理したい特定のサブクラスをキャッチしてください:
begin
result = client.translate(
content: "# Hello",
targets: %w[es],
format: "markdown"
)
rescue PolyLingo::AuthError => e
# HTTP 401 — 無効、欠落、または取り消されたAPIキー
puts "Auth failed: #{e.message}"
rescue PolyLingo::RateLimitError => e
# HTTP 429 — 分あたりの制限に達した
retry_after = e.retry_after # 整数秒またはnil
sleep retry_after if retry_after
retry
rescue PolyLingo::JobFailedError => e
# 非同期ジョブが失敗状態に達したか、ポーリングがタイムアウト
puts "Job failed: #{e.job_id}"
rescue PolyLingo::PolyLingoError => e
# その他すべてのAPIエラー
puts "#{e.status}: #{e.error} — #{e.message}"
end
RateLimitError#retry_afterはJSONレスポンスボディまたはRetry-Afterヘッダーのいずれかにある整数を返し、どちらもなければnilです。JobFailedError#job_idは失敗したジョブの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(job_id) | GET /jobs/:id | はい |
client.jobs.translate(...) | POST /jobs + ポーリング | はい |
はじめに
gemはRubyGemsのrubygems.org/gems/polylingoにあります。ソースコードはgithub.com/UsePolyLingo/polylingo-rubyにあります。完全なAPIドキュメントはusepolylingo.com/docsにあります。
無料プランは月50,000トークンを含みます。クレジットカード不要です。
gem install polylingo