Closed rubas closed 2 years ago
The reason I haven't done this is that it is very possible for the locale to be set by Cldr.Plug.SetLocale
to be different but compatible with Cldr.Route
.
For example with the following route:
localize :de do
get "/pages/:page", PageController
end
But the user arrives at the site with a locale defined (in path, session, params, whatever) as de-CH-u-cu-usd-ca-buddhist-co-phonebk-ka-shifted-nu-latn
.
Hence the session should be set with the locale as requested by the user (which is what `Cldr.Plug.SetLocale does). The route locale identifies how the user arrived at the site (well, somewhat at least, which is what Cldr.Route does).
I agree its a bit messy and thoughts on how to reconcile the "what the user asked for" with "how they got here" and "where do I look for what the user wants" would be most helpful if you have some ideas.
With ex_cldr_plugs version 1.1.0 now supporting :assigns
as an option to Cldr.Plug.SetLocale
I think this issue is largely addressed. It can now recognise the locale from :assigns
and set the locale appropriately.
I'll close this issue, but please reopen if that change doesn't address what you expected.
Thank 👍 . This(:assign
) is exactly what is was doing with my own function. It just felt natural that those library would be compatible out the box.
I agree its a bit messy and thoughts on how to reconcile the "what the user asked for" with "how they got here" and "where do I look for what the user wants" would be most helpful if you have some ideas.
TL;DR: from
is perfect. Wouldn't change.
It is a complicated topic and the order has to be defined on a per-project basis. For example, depending on which site we may look at :assign
, User Preference, Accept Language
Header and Default Language.
from
in Cldr.Plug.SetLocale
allows us to do this. And it's up to us to deal with project-specific edge cases.
:assigns
works perfectly for normaler Controller but the locale is not changed for the LiveView process.
[info] GET /de/test
%{
cldr_locale: #Cldr.LanguageTag<de [validated]>,
current_user: nil,
locale: nil
}
#Cldr.LanguageTag<de [validated]>
[info] GET /de
#Cldr.LanguageTag<en [validated]>
This is the big problem, you referred in https://github.com/elixir-cldr/cldr_routes/issues/6.
on_mount
callbackhttps://hexdocs.pm/phoenix_live_view/using-gettext.html
Setting the locale with on_mount
is neat and would be my go-to-solution.
But this callback has to be defined with live_session
. live_session
may or may not be inside the localize
block. This makes it difficult to deal with it on a library level.
mount
functionOne could write a macro (or a simple Helper) that handles it directly in the mount
function of the Live Controller. But people will forget to add the macro/call the function.
Again, very unsatisfying.
router.exs
defmodule MarkoWeb.Router do
@moduledoc """
# Locale
The locale is set by
1. by user settings, and redirected if it's not matching
2. by cldr_routes
3. by accept_language
4. default
"""
use MarkoWeb, :router
import MarkoWeb.Plug.UserAuth
pipeline :browser do
plug(:accepts, ["html"])
plug(:fetch_session)
plug(Cldr.Plug.SetLocale,
apps: [:cldr, :gettext],
from: [:assigns],
gettext: MarkoGettext,
cldr: MarkoCldr
)
[...]
end
live_session :default do
scope "/", MarkoWeb do
pipe_through([:browser])
get("/", HomeController, :index)
localize do
live("/#{locale}", HomeLive)
get("/#{locale}/test", HomeController, :test)
end
end
end
end
controllers/home_controller.ex
defmodule MarkoWeb.HomeController do
use MarkoWeb, :controller
def index(conn, _opts) do
redirect(conn, to: Routes.home_live_path(conn, MarkoWeb.HomeLive))
end
def test(conn, _opts) do
IO.inspect(conn.assigns)
IO.inspect(MarkoCldr.get_locale())
conn
end
end
live/home_live.ex
defmodule MarkoWeb.HomeLive do
@moduledoc """
Home view
"""
use MarkoWeb, :live_view
@impl Phoenix.LiveView
def mount(_params, session, socket) do
IO.inspect(MarkoCldr.get_locale())
socket =
socket
|> assign(:page_title, gettext("Home"))
{:ok, socket}
end
@impl Phoenix.LiveView
def render(assigns) do
~H"""
<%= gettext("Home") %>
"""
end
@impl Phoenix.LiveView
def handle_params(_params, _uri, socket) do
{:noreply, socket}
end
end
Yes, this is definitely the tricky part. With you help (and great patience!) I think most of the library is now operating correctly (just added more tests too). But I do need to dive more into Liveview, especially how the session and socket are populated and how the interact with routing.
Getting late here, will jump on this tomorrow.
Closing this favour of #6, lets continue the work on that issue since I think its the more relevant one.
cldr_routes
provides localized routes and setscldr_locale
inconn.assigns
.Wouldn't it make sense to work together with
Cldr.Plug.SetLocale
out of the box?I haven't found a
from
configuration forCldr.Plug.SetLocale
that works withcldr_routes
(except custom function).Worse - I ended up with
conn.assigns.cldr_locale
set bycldr_routes
andconn.private.cldr_locale
set byCldr.Plug.SetLocale
.