Quay lại blog
Terminal window showing a Gemfile entry for the PolyLingo gem alongside a short Ruby translate call and its output hash.

Dịch nội dung có cấu trúc từ Ruby với gem PolyLingo

By Robert M

Dịch nội dung có cấu trúc từ Ruby với PolyLingo gem

PolyLingo Ruby gem hiện đã có trên RubyGems. Nó bao phủ toàn bộ bề mặt API PolyLingo: dịch đồng bộ, yêu cầu theo lô, công việc bất đồng bộ với việc kiểm tra trạng thái, và tất cả các điểm cuối tiện ích. Nó không có phụ thuộc thời gian chạy và yêu cầu Ruby 2.7 trở lên.

Bài viết này hướng dẫn cài đặt, thiết lập client, và mọi phương thức có sẵn trong gem.


Cài đặt

Thêm vào Gemfile của bạn:

gem "polylingo"

Sau đó chạy:

bundle install

Hoặc cài đặt trực tiếp:

gem install polylingo

Không có phụ thuộc thời gian chạy. Gem chỉ sử dụng thư viện chuẩn của Ruby cho HTTP.


Thiết lập client

require "polylingo"

client = PolyLingo.new(api_key: ENV.fetch("POLYLINGO_API_KEY"))

Có hai thiết lập tùy chọn:

client = PolyLingo.new(
  api_key:  ENV.fetch("POLYLINGO_API_KEY"),
  base_url: "https://api.usepolylingo.com/v1", # mặc định, ghi đè cho các instance tự host
  timeout:  120,                               # giây (mở + đọc), mặc định 120
)

Giữ API key của bạn trong biến môi trường. Không bao giờ mã hóa cứng và không bao giờ commit vào hệ thống kiểm soát phiên bản.


Dịch nội dung

Yêu cầu đơn lẻ

Truyền nội dung của bạn, một mảng mã ngôn ngữ đích, và một định dạng tùy chọn:

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"]

Tham số format chấp nhận plain, markdown, json, hoặc html. Nếu bỏ qua, API tự động phát hiện định dạng. Bạn cũng có thể truyền source như gợi ý ngôn ngữ và model là "standard" (mặc định) hoặc "advanced".

Việc bảo toàn định dạng hoạt động giống như phần còn lại của API PolyLingo. Với json, chỉ các giá trị chuỗi được dịch, các khóa, cấu trúc lồng nhau và kiểu không phải chuỗi được giữ nguyên. Với markdown, các tiêu đề vẫn là tiêu đề và các khối mã được giữ nguyên. Với html, các thẻ và thuộc tính được giữ nguyên và chỉ các nút văn bản được dịch.

Dịch tệp locale 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

Một yêu cầu xử lý cả ba locale. Các khóa giống hệt nguồn trong mọi tệp đầu ra.


Yêu cầu theo lô

Gửi tối đa 100 mục nội dung trong một yêu cầu, mỗi mục có id riêng và format tùy chọn:

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

Tất cả mục chia sẻ cùng một mảng targets. id bạn truyền vào được giữ nguyên trong phản hồi để bạn có thể ánh xạ kết quả trở lại dữ liệu nguồn mà không phụ thuộc vào thứ tự.


Công việc bất đồng bộ

Đối với các bản dịch chạy lâu, API công việc nhận yêu cầu, trả về job_id ngay lập tức và cho phép bạn kiểm tra kết quả. Gem xử lý theo hai cách.

Đưa vào hàng đợi và kiểm tra thủ công

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

Một lần gọi kiểm tra đến khi xong

done = client.jobs.translate(
  content:       File.read("content/long-article.md"),
  targets:       %w[es fr de],
  format:        "markdown",

  # Ghi đè tùy chọn (mặc định hiển thị):
  poll_interval: 5,    # giây giữa các lần kiểm tra, mặc định 5
  timeout:       1200, # tổng thời gian chờ tính bằng giây, mặc định 1200 (20 phút)
  on_progress:   ->(queue_position) { puts "Queue position: #{queue_position.inspect}" }
)

translations = done["translations"]
usage        = done["usage"]

Tất cả giá trị thời gian trong Ruby gem dùng giây, phù hợp với quy ước Ruby. Lambda on_progress được gọi mỗi lần kiểm tra và nhận vị trí hàng đợi hiện tại dưới dạng số nguyên, hoặc nil nếu API không trả về.


Điểm cuối tiện ích

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 không yêu cầu API key. usage trả về mức tiêu thụ token cho tháng lịch hiện tại của tài khoản đã xác thực.


Xử lý lỗi

Tất cả lỗi kế thừa từ PolyLingo::PolyLingoError. Bắt các lớp con cụ thể bạn muốn xử lý:

begin
  result = client.translate(
    content: "# Hello",
    targets: %w[es],
    format:  "markdown"
  )
rescue PolyLingo::AuthError => e
  # HTTP 401 — khóa API không hợp lệ, thiếu hoặc bị thu hồi
  puts "Auth failed: #{e.message}"
rescue PolyLingo::RateLimitError => e
  # HTTP 429 — đạt giới hạn mỗi phút
  retry_after = e.retry_after # số nguyên giây hoặc nil
  sleep retry_after if retry_after
  retry
rescue PolyLingo::JobFailedError => e
  # Công việc bất đồng bộ đạt trạng thái thất bại cuối cùng hoặc kiểm tra hết thời gian
  puts "Job failed: #{e.job_id}"
rescue PolyLingo::PolyLingoError => e
  # Tất cả lỗi API khác
  puts "#{e.status}: #{e.error} — #{e.message}"
end

RateLimitError#retry_after trả về số nguyên từ phần thân phản hồi JSON hoặc header Retry-After, nếu có, hoặc nil nếu không có. JobFailedError#job_id cung cấp ID công việc thất bại khi biết được.


Tham khảo nhanh

MethodEndpointYêu cầu Auth
client.healthGET /healthKhông
client.languagesGET /languagesKhông
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 + polling

Bắt đầu

Gem có trên RubyGems tại rubygems.org/gems/polylingo. Mã nguồn tại github.com/UsePolyLingo/polylingo-ruby. Tài liệu API đầy đủ tại usepolylingo.com/docs.

Gói miễn phí bao gồm 50.000 token mỗi tháng. Không cần thẻ tín dụng.

gem install polylingo

Nhận API key của bạn