Eiji

Eiji

Hi, I’m working on DSL and the last thing that I don’t like is how I’m extracting translations.

I have 2 version of code:

  1. My current implementation is based on Gettext.Extractor private API - it’s working without any issues

  2. An alternative is to use Gettext.Macros.dpgettext_noop_with_backend/4. It’s also a solution which works very well, but unfortunately it does not allow function generators (other macros, for loops etc.) as Gettext macros requires binary literals.

defmodule MyApp.Example do
  use MyLib.DSL, gettext_backend: MyApp.GettextBackend

  for data <- ~w[first second third] do
    some_dsl data
  end
end

I understand that private API is unstable and can be changed at any time, but I have simply no idea about other possible solutions. From now on I can see only 2 ways to fix it:

  1. Propose to make Gettext.Extractor a public API - that’s the simplest thing that could be done as it’s only about documenting code i.e. no change in code.

  2. Propose to support non-literals, so internal Gettext.Extractor calls are done within quote do … end block instead of directly inside macros.

Both solutions are rather something you consider at the very end. Support for gettext is only optional, so I don’t want to resign from function generators. The whole logic is done only in compile-time, so the generated code is as fast as possible in runtime.

With all above in mind I’m not satisfied in both implementations and I have no idea what to do with that. Did you had a similar problems with gettext when working on DSL? What do you think about making Gettext.Extractor public? Is there any other way to extract translations without above problems?

Showing Posts 1 to 10

LostKobrakai

LostKobrakai

I’d love if Gettext.Extractor could become public api. I had asked for that a few months back on a more esoteric usecase and given the usecase the response was negative. This sounds more in line with the libraries goals. But I wonder why you cannot provide binary literals if you’re in a macro context.

Eiji

Eiji OP

Glad to hear that not only me is looking for this.

This is about said data argument in some_dsl macro, see:

LostKobrakai

LostKobrakai

Ah, yeah. You’d cannot work with variables, you need to know the actual strings in your macro.

maennchen

maennchen

I believe you should be able to use the exposed public APIs in Macros since you can just unquote the variable containing the string.

require Gettext.Macros

for message <- ["message 1", "message 2"] do
  def translate(unquote(message)) do
    Gettext.Macros.dgettext_with_backend(
      Acme.Gettext,
      "default",
      unquote(message)
    )
  end
end

See Gettext.Macros — gettext v1.0.2

Eiji

Eiji OP

I have mentioned it as alternative way in 2nd point and why it’s not an option for me. For now I’m investigating expo as generating pot file sounds like an interesting alternative to current solutions.

maennchen

maennchen

Generally when using macros, you should have access to the literal and not just the variable. Can you share a simplified version of your DSL that shows the issue?

It’s the intention of gettext that this works. If it does not, we’ll need to have a closer look.

Adzz

Adzz

I’m not sure I fully understand your use case but in a project I work on we extract translations from the .POT file. Seems to work fine, we hand rolled a parser of those files but I think Expo.PO.parse_file!("priv/gettext/default.pot") probably works fine

Eiji

Eiji OP

Here you go:

defmodule DummyGettext do
  defmacro dummy_macro(input, _lang \\ "en") do
    # gettext macros require literals at this point (not within quote do … end block)
    IO.inspect(input)
    is_binary(input) == false && raise "gettext fail here"
  end

  def get_locales, do: ["en"]
end

defmodule MyLib.DSL do
  defmacro __using__(_opts \\ []) do
    quote do
      import MyLib.DSL

      require DummyGettext

      def translated_input(input, locale \\ "en")
    end
  end

  defmacro some_dsl(input) do
    for locale <- DummyGettext.get_locales() do
      translated_input = quote do: DummyGettext.dummy_macro(unquote(input))

      quote bind_quoted: [input: input, locale: locale, translated_input: translated_input] do
        def translated_input(unquote(input), unquote(locale)), do: unquote(translated_input)
      end
    end
  end
end

defmodule MyApp.Example do
  use MyLib.DSL

  # this one obviously works
  some_dsl("text to translate")

  # my macros are fine with that, but gettext requires literal at compile time
  # so below code fails
  for data <- ~w[first second third] do
    some_dsl(data)
  end
end
Eiji

Eiji OP

Wrong way. I think now about generating .pot file at compile time and then call mix gettext.merge priv/gettext --locale locale. It’s nothing related to parsing .pot file. Sorry if my post was not clear enough.

Eiji

Eiji OP

Generating a .pot file using expo is definitely the best solution. I have a full control over code, I don’t need to worry about private APIs and it’s also a very simple thing to do.

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
kszambelanczyk
Hello! Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app. I creat...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New
psy-q
I’m trying to set up Emacs with elixir-ls via lsp-mode and credo via Flycheck. This should mostly be preconfigured as Flycheck picks up c...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews