2020-09-29 07:53:48 +00:00
|
|
|
# Portions of this file are derived from Pleroma:
|
|
|
|
# Pleroma: A lightweight social networking server
|
|
|
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
|
|
|
# SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
|
|
|
|
# NOTE: this module is based on https://github.com/smeevil/set_locale
|
|
|
|
defmodule Mobilizon.Web.Plugs.SetLocalePlug do
|
|
|
|
@moduledoc """
|
|
|
|
Plug to set locale for Gettext
|
|
|
|
"""
|
2021-07-27 17:47:54 +00:00
|
|
|
import Plug.Conn, only: [assign: 3]
|
2021-07-21 13:46:04 +00:00
|
|
|
alias Mobilizon.Web.Gettext, as: GettextBackend
|
2020-09-29 07:53:48 +00:00
|
|
|
|
2021-09-27 07:41:36 +00:00
|
|
|
@spec init(any()) :: nil
|
2020-09-29 07:53:48 +00:00
|
|
|
def init(_), do: nil
|
|
|
|
|
2021-09-27 07:41:36 +00:00
|
|
|
@spec call(Plug.Conn.t(), any()) :: Plug.Conn.t()
|
2020-09-29 07:53:48 +00:00
|
|
|
def call(conn, _) do
|
2021-07-27 17:47:54 +00:00
|
|
|
locale =
|
|
|
|
[
|
2021-11-07 20:02:36 +00:00
|
|
|
eventual_path_locale(conn.path_info),
|
2021-07-27 17:47:54 +00:00
|
|
|
conn.assigns[:user_locale],
|
|
|
|
conn.assigns[:detected_locale],
|
|
|
|
default_locale(),
|
|
|
|
"en"
|
|
|
|
]
|
2021-11-07 20:02:36 +00:00
|
|
|
|> Enum.filter(& &1)
|
2021-07-27 17:47:54 +00:00
|
|
|
|> Enum.map(&determine_best_locale/1)
|
|
|
|
|> Enum.filter(&supported_locale?/1)
|
|
|
|
|> hd()
|
|
|
|
|
|
|
|
Gettext.put_locale(locale)
|
2020-09-29 07:53:48 +00:00
|
|
|
assign(conn, :locale, locale)
|
|
|
|
end
|
|
|
|
|
2021-11-07 20:02:36 +00:00
|
|
|
defp eventual_path_locale(path_info) do
|
|
|
|
with [locale] <- path_info,
|
|
|
|
true <- supported_locale?(locale) do
|
|
|
|
locale
|
|
|
|
else
|
|
|
|
_ -> nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-09-27 07:41:36 +00:00
|
|
|
@spec supported_locale?(String.t()) :: boolean()
|
2020-09-29 07:53:48 +00:00
|
|
|
defp supported_locale?(locale) do
|
2021-07-21 13:46:04 +00:00
|
|
|
GettextBackend
|
2020-09-29 07:53:48 +00:00
|
|
|
|> Gettext.known_locales()
|
|
|
|
|> Enum.member?(locale)
|
|
|
|
end
|
|
|
|
|
2021-09-27 07:41:36 +00:00
|
|
|
@spec default_locale :: String.t()
|
2021-07-27 17:47:54 +00:00
|
|
|
defp default_locale do
|
|
|
|
Keyword.get(Mobilizon.Config.instance_config(), :default_language, "en")
|
2020-09-29 07:53:48 +00:00
|
|
|
end
|
|
|
|
|
2021-09-27 07:41:36 +00:00
|
|
|
@doc """
|
|
|
|
Determine the best available locale for a given locale ID
|
|
|
|
"""
|
|
|
|
@spec determine_best_locale(String.t()) :: String.t() | nil
|
2021-07-27 17:47:54 +00:00
|
|
|
def determine_best_locale(locale) when is_binary(locale) do
|
|
|
|
locale = String.trim(locale)
|
|
|
|
locales = Gettext.known_locales(GettextBackend)
|
|
|
|
|
|
|
|
cond do
|
|
|
|
locale == "" -> nil
|
|
|
|
# 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 -> nil
|
|
|
|
end
|
2020-09-29 07:53:48 +00:00
|
|
|
end
|
2021-07-27 17:47:54 +00:00
|
|
|
|
|
|
|
def determine_best_locale(_), do: nil
|
|
|
|
|
|
|
|
# Keep only the first part of the locale
|
2021-09-27 07:41:36 +00:00
|
|
|
@spec split_locale(String.t()) :: String.t()
|
2021-07-27 17:47:54 +00:00
|
|
|
defp split_locale(locale), do: locale |> String.split("_", trim: true, parts: 2) |> hd
|
2020-09-29 07:53:48 +00:00
|
|
|
end
|