Last active
October 28, 2024 20:10
-
-
Save westonganger/7d56856ff441253f9145380c6fab0d3b to your computer and use it in GitHub Desktop.
Good Rails I18n Backend Setup
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module I18n | |
class CustomExceptionHandler < ExceptionHandler | |
def call(exception, locale, key, options) | |
if exception.is_a?(MissingTranslation) && key.to_s != 'i18n.plural.rule' | |
raise exception.to_exception | |
else | |
super | |
end | |
end | |
end | |
end | |
### Exception handler to actually raise translation missing exceptions instead of showing 'translation missing' text | |
I18n.exception_handler = I18n::CustomExceptionHandler.new | |
module I18n | |
module Backend | |
class Custom | |
### Translations are stored in DB and synced to redis | |
### Translations are loaded per-app from Redis | |
include I18n::Backend::Base | |
include I18n::Backend::Flatten | |
def translations | |
@translations || set_translations | |
end | |
def available_locales | |
@available_locales || set_available_locales | |
end | |
def initialized? | |
!@translations.nil? | |
end | |
def reload! | |
set_translations | |
return true | |
end | |
def translate(locale, key, options = EMPTY_HASH) | |
split_keys = I18n.normalize_keys(locale, key, options[:scope], options[:separator]) | |
val = translations.dig(*split_keys) | |
if val.blank? && options[:fallback] | |
if val.blank? && I18n.locale != I18n.default_locale | |
alternate_split_keys = split_keys.dup | |
alternate_split_keys[2] = I18n.default_locale.to_s | |
val = translations.dig(*alternate_split_keys) | |
end | |
# if val.blank? | |
# generic_key = "common.#{key.to_s.split(".").last}" | |
# if I18n.exists?(generic_key) | |
# return I18n.t(generic_key, fallback: false) | |
# end | |
# end | |
end | |
if val.blank? | |
#throw(:exception, I18n::MissingTranslation.new(locale, key, options)) | |
return nil | |
else | |
return val | |
end | |
end | |
def store_translations(locale, data, options = EMPTY_HASH) | |
### IN-MEMORY STORE | |
if @translations.nil? | |
set_translations | |
end | |
locale = locale.to_sym | |
@temporary_translations ||= {} | |
#flattened_h = flatten_translations(locale, data, options.fetch(:escape, true), false) | |
#raise "#{flattened_h}" ### DEBUG | |
@temporary_translations[locale] ||= Concurrent::Hash.new | |
@temporary_translations[locale] = @temporary_translations[locale].deep_merge(data.deep_symbolize_keys) | |
@translations = @translations.deep_merge(@temporary_translations) | |
set_available_locales | |
return true | |
end | |
protected | |
def set_translations | |
@translations = Concurrent::Hash.new | |
db_translation_data = REDIS.get("translations").fetch(APP_NAME).with_indifferent_access rescue {} | |
@translations = @translations.deep_merge(db_translation_data) | |
if @temporary_translations | |
@translations = @translations.deep_merge(@temporary_translations) | |
end | |
set_available_locales | |
return @translations | |
end | |
def set_available_locales | |
@available_locales = translations.keys.map{|x| x.to_sym} | |
end | |
end | |
end | |
end | |
backend_chain = [I18n::Backend::Custom.new] | |
if Rails.env.development? || Rails.env.test? | |
### Keeps the original YAML backend as a fallback so that local development still works without a populated translation DB | |
backend_chain << I18n::Backend::Simple.new | |
end | |
I18n.backend = I18n::Backend::Chain.new(*backend_chain) | |
### Manually add any additional translations here | |
# I18n.backend.store_translations :en, foo: {bar: {foobar: 'asd'} } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment