ca1989

ca1989

Ex_cldr - need to call Gettext.put_locale to make it work

Hi all,

my backend module looks like:

defmodule OHA.Cldr do
  @moduledoc false

  @gettext_module Application.compile_env(:oha, :gettext, OHA.Gettext)

  use Cldr,
    locales: ["en", "de"],
    default_locale: "de",
    gettext: @gettext_module,
    data_dir: "./priv/cldr",
    otp_app: :oha,
    precompile_number_formats: ["¤¤#,##0.##"],
    providers: [
      Cldr.Number,
      Cldr.List,
      Cldr.Unit,
      Cldr.Territory,
      Cldr.DateTime,
      Cldr.LocaleDisplay
    ],
    generate_docs: false,
    force_locale_download: false
end

then I have a Phoenix project that uses that backend. The conf where I set the gettext_module looks like this:

config :oha, gettext: ZdbWeb.Gettext

Then I have the plugs for both the conn and the session in my browser pipeline, as I use both dead and live views:

pipeline :browser do
  plug(:accepts, ["html"])
  plug(:fetch_session)

  plug Cldr.Plug.PutLocale,
    apps: [:cldr, :gettext],
    from: [:query, :session, :path, :body, :cookie, :accept_language],
    param: "l",
    gettext: ZdbWeb.Gettext,
    cldr: OHA.Cldr

  plug Cldr.Plug.PutSession, as: :string
  plug(:fetch_live_flash)
  plug(:protect_from_forgery)
  plug(:put_secure_browser_headers)
  plug(:fetch_current_user)
end

Then I have a mount hook where I set the locale from what I have in the params or the session:

defmodule OHAWeb.RestoreLocale do
  def on_mount(:default, %{"l" => locale}, _session, socket) do
    # Gettext.put_locale(locale)
    OHA.Cldr.put_locale(locale)
    {:cont, socket}
  end

  def on_mount(:default, _params, %{"cldr_locale" => locale}, socket) do
    # Gettext.put_locale(locale)
    OHA.Cldr.put_locale(locale)
    {:cont, socket}
  end

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

This code does not work, I have to manually call Gettect.put_locale(locale) to make it work.

I am doing something wrong for sure, ideas?

Thank you
Cheers!

Marked As Solved

kip

kip

ex_cldr Core Team

Its a good question @ca1989 and it reflects the different environments between the initial HTTP request handled by Cldr.Plug.PutLocale and what happens when the live view is mounted.

The locale set by Cldr.put_locale/1 and Gettext.put_locale/1 are stored in the Process Dictionary which, by definition, is per-process. In the initial HTTP request, Cldr.Plug.PutLocale takes care of this based upon the plug configuration. Since you have configured the plug to set both locales, it does that.

Since each live view is a separate process, Cldr.put_locale/1 and Gettext.put_locale/1 need to be called again in the mount - exactly as you are doing.

Your question might be “why doesn’t Cldr.put_locale/1 also call Gettext.put_locale/1”? My reasoning has been that it would be a little bit too “magic” and that being explicit is better than implicit.

Also Liked

kip

kip

ex_cldr Core Team

Good question - I was a bit brief and inaccurate in my answer. The function Cldr.put_gettext_locale/1 takes care of using the LanguageTag to set the Gettext locale appropriately.

I think the right pattern here would be:

def on_mount(:default, _params, %{"cldr_locale" => locale}, socket) do
  Cldr.put_gettext_locale(locale)
  OHA.Cldr.put_locale(locale)
  {:cont, socket}
end

Cldr.put_gettext_locale/1 takes a CLDR locale, extracts the gettext_locale_name field and uses it with Gettext.put_locale/1. Its implementation is very simple:

@spec put_gettext_locale(LanguageTag.t()) :: {:ok, binary() | nil} | {:error, {module(), String.t()}}

def put_gettext_locale(%LanguageTag{gettext_locale_name: nil} = locale) do
  {:error,
    {Cldr.UnknownLocaleError,
      "Locale #{inspect(locale)} does not map to a known gettext locale name"}}
end

def put_gettext_locale(%LanguageTag{gettext_locale_name: gettext_locale_name} = locale) do
  gettext_backend = locale.backend.__cldr__(:gettext)
  _ = Gettext.put_locale(gettext_backend, gettext_locale_name)
  {:ok, gettext_locale_name}
end

In preparing this response I can see that generating a function OHA.Cldr.put_gettext_locale/1 in the CLDR backend would be more consistent and I have pushed a commit to do just that…

Where Next?

Popular in Questions Top

senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
yawaramin
In the Dialyzer docs ( http://erlang.org/doc/man/dialyzer.html#requesting-or-suppressing-warnings-in-source-files ), there is a way to tu...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
tduccuong
Hi, is there any work on GUI with Elixir, that is similar to Electron/Javascript? My idea is to bundle Phoenix and BEAM into a single se...
New
logicmason
Hi there, I'm working through my first release with elixir/phoenix. I've built a release with distillery and found that it crashes when I...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set? Thanks.
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? https://hexdocs.pm/ecto/Ecto.Repo.h...
New
chewm
Hi guys, nice to meet you to the whole forum, I’m new here, I’m trying to configure visual studio code for elixir, right now the intellis...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New

Other popular topics Top

sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
William
I would like to know that is there any online source for learning Phoenix Framework for building E-Commerce Store? Any advantage on build...
New
ycv005
I have followed this StackOverflow post to install the specific version of Erlang. And When I am running mix ecto.setup then getting fol...
New
quazar
How to set Jason to encode all fields in ecto schema, I don’t care about security and implementing only is taking long list of attributes...
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
script
If I have a string “1000 cfu/ml” . I want to remove the characters and / and space . So the string is like this "1000" What is the ...
New
mgjohns61585
Could someone help me? I'm making my first elixir program, number guessing game. I can't figure out how to convert the user's guess from ...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New

We're in Beta

About us Mission Statement