Workflow to structure translations


Currently there is no consistency in structuring translation file en.yml
Because some do follow (like Spree::Core) ActiveRecord and Views patterns, some go under admin: or js: scopes, but mostly it goes as:

  • registration_detail_name_producer,
  • spree_admin_enterprises_producers_order_cycles
  • report_header_tax_on_delivery
  • validation_msg_relationship_already_established

Link to best practices ( but it doesn’t always cover all cases.

Any thoughts?

Ensure correct translations are maintained and comprehensive

@enricostn @maikel @sigmundpetersen This might be of particular interest to the international developers? Please could someone link everyone I’ve missed?


Yes, it’s a mess. When we started, we didn’t have any guideline and some time pressure. We improved a bit already, but big parts are still in the old flat structure. We had a discussion about this on some pull request, I think. We basically said:

  • Prefer relative paths t('.something') resolving to the namespace of the view/mailer/etc.
  • Use global keys for frequently used terms that should always be the same.


@maikel, do you have opinion on translations in lib folder? - because even with t('.something') it returns translation missing: en.something

And do js: and admin: namespaces are still logical?

I.e. translation in model with t('.something') generates massive path. But what namespace should we use if we can reuse the same translation in more in than one place? Or what about global t('translation_that_explains_what_it_is_used_for') ?

P.S. I am just giving more situations that I was facing during extractions.


Good questions. The Rails I18n guide only mentions views, mailers, errors and ActiveRecord names. There is a potential for conflicts already. If you had a view in app/views/activerecord/models/user, it would share the namespace with that model.

We should aim to keep the global namespace small. The smallest would be with a lib prefix. For example lib.open_food_network/bulk_coop_report.customer. Since all lib classes should be in a namespace, I could also imagine a shorter version without lib: open_food_network/bulk_coop_report.customer

What would you prefer?

I like the property of being able to tell where the key is used. But what about globally shared strings like “Yes” and “No”? The link you gave suggested to put global stuff into the app namespace: app.yes. Seems good.

Can app.yes be used by a library? It is possible. But shouldn’t libraries be independent? Ideally, the application would become more modularised. I personally think that the Spree way of mixing views and logic in report libs is not very clean. What do you think?


Well, some translations are used not only in Bulk Coop, but in Orders & Fulfillment Reports or Orders And Distributors. Or, for example, order has products, order_cycle has products and variant belongs to product.

I have no opinion about app.yes but it doesn’t let you have symbols t(:yes) anymore and if you have symbol, you already know that it is global translation, right?

Still not sure translations by file path is good though still need to maintain activerecord/spree etc.

Another thought is to do some “hacking” to introduce some i18n_namespace = lib.open_food_network/bulk_coop_report into classes or something like that.

My main concern is that if we have many layers it is harder to maintain it. For example, I need to add abn_placeholder to shopfront somewhere and in en.yml I find it is in eg. 99 123 456 789 already. In this case instead of thinking how to refactor it, it would be easier just to create another one Are we find with this kind of duplication? Because then every language needs that duplicated translation as well. (admin and shopfront namespaces where just examples, not sure those are good).
But if we maintain only 2-3 layers then developer would just need to move layer up or so.

I still need to contemplate about it :slight_smile:


cc/ @nduran36 @sseerrggii


Additional context from (copy/pasted) (and other notes from

  • Avoid using interpolation whenever possible. It sounds like I’m recommending to discard one of the most basic features of the I18n gem - and that’s absolutely correct! What might seem like an easy interplation to make in English will always, always turn out to be a problem for a different locale because of its need to adjust for things like gender, pluralizations, conjugation and a range of other grammatical particularities. Proper nouns are the only things that seem reasonable to interpolate and even then…
  • Do not be ashamed of duplication. I know, this goes against every idea you hold sacred as a developer, but trust me, it will work out better in the long run. This problem pops up very often when using English as the base language and developers are trying to re-use existing translations. The issue here is that other languages often use different words in different contexts, whereas English will use the same one everywhere (stupid English…). Just create a new translation key for that specific context and send it off to your translator with your head held up high: you are winning at I18n.

Also is a cool gem (I am not familiar with Transifex if it can do the same) though we can’t use latest version until we upgrade Spree.


@softgust isn’t the point of interpolation in translations to make it easier to translate across languages? The only alternative when you have a dynamic string next to a translatable string is to have their relationship fixed, which feels way worse to me that using interpolation. What is the alternative? Am I missing something?


@oeoeaio, I guess we could move on as it is until we hit something. Because we don’t need to cover all special cases right away. But the the main reason is that some languages use and it is not only with counting. On the other hand there is gem like which might solve the issue. More detailed examples of possible issues at

This is more like a guideline that this might happen and maybe we could avoid this upfront with additional tools.


@maikel @softgust @lin_d_hop - is this still a thing? Can I close this?


I think we can close this.