Solutions for LiveView locale setting?

I understand I can just use the /:locale path in router to get the locale and put_locale to set it. But that also means I’ve got to add Gettext.get_locale to every single link in the app, which is noise. Better would be to save it into session or use live_session.

Anyway seems like this should be a solved problem. What’s your go-to solution? I checked all the packages I could find, they just don’t support LiveView it seems.

2 Likes

welp, I wrote my own plug.

defmodule AskWeb.Plugs.LocalePlug do
  import Plug.Conn
  import Phoenix.Controller

  @locales ["en", "et"]

  def init(default), do: default

  def call(%Plug.Conn{params: %{"locale" => loc}} = conn, _default) when loc in @locales do
    conn
    |> assign(:locale, loc)
    |> put_session(:locale, loc)
  end

  def call(conn, default) do
    locale = get_session(conn, :locale) || default
    path = [locale | conn.path_info] |> Enum.join("/")

    conn
    |> redirect(to: "/" <> path)
  end
end

This uses params and not headers, beacuse I don’t need that atm.

Used in conjunction with

def mount(%{"locale" => locale}, _session, socket) do
    Gettext.put_locale(locale)
    {:ok, socket}
  end

You could utilize hooks in this case to avoid calling it explicitly for each mount.

# on_mount_hooks.ex
def on_mount(:set_locale, %{"locale" => locale} = _params, _session, socket)
      when is_binary(locale) do
    Gettext.put_locale(locale)
    {:cont, socket}
  end

def on_mount(:set_locale, _params, %{"locale" => locale} = _session, socket)
    when is_binary(locale) do
  Gettext.put_locale(locale)
  {:cont, socket}
end

def on_mount(:set_locale, _params, _session, socket) do
  {:cont, socket}
end


# example_web.ex
def live_view() do
  quote do
    on_mount({ExampleWeb.Live.OnMountHooks, :set_locale})
    ...
  end
end

Or go big and use something like GitHub - BartOtten/routex (demo: Listing Products · Phoenix Framework). The CLDR group also has a few helpers for localized routes GitHub - elixir-cldr/cldr: Elixir implementation of CLDR/ICU

Both have the advantage that you get a few helpers for common tasks such as generating a list of all localized links (language menu)

1 Like

Check out this plug specifically: Cldr.Plug.SetLocale – Cldr v1.4.3

2 Likes

thanks for the options everyone.

i just started a new project so gave Cldr a try - oh my god it took me hours! and yet the result doesn’t look so complicated.