diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a71255ff..05cb69c40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - support for setting instance languages in metadata - support for reusing oauth tokens, and not requiring new authorizations - the ability to obfuscate domains in your MRF descriptions +- automatic translation of statuses via DeepL or LibreTranslate ### Changed - MFM parsing is now done on the backend by a modified version of ilja's parser -> https://akkoma.dev/AkkomaGang/mfm-parser diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex index e11e5495a..b809f7733 100644 --- a/lib/pleroma/application.ex +++ b/lib/pleroma/application.ex @@ -154,7 +154,8 @@ defmodule Pleroma.Application do build_cachex("web_resp", limit: 2500), build_cachex("emoji_packs", expiration: emoji_packs_expiration(), limit: 10), build_cachex("failed_proxy_url", limit: 2500), - build_cachex("banned_urls", default_ttl: :timer.hours(24 * 30), limit: 5_000) + build_cachex("banned_urls", default_ttl: :timer.hours(24 * 30), limit: 5_000), + build_cachex("translations", default_ttl: :timer.hours(24 * 30), limit: 2500) ] end diff --git a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex index 43fb63c38..d9b93ca5e 100644 --- a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex @@ -31,6 +31,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do plug(:skip_public_check when action in [:index, :show]) @unauthenticated_access %{fallback: :proceed_unauthenticated, scopes: []} + @cachex Pleroma.Config.get([:cachex, :provider], Cachex) plug( OAuthScopesPlug, @@ -427,7 +428,12 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do {:visible, true} <- {:visible, Visibility.visible_for_user?(activity, user)}, translation_module <- Config.get([:translator, :module]), {:ok, detected, translation} <- - translation_module.translate(activity.object.data["content"], language) do + fetch_or_translate( + activity.id, + activity.object.data["content"], + language, + translation_module + ) do json(conn, %{detected_language: detected, text: translation}) else {:enabled, false} -> @@ -443,6 +449,18 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do end end + defp fetch_or_translate(status_id, text, language, translation_module) do + @cachex.fetch!(:user_cache, "translations:#{status_id}:#{language}", fn _ -> + value = translation_module.translate(text, language) + + with {:ok, _, _} <- value do + value + else + _ -> {:ignore, value} + end + end) + end + defp put_application(params, %{assigns: %{token: %Token{user: %User{} = user} = token}} = _conn) do if user.disclose_client do %{client_name: client_name, website: website} = Repo.preload(token, :app).app diff --git a/lib/pleroma/web/mastodon_api/views/instance_view.ex b/lib/pleroma/web/mastodon_api/views/instance_view.ex index 7ae357e23..436519439 100644 --- a/lib/pleroma/web/mastodon_api/views/instance_view.ex +++ b/lib/pleroma/web/mastodon_api/views/instance_view.ex @@ -81,6 +81,9 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do if Config.get([:instance, :profile_directory]) do "profile_directory" end, + if Config.get([:translator, :enabled], false) do + "akkoma:machine_translation" + end, "custom_emoji_reactions" ] |> Enum.filter(& &1) diff --git a/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs index 771164be3..e38f5fe58 100644 --- a/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs @@ -2083,7 +2083,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do test "should return text and detected language", %{conn: conn} do clear_config([:deepl, :tier], :free) - Tesla.Mock.mock(fn + Tesla.Mock.mock_global(fn %{method: :post, url: "https://api-free.deepl.com/v2/translate"} -> %Tesla.Env{ status: 200, @@ -2116,7 +2116,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do test "should not allow translating of statuses you cannot see", %{conn: conn} do clear_config([:deepl, :tier], :free) - Tesla.Mock.mock(fn + Tesla.Mock.mock_global(fn %{method: :post, url: "https://api-free.deepl.com/v2/translate"} -> %Tesla.Env{ status: 200,