
Tłumaczenie ustrukturyzowanej zawartości z Ruby za pomocą gemu PolyLingo
By Robert M
Tłumaczenie ustrukturyzowanej zawartości z Ruby za pomocą gemu PolyLingo
Gem PolyLingo Ruby jest teraz dostępny na RubyGems. Obejmuje pełny interfejs API PolyLingo: tłumaczenia synchroniczne, żądania wsadowe, zadania asynchroniczne z pollingiem oraz wszystkie punkty końcowe narzędziowe. Nie ma zależności w czasie wykonywania i wymaga Ruby 2.7 lub nowszego.
Ten wpis przeprowadza przez instalację, konfigurację klienta oraz każdą metodę dostępną w gemie.
Instalacja
Dodaj do swojego Gemfile:
gem "polylingo"
Następnie uruchom:
bundle install
Lub zainstaluj bezpośrednio:
gem install polylingo
Brak zależności w czasie wykonywania. Gem używa tylko standardowej biblioteki Ruby do HTTP.
Konfiguracja klienta
require "polylingo"
client = PolyLingo.new(api_key: ENV.fetch("POLYLINGO_API_KEY"))
Dostępne są dwie opcjonalne ustawienia:
client = PolyLingo.new(
api_key: ENV.fetch("POLYLINGO_API_KEY"),
base_url: "https://api.usepolylingo.com/v1", # domyślny, nadpisz dla instancji self-hosted
timeout: 120, # sekundy (otwarcie + odczyt), domyślnie 120
)
Przechowuj swój klucz API w zmiennej środowiskowej. Nigdy nie koduj go na stałe i nigdy nie zatwierdzaj do kontroli wersji.
Tłumaczenie zawartości
Pojedyncze żądanie
Przekaż swoją zawartość, tablicę kodów języków docelowych oraz opcjonalny format:
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"]
Parametr format akceptuje plain, markdown, json lub html. Jeśli zostanie pominięty, API automatycznie wykrywa format. Możesz także przekazać source jako wskazówkę językową oraz model jako "standard" (domyślny) lub "advanced".
Zachowanie formatu działa tak samo jak w reszcie API PolyLingo. Dla json tłumaczone są tylko wartości typu string, a klucze, zagnieżdżenia i typy nie-string pozostają nietknięte. Dla markdown nagłówki pozostają nagłówkami, a bloki kodu są pozostawione dosłownie. Dla html tagi i atrybuty są zachowane, a tłumaczone są tylko węzły tekstowe.
Tłumaczenie pliku 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
Jedno żądanie obsługuje wszystkie trzy locale. Klucze są identyczne jak w źródle w każdym pliku wyjściowym.
Żądania wsadowe
Wyślij do 100 elementów zawartości w jednym żądaniu, każdy z własnym id i opcjonalnym 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
Wszystkie elementy dzielą tę samą tablicę targets. Przekazane id jest zachowywane w odpowiedzi, dzięki czemu możesz mapować wyniki z powrotem do swoich danych źródłowych bez polegania na kolejności.
Zadania asynchroniczne
Dla tłumaczeń długotrwałych API zadań akceptuje żądanie, zwraca natychmiast job_id i pozwala na polling wyniku. Gem obsługuje to na dwa sposoby.
Kolejkowanie i ręczne pollowanie
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
Jedno wywołanie, które polluje aż do zakończenia
done = client.jobs.translate(
content: File.read("content/long-article.md"),
targets: %w[es fr de],
format: "markdown",
# Opcjonalne nadpisania (pokazane wartości domyślne):
poll_interval: 5, # sekundy między pollami, domyślnie 5
timeout: 1200, # całkowity budżet oczekiwania w sekundach, domyślnie 1200 (20 minut)
on_progress: ->(queue_position) { puts "Queue position: #{queue_position.inspect}" }
)
translations = done["translations"]
usage = done["usage"]
Wszystkie wartości czasu w gemie Ruby używają sekund, zgodnie z konwencjami Ruby. Lambda on_progress wywoływana jest przy każdym pollu i otrzymuje aktualną pozycję w kolejce jako liczbę całkowitą lub nil, jeśli API jej nie zwraca.
Punkty końcowe narzędziowe
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 i languages nie wymagają klucza API. usage zwraca zużycie tokenów za bieżący miesiąc kalendarzowy dla uwierzytelnionego konta.
Obsługa błędów
Wszystkie błędy dziedziczą po PolyLingo::PolyLingoError. Przechwytuj konkretne podklasy, które chcesz obsłużyć:
begin
result = client.translate(
content: "# Hello",
targets: %w[es],
format: "markdown"
)
rescue PolyLingo::AuthError => e
# HTTP 401 — nieprawidłowy, brakujący lub cofnięty klucz API
puts "Auth failed: #{e.message}"
rescue PolyLingo::RateLimitError => e
# HTTP 429 — osiągnięto limit na minutę
retry_after = e.retry_after # liczba sekund lub nil
sleep retry_after if retry_after
retry
rescue PolyLingo::JobFailedError => e
# Zadanie async osiągnęło status końcowy niepowodzenia lub polling przekroczył limit czasu
puts "Job failed: #{e.job_id}"
rescue PolyLingo::PolyLingoError => e
# Wszystkie inne błędy API
puts "#{e.status}: #{e.error} — #{e.message}"
end
RateLimitError#retry_after zwraca liczbę całkowitą z ciała odpowiedzi JSON lub nagłówka Retry-After, w zależności co jest obecne, lub nil jeśli żadne z nich nie jest dołączone. JobFailedError#job_id podaje ID nieudanego zadania, gdy jest znane.
Szybkie odniesienie
| Metoda | Punkt końcowy | Wymaga autoryzacji |
|---|---|---|
client.health | GET /health | Nie |
client.languages | GET /languages | Nie |
client.translate(...) | POST /translate | Tak |
client.batch(...) | POST /translate/batch | Tak |
client.usage | GET /usage | Tak |
client.jobs.create(...) | POST /jobs | Tak |
client.jobs.get(job_id) | GET /jobs/:id | Tak |
client.jobs.translate(...) | POST /jobs + polling | Tak |
Zacznij
Gem jest dostępny na RubyGems pod adresem rubygems.org/gems/polylingo. Kod źródłowy jest na github.com/UsePolyLingo/polylingo-ruby. Pełna dokumentacja API jest na usepolylingo.com/docs.
Darmowy plan obejmuje 50 000 tokenów miesięcznie. Nie jest wymagana karta kredytowa.
gem install polylingo