How to wrap Ash validation errors in Gettext

Tags:
  • Elixir
  • Ash

Published


I've been developing Fantapippa.it for a while now. It's a Phoenix application using Ash for all backend resources so far.

While the source code is in English, the default locale is Italian. After running mix gettext.extract --merge most of my strings were in the generated .po files, but I was missing the error messages from resource validations.

Ash is macro-heavy and messages are usually specified in macros. For example:

validate compare(:age, greater_than_or_equal_to: 18) do
message "must be over 18 to sign up"
end

Ash localization story is still a bit underdeveloped. There's a few open issues about it. This is a known area of improvement. I'm quoting one of the maintainers here:

we have definitely talked about adding gettext to Ash's error system but since neither of us speaks another language or has really built anything with translations in it we want to defer to experts

In any case, I have found a solution that works well enough for me using the noop Gettext.Macros.

use Gettext, backend: Core.Gettext
validate compare(:age, greater_than_or_equal_to: 18) do
message "must be over 18 to sign up"
message Gettext.Macros.dgettext_noop("errors", "must be over 18 to sign up")
end

When wrapping error message like so, they are marked for automatic extraction to the translation files.

I'm using the "errors" domain so the errors can be passed through translate_error/1 in the core components of Phoenix 1.8.

This is the default implementation when creating a new project. I only changed the Gettext backend to Core.Gettext.

@doc """
Translates an error message using gettext.
"""
def translate_error({msg, opts}) do
if count = opts[:count] do
Gettext.dngettext(Core.Gettext, "errors", msg, msg, count, opts)
else
Gettext.dgettext(Core.Gettext, "errors", msg, opts)
end
end