tmjoen

tmjoen

Gettext domains with code generation

I’m trying to create some translations for my CMS resources, and I’m trying to automatically create Gettext domains for each resource.

defmodule MyApp.Projects.Project do
  use B.Blueprint
  import MyApp.Gettext

  @singular "project"
  @plural "projects"

  # these macros basically build a map of translations
  translations do
    context :fields do
      translate :title do
        label t("Some label text")
        placeholder t("Some placeholder")
      end
    end
  end
end

The t macro lives in the used B.Blueprint and looks like this:

 # ...
  # 
  defmacro t(msgid) do
    quote do
      dgettext(@plural, msgid)
    end
  end

This doesn’t work of course:

** (ArgumentError) Gettext macros expect translation keys (msgid and msgid_plural),
domains, and comments to expand to strings at compile-time, but the given domain
doesn't. This is what the macro received:

{{:., [], [{:__aliases__, [counter: {MyApp.Projects.Project, 58}, alias: false], [:Module]}, :__get_attribute__]}, [], [{:__MODULE__, [counter: {MyApp.Projects.Project, 58}], Kernel}, :plural, 83]}

Is this doable in any way? I was hoping to not having to put all my translations in the “default.pot” file, and also not having to do t("projects", "msg here") :slight_smile:

Marked As Solved

tmjoen

tmjoen

Thanks for the __CALLER__.module hint!

I did some logging and it seems that the t macro is run before the module attribute is set, so I had to do a slight API adjustment:

defmodule MyApp.Projects.Project do
  use B.Blueprint, 
    singular: "Project",
    plural: "Projects"

  import MyApp.Gettext

  # these macros basically build a map of translations
  translations do
    context :fields do
      translate :title do
        label t("Some label text")
        placeholder t("Some placeholder")
      end
    end
  end
end

then in B.Blueprint

  defmacro __using__(opts) do
    Module.register_attribute(__CALLER__.module, :singular, accumulate: false)
    Module.put_attribute(__CALLER__.module, :singular, Keyword.fetch!(opts, :singular))

    Module.register_attribute(__CALLER__.module, :plural, accumulate: false)
    Module.put_attribute(__CALLER__.module, :plural, Keyword.fetch!(opts, :plural))
    # ...

Now the module attribute is available in my t macro! :tada:

Also Liked

kip

kip

ex_cldr Core Team

Something like this should do the trick however for some reason Module.get_attribute/2 is returning nil which I did not expect. My early morning brain isn’t resolving why so putting here so smarter brains can clarify.

defmodule B.Blueprint do
  defmacro t(msgid) do
    caller = __CALLER__.module

    # On my quick test this is returning `nil` which surprised me
    domain = Module.get_attribute(caller, :plural)

    # Testing this way works
    domain = "plural"

    quote do
      dgettext(unquote(domain), unquote(msgid))
    end
  end

end

defmodule MyApp.Projects.Project do
  import MyApp.Gettext
  import B.Blueprint

  @plural "projects"

  t("some message")
end
kip

kip

ex_cldr Core Team

Cool, I think thats a better and more obvious API too. Glad its up and running for you!

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
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
New
Jim
As a follow up to my earlier question: I have the code compiling and running but not getting a successful login from the rest server. ...
New
dokuzbir
Hello, I am trying to convert my lists to string without losing brackets.For start i have 3 map. They look like these buyer = %{ id: ...
New
Fl4m3Ph03n1x
Background Let’s assume I have a typical GenServer that receives messages as requests, does some operation in a DB and returns responses....
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
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

Other popular topics Top

JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1140 51847 244
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: https://hexdocs.pm/ecto/Ecto.Schema.html#module-...
New
sergio
I couldn’t find any guides that worked well with Phoenix 1.6.0 and esbuild. I hope this helps people test the waters and eases you into t...
New
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
AstonJ
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including. What is Phoenix LiveV...
New
Nvim
Elixir appears to be a superior language to Python. I don’t see any advantage of Python over Elixir. Are there any?
New

We're in Beta

About us Mission Statement