diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index cc8a26b48..6bce832ea 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -747,7 +747,8 @@ defmodule Pleroma.User do
       :emoji,
       :accepts_chat_messages,
       :registration_reason,
-      :birthday
+      :birthday,
+      :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 03efa3c38..c704ef5d6 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/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 @@ defmodule Pleroma.Web.Gettext 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 2c97cadc2..e1c68a98e 100644
--- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
@@ -221,7 +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, 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 @@ defmodule Pleroma.Web.Plugs.SetLocalePlug 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 aa4dfb145..a8a931f2a 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/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs
index f272ed1ae..d5978372b 100644
--- a/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs
+++ b/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs
@@ -13,6 +13,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
 
@@ -1662,6 +1663,75 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest 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"])