@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 %{"language" => code, "name" => name} -> %{code: code, name: name} end)
+ with {:ok, %{status: 200} = source_response} <- do_languages("source"),
+ {:ok, %{status: 200} = dest_response} <- do_languages("target"),
+ {:ok, source_body} <- Jason.decode(source_response.body),
+ {:ok, dest_body} <- Jason.decode(dest_response.body) do
+ source_resp =
+ Enum.map(source_body, fn %{"language" => code, "name" => name} ->
+ %{code: code, name: name}
+ end)
+
+ dest_resp =
+ Enum.map(dest_body, fn %{"language" => code, "name" => name} ->
+ %{code: code, name: name}
+ end)
- {:ok, resp}
+ {:ok, source_resp, dest_resp}
else
{:ok, %{status: status} = response} ->
Logger.warning("DeepL: Request rejected: #{inspect(response)}")
defp maybe_add_source(opts, nil), do: opts
defp maybe_add_source(opts, lang), do: Map.put(opts, :source_lang, lang)
- defp do_languages() do
+ defp do_languages(type) do
HTTP.get(
- base_url(tier()) <> "languages?type=target",
+ base_url(tier()) <> "languages?type=#{type}",
[
{"authorization", "DeepL-Auth-Key #{api_key()}"}
]
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)
- {:ok, resp}
+ # No separate source/dest
+ {:ok, resp, resp}
else
{:ok, %{status: status} = response} ->
Logger.warning("LibreTranslate: Request rejected: #{inspect(response)}")
defmodule Pleroma.Akkoma.Translator do
@callback translate(String.t(), String.t() | nil, String.t()) ::
{:ok, String.t(), String.t()} | {:error, any()}
- @callback languages() :: {:ok, [%{name: String.t(), code: String.t()}]} | {:error, any()}
+ @callback languages() ::
+ {:ok, [%{name: String.t(), code: String.t()}],
+ [%{name: String.t(), code: String.t()}]}
+ | {:error, any()}
end
@doc "GET /api/v1/akkoma/translation/languages"
def languages(conn, _params) do
- with {:ok, languages} <- get_languages() do
+ with {:ok, source_languages, dest_languages} <- get_languages() do
conn
- |> json(languages)
+ |> json(%{source: source_languages, target: dest_languages})
else
e -> IO.inspect(e)
end
module = Pleroma.Config.get([:translator, :module])
@cachex.fetch!(:translations_cache, "languages:#{module}}", fn _ ->
- with {:ok, languages} <- module.languages() do
- {:ok, languages}
+ with {:ok, source_languages, dest_languages} <- module.languages() do
+ {:ok, source_languages, dest_languages}
else
{:error, err} -> {:ignore, {:error, err}}
end
operationId: "AkkomaAPI.TranslationController.languages",
security: [%{"oAuth" => ["read:statuses"]}],
responses: %{
- 200 => Operation.response("Translation", "application/json", languages_schema())
+ 200 =>
+ Operation.response("Translation", "application/json", source_dest_languages_schema())
+ }
+ }
+ end
+
+ defp source_dest_languages_schema do
+ %Schema{
+ type: :object,
+ required: [:source, :target],
+ properties: %{
+ source: languages_schema(),
+ target: languages_schema()
}
}
end
defp languages_schema do
%Schema{
- type: "array",
+ type: :array,
items: %Schema{
- type: "object",
+ type: :object,
properties: %{
code: %Schema{
- type: "string"
+ type: :string
},
name: %Schema{
- type: "string"
+ type: :string
}
}
}
}
])
}
+
+ %{method: :get, url: "https://api-free.deepl.com/v2/languages?type=source"} ->
+ %Tesla.Env{
+ status: 200,
+ body:
+ Jason.encode!([
+ %{
+ "language" => "JA",
+ "name" => "Japanese",
+ "supports_formality" => false
+ }
+ ])
+ }
end)
- assert {:ok, [%{code: "BG", name: "Bulgarian"}, %{code: "CS", name: "Czech"}]} =
+ assert {:ok, [%{code: "JA", name: "Japanese"}],
+ [%{code: "BG", name: "Bulgarian"}, %{code: "CS", name: "Czech"}]} =
DeepL.languages()
end
}
end)
- assert {:ok, [%{code: "en", name: "English"}, %{code: "ar", name: "Arabic"}]} =
+ assert {:ok, [%{code: "en", name: "English"}, %{code: "ar", name: "Arabic"}],
+ [%{code: "en", name: "English"}, %{code: "ar", name: "Arabic"}]} =
LibreTranslate.languages()
end
oauth_access(["read:statuses"])
end
+ test "listing languages", %{conn: conn} do
+ Tesla.Mock.mock_global(fn
+ %{method: :get, url: "https://api-free.deepl.com/v2/languages?type=source"} ->
+ %Tesla.Env{
+ status: 200,
+ body:
+ Jason.encode!([
+ %{language: "en", name: "English"}
+ ])
+ }
+
+ %{method: :get, url: "https://api-free.deepl.com/v2/languages?type=target"} ->
+ %Tesla.Env{
+ status: 200,
+ body:
+ Jason.encode!([
+ %{language: "ja", name: "Japanese"}
+ ])
+ }
+ end)
+
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> get("/api/v1/akkoma/translation/languages")
+
+ response = json_response_and_validate_schema(conn, 200)
+
+ assert %{
+ "source" => [%{"code" => "en", "name" => "English"}],
+ "target" => [%{"code" => "ja", "name" => "Japanese"}]
+ } = response
+ end
+
test "should return text and detected language", %{conn: conn} do
clear_config([:deepl, :tier], :free)