8

How do I set a fallback locale in Rails 5.2?

Right now it prints ''(blank) for attribute names if not found in locale. I would like it to fallback to :en when that happens.

Rails 5 specific?

# config/application.rb 
config.load_defaults 5.0
config.i18n.default_locale = :nb

run specs and get:

#<ActiveRecord::RecordInvalid: Det oppstod en feil: er allerede i bruk>
see the missing part here:
#<ActiveRecord::RecordInvalid: Det oppstod en feil: [MISSING RECORD NAME] er allerede i bruk>

# switch to 
# config.i18n.default_locale = :en
#<ActiveRecord::RecordInvalid: Validation failed: Report date has already been taken> 

UPDATE:

@Nate got the fallback config correct in his answer below (https://stackoverflow.com/a/53453211/252799)

That wasn't the issue though. The problem, I learned, was in my nb.yml.

  • Experiment 1. Deleting the entire content of nb.yml, leaving just hello world. Works: It prints the attribute (associated record) name.
  • Experiment 2. Replacing our nb.yml with the official Rails nb.yml: https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/nb.yml : Works. I get the helpful norwegian-english message Det oppstod feil: Company må eksistere. Not pretty, but helpful and what I wanted!
  • Experiment 3. Proof. The nb.yml reproduces the problem.

Two approaches

# A: SHOW attribute name
nb: 
  errors:
    format: "%{attribute} %{message}"

# B: HIDE attribute name
nb:
  errors:
    format: "%{message}"

Which leads to another problem.

Approach B: HIDE makes you blind serverside. the specs, logs and console will show Validation Failed: can't be blank but it looks good in UI.

I posted another Q: Simpleform errors without attribute name, but using attribute name in logs, console, specs

oma
  • 30,364
  • 11
  • 66
  • 91

2 Answers2

7

Rails 5.2 allows you to set config.i18n.fallbacks to control which fallback locale(s) are able to be used. Set it to an array of symbols to control which locales should be used when a translation is not found. When multiple are set, it goes through the array one by one until a transliterate works (or doesn't).

In your case, you'll want the following in your config/application.rb:

config.i18n.default_locale = :nb
config.i18n.fallbacks = [:en]

This way, if a locale is not specified, it uses the :nb locale (your default locale). Then, any time a translate fails in any locale, it will try the :en locale as a fallback.

Note: if none of your fallback locales have a translation for the key you're trying to translate, you'll still get the translation missing error.

For a more complete answer, here's an example with multiple fallbacks. They will be checked in the order specified:

config.i18n.default_locale = :nb
config.i18n.fallbacks = [:en, :es, :de]
Nate
  • 2,171
  • 1
  • 6
  • 16
  • bounty instructions "No guessing, show me it works.". You present it like guesswork, please provide authoritive answer. Thanks! – oma Nov 24 '18 at 13:13
  • @oma not sure if you saw, but I updated my response. I tried it out on Rails 5.2.0 as well. – Nate Nov 24 '18 at 18:54
  • Nate, it does in fact fallback to `:en` as you say. It didn't solve my problem though, I guess I am asking the wrong question, I made a mistake assuming what the problem was. I think I know what the problem is, it's us/me (as 99% of the time). Our nb.yml is the issue. A fresh Rails 5.2 app with the official nb.yml https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/nb.yml doesn't have the same problem. If I replace it with our nb.yml, the problem re-surface. I'll update my question, add info about what I learned and point to your answer for the fallback. – oma Nov 27 '18 at 07:41
  • Note: It doesn't make any sense to have the fallbacks `[:en, :es, :de]` in this order, because you could end up with a UI partly in 4 languages some of which your users don't speak. – Christopher Oezbek Mar 17 '21 at 20:09
1

Spree (4.1.5) + spree_i18n (3.3.2) on Rails (6.0.3.1), I wanted the site in Spanish and to fall back to English for missing translations. This is what worked for me:

# config/application.rb

config.after_initialize do
    config.i18n.default_locale = :es
    config.i18n.locale = :en
end
config.i18n.fallbacks = true

The config.after_initialize block is necessary, otherwise it wouldn't work (spree_i18n would mess the locales on initialization). That last config.i18n.fallbacks line is actually not needed since spree_i18n sets it to true on initialization. But I leave it there anyway so I know what is going on (furthermore, spree might stop overriding this in future versions since in development it might be useful not to use fallbacks thus making missing translations more visible).

pasqal
  • 131
  • 6