I18n.t with the argument ending with a dot

I have an enum database column (let’s say it’s Foo#color) that can be NULL. My website is for non-English speakers (let’s say Spanish), so enums must be translated. So, I wrote es.yml like this:

es:
  foo:
    color:
      red: rojo
      blue: azul
      green: verde

(Of course, this yml is VERY simplified.)

Now I want to write the translation by I18n.t("foo.color.#{foo.color}"). It shows rojo for :red, azul for :blue, and verde for :green. Everything looks working… Until the color is NULL. Now I get the entire hash: { :red => "rojo", :blue => "azul", :green => "verde" }. So I have to add code for checking if the color is NULL.

This problem disappears if Rails did this:

  • If the argument of I18n.t does not end in a dot (like I18n.t("foo.color")), it returns the hash, as the current Rails does.
  • If the argument of I18n.t ends in a dot (like I18n.t("foo.color."), which is generated when the color is NULL), it simply returns an empty string.

Why did they decide not do this? Is there any benefit in not doing this despite this inconvenience?

I18n.t("foo.color.#{foo.color.presence || "red"})

Other options would be to ensure color cannot be null.

I really want nil for the color is nil (Yes, something the color can really be NULL.) In this case, is color && I18n.t(~~~) the best way to do this?

I think that makes the most sense. If a field can logically be null, then you should handle the null case on your end, rather than having the null case be handled on the callee side.

Otherwise it’s not obvious to future you, or someone else, that a null is even in play.

In general it is better to remove null, and provide some default that doesn’t fail the way that null does, but if you truly want null, then I recommended explicitly handling it and not hiding it.

1 Like

Thank you! I’m going to keep my current explicit null handling.