Gettext extract and .exs files (force compilation of .exs files)?

Is there a way to sometimes include .exs files in the compilation process? Or do something else, gettext-specific, that would allow the mix gettext.extract to also extract strings from .exs files?

Why would I want this?

I’m working on a project that uses gettext in unit tests. We’re trying to avoid coupling between the translations and the code base, so we do not hardcode the translations in the tests, but use gettext. Our assumption is that checking the correctness of the translated string (msgstr) is not the unit test’s concern, but sometimes we need to check that the expected string (msgid) was returned in the expected language, regardless of how it is actually translated. A very simplified example:

# lib/foo.ex
def some_function(n) do
  if n > 0, do: gettext("Call now!"), else: gettext("You're all set.")
end
# test/foo_test.exs
Gettext.with_locale(MyApp.Gettext, "en", fn ->
  assert some_function(2) ~= gettext("Call now")
end)

If you read the example closely, you’ll notice there is a very subtle bug. The msgid in the test is missing a trailing “!”. Now, if the test runs in English only and the msgstr in English is empty or identical to msgid, we will not notice the problem because the msgid with a mistake is a substring of the real msgid.

If it was possible to sometimes run mix gettext.extract in a way that will also check the test files, we could detect this problem early because we would see unexpected messages being added to .po(t) files.

This is not a very serious issue and we should probably run the tests in a different language anyway, which would help us detect almost all errors like this one, but maybe there is a way to extract strings from .exs files?

Well one thing you can, but it probably is not something you want, is to wrap the gettext-using code into helper functions and put them into test/support/gettext_helpers.ex as in *.ex not *.exs. Move the calls to gettext to these wrappers. Then, if test/support is added to elixirc_paths in mix.exs these modules will be compiled and I suspect mix gettext.extract will pick it up.

2 Likes