Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rails - how to dynamically add/override wording to i18n yaml

as an example, i have a default english locale file "en.yml" with contents:

 en:
  messages: messages
  users: users

now, there is a customer which wants messages to be named discussions in his product, but users should remain users. so what i want to do is to create "customer.en.yml" file

en:
 messages: discussions

which would override the default "messages" translation, but would keep all the other words same. how can i achieve it?

because if i load en.yml with :

config.i18n.load_path += Dir[File.join(RAILS_ROOT, 'config', 'locales', '*.{rb,yml}')] 

and afterwards load customer.en.yml (APP_CONFIG['customer_name'] is defined before) with

config.i18n.load_path += Dir[File.join(RAILS_ROOT, 'config', 'custom_locales',  APP_CONFIG['customer_name']+'.{rb|yml}')]

it will just overwrite my "en" locale, and "users" translation will disappear, right?

like image 646
Pavel K. Avatar asked Dec 03 '09 14:12

Pavel K.


3 Answers

Use i18n.fallbacks

I'm not sure when this was added to Rails, but in 4.2.2 you can do:

# application.rb
# If key is not found in a locale, we look in fallback
config.i18n.fallbacks = {
  "locale_1"    => "en",
  "locale_2"    => "en",
  "locale_3"    => "de",
}

If you also set config.action_view.raise_on_missing_translations = true (which I do in development and test), it will raise only if a key isn't found in the locale or the fallback.

like image 112
Nathan Long Avatar answered Nov 14 '22 17:11

Nathan Long


It should not overwrite your "en" locale. Translations are merged. store_translations in the simple I18n backend calls merge_translations, which looks like this:

# Deep merges the given translations hash with the existing translations
# for the given locale
def merge_translations(locale, data)
  locale = locale.to_sym
  translations[locale] ||= {}
  data = deep_symbolize_keys(data)

  # deep_merge by Stefan Rusterholz, see http://www.ruby-forum.com/topic/142809
  merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
  translations[locale].merge!(data, &merger)
end

As you can see, only the keys you enter in the latter translation yml file will be overwritten.

like image 37
Clinton Dreisbach Avatar answered Nov 14 '22 18:11

Clinton Dreisbach


I wanted something similar when we were writing a pirate.yml translation, but I wanted anything not defined in pirate.yml to default to what we had in en.yml.

What I wrote can be found on Github.

like image 1
Amiel Martin Avatar answered Nov 14 '22 16:11

Amiel Martin