aboutsummaryrefslogtreecommitdiff
path: root/lib/pleroma/web
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pleroma/web')
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub_controller.ex11
-rw-r--r--lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex21
-rw-r--r--lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex18
-rw-r--r--lib/pleroma/web/admin_api/controllers/announcement_controller.ex83
-rw-r--r--lib/pleroma/web/admin_api/views/announcement_view.ex15
-rw-r--r--lib/pleroma/web/api_spec/operations/account_operation.ex5
-rw-r--r--lib/pleroma/web/api_spec/operations/admin/announcement_operation.ex165
-rw-r--r--lib/pleroma/web/api_spec/operations/announcement_operation.ex57
-rw-r--r--lib/pleroma/web/api_spec/schemas/announcement.ex45
-rw-r--r--lib/pleroma/web/feed/feed_view.ex1
-rw-r--r--lib/pleroma/web/gettext.ex192
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/account_controller.ex1
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/announcement_controller.ex60
-rw-r--r--lib/pleroma/web/mastodon_api/views/announcement_view.ex15
-rw-r--r--lib/pleroma/web/o_auth/mfa_view.ex1
-rw-r--r--lib/pleroma/web/o_auth/o_auth_view.ex2
-rw-r--r--lib/pleroma/web/plugs/cache.ex12
-rw-r--r--lib/pleroma/web/plugs/set_locale_plug.ex62
-rw-r--r--lib/pleroma/web/router.ex9
-rw-r--r--lib/pleroma/web/templates/email/digest.html.eex10
-rw-r--r--lib/pleroma/web/templates/feed/feed/tag.atom.eex4
-rw-r--r--lib/pleroma/web/templates/feed/feed/tag.rss.eex2
-rw-r--r--lib/pleroma/web/templates/layout/app.html.eex2
-rw-r--r--lib/pleroma/web/templates/layout/email.html.eex4
-rw-r--r--lib/pleroma/web/templates/mailer/subscription/unsubscribe_failure.html.eex2
-rw-r--r--lib/pleroma/web/templates/mailer/subscription/unsubscribe_success.html.eex2
-rw-r--r--lib/pleroma/web/templates/o_auth/mfa/recovery.html.eex8
-rw-r--r--lib/pleroma/web/templates/o_auth/mfa/totp.html.eex8
-rw-r--r--lib/pleroma/web/templates/o_auth/o_auth/_scopes.html.eex2
-rw-r--r--lib/pleroma/web/templates/o_auth/o_auth/consumer.html.eex4
-rw-r--r--lib/pleroma/web/templates/o_auth/o_auth/oob_authorization_created.html.eex4
-rw-r--r--lib/pleroma/web/templates/o_auth/o_auth/oob_token_exists.html.eex4
-rw-r--r--lib/pleroma/web/templates/o_auth/o_auth/register.html.eex18
-rw-r--r--lib/pleroma/web/templates/o_auth/o_auth/show.html.eex20
-rw-r--r--lib/pleroma/web/templates/static_fe/static_fe/profile.html.eex2
-rw-r--r--lib/pleroma/web/templates/twitter_api/password/invalid_token.html.eex2
-rw-r--r--lib/pleroma/web/templates/twitter_api/password/reset.html.eex6
-rw-r--r--lib/pleroma/web/templates/twitter_api/password/reset_failed.html.eex8
-rw-r--r--lib/pleroma/web/templates/twitter_api/password/reset_success.html.eex4
-rw-r--r--lib/pleroma/web/templates/twitter_api/remote_follow/follow.html.eex6
-rw-r--r--lib/pleroma/web/templates/twitter_api/remote_follow/follow_login.html.eex8
-rw-r--r--lib/pleroma/web/templates/twitter_api/remote_follow/follow_mfa.html.eex6
-rw-r--r--lib/pleroma/web/templates/twitter_api/remote_follow/followed.html.eex5
-rw-r--r--lib/pleroma/web/templates/twitter_api/util/subscribe.html.eex8
-rw-r--r--lib/pleroma/web/twitter_api/twitter_api.ex6
-rw-r--r--lib/pleroma/web/twitter_api/views/password_view.ex1
-rw-r--r--lib/pleroma/web/twitter_api/views/remote_follow_view.ex1
-rw-r--r--lib/pleroma/web/twitter_api/views/util_view.ex1
-rw-r--r--lib/pleroma/web/views/email_view.ex1
-rw-r--r--lib/pleroma/web/views/mailer/subscription_view.ex1
50 files changed, 837 insertions, 98 deletions
diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
index 20f8bbc2d..b8f63d69d 100644
--- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
@@ -84,6 +84,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
user <- Map.get(assigns, :user, nil),
{_, true} <- {:visible?, Visibility.visible_for_user?(object, user)} do
conn
+ |> maybe_skip_cache(user)
|> assign(:tracking_fun_data, object.id)
|> set_cache_ttl_for(object)
|> put_resp_content_type("application/activity+json")
@@ -112,6 +113,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
user <- Map.get(assigns, :user, nil),
{_, true} <- {:visible?, Visibility.visible_for_user?(activity, user)} do
conn
+ |> maybe_skip_cache(user)
|> maybe_set_tracking_data(activity)
|> set_cache_ttl_for(activity)
|> put_resp_content_type("application/activity+json")
@@ -151,6 +153,15 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
assign(conn, :cache_ttl, ttl)
end
+ def maybe_skip_cache(conn, user) do
+ if user do
+ conn
+ |> assign(:skip_cache, true)
+ else
+ conn
+ end
+ end
+
# GET /relay/following
def relay_following(conn, _params) do
with %{halted: false} = conn <- FederatingPlug.call(conn, []) do
diff --git a/lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex b/lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex
index 605ca9971..97d75ecf2 100644
--- a/lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex
@@ -24,7 +24,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicy do
defp score_displayname("fedibot"), do: 1.0
defp score_displayname(_), do: 0.0
- defp determine_if_followbot(%User{nickname: nickname, name: displayname}) do
+ defp determine_if_followbot(%User{nickname: nickname, name: displayname, actor_type: actor_type}) do
# nickname will be a binary string except when following a relay
nick_score =
if is_binary(nickname) do
@@ -45,19 +45,32 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicy do
0.0
end
- nick_score + name_score
+ # actor_type "Service" is a Bot account
+ actor_type_score =
+ if actor_type == "Service" do
+ 1.0
+ else
+ 0.0
+ end
+
+ nick_score + name_score + actor_type_score
end
defp determine_if_followbot(_), do: 0.0
+ defp bot_allowed?(%{"object" => target}, bot_actor) do
+ %User{} = user = normalize_by_ap_id(target)
+
+ User.following?(user, bot_actor)
+ end
+
@impl true
def filter(%{"type" => "Follow", "actor" => actor_id} = message) do
%User{} = actor = normalize_by_ap_id(actor_id)
score = determine_if_followbot(actor)
- # TODO: scan biography data for keywords and score it somehow.
- if score < 0.8 do
+ if score < 0.8 || bot_allowed?(message, actor) do
{:ok, message}
else
{:reject, "[AntiFollowbotPolicy] Scored #{actor_id} as #{score}"}
diff --git a/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex b/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex
index 06305235e..f66c379b5 100644
--- a/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex
@@ -12,6 +12,14 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy do
defp accept_host?(host), do: host in Config.get([:mrf_steal_emoji, :hosts], [])
+ defp shortcode_matches?(shortcode, pattern) when is_binary(pattern) do
+ shortcode == pattern
+ end
+
+ defp shortcode_matches?(shortcode, pattern) do
+ String.match?(shortcode, pattern)
+ end
+
defp steal_emoji({shortcode, url}, emoji_dir_path) do
url = Pleroma.Web.MediaProxy.url(url)
@@ -72,7 +80,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy do
reject_emoji? =
[:mrf_steal_emoji, :rejected_shortcodes]
|> Config.get([])
- |> Enum.find(false, fn regex -> String.match?(shortcode, regex) end)
+ |> Enum.find(false, fn pattern -> shortcode_matches?(shortcode, pattern) end)
!reject_emoji?
end)
@@ -122,8 +130,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy do
%{
key: :rejected_shortcodes,
type: {:list, :string},
- description: "Regex-list of shortcodes to reject",
- suggestions: [""]
+ description: """
+ A list of patterns or matches to reject shortcodes with.
+
+ Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
+ """,
+ suggestions: ["foo", ~r/foo/]
},
%{
key: :size_limit,
diff --git a/lib/pleroma/web/admin_api/controllers/announcement_controller.ex b/lib/pleroma/web/admin_api/controllers/announcement_controller.ex
new file mode 100644
index 000000000..6ad5fc12c
--- /dev/null
+++ b/lib/pleroma/web/admin_api/controllers/announcement_controller.ex
@@ -0,0 +1,83 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.AdminAPI.AnnouncementController do
+ use Pleroma.Web, :controller
+
+ alias Pleroma.Announcement
+ alias Pleroma.Web.ControllerHelper
+ alias Pleroma.Web.Plugs.OAuthScopesPlug
+
+ plug(Pleroma.Web.ApiSpec.CastAndValidate)
+ plug(OAuthScopesPlug, %{scopes: ["admin:write"]} when action in [:create, :delete, :change])
+ plug(OAuthScopesPlug, %{scopes: ["admin:read"]} when action in [:index, :show])
+ action_fallback(Pleroma.Web.AdminAPI.FallbackController)
+
+ defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.AnnouncementOperation
+
+ defp default_limit, do: 20
+
+ def index(conn, params) do
+ limit = Map.get(params, :limit, default_limit())
+ offset = Map.get(params, :offset, 0)
+
+ announcements = Announcement.list_paginated(%{limit: limit, offset: offset})
+
+ render(conn, "index.json", announcements: announcements)
+ end
+
+ def show(conn, %{id: id} = _params) do
+ announcement = Announcement.get_by_id(id)
+
+ if is_nil(announcement) do
+ {:error, :not_found}
+ else
+ render(conn, "show.json", announcement: announcement)
+ end
+ end
+
+ def create(%{body_params: params} = conn, _params) do
+ with {:ok, announcement} <- Announcement.add(change_params(params)) do
+ render(conn, "show.json", announcement: announcement)
+ else
+ _ ->
+ {:error, 400}
+ end
+ end
+
+ def change_params(orig_params) do
+ data =
+ %{}
+ |> Pleroma.Maps.put_if_present("content", orig_params, &Map.fetch(&1, :content))
+ |> Pleroma.Maps.put_if_present("all_day", orig_params, &Map.fetch(&1, :all_day))
+
+ orig_params
+ |> Map.merge(%{data: data})
+ end
+
+ def change(%{body_params: params} = conn, %{id: id} = _params) do
+ with announcement <- Announcement.get_by_id(id),
+ {:exists, true} <- {:exists, not is_nil(announcement)},
+ {:ok, announcement} <- Announcement.update(announcement, change_params(params)) do
+ render(conn, "show.json", announcement: announcement)
+ else
+ {:exists, false} ->
+ {:error, :not_found}
+
+ _ ->
+ {:error, 400}
+ end
+ end
+
+ def delete(conn, %{id: id} = _params) do
+ case Announcement.delete_by_id(id) do
+ :ok ->
+ conn
+ |> ControllerHelper.json_response(:ok, %{})
+
+ _ ->
+ {:error, :not_found}
+ end
+ end
+end
diff --git a/lib/pleroma/web/admin_api/views/announcement_view.ex b/lib/pleroma/web/admin_api/views/announcement_view.ex
new file mode 100644
index 000000000..a35bd60cf
--- /dev/null
+++ b/lib/pleroma/web/admin_api/views/announcement_view.ex
@@ -0,0 +1,15 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.AdminAPI.AnnouncementView do
+ use Pleroma.Web, :view
+
+ def render("index.json", %{announcements: announcements}) do
+ render_many(announcements, __MODULE__, "show.json")
+ end
+
+ def render("show.json", %{announcement: announcement}) do
+ Pleroma.Announcement.render_json(announcement, admin: true)
+ end
+end
diff --git a/lib/pleroma/web/api_spec/operations/account_operation.ex b/lib/pleroma/web/api_spec/operations/account_operation.ex
index 026e92c5d..a64762285 100644
--- a/lib/pleroma/web/api_spec/operations/account_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/account_operation.ex
@@ -549,6 +549,11 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
nullable: true,
description: "User's birthday",
format: :date
+ },
+ language: %Schema{
+ type: :string,
+ nullable: true,
+ description: "User's preferred language for emails"
}
},
example: %{
diff --git a/lib/pleroma/web/api_spec/operations/admin/announcement_operation.ex b/lib/pleroma/web/api_spec/operations/admin/announcement_operation.ex
new file mode 100644
index 000000000..58a039e72
--- /dev/null
+++ b/lib/pleroma/web/api_spec/operations/admin/announcement_operation.ex
@@ -0,0 +1,165 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ApiSpec.Admin.AnnouncementOperation do
+ alias OpenApiSpex.Operation
+ alias OpenApiSpex.Schema
+ alias Pleroma.Web.ApiSpec.Schemas.Announcement
+ alias Pleroma.Web.ApiSpec.Schemas.ApiError
+
+ import Pleroma.Web.ApiSpec.Helpers
+
+ def open_api_operation(action) do
+ operation = String.to_existing_atom("#{action}_operation")
+ apply(__MODULE__, operation, [])
+ end
+
+ def index_operation do
+ %Operation{
+ tags: ["Announcement managment"],
+ summary: "Retrieve a list of announcements",
+ operationId: "AdminAPI.AnnouncementController.index",
+ security: [%{"oAuth" => ["admin:read"]}],
+ parameters: [
+ Operation.parameter(
+ :limit,
+ :query,
+ %Schema{type: :integer, minimum: 1},
+ "the maximum number of announcements to return"
+ ),
+ Operation.parameter(
+ :offset,
+ :query,
+ %Schema{type: :integer, minimum: 0},
+ "the offset of the first announcement to return"
+ )
+ | admin_api_params()
+ ],
+ responses: %{
+ 200 => Operation.response("Response", "application/json", list_of_announcements()),
+ 400 => Operation.response("Forbidden", "application/json", ApiError),
+ 403 => Operation.response("Forbidden", "application/json", ApiError)
+ }
+ }
+ end
+
+ def show_operation do
+ %Operation{
+ tags: ["Announcement managment"],
+ summary: "Display one announcement",
+ operationId: "AdminAPI.AnnouncementController.show",
+ security: [%{"oAuth" => ["admin:read"]}],
+ parameters: [
+ Operation.parameter(
+ :id,
+ :path,
+ :string,
+ "announcement id"
+ )
+ | admin_api_params()
+ ],
+ responses: %{
+ 200 => Operation.response("Response", "application/json", Announcement),
+ 403 => Operation.response("Forbidden", "application/json", ApiError),
+ 404 => Operation.response("Not Found", "application/json", ApiError)
+ }
+ }
+ end
+
+ def delete_operation do
+ %Operation{
+ tags: ["Announcement managment"],
+ summary: "Delete one announcement",
+ operationId: "AdminAPI.AnnouncementController.delete",
+ security: [%{"oAuth" => ["admin:write"]}],
+ parameters: [
+ Operation.parameter(
+ :id,
+ :path,
+ :string,
+ "announcement id"
+ )
+ | admin_api_params()
+ ],
+ responses: %{
+ 200 => Operation.response("Response", "application/json", %Schema{type: :object}),
+ 403 => Operation.response("Forbidden", "application/json", ApiError),
+ 404 => Operation.response("Not Found", "application/json", ApiError)
+ }
+ }
+ end
+
+ def create_operation do
+ %Operation{
+ tags: ["Announcement managment"],
+ summary: "Create one announcement",
+ operationId: "AdminAPI.AnnouncementController.create",
+ security: [%{"oAuth" => ["admin:write"]}],
+ requestBody: request_body("Parameters", create_request(), required: true),
+ responses: %{
+ 200 => Operation.response("Response", "application/json", Announcement),
+ 400 => Operation.response("Bad Request", "application/json", ApiError),
+ 403 => Operation.response("Forbidden", "application/json", ApiError)
+ }
+ }
+ end
+
+ def change_operation do
+ %Operation{
+ tags: ["Announcement managment"],
+ summary: "Change one announcement",
+ operationId: "AdminAPI.AnnouncementController.change",
+ security: [%{"oAuth" => ["admin:write"]}],
+ parameters: [
+ Operation.parameter(
+ :id,
+ :path,
+ :string,
+ "announcement id"
+ )
+ | admin_api_params()
+ ],
+ requestBody: request_body("Parameters", change_request(), required: true),
+ responses: %{
+ 200 => Operation.response("Response", "application/json", Announcement),
+ 400 => Operation.response("Bad Request", "application/json", ApiError),
+ 403 => Operation.response("Forbidden", "application/json", ApiError),
+ 404 => Operation.response("Not Found", "application/json", ApiError)
+ }
+ }
+ end
+
+ defp create_or_change_props do
+ %{
+ content: %Schema{type: :string},
+ starts_at: %Schema{type: :string, format: "date-time", nullable: true},
+ ends_at: %Schema{type: :string, format: "date-time", nullable: true},
+ all_day: %Schema{type: :boolean}
+ }
+ end
+
+ def create_request do
+ %Schema{
+ title: "AnnouncementCreateRequest",
+ type: :object,
+ required: [:content],
+ properties: create_or_change_props()
+ }
+ end
+
+ def change_request do
+ %Schema{
+ title: "AnnouncementChangeRequest",
+ type: :object,
+ properties: create_or_change_props()
+ }
+ end
+
+ def list_of_announcements do
+ %Schema{
+ type: :array,
+ items: Announcement
+ }
+ end
+end
diff --git a/lib/pleroma/web/api_spec/operations/announcement_operation.ex b/lib/pleroma/web/api_spec/operations/announcement_operation.ex
new file mode 100644
index 000000000..71be0002a
--- /dev/null
+++ b/lib/pleroma/web/api_spec/operations/announcement_operation.ex
@@ -0,0 +1,57 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ApiSpec.AnnouncementOperation do
+ alias OpenApiSpex.Operation
+ alias OpenApiSpex.Schema
+ alias Pleroma.Web.ApiSpec.Schemas.Announcement
+ alias Pleroma.Web.ApiSpec.Schemas.ApiError
+
+ def open_api_operation(action) do
+ operation = String.to_existing_atom("#{action}_operation")
+ apply(__MODULE__, operation, [])
+ end
+
+ def index_operation do
+ %Operation{
+ tags: ["Announcement"],
+ summary: "Retrieve a list of announcements",
+ operationId: "MastodonAPI.AnnouncementController.index",
+ security: [%{"oAuth" => []}],
+ responses: %{
+ 200 => Operation.response("Response", "application/json", list_of_announcements()),
+ 403 => Operation.response("Forbidden", "application/json", ApiError)
+ }
+ }
+ end
+
+ def mark_read_operation do
+ %Operation{
+ tags: ["Announcement"],
+ summary: "Mark one announcement as read",
+ operationId: "MastodonAPI.AnnouncementController.mark_read",
+ security: [%{"oAuth" => ["write:accounts"]}],
+ parameters: [
+ Operation.parameter(
+ :id,
+ :path,
+ :string,
+ "announcement id"
+ )
+ ],
+ responses: %{
+ 200 => Operation.response("Response", "application/json", %Schema{type: :object}),
+ 403 => Operation.response("Forbidden", "application/json", ApiError),
+ 404 => Operation.response("Not Found", "application/json", ApiError)
+ }
+ }
+ end
+
+ def list_of_announcements do
+ %Schema{
+ type: :array,
+ items: Announcement
+ }
+ end
+end
diff --git a/lib/pleroma/web/api_spec/schemas/announcement.ex b/lib/pleroma/web/api_spec/schemas/announcement.ex
new file mode 100644
index 000000000..67d129ef6
--- /dev/null
+++ b/lib/pleroma/web/api_spec/schemas/announcement.ex
@@ -0,0 +1,45 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ApiSpec.Schemas.Announcement do
+ alias OpenApiSpex.Schema
+ alias Pleroma.Web.ApiSpec.Schemas.FlakeID
+
+ require OpenApiSpex
+
+ OpenApiSpex.schema(%{
+ title: "Announcement",
+ description: "Response schema for an announcement",
+ type: :object,
+ properties: %{
+ id: FlakeID,
+ content: %Schema{type: :string},
+ starts_at: %Schema{
+ type: :string,
+ format: "date-time",
+ nullable: true
+ },
+ ends_at: %Schema{
+ type: :string,
+ format: "date-time",
+ nullable: true
+ },
+ all_day: %Schema{type: :boolean},
+ published_at: %Schema{type: :string, format: "date-time"},
+ updated_at: %Schema{type: :string, format: "date-time"},
+ read: %Schema{type: :boolean},
+ mentions: %Schema{type: :array},
+ statuses: %Schema{type: :array},
+ tags: %Schema{type: :array},
+ emojis: %Schema{type: :array},
+ reactions: %Schema{type: :array},
+ pleroma: %Schema{
+ type: :object,
+ properties: %{
+ raw_content: %Schema{type: :string}
+ }
+ }
+ }
+ })
+end
diff --git a/lib/pleroma/web/feed/feed_view.ex b/lib/pleroma/web/feed/feed_view.ex
index eb80043f6..35a5f9482 100644
--- a/lib/pleroma/web/feed/feed_view.ex
+++ b/lib/pleroma/web/feed/feed_view.ex
@@ -9,6 +9,7 @@ defmodule Pleroma.Web.Feed.FeedView do
alias Pleroma.Formatter
alias Pleroma.Object
alias Pleroma.User
+ alias Pleroma.Web.Gettext
alias Pleroma.Web.MediaProxy
require Pleroma.Constants
diff --git a/lib/pleroma/web/gettext.ex b/lib/pleroma/web/gettext.ex
index 3771c316d..5ef49d841 100644
--- a/lib/pleroma/web/gettext.ex
+++ b/lib/pleroma/web/gettext.ex
@@ -25,4 +25,196 @@ defmodule Pleroma.Web.Gettext do
See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage.
"""
use Gettext, otp_app: :pleroma
+
+ def language_tag do
+ # Naive implementation: HTML lang attribute uses BCP 47, which
+ # uses - as a separator.
+ # https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang
+
+ Gettext.get_locale()
+ |> String.replace("_", "-", global: true)
+ end
+
+ def normalize_locale(locale) do
+ if is_binary(locale) do
+ String.replace(locale, "-", "_", global: true)
+ else
+ nil
+ end
+ end
+
+ def supports_locale?(locale) do
+ Pleroma.Web.Gettext
+ |> Gettext.known_locales()
+ |> Enum.member?(locale)
+ end
+
+ def variant?(locale), do: String.contains?(locale, "_")
+
+ def language_for_variant(locale) do
+ Enum.at(String.split(locale, "_"), 0)
+ end
+
+ def ensure_fallbacks(locales) do
+ locales
+ |> Enum.flat_map(fn locale ->
+ others =
+ other_supported_variants_of_locale(locale)
+ |> Enum.filter(fn l -> not Enum.member?(locales, l) end)
+
+ [locale] ++ others
+ end)
+ end
+
+ def other_supported_variants_of_locale(locale) do
+ cond do
+ supports_locale?(locale) ->
+ []
+
+ variant?(locale) ->
+ lang = language_for_variant(locale)
+ if supports_locale?(lang), do: [lang], else: []
+
+ true ->
+ Gettext.known_locales(Pleroma.Web.Gettext)
+ |> Enum.filter(fn l -> String.starts_with?(l, locale <> "_") end)
+ end
+ end
+
+ def get_locales do
+ Process.get({Pleroma.Web.Gettext, :locales}, [])
+ end
+
+ def is_locale_list(locales) do
+ Enum.all?(locales, &is_binary/1)
+ end
+
+ def put_locales(locales) do
+ if is_locale_list(locales) do
+ Process.put({Pleroma.Web.Gettext, :locales}, Enum.uniq(locales))
+ Gettext.put_locale(Enum.at(locales, 0, Gettext.get_locale()))
+ :ok
+ else
+ {:error, :not_locale_list}
+ end
+ end
+
+ def locale_or_default(locale) do
+ if supports_locale?(locale) do
+ locale
+ else
+ Gettext.get_locale()
+ end
+ end
+
+ def with_locales_func(locales, fun) do
+ prev_locales = Process.get({Pleroma.Web.Gettext, :locales})
+ put_locales(locales)
+
+ try do
+ fun.()
+ after
+ if prev_locales do
+ put_locales(prev_locales)
+ else
+ Process.delete({Pleroma.Web.Gettext, :locales})
+ Process.delete(Gettext)
+ end
+ end
+ end
+
+ defmacro with_locales(locales, do: fun) do
+ quote do
+ Pleroma.Web.Gettext.with_locales_func(unquote(locales), fn ->
+ unquote(fun)
+ end)
+ end
+ end
+
+ def to_locale_list(locale) when is_binary(locale) do
+ locale
+ |> String.split(",")
+ |> Enum.filter(&supports_locale?/1)
+ end
+
+ def to_locale_list(_), do: []
+
+ defmacro with_locale_or_default(locale, do: fun) do
+ quote do
+ Pleroma.Web.Gettext.with_locales_func(
+ Pleroma.Web.Gettext.to_locale_list(unquote(locale))
+ |> Enum.concat(Pleroma.Web.Gettext.get_locales()),
+ fn ->
+ unquote(fun)
+ end
+ )
+ end
+ end
+
+ defp next_locale(locale, list) do
+ index = Enum.find_index(list, fn item -> item == locale end)
+
+ if not is_nil(index) do
+ Enum.at(list, index + 1)
+ else
+ nil
+ end
+ end
+
+ # We do not yet have a proper English translation. The "English"
+ # version is currently but the fallback msgid. However, this
+ # will not work if the user puts English as the first language,
+ # and at the same time specifies other languages, as gettext will
+ # think the English translation is missing, and call
+ # handle_missing_translation functions. This may result in
+ # text in other languages being shown even if English is preferred
+ # by the user.
+ #
+ # To prevent this, we do not allow fallbacking when the current
+ # locale missing a translation is English.
+ defp should_fallback?(locale) do
+ locale != "en"
+ end
+
+ def handle_missing_translation(locale, domain, msgctxt, msgid, bindings) do
+ next = next_locale(locale, get_locales())
+
+ if is_nil(next) or not should_fallback?(locale) do
+ super(locale, domain, msgctxt, msgid, bindings)
+ else
+ {:ok,
+ Gettext.with_locale(next, fn ->
+ Gettext.dpgettext(Pleroma.Web.Gettext, domain, msgctxt, msgid, bindings)
+ end)}
+ end
+ end
+
+ def handle_missing_plural_translation(
+ locale,
+ domain,
+ msgctxt,
+ msgid,
+ msgid_plural,
+ n,
+ bindings
+ ) do
+ next = next_locale(locale, get_locales())
+
+ if is_nil(next) or not should_fallback?(locale) do
+ super(locale, domain, msgctxt, msgid, msgid_plural, n, bindings)
+ else
+ {:ok,
+ Gettext.with_locale(next, fn ->
+ Gettext.dpngettext(
+ Pleroma.Web.Gettext,
+ domain,
+ msgctxt,
+ msgid,
+ msgid_plural,
+ n,
+ bindings
+ )
+ end)}
+ end
+ end
end
diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
index f15305f9c..50c12a1b1 100644
--- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
@@ -221,6 +221,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
# Note: param name is indeed :discoverable (not an error)
|> Maps.put_if_present(:is_discoverable, params[:discoverable])
|> Maps.put_if_present(:birthday, params[:birthday])
+ |> Maps.put_if_present(:language, Pleroma.Web.Gettext.normalize_locale(params[:language]))
# What happens here:
#
diff --git a/lib/pleroma/web/mastodon_api/controllers/announcement_controller.ex b/lib/pleroma/web/mastodon_api/controllers/announcement_controller.ex
new file mode 100644
index 000000000..080af96d5
--- /dev/null
+++ b/lib/pleroma/web/mastodon_api/controllers/announcement_controller.ex
@@ -0,0 +1,60 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.MastodonAPI.AnnouncementController do
+ use Pleroma.Web, :controller
+
+ import Pleroma.Web.ControllerHelper,
+ only: [
+ json_response: 3
+ ]
+
+ alias Pleroma.Announcement
+ alias Pleroma.Web.Plugs.OAuthScopesPlug
+
+ plug(Pleroma.Web.ApiSpec.CastAndValidate)
+
+ # Mastodon docs say this only requires a user token, no scopes needed
+ # As the op `|` requires at least one scope to be present, we use `&` here.
+ plug(
+ OAuthScopesPlug,
+ %{scopes: [], op: :&}
+ when action in [:index]
+ )
+
+ # Same as in MastodonAPI specs
+ plug(
+ OAuthScopesPlug,
+ %{scopes: ["write:accounts"]}
+ when action in [:mark_read]
+ )
+
+ action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
+
+ defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.AnnouncementOperation
+
+ @doc "GET /api/v1/announcements"
+ def index(%{assigns: %{user: user}} = conn, _params) do
+ render(conn, "index.json", announcements: all_visible(), user: user)
+ end
+
+ def index(conn, _params) do
+ render(conn, "index.json", announcements: all_visible(), user: nil)
+ end
+
+ defp all_visible do
+ Announcement.list_all_visible()
+ end
+
+ @doc "POST /api/v1/announcements/:id/dismiss"
+ def mark_read(%{assigns: %{user: user}} = conn, %{id: id} = _params) do
+ with announcement when not is_nil(announcement) <- Announcement.get_by_id(id),
+ {:ok, _} <- Announcement.mark_read_by(announcement, user) do
+ json_response(conn, :ok, %{})
+ else
+ _ ->
+ {:error, :not_found}
+ end
+ end
+end
diff --git a/lib/pleroma/web/mastodon_api/views/announcement_view.ex b/lib/pleroma/web/mastodon_api/views/announcement_view.ex
new file mode 100644
index 000000000..93fdfb1f1
--- /dev/null
+++ b/lib/pleroma/web/mastodon_api/views/announcement_view.ex
@@ -0,0 +1,15 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.MastodonAPI.AnnouncementView do
+ use Pleroma.Web, :view
+
+ def render("index.json", %{announcements: announcements, user: user}) do
+ render_many(announcements, __MODULE__, "show.json", user: user)
+ end
+
+ def render("show.json", %{announcement: announcement, user: user}) do
+ Pleroma.Announcement.render_json(announcement, for: user)
+ end
+end
diff --git a/lib/pleroma/web/o_auth/mfa_view.ex b/lib/pleroma/web/o_auth/mfa_view.ex
index e6b142ac0..bcadafe57 100644
--- a/lib/pleroma/web/o_auth/mfa_view.ex
+++ b/lib/pleroma/web/o_auth/mfa_view.ex
@@ -6,6 +6,7 @@ defmodule Pleroma.Web.OAuth.MFAView do
use Pleroma.Web, :view
import Phoenix.HTML.Form
alias Pleroma.MFA
+ alias Pleroma.Web.Gettext
def render("mfa_response.json", %{token: token, user: user}) do
%{
diff --git a/lib/pleroma/web/o_auth/o_auth_view.ex b/lib/pleroma/web/o_auth/o_auth_view.ex
index 6f006b72b..108102ce2 100644
--- a/lib/pleroma/web/o_auth/o_auth_view.ex
+++ b/lib/pleroma/web/o_auth/o_auth_view.ex
@@ -5,6 +5,8 @@
defmodule Pleroma.Web.OAuth.OAuthView do
use Pleroma.Web, :view
import Phoenix.HTML.Form
+ import Phoenix.HTML
+ alias Pleroma.Web.Gettext
alias Pleroma.Web.OAuth.Token.Utils
diff --git a/lib/pleroma/web/plugs/cache.ex b/lib/pleroma/web/plugs/cache.ex
index e2cf5759d..667477857 100644
--- a/lib/pleroma/web/plugs/cache.ex
+++ b/lib/pleroma/web/plugs/cache.ex
@@ -97,13 +97,21 @@ defmodule Pleroma.Web.Plugs.Cache do
key = cache_key(conn, opts)
content_type = content_type(conn)
+ should_cache = not Map.get(conn.assigns, :skip_cache, false)
+
conn =
unless opts[:tracking_fun] do
- @cachex.put(:web_resp_cache, key, {content_type, body}, ttl: ttl)
+ if should_cache do
+ @cachex.put(:web_resp_cache, key, {content_type, body}, ttl: ttl)
+ end
+
conn
else
tracking_fun_data = Map.get(conn.assigns, :tracking_fun_data, nil)
- @cachex.put(:web_resp_cache, key, {content_type, body, tracking_fun_data}, ttl: ttl)
+
+ if should_cache do
+ @cachex.put(:web_resp_cache, key, {content_type, body, tracking_fun_data}, ttl: ttl)
+ end
opts.tracking_fun.(conn, tracking_fun_data)
end
diff --git a/lib/pleroma/web/plugs/set_locale_plug.ex b/lib/pleroma/web/plugs/set_locale_plug.ex
index 850a9b3bc..271912ace 100644
--- a/lib/pleroma/web/plugs/set_locale_plug.ex
+++ b/lib/pleroma/web/plugs/set_locale_plug.ex
@@ -6,18 +6,56 @@
defmodule Pleroma.Web.Plugs.SetLocalePlug do
import Plug.Conn, only: [get_req_header: 2, assign: 3]
+ def frontend_language_cookie_name, do: "userLanguage"
+
def init(_), do: nil
def call(conn, _) do
- locale = get_locale_from_header(conn) || Gettext.get_locale()
- Gettext.put_locale(locale)
- assign(conn, :locale, locale)
+ locales = get_locales_from_header(conn)
+ first_locale = Enum.at(locales, 0, Gettext.get_locale())
+
+ Pleroma.Web.Gettext.put_locales(locales)
+
+ conn
+ |> assign(:locale, first_locale)
+ |> assign(:locales, locales)
end
- defp get_locale_from_header(conn) do
+ defp get_locales_from_header(conn) do
conn
- |> extract_accept_language()
- |> Enum.find(&supported_locale?/1)
+ |> extract_preferred_language()
+ |> normalize_language_codes()
+ |> all_supported()
+ |> Enum.uniq()
+ end
+
+ defp all_supported(locales) do
+ locales
+ |> Pleroma.Web.Gettext.ensure_fallbacks()
+ |> Enum.filter(&supported_locale?/1)
+ end
+
+ defp normalize_language_codes(codes) do
+ codes
+ |> Enum.map(fn code -> Pleroma.Web.Gettext.normalize_locale(code) end)
+ end
+
+ defp extract_preferred_language(conn) do
+ extract_frontend_language(conn) ++ extract_accept_language(conn)
+ end
+
+ defp extract_frontend_language(conn) do
+ %{req_cookies: cookies} =
+ conn
+ |> Plug.Conn.fetch_cookies()
+
+ case cookies[frontend_language_cookie_name()] do
+ nil ->
+ []
+
+ fe_lang ->
+ String.split(fe_lang, ",")
+ end
end
defp extract_accept_language(conn) do
@@ -29,7 +67,6 @@ defmodule Pleroma.Web.Plugs.SetLocalePlug do
|> Enum.sort(&(&1.quality > &2.quality))
|> Enum.map(& &1.tag)
|> Enum.reject(&is_nil/1)
- |> ensure_language_fallbacks()
_ ->
[]
@@ -37,9 +74,7 @@ defmodule Pleroma.Web.Plugs.SetLocalePlug do
end
defp supported_locale?(locale) do
- Pleroma.Web.Gettext
- |> Gettext.known_locales()
- |> Enum.member?(locale)
+ Pleroma.Web.Gettext.supports_locale?(locale)
end
defp parse_language_option(string) do
@@ -53,11 +88,4 @@ defmodule Pleroma.Web.Plugs.SetLocalePlug do
%{tag: captures["tag"], quality: quality}
end
-
- defp ensure_language_fallbacks(tags) do
- Enum.flat_map(tags, fn tag ->
- [language | _] = String.split(tag, "-")
- if Enum.member?(tags, language), do: [tag], else: [tag, language]
- end)
- end
end
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index ceb6c3cfd..7bbc20275 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -229,6 +229,12 @@ defmodule Pleroma.Web.Router do
post("/frontends/install", FrontendController, :install)
post("/backups", AdminAPIController, :create_backup)
+
+ get("/announcements", AnnouncementController, :index)
+ post("/announcements", AnnouncementController, :create)
+ get("/announcements/:id", AnnouncementController, :show)
+ patch("/announcements/:id", AnnouncementController, :change)
+ delete("/announcements/:id", AnnouncementController, :delete)
end
# AdminAPI: admins and mods (staff) can perform these actions (if enabled by config)
@@ -575,6 +581,9 @@ defmodule Pleroma.Web.Router do
get("/timelines/home", TimelineController, :home)
get("/timelines/direct", TimelineController, :direct)
get("/timelines/list/:list_id", TimelineController, :list)
+
+ get("/announcements", AnnouncementController, :index)
+ post("/announcements/:id/dismiss", AnnouncementController, :mark_read)
end
scope "/api/v1", Pleroma.Web.MastodonAPI do
diff --git a/lib/pleroma/web/templates/email/digest.html.eex b/lib/pleroma/web/templates/email/digest.html.eex
index 60eceff22..1efc76e1a 100644
--- a/lib/pleroma/web/templates/email/digest.html.eex
+++ b/lib/pleroma/web/templates/email/digest.html.eex
@@ -160,7 +160,7 @@
<div
style="font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif;line-height: 14px; color: <%= @styling.header_color %>;">
<p style="line-height: 36px; text-align: center; margin: 0;"><span
- style="font-size: 30px; color: <%= @styling.header_color %>;">Hey <%= @user.nickname %>, here is what you've missed!</span></p>
+ style="font-size: 30px; color: <%= @styling.header_color %>;"><%= Gettext.dpgettext("static_pages", "digest email header line", "Hey %{nickname}, here is what you've missed!", nickname: @user.nickname) %></span></p>
</div>
</div>
<!--[if mso]></td></tr></table><![endif]-->
@@ -382,7 +382,7 @@
<div
style="font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; font-size: 12px; line-height: 14px; color: <%= @styling.text_color %>;">
<p style="font-size: 12px; line-height: 24px; text-align: center; margin: 0;"><span
- style="font-size: 20px;"><%= length(@followers) %> New Followers</span><span
+ style="font-size: 20px;"><%= Gettext.dpngettext("static_pages", "new followers count header", "%{count} New Follower", "%{count} New Followers", length(@followers), count: length(@followers)) %></span><span
style="font-size: 20px; line-height: 24px;"></span></p>
</div>
</div>
@@ -535,16 +535,16 @@
style="color:<%= @styling.text_color %>;font-family:Arial, 'Helvetica Neue', Helvetica, sans-serif;line-height:120%;padding-top:10px;padding-right:10px;padding-bottom:10px;padding-left:10px;">
<p
style="font-size: 12px; line-height: 16px; text-align: center; color: <%= @styling.text_color %>; font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; margin: 0;">
- <span style="font-size: 14px;">You have received this email because you have signed up to receive digest emails from <b><%= @instance %></b> Pleroma instance.</span></p>
+ <span style="font-size: 14px;"><%= raw Gettext.dpgettext("static_pages", "digest email sending reason", "You have received this email because you have signed up to receive digest emails from <b>%{instance}</b> Pleroma instance.", instance: safe_to_string(html_escape(@instance))) %></span></p>
<p
style="font-size: 12px; line-height: 14px; text-align: center; color: <%= @styling.text_color %>; font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; margin: 0;">
 </p>
<p
style="font-size: 12px; line-height: 16px; text-align: center; color: <%= @styling.text_color %>; font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; margin: 0;">
- <span style="font-size: 14px;">The email address you are subscribed as is <a href="mailto:<%= @user.email %>" style="color: <%= @styling.link_color %>;text-decoration: none;"><%= @user.email %></a>. </span></p>
+ <span style="font-size: 14px;"><%= raw Gettext.dpgettext("static_pages", "digest email receiver address", "The email address you are subscribed as is <a href='mailto:%{@user.email}' style='color: %{color};text-decoration: none;'>%{email}</a>. ", color: safe_to_string(html_escape(@styling.link_color)), email: safe_to_string(html_escape(@user.email))) %></span></p>
<p
style="font-size: 12px; line-height: 16px; text-align: center; color: <%= @styling.text_color %>; font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; margin: 0;">
- <span style="font-size: 14px;">To unsubscribe, please go <%= link "here", style: "color: #{@styling.link_color};text-decoration: none;", to: @unsubscribe_link %>.</span></p>
+ <span style="font-size: 14px;"><%= raw Gettext.dpgettext("static_pages", "digest email unsubscribe action", "To unsubscribe, please go %{here}.", here: safe_to_string link(Gettext.dpgettext("static_pages", "digest email unsubscribe action link text", "here"), style: "color: #{@styling.link_color};text-decoration: none;", to: @unsubscribe_link)) %></span></p>
</div>
<!--[if mso]></td></tr></table><![endif]-->
<!--[if (!mso)&(!IE)]><!-->
diff --git a/lib/pleroma/web/templates/feed/feed/tag.atom.eex b/lib/pleroma/web/templates/feed/feed/tag.atom.eex
index de0731085..6d497e84c 100644
--- a/lib/pleroma/web/templates/feed/feed/tag.atom.eex
+++ b/lib/pleroma/web/templates/feed/feed/tag.atom.eex
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
-<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom"
+<feed xml:lang="<%= Gettext.language_tag() %>" xmlns="http://www.w3.org/2005/Atom"
xmlns:thr="http://purl.org/syndication/thread/1.0"
xmlns:georss="http://www.georss.org/georss"
xmlns:activity="http://activitystrea.ms/spec/1.0/"
@@ -12,7 +12,7 @@
<id><%= '#{Routes.tag_feed_url(@conn, :feed, @tag)}.rss' %></id>
<title>#<%= @tag %></title>
- <subtitle>These are public toots tagged with #<%= @tag %>. You can interact with them if you have an account anywhere in the fediverse.</subtitle>
+ <subtitle><%= Gettext.dpgettext("static_pages", "tag feed description", "These are public toots tagged with #%{tag}. You can interact with them if you have an account anywhere in the fediverse.", tag: @tag) %></subtitle>
<logo><%= feed_logo() %></logo>
<updated><%= most_recent_update(@activities) %></updated>
<link rel="self" href="<%= '#{Routes.tag_feed_url(@conn, :feed, @tag)}.atom' %>" type="application/atom+xml"/>
diff --git a/lib/pleroma/web/templates/feed/feed/tag.rss.eex b/lib/pleroma/web/templates/feed/feed/tag.rss.eex
index 9c3613feb..edcc3e436 100644
--- a/lib/pleroma/web/templates/feed/feed/tag.rss.eex
+++ b/lib/pleroma/web/templates/feed/feed/tag.rss.eex
@@ -4,7 +4,7 @@
<title>#<%= @tag %></title>
- <description>These are public toots tagged with #<%= @tag %>. You can interact with them if you have an account anywhere in the fediverse.</description>
+ <description><%= Gettext.dpgettext("static_pages", "tag feed description", "These are public toots tagged with #%{tag}. You can interact with them if you have an account anywhere in the fediverse.", tag: @tag) %></description>
<link><%= '#{Routes.tag_feed_url(@conn, :feed, @tag)}.rss' %></link>
<webfeeds:logo><%= feed_logo() %></webfeeds:logo>
<webfeeds:accentColor>2b90d9</webfeeds:accentColor>
diff --git a/lib/pleroma/web/templates/layout/app.html.eex b/lib/pleroma/web/templates/layout/app.html.eex
index 1ede59fd8..e33bada85 100644
--- a/lib/pleroma/web/templates/layout/app.html.eex
+++ b/lib/pleroma/web/templates/layout/app.html.eex
@@ -1,5 +1,5 @@
<!DOCTYPE html>
-<html lang="en">
+<html lang="<%= Pleroma.Web.Gettext.language_tag() %>">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,minimal-ui">
diff --git a/lib/pleroma/web/templates/layout/email.html.eex b/lib/pleroma/web/templates/layout/email.html.eex
index f6dcd7f0f..087aa4fc0 100644
--- a/lib/pleroma/web/templates/layout/email.html.eex
+++ b/lib/pleroma/web/templates/layout/email.html.eex
@@ -1,5 +1,5 @@
<!DOCTYPE html>
-<html lang="en">
+<html lang="<%= Pleroma.Web.Gettext.language_tag() %>">
<head>
<meta charset="utf-8">
<title><%= @email.subject %></title>
@@ -7,4 +7,4 @@
<body>
<%= render @view_module, @view_template, assigns %>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/lib/pleroma/web/templates/mailer/subscription/unsubscribe_failure.html.eex b/lib/pleroma/web/templates/mailer/subscription/unsubscribe_failure.html.eex
index 7b476f02d..df090ffcd 100644
--- a/lib/pleroma/web/templates/mailer/subscription/unsubscribe_failure.html.eex
+++ b/lib/pleroma/web/templates/mailer/subscription/unsubscribe_failure.html.eex
@@ -1 +1 @@
-<h1>UNSUBSCRIBE FAILURE</h1>
+<h1><%= Gettext.dpgettext("static_pages", "mailer unsubscribe failed message", "UNSUBSCRIBE FAILURE") %></h1>
diff --git a/lib/pleroma/web/templates/mailer/subscription/unsubscribe_success.html.eex b/lib/pleroma/web/templates/mailer/subscription/unsubscribe_success.html.eex
index 6dfa2c185..cbce495d4 100644
--- a/lib/pleroma/web/templates/mailer/subscription/unsubscribe_success.html.eex
+++ b/lib/pleroma/web/templates/mailer/subscription/unsubscribe_success.html.eex
@@ -1 +1 @@
-<h1>UNSUBSCRIBE SUCCESSFUL</h1>
+<h1><%= Gettext.dpgettext("static_pages", "mailer unsubscribe successful message", "UNSUBSCRIBE SUCCESSFUL") %></h1>
diff --git a/lib/pleroma/web/templates/o_auth/mfa/recovery.html.eex b/lib/pleroma/web/templates/o_auth/mfa/recovery.html.eex
index b9daa8d8b..e45d13bdf 100644
--- a/lib/pleroma/web/templates/o_auth/mfa/recovery.html.eex
+++ b/lib/pleroma/web/templates/o_auth/mfa/recovery.html.eex
@@ -5,11 +5,11 @@
<p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p>
<% end %>
-<h2>Two-factor recovery</h2>
+<h2><%= Gettext.dpgettext("static_pages", "mfa recover page title", "Two-factor recovery") %></h2>
<%= form_for @conn, Routes.mfa_verify_path(@conn, :verify), [as: "mfa"], fn f -> %>
<div class="input">
- <%= label f, :code, "Recovery code" %>
+ <%= label f, :code, Gettext.dpgettext("static_pages", "mfa recover recovery code prompt", "Recovery code") %>
<%= text_input f, :code, [autocomplete: false, autocorrect: "off", autocapitalize: "off", autofocus: true, spellcheck: false] %>
<%= hidden_input f, :mfa_token, value: @mfa_token %>
<%= hidden_input f, :state, value: @state %>
@@ -17,8 +17,8 @@
<%= hidden_input f, :challenge_type, value: "recovery" %>
</div>
-<%= submit "Verify" %>
+<%= submit Gettext.dpgettext("static_pages", "mfa recover verify recovery code button", "Verify") %>
<% end %>
<a href="<%= Routes.mfa_path(@conn, :show, %{challenge_type: "totp", mfa_token: @mfa_token, state: @state, redirect_uri: @redirect_uri}) %>">
- Enter a two-factor code
+ <%= Gettext.dpgettext("static_pages", "mfa recover use 2fa code link", "Enter a two-factor code") %>
</a>
diff --git a/lib/pleroma/web/templates/o_auth/mfa/totp.html.eex b/lib/pleroma/web/templates/o_auth/mfa/totp.html.eex
index 27600253c..50e6c04b6 100644
--- a/lib/pleroma/web/templates/o_auth/mfa/totp.html.eex
+++ b/lib/pleroma/web/templates/o_auth/mfa/totp.html.eex
@@ -5,11 +5,11 @@
<p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p>
<% end %>
-<h2>Two-factor authentication</h2>
+<h2><%= Gettext.dpgettext("static_pages", "mfa auth page title", "Two-factor authentication") %></h2>
<%= form_for @conn, Routes.mfa_verify_path(@conn, :verify), [as: "mfa"], fn f -> %>
<div class="input">
- <%= label f, :code, "Authentication code" %>
+ <%= label f, :code, Gettext.dpgettext("static_pages", "mfa auth code prompt", "Authentication code") %>
<%= text_input f, :code, [autocomplete: "one-time-code", autocorrect: "off", autocapitalize: "off", autofocus: true, pattern: "[0-9]*", spellcheck: false] %>
<%= hidden_input f, :mfa_token, value: @mfa_token %>
<%= hidden_input f, :state, value: @state %>
@@ -17,8 +17,8 @@
<%= hidden_input f, :challenge_type, value: "totp" %>
</div>
-<%= submit "Verify" %>
+<%= submit Gettext.dpgettext("static_pages", "mfa auth verify code button", "Verify") %>
<% end %>
<a href="<%= Routes.mfa_path(@conn, :show, %{challenge_type: "recovery", mfa_token: @mfa_token, state: @state, redirect_uri: @redirect_uri}) %>">
- Enter a two-factor recovery code
+ <%= Gettext.dpgettext("static_pages", "mfa auth page use recovery code link", "Enter a two-factor recovery code") %>
</a>
diff --git a/lib/pleroma/web/templates/o_auth/o_auth/_scopes.html.eex b/lib/pleroma/web/templates/o_auth/o_auth/_scopes.html.eex
index c9ec1ecbf..73115e92a 100644
--- a/lib/pleroma/web/templates/o_auth/o_auth/_scopes.html.eex
+++ b/lib/pleroma/web/templates/o_auth/o_auth/_scopes.html.eex
@@ -1,5 +1,5 @@
<div class="scopes-input">
- <%= label @form, :scope, "The following permissions will be granted" %>
+ <%= label @form, :scope, Gettext.dpgettext("static_pages", "oauth scopes message", "The following permissions will be granted") %>
<div class="scopes">
<%= for scope <- @available_scopes do %>
<%# Note: using hidden input with `unchecked_value` in order to distinguish user's empty selection from `scope` param being omitted %>
diff --git a/lib/pleroma/web/templates/o_auth/o_auth/consumer.html.eex b/lib/pleroma/web/templates/o_auth/o_auth/consumer.html.eex
index dc4521a62..8b894cd58 100644
--- a/lib/pleroma/web/templates/o_auth/o_auth/consumer.html.eex
+++ b/lib/pleroma/web/templates/o_auth/o_auth/consumer.html.eex
@@ -1,4 +1,4 @@
-<h2>Sign in with external provider</h2>
+<h2><%= Gettext.dpgettext("static_pages", "oauth external provider page title", "Sign in with external provider") %></h2>
<%= form_for @conn, Routes.o_auth_path(@conn, :prepare_request), [as: "authorization", method: "get"], fn f -> %>
<div style="display: none">
@@ -10,6 +10,6 @@
<%= hidden_input f, :state, value: @state %>
<%= for strategy <- Pleroma.Config.oauth_consumer_strategies() do %>
- <%= submit "Sign in with #{String.capitalize(strategy)}", name: "provider", value: strategy %>
+ <%= submit Gettext.dpgettext("static_pages", "oauth external provider sign in button", "Sign in with %{strategy}", strategy: String.capitalize(strategy)), name: "provider", value: strategy %>
<% end %>
<% end %>
diff --git a/lib/pleroma/web/templates/o_auth/o_auth/oob_authorization_created.html.eex b/lib/pleroma/web/templates/o_auth/o_auth/oob_authorization_created.html.eex
index ffabe29a6..76ed3fda5 100644
--- a/lib/pleroma/web/templates/o_auth/o_auth/oob_authorization_created.html.eex
+++ b/lib/pleroma/web/templates/o_auth/o_auth/oob_authorization_created.html.eex
@@ -1,2 +1,2 @@
-<h1>Successfully authorized</h1>
-<h2>Token code is <br><%= @auth.token %></h2>
+<h1><%= Gettext.dpgettext("static_pages", "oauth authorized page title", "Successfully authorized") %></h1>
+<h2><%= raw Gettext.dpgettext("static_pages", "oauth token code message", "Token code is <br>%{token}", token: safe_to_string(html_escape(@auth.token))) %></h2>
diff --git a/lib/pleroma/web/templates/o_auth/o_auth/oob_token_exists.html.eex b/lib/pleroma/web/templates/o_auth/o_auth/oob_token_exists.html.eex
index 82785c4b9..754bf2eb0 100644
--- a/lib/pleroma/web/templates/o_auth/o_auth/oob_token_exists.html.eex
+++ b/lib/pleroma/web/templates/o_auth/o_auth/oob_token_exists.html.eex
@@ -1,2 +1,2 @@
-<h1>Authorization exists</h1>
-<h2>Access token is <br><%= @token.token %></h2>
+<h1><%= Gettext.dpgettext("static_pages", "oauth authorization exists page title", "Authorization exists") %></h1>
+<h2><%= raw Gettext.dpgettext("static_pages", "oauth token code message", "Token code is <br>%{token}", token: safe_to_string(html_escape(@token.token))) %></h2>
diff --git a/lib/pleroma/web/templates/o_auth/o_auth/register.html.eex b/lib/pleroma/web/templates/o_auth/o_auth/register.html.eex
index 3ac428b2f..1f661efb2 100644
--- a/lib/pleroma/web/templates/o_auth/o_auth/register.html.eex
+++ b/lib/pleroma/web/templates/o_auth/o_auth/register.html.eex
@@ -5,34 +5,34 @@
<p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p>
<% end %>
-<h2>Registration Details</h2>
+<h2><%= Gettext.dpgettext("static_pages", "oauth register page title", "Registration Details") %></h2>
-<p>If you'd like to register a new account, please provide the details below.</p>
+<p><%= Gettext.dpgettext("static_pages", "oauth register page fill form prompt", "If you'd like to register a new account, please provide the details below.") %></p>
<%= form_for @conn, Routes.o_auth_path(@conn, :register), [as: "authorization"], fn f -> %>
<div class="input">
- <%= label f, :nickname, "Nickname" %>
+ <%= label f, :nickname, Gettext.dpgettext("static_pages", "oauth register page nickname prompt", "Nickname") %>
<%= text_input f, :nickname, value: @nickname, autocomplete: "username" %>
</div>
<div class="input">
- <%= label f, :email, "Email" %>
+ <%= label f, :email, Gettext.dpgettext("static_pages", "oauth register page email prompt", "Email") %>
<%= text_input f, :email, value: @email, autocomplete: "email" %>
</div>
-<%= submit "Proceed as new user", name: "op", value: "register" %>
+<%= submit Gettext.dpgettext("static_pages", "oauth register page register button", "Proceed as new user"), name: "op", value: "register" %>
-<p>Alternatively, sign in to connect to existing account.</p>
+<p><%= Gettext.dpgettext("static_pages", "oauth register page login prompt", "Alternatively, sign in to connect to existing account.") %></p>
<div class="input">
- <%= label f, :name, "Name or email" %>
+ <%= label f, :name, Gettext.dpgettext("static_pages", "oauth register page login username prompt", "Name or email") %>
<%= text_input f, :name, autocomplete: "username" %>
</div>
<div class="input">
- <%= label f, :password, "Password" %>
+ <%= label f, :password, Gettext.dpgettext("static_pages", "oauth register page login password prompt", "Password") %>
<%= password_input f, :password, autocomplete: "password" %>
</div>
-<%= submit "Proceed as existing user", name: "op", value: "connect" %>
+<%= submit Gettext.dpgettext("static_pages", "oauth register page login button", "Proceed as existing user"), name: "op", value: "connect" %>
<%= hidden_input f, :client_id, value: @client_id %>
<%= hidden_input f, :redirect_uri, value: @redirect_uri %>
diff --git a/lib/pleroma/web/templates/o_auth/o_auth/show.html.eex b/lib/pleroma/web/templates/o_auth/o_auth/show.html.eex
index d63da6c1d..a2f41618e 100644
--- a/lib/pleroma/web/templates/o_auth/o_auth/show.html.eex
+++ b/lib/pleroma/web/templates/o_auth/o_auth/show.html.eex
@@ -20,21 +20,23 @@
<div class="container__content">
<%= if @app do %>
- <p>Application <strong><%= @app.client_name %></strong> is requesting access to your account.</p>
+ <p><%= raw Gettext.dpgettext("static_pages", "oauth authorize message", "Application <strong>%{client_name}</strong> is requesting access to your account.", client_name: safe_to_string(html_escape(@app.client_name))) %></p>
<%= render @view_module, "_scopes.html", Map.merge(assigns, %{form: f}) %>
<% end %>
<%= if @user do %>
<div class="actions">
- <a class="button button--cancel" href="/">Cancel</a>
- <%= submit "Approve", class: "button--approve" %>
+ <a class="button button--cancel" href="/">
+ <%= Gettext.dpgettext("static_pages", "oauth authorize cancel button", "Cancel") %>
+ </a>
+ <%= submit Gettext.dpgettext("static_pages", "oauth authorize approve button", "Approve"), class: "button--approve" %>
</div>
<% else %>
<%= if @params["registration"] in ["true", true] do %>
- <h3>This is the first time you visit! Please enter your Pleroma handle.</h3>
- <p>Choose carefully! You won't be able to change this later. You will be able to change your display name, though.</p>
+ <h3><%= Gettext.dpgettext("static_pages", "oauth register page title", "This is the first time you visit! Please enter your Pleroma handle.") %></h3>
+ <p><%= Gettext.dpgettext("static_pages", "oauth register nickname unchangeable warning", "Choose carefully! You won't be able to change this later. You will be able to change your display name, though.") %></p>
<div class="input">
- <%= label f, :nickname, "Pleroma Handle" %>
+ <%= label f, :nickname, Gettext.dpgettext("static_pages", "oauth register nickname prompt", "Pleroma Handle") %>
<%= text_input f, :nickname, placeholder: "lain", autocomplete: "username" %>
</div>
<%= hidden_input f, :name, value: @params["name"] %>
@@ -42,14 +44,14 @@
<br>
<% else %>
<div class="input">
- <%= label f, :name, "Username" %>
+ <%= label f, :name, Gettext.dpgettext("static_pages", "oauth login username prompt", "Username") %>
<%= text_input f, :name %>
</div>
<div class="input">
- <%= label f, :password, "Password" %>
+ <%= label f, :password, Gettext.dpgettext("static_pages", "oauth login password prompt", "Password") %>
<%= password_input f, :password %>
</div>
- <%= submit "Log In" %>
+ <%= submit Gettext.dpgettext("static_pages", "oauth login button", "Log In") %>
<% end %>
<% end %>
</div>
diff --git a/lib/pleroma/web/templates/static_fe/static_fe/profile.html.eex b/lib/pleroma/web/templates/static_fe/static_fe/profile.html.eex
index 3191bf450..a14ca305e 100644
--- a/lib/pleroma/web/templates/static_fe/static_fe/profile.html.eex
+++ b/lib/pleroma/web/templates/static_fe/static_fe/profile.html.eex
@@ -5,7 +5,7 @@
<form class="pull-right collapse" method="POST" action="<%= Helpers.util_path(@conn, :remote_subscribe) %>">
<input type="hidden" name="nickname" value="<%= @user.nickname %>">
<input type="hidden" name="profile" value="">
- <button type="submit" class="collapse">Remote follow</button>
+ <button type="submit" class="collapse"><%= Gettext.dpgettext("static_pages", "static fe profile page remote follow button", "Remote follow") %></button>
</form>
<%= raw Formatter.emojify(@user.name, @user.emoji) %> |
<%= link "@#{@user.nickname}@#{Endpoint.host()}", to: (@user.uri || @user.ap_id) %>
diff --git a/lib/pleroma/web/templates/twitter_api/password/invalid_token.html.eex b/lib/pleroma/web/templates/twitter_api/password/invalid_token.html.eex
index ee84750c7..5ac0aa4e0 100644
--- a/lib/pleroma/web/templates/twitter_api/password/invalid_token.html.eex
+++ b/lib/pleroma/web/templates/twitter_api/password/invalid_token.html.eex
@@ -1 +1 @@
-<h2>Invalid Token</h2>
+<h2><%= Gettext.dpgettext("static_pages", "password reset invalid token message", "Invalid Token") %></h2>
diff --git a/lib/pleroma/web/templates/twitter_api/password/reset.html.eex b/lib/pleroma/web/templates/twitter_api/password/reset.html.eex
index fbcacdc14..6a544af51 100644
--- a/lib/pleroma/web/templates/twitter_api/password/reset.html.eex
+++ b/lib/pleroma/web/templates/twitter_api/password/reset.html.eex
@@ -1,13 +1,13 @@
<h2>Password Reset for <%= @user.nickname %></h2>
<%= form_for @conn, Routes.reset_password_path(@conn, :do_reset), [as: "data"], fn f -> %>
<div class="form-row">
- <%= label f, :password, "Password" %>
+ <%= label f, :password, Gettext.dpgettext("static_pages", "password reset form password prompt", "Password") %>
<%= password_input f, :password %>
</div>
<div class="form-row">
- <%= label f, :password_confirmation, "Confirmation" %>
+ <%= label f, :password_confirmation, Gettext.dpgettext("static_pages", "password reset form confirm password prompt", "Confirmation") %>
<%= password_input f, :password_confirmation %>
</div>
<%= hidden_input f, :token, value: @token.token %>
- <%= submit "Reset" %>
+ <%= submit Gettext.dpgettext("static_pages", "password reset button", "Reset") %>
<% end %>
diff --git a/lib/pleroma/web/templates/twitter_api/password/reset_failed.html.eex b/lib/pleroma/web/templates/twitter_api/password/reset_failed.html.eex
index 4ed4ac8bc..774e3462a 100644
--- a/lib/pleroma/web/templates/twitter_api/password/reset_failed.html.eex
+++ b/lib/pleroma/web/templates/twitter_api/password/reset_failed.html.eex
@@ -1,2 +1,6 @@
-<h2>Password reset failed</h2>
-<h3><a href="<%= Pleroma.Web.Endpoint.url() %>">Homepage</a></h3>
+<h2><%= Gettext.dpgettext("static_pages", "password reset failed message", "Password reset failed") %></h2>
+<h3>
+ <a href="<%= Pleroma.Web.Endpoint.url() %>">
+ <%= Gettext.dpgettext("static_pages", "password reset failed homepage link", "Homepage") %>
+ </a>
+</h3>
diff --git a/lib/pleroma/web/templates/twitter_api/password/reset_success.html.eex b/lib/pleroma/web/templates/twitter_api/password/reset_success.html.eex
index 086d4e08b..40f6bb3fc 100644
--- a/lib/pleroma/web/templates/twitter_api/password/reset_success.html.eex
+++ b/lib/pleroma/web/templates/twitter_api/password/reset_success.html.eex
@@ -1,2 +1,2 @@
-<h2>Password changed!</h2>
-<h3><a href="<%= Pleroma.Web.Endpoint.url() %>">Homepage</a></h3>
+<h2><%= Gettext.dpgettext("static_pages", "password reset successful message", "Password changed!") %></h2>
+<h3><a href="<%= Pleroma.Web.Endpoint.url() %>"><%= Gettext.dpgettext("static_pages", "password reset successful homepage link", "Homepage") %></a></h3>
diff --git a/lib/pleroma/web/templates/twitter_api/remote_follow/follow.html.eex b/lib/pleroma/web/templates/twitter_api/remote_follow/follow.html.eex
index a7be53091..e2d251fac 100644
--- a/lib/pleroma/web/templates/twitter_api/remote_follow/follow.html.eex
+++ b/lib/pleroma/web/templates/twitter_api/remote_follow/follow.html.eex
@@ -1,11 +1,11 @@
<%= if @error == :error do %>
- <h2>Error fetching user</h2>
+ <h2><%= Gettext.dpgettext("static_pages", "remote follow error", "Error fetching user") %></h2>
<% else %>
- <h2>Remote follow</h2>
+ <h2><%= Gettext.dpgettext("static_pages", "remote follow header", "Remote follow") %></h2>
<img height="128" width="128" src="<%= avatar_url(@followee) %>">
<p><%= @followee.nickname %></p>
<%= form_for @conn, Routes.remote_follow_path(@conn, :do_follow), [as: "user"], fn f -> %>
<%= hidden_input f, :id, value: @followee.id %>
- <%= submit "Authorize" %>
+ <%= submit Gettext.dpgettext("static_pages", "remote follow authorization button", "Authorize") %>
<% end %>
<% end %>
diff --git a/lib/pleroma/web/templates/twitter_api/remote_follow/follow_login.html.eex b/lib/pleroma/web/templates/twitter_api/remote_follow/follow_login.html.eex
index bc5fb28e3..26340a906 100644
--- a/lib/pleroma/web/templates/twitter_api/remote_follow/follow_login.html.eex
+++ b/lib/pleroma/web/templates/twitter_api/remote_follow/follow_login.html.eex
@@ -1,14 +1,14 @@
<%= if @error do %>
<h2><%= @error %></h2>
<% end %>
-<h2>Log in to follow</h2>
+<h2><%= Gettext.dpgettext("static_pages", "remote follow header, need login", "Log in to follow") %></h2>
<p><%= @followee.nickname %></p>
<img height="128" width="128" src="<%= avatar_url(@followee) %>">
<%= form_for @conn, Routes.remote_follow_path(@conn, :do_follow), [as: "authorization"], fn f -> %>
-<%= text_input f, :name, placeholder: "Username", required: true, autocomplete: "username" %>
+<%= text_input f, :name, placeholder: Gettext.dpgettext("static_pages", "placeholder text for username entry", "Username"), required: true, autocomplete: "username" %>
<br>
-<%= password_input f, :password, placeholder: "Password", required: true, autocomplete: "password" %>
+<%= password_input f, :password, placeholder: Gettext.dpgettext("static_pages", "placeholder text for password entry", "Password"), required: true, autocomplete: "password" %>
<br>
<%= hidden_input f, :id, value: @followee.id %>
-<%= submit "Authorize" %>
+<%= submit Gettext.dpgettext("static_pages", "remote follow authorization button for login", "Authorize") %>
<% end %>
diff --git a/lib/pleroma/web/templates/twitter_api/remote_follow/follow_mfa.html.eex b/lib/pleroma/web/templates/twitter_api/remote_follow/follow_mfa.html.eex
index a54ed83b5..638212c1e 100644
--- a/lib/pleroma/web/templates/twitter_api/remote_follow/follow_mfa.html.eex
+++ b/lib/pleroma/web/templates/twitter_api/remote_follow/follow_mfa.html.eex
@@ -1,13 +1,13 @@
<%= if @error do %>
<h2><%= @error %></h2>
<% end %>
-<h2>Two-factor authentication</h2>
+<h2><%= Gettext.dpgettext("static_pages", "remote follow mfa header", "Two-factor authentication") %></h2>
<p><%= @followee.nickname %></p>
<img height="128" width="128" src="<%= avatar_url(@followee) %>">
<%= form_for @conn, Routes.remote_follow_path(@conn, :do_follow), [as: "mfa"], fn f -> %>
-<%= text_input f, :code, placeholder: "Authentication code", required: true %>
+<%= text_input f, :code, placeholder: Gettext.dpgettext("static_pages", "placeholder text for auth code entry", "Authentication code"), required: true %>
<br>
<%= hidden_input f, :id, value: @followee.id %>
<%= hidden_input f, :token, value: @mfa_token %>
-<%= submit "Authorize" %>
+<%= submit Gettext.dpgettext("static_pages", "remote follow authorization button for mfa", "Authorize") %>
<% end %>
diff --git a/lib/pleroma/web/templates/twitter_api/remote_follow/followed.html.eex b/lib/pleroma/web/templates/twitter_api/remote_follow/followed.html.eex
index da473d502..2fb4cc5d3 100644
--- a/lib/pleroma/web/templates/twitter_api/remote_follow/followed.html.eex
+++ b/lib/pleroma/web/templates/twitter_api/remote_follow/followed.html.eex
@@ -1,6 +1,5 @@
<%= if @error do %>
-<p>Error following account</p>
+<p><%= Gettext.dpgettext("static_pages", "remote follow error", "Error following account") %></p>
<% else %>
-<h2>Account followed!</h2>
+<h2><%= Gettext.dpgettext("static_pages", "remote follow success", "Account followed!") %></h2>
<% end %>
-
diff --git a/lib/pleroma/web/templates/twitter_api/util/subscribe.html.eex b/lib/pleroma/web/templates/twitter_api/util/subscribe.html.eex
index a6b313d8a..848660f26 100644
--- a/lib/pleroma/web/templates/twitter_api/util/subscribe.html.eex
+++ b/lib/pleroma/web/templates/twitter_api/util/subscribe.html.eex
@@ -1,10 +1,10 @@
<%= if @error do %>
- <h2>Error: <%= @error %></h2>
+ <h2><%= Gettext.dpgettext("static_pages", "remote follow error", "Error: %{error}", error: @error) %></h2>
<% else %>
- <h2>Remotely follow <%= @nickname %></h2>
+ <h2><%= Gettext.dpgettext("static_pages", "remote follow header", "Remotely follow %{nickname}", nickname: @nickname) %></h2>
<%= form_for @conn, Routes.util_path(@conn, :remote_subscribe), [as: "user"], fn f -> %>
<%= hidden_input f, :nickname, value: @nickname %>
- <%= text_input f, :profile, placeholder: "Your account ID, e.g. lain@quitter.se" %>
- <%= submit "Follow" %>
+ <%= text_input f, :profile, placeholder: Gettext.dpgettext("static_pages", "placeholder text for account id", "Your account ID, e.g. lain@quitter.se") %>
+ <%= submit Gettext.dpgettext("static_pages", "remote follow authorization button for following with a remote account", "Follow") %>
<% end %>
<% end %>
diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex
index 02b76da32..ef2eb75f4 100644
--- a/lib/pleroma/web/twitter_api/twitter_api.ex
+++ b/lib/pleroma/web/twitter_api/twitter_api.ex
@@ -12,6 +12,8 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
alias Pleroma.UserInviteToken
def register_user(params, opts \\ []) do
+ fallback_language = Gettext.get_locale()
+
params =
params
|> Map.take([:email, :token, :password])
@@ -21,6 +23,10 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
|> Map.put(:password_confirmation, params[:password])
|> Map.put(:registration_reason, params[:reason])
|> Map.put(:birthday, params[:birthday])
+ |> Map.put(
+ :language,
+ Pleroma.Web.Gettext.normalize_locale(params[:language]) || fallback_language
+ )
if Pleroma.Config.get([:instance, :registrations_open]) do
create_user(params, opts)
diff --git a/lib/pleroma/web/twitter_api/views/password_view.ex b/lib/pleroma/web/twitter_api/views/password_view.ex
index e6bef19dc..55790941f 100644
--- a/lib/pleroma/web/twitter_api/views/password_view.ex
+++ b/lib/pleroma/web/twitter_api/views/password_view.ex
@@ -5,4 +5,5 @@
defmodule Pleroma.Web.TwitterAPI.PasswordView do
use Pleroma.Web, :view
import Phoenix.HTML.Form
+ alias Pleroma.Web.Gettext
end
diff --git a/lib/pleroma/web/twitter_api/views/remote_follow_view.ex b/lib/pleroma/web/twitter_api/views/remote_follow_view.ex
index 93993cf40..bd33d4c0a 100644
--- a/lib/pleroma/web/twitter_api/views/remote_follow_view.ex
+++ b/lib/pleroma/web/twitter_api/views/remote_follow_view.ex
@@ -5,6 +5,7 @@
defmodule Pleroma.Web.TwitterAPI.RemoteFollowView do
use Pleroma.Web, :view
import Phoenix.HTML.Form
+ alias Pleroma.Web.Gettext
defdelegate avatar_url(user), to: Pleroma.User
end
diff --git a/lib/pleroma/web/twitter_api/views/util_view.ex b/lib/pleroma/web/twitter_api/views/util_view.ex
index 2b9005dae..69f243097 100644
--- a/lib/pleroma/web/twitter_api/views/util_view.ex
+++ b/lib/pleroma/web/twitter_api/views/util_view.ex
@@ -7,6 +7,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilView do
import Phoenix.HTML.Form
alias Pleroma.Config
alias Pleroma.Web.Endpoint
+ alias Pleroma.Web.Gettext
def status_net_config(instance) do
"""
diff --git a/lib/pleroma/web/views/email_view.ex b/lib/pleroma/web/views/email_view.ex
index c28ffaed2..9ab708212 100644
--- a/lib/pleroma/web/views/email_view.ex
+++ b/lib/pleroma/web/views/email_view.ex
@@ -6,6 +6,7 @@ defmodule Pleroma.Web.EmailView do
use Pleroma.Web, :view
import Phoenix.HTML
import Phoenix.HTML.Link
+ alias Pleroma.Web.Gettext
def avatar_url(user) do
Pleroma.User.avatar_url(user)
diff --git a/lib/pleroma/web/views/mailer/subscription_view.ex b/lib/pleroma/web/views/mailer/subscription_view.ex
index dd112dbbb..037fb6578 100644
--- a/lib/pleroma/web/views/mailer/subscription_view.ex
+++ b/lib/pleroma/web/views/mailer/subscription_view.ex
@@ -4,4 +4,5 @@
defmodule Pleroma.Web.Mailer.SubscriptionView do
use Pleroma.Web, :view
+ alias Pleroma.Web.Gettext
end