libre_translate.rb 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. # frozen_string_literal: true
  2. class TranslationService::LibreTranslate < TranslationService
  3. def initialize(base_url, api_key)
  4. super()
  5. @base_url = base_url
  6. @api_key = api_key
  7. end
  8. def translate(texts, source_language, target_language)
  9. body = Oj.dump(q: texts, source: source_language.presence || 'auto', target: target_language, format: 'html', api_key: @api_key)
  10. request(:post, '/translate', body: body) do |res|
  11. transform_response(res.body_with_limit, source_language)
  12. end
  13. end
  14. def languages
  15. request(:get, '/languages') do |res|
  16. languages = Oj.load(res.body_with_limit).to_h do |language|
  17. [language['code'], language['targets'].without(language['code'])]
  18. end
  19. languages[nil] = languages.values.flatten.uniq.sort
  20. languages
  21. end
  22. end
  23. private
  24. def request(verb, path, **options)
  25. req = Request.new(verb, "#{@base_url}#{path}", allow_local: true, **options)
  26. req.add_headers('Content-Type': 'application/json')
  27. req.perform do |res|
  28. case res.code
  29. when 429
  30. raise TooManyRequestsError
  31. when 403
  32. raise QuotaExceededError
  33. when 200...300
  34. yield res
  35. else
  36. raise UnexpectedResponseError
  37. end
  38. end
  39. end
  40. def transform_response(json, source_language)
  41. data = Oj.load(json, mode: :strict)
  42. raise UnexpectedResponseError unless data.is_a?(Hash)
  43. data['translatedText'].map.with_index do |text, index|
  44. Translation.new(
  45. text: text,
  46. detected_source_language: data.dig('detectedLanguage', index, 'language') || source_language,
  47. provider: 'LibreTranslate'
  48. )
  49. end
  50. rescue Oj::ParseError
  51. raise UnexpectedResponseError
  52. end
  53. end