Development/Production parity for Rails Internationalization

Mauro Otonelli

To support both English and Spanish in web apps, we can use Ruby’s I18n library, which allows for easy translations through YAML files for each language. If a translation is missing, ideally we’d like to see an error in our tests, which makes the test suite fail. However, if our development environment is not set up to raise exceptions, there could be bugs lurking, or waiting to be introduced.

One such instance happened to us recently, because our I18n.backend (yes, that’s a thing!) in Rails was different in the development/testing and production environments. Development used the “base” i18n backend, while production was set up to use the “fallbacks” backend.

This difference made it so that production showed this output when rendering a PDF:

1 2 2.5 . 1 : 001 > helper . render inline: "<%= t(nil, scope: 'contact_relationship_mappings') %>" => "<span class= \" translation_missing \" title= \" translation missing: en.contact_relationship_mappings \" >Contact Relationship Mappings</span>"

While development/testing showed this:

1 2 2.5 . 1 : 001 > helper . render inline: "<%= t(nil, scope: 'contact_relationship_mappings') %>" => ""

Two very different outputs, produced by the difference in the i18n backends. The first one falls back to whatever string the scope was, and the second one returns an empty string. By using the same backend, we can more easily detect failures and have it behave the same way across environments.

Factor #10 in the twelve-factor app methodology is keeping development and production as similar as possible, which is what I tried to exemplify in this article.

The twelve-factor developer resists the urge to use different backing services between development and production, …

The same applies to other parts of our tech stack. The more things we have in common between development and production, the more things we can expect to go right or wrong earlier. And when things do go wrong, we have a better debugging environment set up.