Hi all!
In our current project, we want to be able to live update all translated strings on the page (using gettext
) as soon as the user selects a new language.
The event is handled using handle_event
which calls Gettext.put_locale/1
as well as assigns the locale to the socket (assign(socket, locale: locale)
).
Unfortunately, the translated strings on the page do not update for regular <%= gettext "foo" %>
tags in EEx live templates.
We currently know of two workarounds that we can apply in our application to get translated text to update immedately:
-
Wrap all content in the template in
Gettext.with_locale(fn -> ... end)
. This has the major drawback that it prevents us from usinglive_component
anywhere within that function call, as Live View doesn’t manage the elements anymore. -
Access
assigns
within tags that have translated text, e.g.<%= assigns && gettext "foo" %>
or<%= gettext "foo", locale: @locale %>
. Unfortunately, this approach seems cumbersume, repetitive and (in the second variant) requires us to pass@locale
down to all views/components.
Thinking about there workarounds, I seemed to me as if gettext itself is working perfectly fine, but liveview doesn’t give it a chance to update if used in the simple form without any access to assigns
.
After digging in the liveview source code, I found that tags are analyzed to find out whether they need to be re-rendered for changed assigns.
Trying to replicate the “any access to assigns
will cause a rerender” situation, I tried to create a macro like this:
defmacro trans(msgid) do
quote do
var!(assigns) && gettext(unquote(msgid))
end
end
and use it as <%= trans("foo") %>
, but that still doesn’t update when it should.
I suspect that the macro is not expanded when the EEx template is compiled for live view and the access to assigns
is thus not recognized.
What I found to be working well, but which requires source code modification in phoenix_live_view, is adding defp classify_taint(:gettext, _), do: :always
to https://github.com/phoenixframework/phoenix_live_view/blob/900b151809ec4064f58e763c45c3906a5ff57ec2/lib/phoenix_live_view/engine.ex#L899
I’d like to hear some opinions of what would be a good solution to the problem we’re currently facing. I do understand that not all users “need” live updating translations on their page and always re-evaluating tags containing gettext
calls incurs a performance penalty when compared to evaluating them just once.
Would it make sense to allow configuring custom “signatures” in config.exs
to cater to such problems where live view can not correctly infer which tags need recomputation?