Use correct default language when no Accept-Language is set

Closes #792

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel 2021-07-21 15:46:04 +02:00
parent cc33ee7ada
commit ae25cba97a
No known key found for this signature in database
GPG Key ID: A061B9DDE0CA0773
8 changed files with 92 additions and 20 deletions

View File

@ -24,21 +24,24 @@ defmodule Mobilizon.Web.Gettext do
def put_locale(locale) do def put_locale(locale) do
locale = determine_best_locale(locale) locale = determine_best_locale(locale)
Gettext.put_locale(Mobilizon.Web.Gettext, locale) Gettext.put_locale(__MODULE__, locale)
end end
@spec determine_best_locale(String.t()) :: String.t() @spec determine_best_locale(String.t()) :: String.t()
def determine_best_locale(locale) do def determine_best_locale(locale) do
locale = String.trim(locale) 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 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 locale in locales -> locale
# Either the first part matches, "fr_CA" => "fr" # Either the first part matches, "fr_CA" => "fr"
split_locale(locale) in locales -> split_locale(locale) split_locale(locale) in locales -> split_locale(locale)
# Otherwise set to default # Otherwise set to default
true -> Keyword.get(Mobilizon.Config.instance_config(), :default_language, "en") || "en" true -> default
end end
end end

View File

@ -9,19 +9,20 @@ defmodule Mobilizon.Web.Plugs.SetLocalePlug do
Plug to set locale for Gettext Plug to set locale for Gettext
""" """
import Plug.Conn, only: [get_req_header: 2, assign: 3] import Plug.Conn, only: [get_req_header: 2, assign: 3]
alias Mobilizon.Web.Gettext, as: GettextBackend
def init(_), do: nil def init(_), do: nil
def call(conn, _) do def call(conn, _) do
locale = get_locale_from_header(conn) || Gettext.get_locale() locale = get_locale_from_header(conn)
Gettext.put_locale(locale) GettextBackend.put_locale(locale)
assign(conn, :locale, locale) assign(conn, :locale, locale)
end end
defp get_locale_from_header(conn) do defp get_locale_from_header(conn) do
conn conn
|> extract_accept_language() |> extract_accept_language()
|> Enum.find(&supported_locale?/1) |> Enum.find("", &supported_locale?/1)
end end
defp extract_accept_language(conn) do defp extract_accept_language(conn) do
@ -41,7 +42,7 @@ defmodule Mobilizon.Web.Plugs.SetLocalePlug do
end end
defp supported_locale?(locale) do defp supported_locale?(locale) do
Mobilizon.Web.Gettext GettextBackend
|> Gettext.known_locales() |> Gettext.known_locales()
|> Enum.member?(locale) |> Enum.member?(locale)
end end

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="<%= Gettext.get_locale() %>"> <html lang="<%= @locale %>">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">

View File

@ -56,15 +56,18 @@ defmodule Mobilizon.Web.ErrorView do
end end
def render("500.html", assigns) do def render("500.html", assigns) do
locale =
Mobilizon.Config.instance_config() Mobilizon.Config.instance_config()
|> Keyword.get(:default_language, "en") |> Keyword.get(:default_language, "en")
|> Gettext.put_locale()
Gettext.put_locale(locale)
assigns = assigns =
assigns assigns
|> Map.update(:details, [], & &1) |> Map.update(:details, [], & &1)
|> Map.put(:instance, Mobilizon.Config.instance_name()) |> Map.put(:instance, Mobilizon.Config.instance_name())
|> Map.put(:contact, Mobilizon.Config.contact()) |> Map.put(:contact, Mobilizon.Config.contact())
|> Map.put(:locale, locale)
render("500_page.html", assigns) render("500_page.html", assigns)
end end

View File

