From 72bdb0640f28021ecbcc28711cc9268b17f5ea87 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Wed, 2 Mar 2022 01:41:13 -0500 Subject: [PATCH] Allow user to register with custom language --- lib/pleroma/user.ex | 3 +- .../api_spec/operations/account_operation.ex | 5 ++ lib/pleroma/web/gettext.ex | 8 +++ .../controllers/account_controller.ex | 2 +- lib/pleroma/web/plugs/set_locale_plug.ex | 2 +- lib/pleroma/web/twitter_api/twitter_api.ex | 6 ++ .../controllers/account_controller_test.exs | 70 +++++++++++++++++++ 7 files changed, 93 insertions(+), 3 deletions(-) diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 70afba3ae..9a50ee3ec 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -735,7 +735,8 @@ def register_changeset(struct, params \\ %{}, opts \\ []) do :password_confirmation, :emoji, :accepts_chat_messages, - :registration_reason + :registration_reason, + :language ]) |> validate_required([:name, :nickname, :password, :password_confirmation]) |> validate_confirmation(:password) diff --git a/lib/pleroma/web/api_spec/operations/account_operation.ex b/lib/pleroma/web/api_spec/operations/account_operation.ex index f5304d7d6..bdbae9b74 100644 --- a/lib/pleroma/web/api_spec/operations/account_operation.ex +++ b/lib/pleroma/web/api_spec/operations/account_operation.ex @@ -507,6 +507,11 @@ defp create_request do type: :string, nullable: true, description: "Invite token required when the registrations aren't public" + }, + language: %Schema{ + type: :string, + nullable: true, + description: "User's preferred language for emails" } }, example: %{ diff --git a/lib/pleroma/web/gettext.ex b/lib/pleroma/web/gettext.ex index e85290496..828b98b15 100644 --- a/lib/pleroma/web/gettext.ex +++ b/lib/pleroma/web/gettext.ex @@ -35,6 +35,14 @@ def language_tag do |> String.replace("_", "-", global: true) end + def normalize_locale(locale) do + if is_binary(locale) do + String.replace(locale, "-", "_") + else + nil + end + end + def supports_locale?(locale) do Pleroma.Web.Gettext |> Gettext.known_locales() diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex index 5303bdfd9..83cebbb96 100644 --- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex @@ -217,7 +217,7 @@ def update_credentials(%{assigns: %{user: user}, body_params: params} = conn, _p |> Maps.put_if_present(:is_locked, params[:locked]) # Note: param name is indeed :discoverable (not an error) |> Maps.put_if_present(:is_discoverable, params[:discoverable]) - |> Maps.put_if_present(:language, params[:language]) + |> Maps.put_if_present(:language, Pleroma.Web.Gettext.normalize_locale(params[:language])) # What happens here: # diff --git a/lib/pleroma/web/plugs/set_locale_plug.ex b/lib/pleroma/web/plugs/set_locale_plug.ex index 3c3fffa81..4c6e44fb5 100644 --- a/lib/pleroma/web/plugs/set_locale_plug.ex +++ b/lib/pleroma/web/plugs/set_locale_plug.ex @@ -25,7 +25,7 @@ defp get_locale_from_header(conn) do defp normalize_language_codes(codes) do codes - |> Enum.map(fn code -> String.replace(code, "-", "_") end) + |> Enum.map(fn code -> Pleroma.Web.Gettext.normalize_locale(code) end) end defp extract_preferred_language(conn) do diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex index 76ca82d20..7921653a8 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]) @@ -20,6 +22,10 @@ def register_user(params, opts \\ []) do |> Map.put(:name, Map.get(params, :fullname, params[:username])) |> Map.put(:password_confirmation, params[:password]) |> Map.put(:registration_reason, params[:reason]) + |> 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/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs index 374e2048a..de38a9798 100644 --- a/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs @@ -11,6 +11,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do alias Pleroma.Web.ActivityPub.InternalFetchActor alias Pleroma.Web.CommonAPI alias Pleroma.Web.OAuth.Token + alias Pleroma.Web.Plugs.SetLocalePlug import Pleroma.Factory @@ -1586,6 +1587,75 @@ test "returns an error if captcha is invalid", %{conn: conn} do end end + describe "create account with language" do + setup %{conn: conn} do + app_token = insert(:oauth_token, user: nil) + + conn = + conn + |> put_req_header("authorization", "Bearer " <> app_token.token) + |> put_req_header("content-type", "multipart/form-data") + |> put_req_cookie(SetLocalePlug.frontend_language_cookie_name(), "zh-Hans") + |> SetLocalePlug.call([]) + + [conn: conn] + end + + test "creates an account with language parameter", %{conn: conn} do + params = %{ + username: "foo", + email: "foo@example.org", + password: "dupa.8", + agreement: true, + language: "ru" + } + + res = + conn + |> post("/api/v1/accounts", params) + + assert json_response_and_validate_schema(res, 200) + + assert %{language: "ru"} = Pleroma.User.get_by_nickname("foo") + end + + test "language parameter should be normalized", %{conn: conn} do + params = %{ + username: "foo", + email: "foo@example.org", + password: "dupa.8", + agreement: true, + language: "ru-RU" + } + + res = + conn + |> post("/api/v1/accounts", params) + + assert json_response_and_validate_schema(res, 200) + + assert %{language: "ru_RU"} = Pleroma.User.get_by_nickname("foo") + end + + test "createing an account without language parameter should fallback to cookie/header language", + %{conn: conn} do + params = %{ + username: "foo2", + email: "foo2@example.org", + password: "dupa.8", + agreement: true + } + + res = + conn + |> post("/api/v1/accounts", params) + + assert json_response_and_validate_schema(res, 200) + + assert %{language: "zh_Hans"} = Pleroma.User.get_by_nickname("foo2") + end + end + describe "GET /api/v1/accounts/:id/lists - account_lists" do test "returns lists to which the account belongs" do %{user: user, conn: conn} = oauth_access(["read:lists"])