1 defmodule Pleroma.Akkoma.Translators.DeepL do
2 @behaviour Pleroma.Akkoma.Translator
8 defp base_url(:free) do
9 "https://api-free.deepl.com/v2/"
12 defp base_url(:pro) do
13 "https://api.deepl.com/v2/"
17 Config.get([:deepl, :api_key])
21 Config.get([:deepl, :tier])
24 @impl Pleroma.Akkoma.Translator
26 with {:ok, %{status: 200} = source_response} <- do_languages("source"),
27 {:ok, %{status: 200} = dest_response} <- do_languages("target"),
28 {:ok, source_body} <- Jason.decode(source_response.body),
29 {:ok, dest_body} <- Jason.decode(dest_response.body) do
31 Enum.map(source_body, fn %{"language" => code, "name" => name} ->
32 %{code: code, name: name}
36 Enum.map(dest_body, fn %{"language" => code, "name" => name} ->
37 %{code: code, name: name}
40 {:ok, source_resp, dest_resp}
42 {:ok, %{status: status} = response} ->
43 Logger.warning("DeepL: Request rejected: #{inspect(response)}")
44 {:error, "DeepL request failed (code #{status})"}
51 @impl Pleroma.Akkoma.Translator
52 def translate(string, from_language, to_language) do
53 with {:ok, %{status: 200} = response} <-
54 do_request(api_key(), tier(), string, from_language, to_language),
55 {:ok, body} <- Jason.decode(response.body) do
56 %{"translations" => [%{"text" => translated, "detected_source_language" => detected}]} =
59 {:ok, detected, translated}
61 {:ok, %{status: status} = response} ->
62 Logger.warning("DeepL: Request rejected: #{inspect(response)}")
63 {:error, "DeepL request failed (code #{status})"}
70 defp do_request(api_key, tier, string, from_language, to_language) do
72 base_url(tier) <> "translate",
76 target_lang: to_language,
79 |> maybe_add_source(from_language),
83 {"authorization", "DeepL-Auth-Key #{api_key}"},
84 {"content-type", "application/x-www-form-urlencoded"}
89 defp maybe_add_source(opts, nil), do: opts
90 defp maybe_add_source(opts, lang), do: Map.put(opts, :source_lang, lang)
92 defp do_languages(type) do
94 base_url(tier()) <> "languages?type=#{type}",
96 {"authorization", "DeepL-Auth-Key #{api_key()}"}