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

View File

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

View File

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

View File

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

View File

@ -51,8 +51,29 @@ defmodule Mobilizon.Web.Views.Utils do
|> String.replace("<html lang=\"en\">", "<html lang=\"#{locale}\">")
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

View File

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

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