ブログに戻る
Terminal window showing a Gemfile entry for the PolyLingo gem alongside a short Ruby translate call and its output hash.

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パラメータはplainmarkdownjson、または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, ... } }

healthlanguagesは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.healthGET /healthいいえ
client.languagesGET /languagesいいえ
client.translate(...)POST /translateはい
client.batch(...)POST /translate/batchはい
client.usageGET /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

APIキーを取得