chore: refactored the UI locale handling
This commit is contained in:
65
lib/bds/desktop/ui_locale.ex
Normal file
65
lib/bds/desktop/ui_locale.ex
Normal file
@@ -0,0 +1,65 @@
|
||||
defmodule BDS.Desktop.UILocale do
|
||||
@moduledoc """
|
||||
Per-render UI locale binding for the desktop LiveView shell.
|
||||
|
||||
The shell renders the UI in the user's selected language, which can differ
|
||||
from the OS locale and from the project's `mainLanguage`. Phoenix HEEx
|
||||
templates call `translated/1,2` helpers without an explicit locale, so we
|
||||
bind the active locale once per `render/1` and the helpers read it back.
|
||||
|
||||
This module encapsulates that binding so call sites do not touch the raw
|
||||
process dictionary directly. Use `with_locale/2` around any render or
|
||||
component that needs a locale binding; use `current/0` to read it.
|
||||
|
||||
Direct use of `Process.put(:bds_ui_locale, _)` or
|
||||
`Process.get(:bds_ui_locale)` is forbidden outside this module.
|
||||
"""
|
||||
|
||||
@key :bds_ui_locale
|
||||
|
||||
@typedoc "A normalized UI locale code such as `\"en\"` or `\"de\"`."
|
||||
@type locale :: String.t() | nil
|
||||
|
||||
@doc """
|
||||
Bind `locale` for any subsequent reads of `current/0` in this process.
|
||||
|
||||
Used at LiveView render boundaries. The binding persists past the call
|
||||
(mirroring per-process locale state) so that lazily evaluated child
|
||||
components see the active locale. Each render boundary overwrites it.
|
||||
"""
|
||||
@spec put(locale()) :: :ok
|
||||
def put(locale) do
|
||||
Process.put(@key, locale)
|
||||
:ok
|
||||
end
|
||||
|
||||
@doc """
|
||||
Set the UI locale for the duration of `fun`, then restore the prior value.
|
||||
|
||||
Safe under exceptions: the prior binding is restored in an `after` clause.
|
||||
Use this for short-lived non-LiveView contexts (background tasks, scripts)
|
||||
where eager evaluation guarantees the binding is consumed before `fun`
|
||||
returns. Do not use around LiveView `render/1` because the returned
|
||||
`Phoenix.LiveView.Rendered` struct evaluates its dynamic parts lazily.
|
||||
"""
|
||||
@spec with_locale(locale(), (-> result)) :: result when result: var
|
||||
def with_locale(locale, fun) when is_function(fun, 0) do
|
||||
previous = Process.get(@key)
|
||||
Process.put(@key, locale)
|
||||
|
||||
try do
|
||||
fun.()
|
||||
after
|
||||
restore(previous)
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Read the active UI locale binding for this process, or `nil` when unset.
|
||||
"""
|
||||
@spec current() :: locale()
|
||||
def current, do: Process.get(@key)
|
||||
|
||||
defp restore(nil), do: Process.delete(@key)
|
||||
defp restore(value), do: Process.put(@key, value)
|
||||
end
|
||||
Reference in New Issue
Block a user