Повернутися до блогу
Terminal window showing a Gemfile entry for the PolyLingo gem alongside a short Ruby translate call and its output hash.

Переклад структурованого контенту з Ruby за допомогою бібліотеки PolyLingo

By Robert M

Переклад структурованого контенту з Ruby за допомогою PolyLingo gem

PolyLingo Ruby gem тепер доступний на RubyGems. Він охоплює повний API PolyLingo: синхронний переклад, пакетні запити, асинхронні завдання з опитуванням та всі допоміжні кінцеві точки. Не має залежностей під час виконання і вимагає 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"))

Доступні два необов’язкові параметри:

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

Збереження формату працює так само, як і в решті API PolyLingo. Для json перекладаються лише рядкові значення, ключі, вкладені структури та не рядкові типи залишаються без змін. Для markdown заголовки залишаються заголовками, а блоки коду залишаються без змін. Для html теги та атрибути зберігаються, перекладаються лише текстові вузли.

Переклад JSON locale файлу

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

Один запит обробляє всі три локалі. Ключі ідентичні джерелу у кожному вихідному файлі.


Пакетні запити

Надішліть до 100 елементів контенту в одному запиті, кожен з власним 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 підтримує це двома способами.

Поміщення в чергу та ручне опитування

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

Один виклик, що опитує до завершення

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 виконується при кожному опитуванні і отримує поточну позицію в черзі як ціле число або nil, якщо API не повертає її.


Допоміжні кінцеві точки

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 невдалого завдання, якщо він відомий.


Швидкий довідник

MethodEndpointПотрібен Auth
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 + pollingТак

Початок роботи

Gem доступний на RubyGems за адресою rubygems.org/gems/polylingo. Вихідний код на github.com/UsePolyLingo/polylingo-ruby. Повна документація API на usepolylingo.com/docs.

Безкоштовний рівень включає 50 000 токенів на місяць. Кредитна картка не потрібна.

gem install polylingo

Отримайте свій API ключ