From ae25cba97ad0057df492e2cd660e5493d4ad4e80 Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Wed, 21 Jul 2021 15:46:04 +0200 Subject: [PATCH] Use correct default language when no Accept-Language is set Closes #792 Signed-off-by: Thomas Citharel --- lib/web/gettext.ex | 11 ++++--- lib/web/plugs/set_locale_plug.ex | 9 +++--- lib/web/templates/error/500_page.html.eex | 2 +- lib/web/views/error_view.ex | 9 ++++-- lib/web/views/utils.ex | 29 ++++++++++++++--- test/graphql/resolvers/user_test.exs | 4 +++ test/web/gettext_test.exs | 39 +++++++++++++++++++++++ test/web/plugs/set_locale_plug_test.exs | 9 +++--- 8 files changed, 92 insertions(+), 20 deletions(-) create mode 100644 test/web/gettext_test.exs diff --git a/lib/web/gettext.ex b/lib/web/gettext.ex index 7718ce6e..9f960477 100644 --- a/lib/web/gettext.ex +++ b/lib/web/gettext.ex @@ -24,21 +24,24 @@ defmodule Mobilizon.Web.Gettext do def put_locale(locale) do locale = determine_best_locale(locale) - Gettext.put_locale(Mobilizon.Web.Gettext, locale) + Gettext.put_locale(__MODULE__, locale) end @spec determine_best_locale(String.t()) :: String.t() def determine_best_locale(locale) do locale = String.trim(locale) - locales = Gettext.known_locales(Mobilizon.Web.Gettext) + locales = Gettext.known_locales(__MODULE__) + default = Keyword.get(Mobilizon.Config.instance_config(), :default_language, "en") || "en" cond do - # Either it matches directly, eg: "en" => "en", "fr" => "fr", "fr_FR" => "fr_FR" + # Default if nothing provided + locale == "" -> default + # Either it matches directly, eg: "en" => "en", "fr" => "fr" locale in locales -> locale # Either the first part matches, "fr_CA" => "fr" split_locale(locale) in locales -> split_locale(locale) # Otherwise set to default - true -> Keyword.get(Mobilizon.Config.instance_config(), :default_language, "en") || "en" + true -> default end end diff --git a/lib/web/plugs/set_locale_plug.ex b/lib/web/plugs/set_locale_plug.ex index 14d82ff8..8bcc8332 100644 --- a/lib/web/plugs/set_locale_plug.ex +++ b/lib/web/plugs/set_locale_plug.ex @@ -9,19 +9,20 @@ defmodule Mobilizon.Web.Plugs.SetLocalePlug do Plug to set locale for Gettext """ import Plug.Conn, only: [get_req_header: 2, assign: 3] + alias Mobilizon.Web.Gettext, as: GettextBackend def init(_), do: nil def call(conn, _) do - locale = get_locale_from_header(conn) || Gettext.get_locale() - Gettext.put_locale(locale) + locale = get_locale_from_header(conn) + GettextBackend.put_locale(locale) assign(conn, :locale, locale) end defp get_locale_from_header(conn) do conn |> extract_accept_language() - |> Enum.find(&supported_locale?/1) + |> Enum.find("", &supported_locale?/1) end defp extract_accept_language(conn) do @@ -41,7 +42,7 @@ defmodule Mobilizon.Web.Plugs.SetLocalePlug do end defp supported_locale?(locale) do - Mobilizon.Web.Gettext + GettextBackend |> Gettext.known_locales() |> Enum.member?(locale) end diff --git a/lib/web/templates/error/500_page.html.eex b/lib/web/templates/error/500_page.html.eex index 5af0859d..1ea14e90 100644 --- a/lib/web/templates/error/500_page.html.eex +++ b/lib/web/templates/error/500_page.html.eex @@ -1,5 +1,5 @@ - + diff --git a/lib/web/views/error_view.ex b/lib/web/views/error_view.ex index 8d4ba778..de8e7a70 100644 --- a/lib/web/views/error_view.ex +++ b/lib/web/views/error_view.ex @@ -56,15 +56,18 @@ defmodule Mobilizon.Web.ErrorView do end def render("500.html", assigns) do - Mobilizon.Config.instance_config() - |> Keyword.get(:default_language, "en") - |> Gettext.put_locale() + locale = + Mobilizon.Config.instance_config() + |> Keyword.get(:default_language, "en") + + Gettext.put_locale(locale) assigns = assigns |> Map.update(:details, [], & &1) |> Map.put(:instance, Mobilizon.Config.instance_name()) |> Map.put(:contact, Mobilizon.Config.contact()) + |> Map.put(:locale, locale) render("500_page.html", assigns) end diff --git a/lib/web/views/utils.ex b/lib/web/views/utils.ex index 1997e2a0..28d167ed 100644 --- a/lib/web/views/utils.ex +++ b/lib/web/views/utils.ex @@ -51,8 +51,29 @@ defmodule Mobilizon.Web.Views.Utils do |> String.replace("", "") end - @spec get_locale(Conn.t()) :: String.t() - def get_locale(%{private: %{cldr_locale: nil}}), do: "en" - def get_locale(%{private: %{cldr_locale: %{requested_locale_name: locale}}}), do: locale - def get_locale(_), do: "en" + @spec get_locale(Plug.Conn.t()) :: String.t() + def get_locale(%Plug.Conn{assigns: assigns}) do + assigns + |> Map.get(:locale) + |> check_locale() + end + + def get_locale(_), do: default_locale() + + defp check_locale(nil) do + default_locale() + |> check_locale() + end + + defp check_locale("") do + check_locale(nil) + end + + defp check_locale(locale) when is_binary(locale), do: locale + + defp default_locale do + Mobilizon.Config.instance_config() + |> Keyword.get(:default_language, "en") + |> Kernel.||("en") + end end diff --git a/test/graphql/resolvers/user_test.exs b/test/graphql/resolvers/user_test.exs index e701553c..1b8f3d69 100644 --- a/test/graphql/resolvers/user_test.exs +++ b/test/graphql/resolvers/user_test.exs @@ -317,6 +317,7 @@ defmodule Mobilizon.GraphQL.Resolvers.UserTest do res = conn + |> put_req_header("accept-language", "fr") |> AbsintheHelpers.graphql_query( query: @create_user_mutation, variables: @user_creation @@ -403,6 +404,7 @@ defmodule Mobilizon.GraphQL.Resolvers.UserTest do res = conn + |> put_req_header("accept-language", "fr") |> AbsintheHelpers.graphql_query( query: @register_person_mutation, variables: Map.put(@user_creation, :email, "random") @@ -431,6 +433,7 @@ defmodule Mobilizon.GraphQL.Resolvers.UserTest do res = conn + |> put_req_header("accept-language", "fr") |> AbsintheHelpers.graphql_query( query: @register_person_mutation, variables: @user_creation @@ -451,6 +454,7 @@ defmodule Mobilizon.GraphQL.Resolvers.UserTest do res = conn + |> put_req_header("accept-language", "fr") |> AbsintheHelpers.graphql_query( query: @register_person_mutation, variables: Map.put(@user_creation, :preferredUsername, "Myactor") diff --git a/test/web/gettext_test.exs b/test/web/gettext_test.exs new file mode 100644 index 00000000..3ed4f962 --- /dev/null +++ b/test/web/gettext_test.exs @@ -0,0 +1,39 @@ +defmodule Mobilizon.Web.GettextTest do + use ExUnit.Case, async: true + + alias Mobilizon.Config + alias Mobilizon.Web.Gettext, as: GettextBackend + + describe "test determine_best_locale/1" do + setup do + Config.put([:instance, :default_language], "en") + :ok + end + + test "with empty string returns the default locale" do + assert GettextBackend.determine_best_locale("") == "en" + end + + test "with empty string returns the default configured locale" do + Config.put([:instance, :default_language], "es") + assert GettextBackend.determine_best_locale("") == "es" + end + + test "with empty string returns english as a proper fallback if the default configured locale is nil" do + Config.put([:instance, :default_language], nil) + assert GettextBackend.determine_best_locale("") == "en" + end + + test "returns fallback with an unexisting locale" do + assert GettextBackend.determine_best_locale("yolo") == "en" + end + + test "maps the correct part if the locale has multiple ones" do + assert GettextBackend.determine_best_locale("fr_CA") == "fr" + end + + test "returns the locale if valid" do + assert GettextBackend.determine_best_locale("es") == "es" + end + end +end diff --git a/test/web/plugs/set_locale_plug_test.exs b/test/web/plugs/set_locale_plug_test.exs index 13fae0b5..8804a8a5 100644 --- a/test/web/plugs/set_locale_plug_test.exs +++ b/test/web/plugs/set_locale_plug_test.exs @@ -7,6 +7,7 @@ defmodule Mobilizon.Web.Plugs.SetLocalePlugTest do use ExUnit.Case, async: true use Plug.Test + alias Mobilizon.Web.Gettext, as: GettextBackend alias Mobilizon.Web.Plugs.SetLocalePlug alias Plug.Conn @@ -17,7 +18,7 @@ defmodule Mobilizon.Web.Plugs.SetLocalePlugTest do |> SetLocalePlug.call([]) assert "en" == Gettext.get_locale() - assert %{locale: "en"} == conn.assigns + assert %{locale: ""} == conn.assigns end test "use supported locale from `accept-language`" do @@ -30,7 +31,7 @@ defmodule Mobilizon.Web.Plugs.SetLocalePlugTest do ) |> SetLocalePlug.call([]) - assert "ru" == Gettext.get_locale() + assert "ru" == Gettext.get_locale(GettextBackend) assert %{locale: "ru"} == conn.assigns end @@ -41,7 +42,7 @@ defmodule Mobilizon.Web.Plugs.SetLocalePlugTest do |> Conn.put_req_header("accept-language", "tlh") |> SetLocalePlug.call([]) - assert "en" == Gettext.get_locale() - assert %{locale: "en"} == conn.assigns + assert "en" == Gettext.get_locale(GettextBackend) + assert %{locale: ""} == conn.assigns end end