defmodule Pleroma.Akkoma.Translators.LibreTranslate do @behaviour Pleroma.Akkoma.Translator alias Pleroma.Config alias Pleroma.HTTP require Logger defp api_key do Config.get([:libre_translate, :api_key]) end defp url do Config.get([:libre_translate, :url]) end @impl Pleroma.Akkoma.Translator def languages do with {:ok, %{status: 200} = response} <- do_languages(), {:ok, body} <- Jason.decode(response.body) do resp = Enum.map(body, fn %{"code" => code, "name" => name} -> %{code: code, name: name} end) # No separate source/dest {:ok, resp, resp} else {:ok, %{status: status} = response} -> Logger.warning("LibreTranslate: Request rejected: #{inspect(response)}") {:error, "LibreTranslate request failed (code #{status})"} {:error, reason} -> {:error, reason} end end @impl Pleroma.Akkoma.Translator def translate(string, from_language, to_language) do with {:ok, %{status: 200} = response} <- do_request(string, from_language, to_language), {:ok, body} <- Jason.decode(response.body) do %{"translatedText" => translated} = body detected = if Map.has_key?(body, "detectedLanguage") do get_in(body, ["detectedLanguage", "language"]) else from_language || "" end {:ok, detected, translated} else {:ok, %{status: status} = response} -> Logger.warning("libre_translate: request failed, #{inspect(response)}") {:error, "libre_translate: request failed (code #{status})"} {:error, reason} -> {:error, reason} end end defp do_request(string, from_language, to_language) do url = URI.parse(url()) url = %{url | path: "/translate"} HTTP.post( to_string(url), Jason.encode!(%{ q: string, source: if(is_nil(from_language), do: "auto", else: from_language), target: to_language, format: "html", api_key: api_key() }), [ {"content-type", "application/json"} ] ) end defp do_languages() do url = URI.parse(url()) url = %{url | path: "/languages"} HTTP.get(to_string(url)) end end