Gettext - block some locales

Hello,
I am currently implementing a system, which needs blocking some locales on certain environments. I don’t know what might be wrong in my solution. They way I implemented it:

  1. Set environmental variable, which defines allowed locales.
  2. In the plug read the current locale. If the locale is not in allowed locales - put default locale and redirect to the last correct (without forbidden variable) page. If there is no correct page, redirect to the main page.

Redirects are working fine. It redirects me to the correct page (last page without forbidden locale). The problem is that after redirect the app still has forbidden locale, though I’m setting it up before redirect to correct one. Then the plug launches again and redirects me again… and again… and again… :slight_smile:

defmodule MyAppWeb.CheckLocalePlug do
  import MyApp.Gettext, only: [default_locale: 0]

  def init(opts), do: opts

  def call(conn, _) do
    if Gettext.get_locale() in MyApp.Gettext.get_allowed_locales() do
      conn
    else
      #inspecting Gettext.get_locale() here gives forbidden locale
      Gettext.put_locale(default_locale())
      #inspecting Gettext.get_locale() here gives corrected locale

      conn
      |> Plug.Conn.halt()
      |> Plug.Conn.assign(:locale, default_locale())
      |> Phoenix.Controller.redirect(to: last_allowed_path(conn))
      # after redirect there is still forbidden locale :(
    end
  end

  defp last_allowed_path(conn) do
    conn
    |> NavigationHistory.last_paths()
    |> find_first_allowed_path()
  end

  defp find_first_allowed_path([]), do: "/"

  defp find_first_allowed_path([head | tail]) do
    maybe_locale = head |> String.split("/") |> Enum.reject(&(&1 == "")) |> List.first()
    case {is_locale?(maybe_locale), is_allowed_locale?(maybe_locale)} do
      {true, true} -> head
      {true, false} -> find_first_allowed_path(tail)
      {false, _} -> head
    end)
  end

  defp is_locale?(maybe_locale) do
    (maybe_locale in MyApp.Gettext.get_locales())
  end

  defp is_allowed_locale?(maybe_locale) do
    (maybe_locale in MyApp.Gettext.get_allowed_locales())
  end
end

Gettext.put_locale/1 sets the locale only for the current process. After the redirect, the process handling the request will be a different one, hence the redirect loop.

Is the user redirected to the correct path? How do you set the locale for a request?

1 Like