chore: refactored the UI locale handling
This commit is contained in:
14
CODESMELL.md
14
CODESMELL.md
@@ -37,11 +37,15 @@ _None._ All modules previously on the queue have been split; refresh the queue i
|
||||
|
||||
## 2. Process Dictionary for i18n State
|
||||
|
||||
**Status:** open. `Process.put(:bds_ui_locale, …)` + `Process.get(:bds_ui_locale)` in `render/1` of `BDS.Desktop.ShellLive` and every `*_editor.ex` (15 sites total).
|
||||
**Status:** ✅ encapsulated (2026-05-10). Raw `Process.put(:bds_ui_locale, _)` / `Process.get(:bds_ui_locale)` no longer appears outside `BDS.Desktop.UILocale`. The two render boundaries (`BDS.Desktop.ShellLive.render/1` and `BDS.Desktop.ShellLive.SidebarComponents.sidebar_content/1`) now call `UILocale.put/1`; the ~30 helper read sites call `BDS.Desktop.UILocale.current/0`. The full thread-locale-through-assigns rewrite (~733 HEEx call sites) was rejected as too invasive for the marginal benefit; the encapsulation removes the implicit-global smell while keeping the LiveView lazy-render path intact.
|
||||
|
||||
**Why it matters:** implicit global state; complicates per-process isolation in tests and risks leaks between concurrent operations in the same process.
|
||||
**Why the helper does not restore on render exit:** Phoenix's `~H` returns a `Phoenix.LiveView.Rendered` whose `dynamic` function is invoked lazily by LiveView *after* `render/1` returns. A `try/after Process.delete` wrapper around `render/1` would clear the binding before child components materialize, so render boundaries use `UILocale.put/1` (set-only). `UILocale.with_locale/2` is provided for short-lived non-LiveView contexts (background tasks, scripts) that consume the binding eagerly inside the closure.
|
||||
|
||||
**Plan:** thread `locale` through `assigns`/render args; replace `translated/1,2` with a 3-arity helper that takes the locale explicitly; ban `Process.put` via Credo afterwards.
|
||||
**Module rules:**
|
||||
|
||||
- Only `lib/bds/desktop/ui_locale.ex` may touch the `:bds_ui_locale` process key.
|
||||
- New code that needs the active UI locale must call `BDS.Desktop.UILocale.current/0` (or take it as an argument).
|
||||
- New render entry points that change the locale must call `BDS.Desktop.UILocale.put/1` at the top of `render/1`.
|
||||
|
||||
---
|
||||
|
||||
@@ -165,6 +169,10 @@ Most tests share the SQLite repo and named GenServers (`BDS.Tasks`, `BDS.Search`
|
||||
|
||||
## Changelog
|
||||
|
||||
### 2026-05-10
|
||||
|
||||
- **Process dictionary for i18n state (Section 2)**: encapsulated behind `BDS.Desktop.UILocale` (`lib/bds/desktop/ui_locale.ex`, ~50 lines). Public surface: `put/1` (set without restore, for LV render boundaries that return lazy `Rendered`), `with_locale/2` (set + try/after restore, for short-lived eager contexts), `current/0` (read, returns `nil` when unset). The two raw `Process.put(:bds_ui_locale, _)` sites (`BDS.Desktop.ShellLive.render/1` and `BDS.Desktop.ShellLive.SidebarComponents.sidebar_content/1`) now call `UILocale.put/1`; the ~30 raw `Process.get(:bds_ui_locale)` reads (every editor `translated/1,2` helper plus `BDS.Desktop.ShellData.effective_ui_language/1`) now call `BDS.Desktop.UILocale.current/0`. The full thread-locale-through-assigns rewrite (~733 HEEx call sites) was deliberately rejected as too invasive; the encapsulation removes the implicit-global smell while preserving Phoenix's lazy `Rendered` evaluation. The render path uses `put/1` (not `with_locale/2`) because Phoenix `~H` returns a `Rendered` whose `dynamic` is invoked by LiveView *after* `render/1` returns; a `try/after Process.delete` would clear the binding before child components materialize. Only `BDS.Desktop.UILocale` is allowed to touch the `:bds_ui_locale` process key. Validates clean: `mix compile --warnings-as-errors`, `mix dialyzer --format short` (Total errors: 0), `mix test` (342 tests, 0 failures, 4 skipped, three consecutive runs).
|
||||
|
||||
### 2026-05-09
|
||||
|
||||
- **God modules**:
|
||||
|
||||
@@ -249,7 +249,7 @@ defmodule BDS.Desktop.ShellData do
|
||||
end
|
||||
|
||||
defp effective_ui_language(nil) do
|
||||
Process.get(:bds_ui_locale) || ui_language()
|
||||
BDS.Desktop.UILocale.current() || ui_language()
|
||||
end
|
||||
|
||||
defp effective_ui_language(locale), do: locale
|
||||
|
||||
@@ -7,7 +7,7 @@ defmodule BDS.Desktop.ShellLive do
|
||||
|
||||
alias BDS.AI
|
||||
alias BDS.CliSync.Watcher
|
||||
alias BDS.Desktop.{FolderPicker, Overlay, ShellData}
|
||||
alias BDS.Desktop.{FolderPicker, Overlay, ShellData, UILocale}
|
||||
alias BDS.Desktop.ShellLive.{ChatEditor, CodeEntityEditor, ImportEditor, MediaEditor, MenuEditor, MiscEditor, SettingsEditor, TagsEditor}
|
||||
alias BDS.Desktop.ShellLive.OverlayComponents, as: ShellOverlayComponents
|
||||
alias BDS.Desktop.ShellLive.PostEditor
|
||||
@@ -1285,7 +1285,7 @@ defmodule BDS.Desktop.ShellLive do
|
||||
|
||||
@impl true
|
||||
def render(assigns) do
|
||||
Process.put(:bds_ui_locale, assigns.page_language)
|
||||
UILocale.put(assigns.page_language)
|
||||
index(assigns)
|
||||
end
|
||||
|
||||
@@ -1346,7 +1346,7 @@ defmodule BDS.Desktop.ShellLive do
|
||||
|> assign_misc_editor()
|
||||
end
|
||||
|
||||
defp translated(text, bindings \\ %{}), do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
defp translated(text, bindings \\ %{}), do: ShellData.translate(text, bindings, UILocale.current())
|
||||
|
||||
defp encoded_shortcuts(shortcuts), do: Jason.encode!(shortcuts)
|
||||
|
||||
|
||||
@@ -572,5 +572,5 @@ defmodule BDS.Desktop.ShellLive.ChatEditor do
|
||||
defp format_error(reason), do: inspect(reason)
|
||||
|
||||
def translated(text, bindings \\ %{}),
|
||||
do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
end
|
||||
|
||||
@@ -114,5 +114,5 @@ defmodule BDS.Desktop.ShellLive.ChatEditor.MessageBuild do
|
||||
defp streaming_content(_request), do: ""
|
||||
|
||||
defp translated(text, bindings \\ %{}),
|
||||
do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
end
|
||||
|
||||
@@ -76,5 +76,5 @@ defmodule BDS.Desktop.ShellLive.ChatEditor.ModelSelection do
|
||||
defp blank?(nil), do: true
|
||||
|
||||
defp translated(text, bindings \\ %{}),
|
||||
do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
end
|
||||
|
||||
@@ -270,5 +270,5 @@ defmodule BDS.Desktop.ShellLive.ChatEditor.ToolSurfaces do
|
||||
defp truthy?(_value), do: false
|
||||
|
||||
defp translated(text, bindings \\ %{}),
|
||||
do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
end
|
||||
|
||||
@@ -229,5 +229,5 @@ defmodule BDS.Desktop.ShellLive.ChatSurface do
|
||||
end
|
||||
end
|
||||
|
||||
defp translated(text), do: ShellData.translate(text, %{}, Process.get(:bds_ui_locale))
|
||||
defp translated(text), do: ShellData.translate(text, %{}, BDS.Desktop.UILocale.current())
|
||||
end
|
||||
|
||||
@@ -190,7 +190,7 @@ defmodule BDS.Desktop.ShellLive.CodeEntityEditor do
|
||||
|
||||
def build_template(_assigns), do: nil
|
||||
|
||||
def translated(text, bindings \\ %{}), do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
def translated(text, bindings \\ %{}), do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
|
||||
def format_timestamp(nil), do: ""
|
||||
def format_timestamp(timestamp), do: BDS.Persistence.timestamp_to_iso8601(timestamp)
|
||||
|
||||
@@ -770,7 +770,7 @@ defmodule BDS.Desktop.ShellLive.ImportEditor do
|
||||
end
|
||||
end
|
||||
|
||||
defp translated(text, bindings \\ %{}), do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
defp translated(text, bindings \\ %{}), do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
defp present?(value), do: value not in [nil, ""]
|
||||
defp blank?(value), do: value in [nil, ""]
|
||||
end
|
||||
|
||||
@@ -243,6 +243,6 @@ defmodule BDS.Desktop.ShellLive.ImportEditor.AnalysisState do
|
||||
|
||||
def translate_phase(other), do: other
|
||||
|
||||
defp translated(text, bindings \\ %{}), do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
defp translated(text, bindings \\ %{}), do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
defp present?(value), do: value not in [nil, ""]
|
||||
end
|
||||
|
||||
@@ -242,5 +242,5 @@ defmodule BDS.Desktop.ShellLive.ImportEditor.ProgressTracking do
|
||||
|
||||
def translate_execution_phase(other), do: other
|
||||
|
||||
defp translated(text, bindings \\ %{}), do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
defp translated(text, bindings \\ %{}), do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
end
|
||||
|
||||
@@ -199,7 +199,7 @@ defmodule BDS.Desktop.ShellLive.ImportEditor.TaxonomyEditing do
|
||||
def maybe_put_option(opts, _key, nil), do: opts
|
||||
def maybe_put_option(opts, key, value), do: Keyword.put(opts, key, value)
|
||||
|
||||
defp translated(text, bindings \\ %{}), do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
defp translated(text, bindings \\ %{}), do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
defp present?(value), do: value not in [nil, ""]
|
||||
defp blank_to_nil(""), do: nil
|
||||
defp blank_to_nil(value), do: value
|
||||
|
||||
@@ -415,7 +415,7 @@ defmodule BDS.Desktop.ShellLive.MediaEditor do
|
||||
|
||||
def build(_assigns), do: nil
|
||||
|
||||
def translated(text, bindings \\ %{}), do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
def translated(text, bindings \\ %{}), do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
|
||||
def media_editor_save_state_label(:dirty), do: translated("Unsaved")
|
||||
def media_editor_save_state_label(:saved), do: translated("Saved")
|
||||
|
||||
@@ -307,7 +307,7 @@ defmodule BDS.Desktop.ShellLive.MenuEditor do
|
||||
end
|
||||
|
||||
def translated(text, bindings \\ %{}),
|
||||
do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
|
||||
def row_label(item, category_titles) do
|
||||
if item.kind == :category_archive do
|
||||
|
||||
@@ -128,5 +128,5 @@ defmodule BDS.Desktop.ShellLive.MenuEditor.DraftManagement do
|
||||
end
|
||||
|
||||
defp translated(text, bindings \\ %{}),
|
||||
do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
end
|
||||
|
||||
@@ -81,5 +81,5 @@ defmodule BDS.Desktop.ShellLive.MenuEditor.State do
|
||||
end
|
||||
|
||||
defp translated(text, bindings \\ %{}),
|
||||
do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
end
|
||||
|
||||
@@ -214,7 +214,7 @@ defmodule BDS.Desktop.ShellLive.MiscEditor do
|
||||
|
||||
def build(_assigns), do: nil
|
||||
|
||||
def translated(text, bindings \\ %{}), do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
def translated(text, bindings \\ %{}), do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
|
||||
def misc_class(:site_validation), do: "site-validation-view"
|
||||
def misc_class(:metadata_diff), do: "metadata-diff-view"
|
||||
|
||||
@@ -59,7 +59,7 @@ defmodule BDS.Desktop.ShellLive.OverlayComponents do
|
||||
|
||||
def markdown_link(text, url), do: "[#{text}](#{url})"
|
||||
|
||||
def translated(text, bindings \\ %{}), do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
def translated(text, bindings \\ %{}), do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
|
||||
def project_metadata(nil), do: %{main_language: "en", blog_languages: []}
|
||||
|
||||
|
||||
@@ -286,5 +286,5 @@ defmodule BDS.Desktop.ShellLive.PanelRenderer do
|
||||
|
||||
defp present?(value), do: value not in [nil, ""]
|
||||
|
||||
defp translated(text, bindings \\ %{}), do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
defp translated(text, bindings \\ %{}), do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
end
|
||||
|
||||
@@ -500,7 +500,7 @@ defmodule BDS.Desktop.ShellLive.PostEditor do
|
||||
def post_editor_mode_label(:preview), do: translated("Preview")
|
||||
|
||||
def translated(text, bindings \\ %{}),
|
||||
do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
|
||||
defp assigned_project_metadata(assigns), do: Map.get(assigns, :project_metadata, %{})
|
||||
end
|
||||
|
||||
@@ -101,5 +101,5 @@ defmodule BDS.Desktop.ShellLive.PostEditor.Persistence do
|
||||
end
|
||||
|
||||
defp translated(text, bindings \\ %{}),
|
||||
do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
end
|
||||
|
||||
@@ -186,5 +186,5 @@ defmodule BDS.Desktop.ShellLive.PostEditor.PostMetadata do
|
||||
end
|
||||
|
||||
defp translated(text, bindings \\ %{}),
|
||||
do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
end
|
||||
|
||||
@@ -143,7 +143,7 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor do
|
||||
end
|
||||
|
||||
def translated(text, bindings \\ %{}),
|
||||
do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
|
||||
defp current_settings_section(assigns) do
|
||||
meta = current_tab_meta(assigns)
|
||||
|
||||
@@ -199,5 +199,5 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor.AISettings do
|
||||
end
|
||||
|
||||
defp translated(text, bindings \\ %{}),
|
||||
do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
end
|
||||
|
||||
@@ -89,5 +89,5 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor.EditorSettings do
|
||||
defp boolean_string(false), do: "false"
|
||||
|
||||
defp translated(text, bindings \\ %{}),
|
||||
do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
end
|
||||
|
||||
@@ -190,5 +190,5 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor.ManagedCategories do
|
||||
end
|
||||
|
||||
defp translated(text, bindings \\ %{}),
|
||||
do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
end
|
||||
|
||||
@@ -96,5 +96,5 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor.MCPConfig do
|
||||
end
|
||||
|
||||
defp translated(text, bindings \\ %{}),
|
||||
do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
end
|
||||
|
||||
@@ -108,5 +108,5 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor.ProjectSettings do
|
||||
end
|
||||
|
||||
defp translated(text, bindings \\ %{}),
|
||||
do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
end
|
||||
|
||||
@@ -85,5 +85,5 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor.PublishingSettings do
|
||||
end
|
||||
|
||||
defp translated(text, bindings \\ %{}),
|
||||
do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
end
|
||||
|
||||
@@ -99,5 +99,5 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor.StyleEditor do
|
||||
end
|
||||
|
||||
defp translated(text, bindings \\ %{}),
|
||||
do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
end
|
||||
|
||||
@@ -4,10 +4,11 @@ defmodule BDS.Desktop.ShellLive.SidebarComponents do
|
||||
use Phoenix.Component
|
||||
|
||||
alias BDS.Desktop.ShellData
|
||||
alias BDS.Desktop.UILocale
|
||||
alias BDS.UI.Registry
|
||||
|
||||
def sidebar_content(assigns) do
|
||||
Process.put(:bds_ui_locale, assigns.page_language)
|
||||
UILocale.put(assigns.page_language)
|
||||
assigns = prepare_filter_assigns(assigns)
|
||||
|
||||
~H"""
|
||||
@@ -462,7 +463,7 @@ defmodule BDS.Desktop.ShellLive.SidebarComponents do
|
||||
"""
|
||||
end
|
||||
|
||||
defp translated(text, bindings \\ %{}), do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
defp translated(text, bindings \\ %{}), do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
|
||||
defp template_sidebar?(sidebar_data), do: Map.get(sidebar_data, :title) == "Templates"
|
||||
|
||||
|
||||
@@ -127,5 +127,5 @@ defmodule BDS.Desktop.ShellLive.SidebarCreate do
|
||||
def action(:import), do: %{kind: "import", label: "sidebar.import.newDefinition"}
|
||||
def action(_view), do: nil
|
||||
|
||||
defp translated(text), do: ShellData.translate(text, %{}, Process.get(:bds_ui_locale))
|
||||
defp translated(text), do: ShellData.translate(text, %{}, BDS.Desktop.UILocale.current())
|
||||
end
|
||||
|
||||
@@ -95,5 +95,5 @@ defmodule BDS.Desktop.ShellLive.TabHelpers do
|
||||
end
|
||||
end
|
||||
|
||||
defp translated(text), do: ShellData.translate(text, %{}, Process.get(:bds_ui_locale))
|
||||
defp translated(text), do: ShellData.translate(text, %{}, BDS.Desktop.UILocale.current())
|
||||
end
|
||||
|
||||
@@ -187,7 +187,7 @@ defmodule BDS.Desktop.ShellLive.TagsEditor do
|
||||
|
||||
def build(_assigns), do: nil
|
||||
|
||||
def translated(text, bindings \\ %{}), do: ShellData.translate(text, bindings, Process.get(:bds_ui_locale))
|
||||
def translated(text, bindings \\ %{}), do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
||||
|
||||
def tag_font_size(count, counts) do
|
||||
max_count = Enum.max([1 | Enum.map(counts, & &1.count)])
|
||||
|
||||
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