@ -51,8 +51,29 @@ defmodule Mobilizon.Web.Views.Utils do
|> String.replace("<html lang=\"en\">", "<html lang=\"#{locale}\">") |> String.replace("<html lang=\"en\">", "<html lang=\"#{locale}\">")
end end
@spec get_locale(Conn.t()) :: String.t() @spec get_locale(Plug.Conn.t()) :: String.t()
def get_locale(%{private: %{cldr_locale: nil}}), do: "en" def get_locale(%Plug.Conn{assigns: assigns}) do
def get_locale(%{private: %{cldr_locale: %{requested_locale_name: locale}}}), do: locale assigns
def get_locale(_), do: "en" |> 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 end

View File

@ -317,6 +317,7 @@ defmodule Mobilizon.GraphQL.Resolvers.UserTest do
res = res =
conn conn
|> put_req_header("accept-language", "fr")
|> AbsintheHelpers.graphql_query( |> AbsintheHelpers.graphql_query(
query: @create_user_mutation, query: @create_user_mutation,
variables: @user_creation variables: @user_creation
@ -403,6 +404,7 @@ defmodule Mobilizon.GraphQL.Resolvers.UserTest do
res = res =
conn conn
|> put_req_header("accept-language", "fr")
|> AbsintheHelpers.graphql_query( |> AbsintheHelpers.graphql_query(
query: @register_person_mutation, query: @register_person_mutation,
variables: Map.put(@user_creation, :email, "random") variables: Map.put(@user_creation, :email, "random")
@ -431,6 +433,7 @@ defmodule Mobilizon.GraphQL.Resolvers.UserTest do
res = res =
conn conn
|> put_req_header("accept-language", "fr")
|> AbsintheHelpers.graphql_query( |> AbsintheHelpers.graphql_query(
query: @register_person_mutation, query: @register_person_mutation,
variables: @user_creation variables: @user_creation
@ -451,6 +454,7 @@ defmodule Mobilizon.GraphQL.Resolvers.UserTest do
res = res =
conn conn
|> put_req_header("accept-language", "fr")
|> AbsintheHelpers.graphql_query( |> AbsintheHelpers.graphql_query(
query: @register_person_mutation, query: @register_person_mutation,
variables: Map.put(@user_creation, :preferredUsername, "Myactor") variables: Map.put(@user_creation, :preferredUsername, "Myactor")

39
test/web/gettext_test.exs Normal file
View File

@ -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

View File

@ -7,6 +7,7 @@ defmodule Mobilizon.Web.Plugs.SetLocalePlugTest do
use ExUnit.Case, async: true use ExUnit.Case, async: true
use Plug.Test use Plug.Test
alias Mobilizon.Web.Gettext, as: GettextBackend
alias Mobilizon.Web.Plugs.SetLocalePlug alias Mobilizon.Web.Plugs.SetLocalePlug
alias Plug.Conn alias Plug.Conn
@ -17,7 +18,7 @@ defmodule Mobilizon.Web.Plugs.SetLocalePlugTest do
|> SetLocalePlug.call([]) |> SetLocalePlug.call([])
assert "en" == Gettext.get_locale() assert "en" == Gettext.get_locale()
assert %{locale: "en"} == conn.assigns assert %{locale: ""} == conn.assigns
end end
test "use supported locale from `accept-language`" do test "use supported locale from `accept-language`" do
@ -30,7 +31,7 @@ defmodule Mobilizon.Web.Plugs.SetLocalePlugTest do
) )
|> SetLocalePlug.call([]) |> SetLocalePlug.call([])
assert "ru" == Gettext.get_locale() assert "ru" == Gettext.get_locale(GettextBackend)
assert %{locale: "ru"} == conn.assigns assert %{locale: "ru"} == conn.assigns
end end
@ -41,7 +42,7 @@ defmodule Mobilizon.Web.Plugs.SetLocalePlugTest do
|> Conn.put_req_header("accept-language", "tlh") |> Conn.put_req_header("accept-language", "tlh")
|> SetLocalePlug.call([]) |> SetLocalePlug.call([])
assert "en" == Gettext.get_locale() assert "en" == Gettext.get_locale(GettextBackend)
assert %{locale: "en"} == conn.assigns assert %{locale: ""} == conn.assigns
end end
end end