Terug naar blog
Terminal window showing a Gemfile entry for the PolyLingo gem alongside a short Ruby translate call and its output hash.

Vertaal gestructureerde inhoud uit Ruby met de PolyLingo-gem

By Robert M

Vertaal gestructureerde inhoud vanuit Ruby met de PolyLingo gem

De PolyLingo Ruby gem is nu beschikbaar op RubyGems. Het dekt het volledige PolyLingo API-oppervlak: synchrone vertaling, batchverzoeken, async jobs met polling, en alle utility endpoints. Het heeft geen runtime afhankelijkheden en vereist Ruby 2.7 of later.

Deze post loopt door installatie, de client setup, en elke methode die beschikbaar is in de gem.


Installatie

Voeg toe aan je Gemfile:

gem "polylingo"

Voer dan uit:

bundle install

Of installeer direct:

gem install polylingo

Geen runtime afhankelijkheden. De gem gebruikt alleen Ruby's standaardbibliotheek voor HTTP.


De client instellen

require "polylingo"

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

Twee optionele instellingen zijn beschikbaar:

client = PolyLingo.new(
  api_key:  ENV.fetch("POLYLINGO_API_KEY"),
  base_url: "https://api.usepolylingo.com/v1", # standaard, overschrijven voor zelf-gehoste instanties
  timeout:  120,                               # seconden (open + read), standaard 120
)

Bewaar je API-sleutel in een omgevingsvariabele. Nooit hardcoderen en nooit committen naar versiebeheer.


Inhoud vertalen

Enkel verzoek

Geef je inhoud door, een array van doeltaalcodes, en een optioneel formaat:

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

De parameter format accepteert plain, markdown, json, of html. Als het wordt weggelaten, detecteert de API het formaat automatisch. Je kunt ook source doorgeven als taalhint en model als ofwel "standard" (standaard) of "advanced".

Formaatbehoud werkt hetzelfde als de rest van de PolyLingo API. Voor json worden alleen stringwaarden vertaald en sleutels, nesting en niet-string types blijven onaangeroerd. Voor markdown blijven koppen koppen en codeblokken worden letterlijk gelaten. Voor html worden tags en attributen behouden en alleen tekstknopen vertaald.

Een JSON locale-bestand vertalen

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

Eén verzoek behandelt alle drie de locales. Sleutels zijn identiek aan de bron in elk uitvoerbestand.


Batchverzoeken

Verstuur tot 100 inhoudsitems in één verzoek, elk met een eigen id en optioneel 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

Alle items delen dezelfde targets array. De id die je doorgeeft wordt behouden in de respons zodat je resultaten kunt terugkoppelen naar je brondata zonder op volgorde te vertrouwen.


Async jobs

Voor langlopende vertalingen accepteert de jobs API het verzoek, retourneert direct een job_id, en laat je pollen voor het resultaat. De gem behandelt dit op twee manieren.

Handmatig in de wachtrij zetten en pollen

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

Eén oproep die blijft pollen tot klaar

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

  # Optionele overschrijvingen (standaardwaarden getoond):
  poll_interval: 5,    # seconden tussen polls, standaard 5
  timeout:       1200, # totale wachttijd in seconden, standaard 1200 (20 minuten)
  on_progress:   ->(queue_position) { puts "Queue position: #{queue_position.inspect}" }
)

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

Alle tijdwaarden in de Ruby gem gebruiken seconden, consistent met Ruby conventies. De on_progress lambda wordt bij elke poll aangeroepen en ontvangt de huidige wachtrijpositie als een integer, of nil als de API deze niet teruggeeft.


Utility endpoints

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 en languages vereisen geen API-sleutel. usage retourneert tokenverbruik voor de huidige kalendermaand voor het geauthenticeerde account.


Foutafhandeling

Alle fouten erven van PolyLingo::PolyLingoError. Vang de specifieke subklassen die je wilt afhandelen:

begin
  result = client.translate(
    content: "# Hello",
    targets: %w[es],
    format:  "markdown"
  )
rescue PolyLingo::AuthError => e
  # HTTP 401 — ongeldige, ontbrekende of ingetrokken API-sleutel
  puts "Auth failed: #{e.message}"
rescue PolyLingo::RateLimitError => e
  # HTTP 429 — per-minuut limiet bereikt
  retry_after = e.retry_after # integer seconden of nil
  sleep retry_after if retry_after
  retry
rescue PolyLingo::JobFailedError => e
  # Async job bereikte een mislukte eindstatus, of polling time-out
  puts "Job failed: #{e.job_id}"
rescue PolyLingo::PolyLingoError => e
  # Alle andere API fouten
  puts "#{e.status}: #{e.error} — #{e.message}"
end

RateLimitError#retry_after retourneert een integer van ofwel de JSON response body of de Retry-After header, welke aanwezig is, of nil als geen van beide is inbegrepen. JobFailedError#job_id geeft je de ID van de mislukte job wanneer deze bekend is.


Snelle referentie

MethodeEndpointAuth vereist
client.healthGET /healthNee
client.languagesGET /languagesNee
client.translate(...)POST /translateJa
client.batch(...)POST /translate/batchJa
client.usageGET /usageJa
client.jobs.create(...)POST /jobsJa
client.jobs.get(job_id)GET /jobs/:idJa
client.jobs.translate(...)POST /jobs + pollingJa

Aan de slag

De gem staat op RubyGems op rubygems.org/gems/polylingo. Broncode is op github.com/UsePolyLingo/polylingo-ruby. Volledige API documentatie is op usepolylingo.com/docs.

De gratis laag bevat 50.000 tokens per maand. Geen creditcard vereist.

gem install polylingo

Haal je API-sleutel op