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

Traduire du contenu structuré depuis Ruby avec la gem PolyLingo

By Robert M

Traduire du contenu structuré depuis Ruby avec la gem PolyLingo

La gem Ruby PolyLingo est désormais disponible sur RubyGems. Elle couvre toute la surface de l'API PolyLingo : traduction synchrone, requêtes par lots, tâches asynchrones avec sondage, et tous les points de terminaison utilitaires. Elle n'a aucune dépendance à l'exécution et nécessite Ruby 2.7 ou ultérieur.

Ce billet explique l'installation, la configuration du client, et chaque méthode disponible dans la gem.


Installation

Ajoutez à votre Gemfile :

gem "polylingo"

Puis lancez :

bundle install

Ou installez directement :

gem install polylingo

Aucune dépendance à l'exécution. La gem utilise uniquement la bibliothèque standard Ruby pour HTTP.


Configuration du client

require "polylingo"

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

Deux paramètres optionnels sont disponibles :

client = PolyLingo.new(
  api_key:  ENV.fetch("POLYLINGO_API_KEY"),
  base_url: "https://api.usepolylingo.com/v1", # par défaut, à surcharger pour les instances auto-hébergées
  timeout:  120,                               # secondes (ouverture + lecture), défaut 120
)

Gardez votre clé API dans une variable d'environnement. Ne la codez jamais en dur et ne la commettez jamais dans un contrôle de version.


Traduction de contenu

Requête unique

Passez votre contenu, un tableau de codes de langues cibles, et un format optionnel :

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

Le paramètre format accepte plain, markdown, json ou html. S'il est omis, l'API détecte automatiquement le format. Vous pouvez aussi passer source comme indice de langue et model comme "standard" (par défaut) ou "advanced".

La préservation du format fonctionne de la même manière que le reste de l'API PolyLingo. Pour json, seules les valeurs chaînes sont traduites, les clés, la structure et les types non chaînes restent inchangés. Pour markdown, les titres restent des titres et les blocs de code sont laissés tels quels. Pour html, les balises et attributs sont préservés et seuls les nœuds texte sont traduits.

Traduction d'un fichier de localisation 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

Une seule requête gère les trois locales. Les clés sont identiques à la source dans chaque fichier de sortie.


Requêtes par lots

Envoyez jusqu'à 100 éléments de contenu dans une seule requête, chacun avec son propre id et un format optionnel :

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

Tous les éléments partagent le même tableau targets. L'id que vous passez est conservé dans la réponse afin que vous puissiez associer les résultats à vos données sources sans dépendre de l'ordre.


Tâches asynchrones

Pour les traductions longues, l'API jobs accepte la requête, retourne immédiatement un job_id et vous permet de sonder le résultat. La gem gère cela de deux façons.

Mise en file et sondage manuel

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

Un appel qui sonde jusqu'à la fin

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

  # Surcharges optionnelles (valeurs par défaut affichées) :
  poll_interval: 5,    # secondes entre les sondages, défaut 5
  timeout:       1200, # budget total d'attente en secondes, défaut 1200 (20 minutes)
  on_progress:   ->(queue_position) { puts "Queue position: #{queue_position.inspect}" }
)

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

Toutes les valeurs temporelles dans la gem Ruby sont en secondes, conformément aux conventions Ruby. Le lambda on_progress est appelé à chaque sondage et reçoit la position actuelle dans la file d'attente en entier, ou nil si l'API ne la retourne pas.


Points de terminaison utilitaires

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 et languages ne nécessitent pas de clé API. usage retourne la consommation de jetons pour le mois calendaire en cours pour le compte authentifié.


Gestion des erreurs

Toutes les erreurs héritent de PolyLingo::PolyLingoError. Attrapez les sous-classes spécifiques que vous souhaitez gérer :

begin
  result = client.translate(
    content: "# Hello",
    targets: %w[es],
    format:  "markdown"
  )
rescue PolyLingo::AuthError => e
  # HTTP 401 — clé API invalide, manquante ou révoquée
  puts "Auth failed: #{e.message}"
rescue PolyLingo::RateLimitError => e
  # HTTP 429 — limite par minute atteinte
  retry_after = e.retry_after # entier en secondes ou nil
  sleep retry_after if retry_after
  retry
rescue PolyLingo::JobFailedError => e
  # Tâche asynchrone arrivée à un statut terminal échoué, ou sondage expiré
  puts "Job failed: #{e.job_id}"
rescue PolyLingo::PolyLingoError => e
  # Toutes les autres erreurs API
  puts "#{e.status}: #{e.error} — #{e.message}"
end

RateLimitError#retry_after retourne un entier provenant soit du corps JSON de la réponse, soit de l'en-tête Retry-After, selon ce qui est présent, ou nil si aucun n'est inclus. JobFailedError#job_id vous donne l'ID de la tâche échouée lorsqu'il est connu.


Référence rapide

MéthodeEndpointAuth requise
client.healthGET /healthNon
client.languagesGET /languagesNon
client.translate(...)POST /translateOui
client.batch(...)POST /translate/batchOui
client.usageGET /usageOui
client.jobs.create(...)POST /jobsOui
client.jobs.get(job_id)GET /jobs/:idOui
client.jobs.translate(...)POST /jobs + sondageOui

Commencer

La gem est sur RubyGems à rubygems.org/gems/polylingo. Le code source est sur github.com/UsePolyLingo/polylingo-ruby. La documentation complète de l'API est sur usepolylingo.com/docs.

Le niveau gratuit inclut 50 000 jetons par mois. Pas de carte de crédit requise.

gem install polylingo

Obtenez votre clé API