commit: 9548c31ef997e4c84cbdc7dc534873c921b32e42
parent 4fc1a62264dc984e588062e53bec0bfa0f89cdd5
Author: nicole mikołajczyk <me@mkljczk.pl>
Date: Fri, 28 Nov 2025 14:48:21 +0100
Merge branch 'translation-provider-mozhi' into 'develop'
Support Mozhi as translation provider
See merge request pleroma/pleroma!4376
Diffstat:
3 files changed, 125 insertions(+), 1 deletion(-)
diff --git a/changelog.d/translation-provider-mozhi.add b/changelog.d/translation-provider-mozhi.add
@@ -0,0 +1 @@
+Support Mozhi translation provider
diff --git a/config/description.exs b/config/description.exs
@@ -3558,7 +3558,8 @@ config :pleroma, :config_description, [
type: :module,
suggestions: [
Pleroma.Language.Translation.Deepl,
- Pleroma.Language.Translation.Libretranslate
+ Pleroma.Language.Translation.Libretranslate,
+ Pleroma.Language.Translation.Mozhi
]
},
%{
@@ -3588,6 +3589,19 @@ config :pleroma, :config_description, [
label: "LibreTranslate API Key",
type: :string,
suggestions: ["YOUR_API_KEY"]
+ },
+ %{
+ group: {:subgroup, Pleroma.Language.Translation.Mozhi},
+ key: :base_url,
+ label: "Mozhi instance URL",
+ type: :string
+ },
+ %{
+ group: {:subgroup, Pleroma.Language.Translation.Mozhi},
+ key: :engine,
+ label: "Engine used for Mozhi",
+ type: :string,
+ suggestions: ["libretranslate"]
}
]
}
diff --git a/lib/pleroma/language/translation/mozhi.ex b/lib/pleroma/language/translation/mozhi.ex
@@ -0,0 +1,109 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2024 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Language.Translation.Mozhi do
+ import Pleroma.Web.Utils.Guards, only: [not_empty_string: 1]
+
+ alias Pleroma.Language.Translation.Provider
+
+ use Provider
+
+ @behaviour Provider
+
+ @name "Mozhi"
+
+ @impl Provider
+ def configured?, do: not_empty_string(base_url()) and not_empty_string(engine())
+
+ @impl Provider
+ def translate(content, source_language, target_language) do
+ endpoint =
+ base_url()
+ |> URI.merge("/api/translate")
+ |> URI.to_string()
+
+ case Pleroma.HTTP.get(
+ endpoint <>
+ "?" <>
+ URI.encode_query(%{
+ engine: engine(),
+ text: content,
+ from: source_language,
+ to: target_language
+ }),
+ [{"Accept", "application/json"}]
+ ) do
+ {:ok, %{status: 200} = res} ->
+ %{
+ "translated-text" => content,
+ "source_language" => source_language
+ } = Jason.decode!(res.body)
+
+ {:ok,
+ %{
+ content: content,
+ detected_source_language: source_language,
+ provider: @name
+ }}
+
+ _ ->
+ {:error, :internal_server_error}
+ end
+ end
+
+ @impl Provider
+ def supported_languages(type) when type in [:source, :target] do
+ path =
+ case type do
+ :source -> "/api/source_languages"
+ :target -> "/api/target_languages"
+ end
+
+ endpoint =
+ base_url()
+ |> URI.merge(path)
+ |> URI.to_string()
+
+ case Pleroma.HTTP.get(
+ endpoint <>
+ "?" <>
+ URI.encode_query(%{
+ engine: engine()
+ }),
+ [{"Accept", "application/json"}]
+ ) do
+ {:ok, %{status: 200} = res} ->
+ languages =
+ Jason.decode!(res.body)
+ |> Enum.map(fn %{"Id" => language} -> language end)
+
+ {:ok, languages}
+
+ _ ->
+ {:error, :internal_server_error}
+ end
+ end
+
+ @impl Provider
+ def languages_matrix do
+ with {:ok, source_languages} <- supported_languages(:source),
+ {:ok, target_languages} <- supported_languages(:target) do
+ {:ok,
+ Map.new(source_languages, fn language -> {language, target_languages -- [language]} end)}
+ else
+ {:error, error} -> {:error, error}
+ end
+ end
+
+ @impl Provider
+ def name, do: @name
+
+ defp base_url do
+ Pleroma.Config.get([__MODULE__, :base_url])
+ end
+
+ defp engine do
+ Pleroma.Config.get([__MODULE__, :engine])
+ end
+end