2019-05-02 18:17:27 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2017-06-15 04:08:23 -04:00
|
|
|
require "i18n/i18n_interpolation_keys_finder"
|
2016-04-08 14:49:50 -04:00
|
|
|
|
2015-11-13 16:34:13 -05:00
|
|
|
class TranslationOverride < ActiveRecord::Base
|
2017-11-20 03:10:06 -05:00
|
|
|
# Whitelist i18n interpolation keys that can be included when customizing translations
|
|
|
|
CUSTOM_INTERPOLATION_KEYS_WHITELIST = {
|
|
|
|
"user_notifications.user_" => %w{
|
|
|
|
topic_title_url_encoded
|
|
|
|
site_title_url_encoded
|
|
|
|
context
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-13 16:34:13 -05:00
|
|
|
validates_uniqueness_of :translation_key, scope: :locale
|
|
|
|
validates_presence_of :locale, :translation_key, :value
|
|
|
|
|
2017-06-15 04:08:23 -04:00
|
|
|
validate :check_interpolation_keys
|
|
|
|
|
2015-11-13 16:34:13 -05:00
|
|
|
def self.upsert!(locale, key, value)
|
|
|
|
params = { locale: locale, translation_key: key }
|
2016-04-08 14:49:50 -04:00
|
|
|
|
|
|
|
data = { value: value }
|
|
|
|
if key.end_with?('_MF')
|
2019-02-19 08:42:58 -05:00
|
|
|
_, filename = JsLocaleHelper.find_message_format_locale([locale], fallback_to_english: false)
|
2018-01-25 06:09:18 -05:00
|
|
|
data[:compiled_js] = JsLocaleHelper.compile_message_format(filename, locale, value)
|
2016-04-08 14:49:50 -04:00
|
|
|
end
|
|
|
|
|
2017-06-15 04:08:23 -04:00
|
|
|
translation_override = find_or_initialize_by(params)
|
|
|
|
params.merge!(data) if translation_override.new_record?
|
2020-05-18 12:05:34 -04:00
|
|
|
i18n_changed(locale, [key]) if translation_override.update(data)
|
2017-06-15 04:08:23 -04:00
|
|
|
translation_override
|
2015-11-20 12:30:04 -05:00
|
|
|
end
|
2015-11-17 16:14:42 -05:00
|
|
|
|
2020-05-18 12:05:34 -04:00
|
|
|
def self.revert!(locale, keys)
|
|
|
|
keys = Array.wrap(keys)
|
2015-11-20 12:30:04 -05:00
|
|
|
TranslationOverride.where(locale: locale, translation_key: keys).delete_all
|
2020-05-18 12:05:34 -04:00
|
|
|
i18n_changed(locale, keys)
|
2015-11-13 16:34:13 -05:00
|
|
|
end
|
|
|
|
|
2020-05-18 12:45:47 -04:00
|
|
|
def self.reload_all_overrides!
|
|
|
|
reload_locale!
|
|
|
|
|
|
|
|
overrides = TranslationOverride.pluck(:locale, :translation_key)
|
|
|
|
overrides = overrides.group_by(&:first).map { |k, a| [k, a.map(&:last)] }
|
|
|
|
overrides.each do |locale, keys|
|
|
|
|
clear_cached_keys!(locale, keys)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-05-18 12:05:34 -04:00
|
|
|
def self.reload_locale!
|
2018-03-16 16:46:49 -04:00
|
|
|
I18n.reload!
|
2019-11-04 20:15:44 -05:00
|
|
|
ExtraLocalesController.clear_cache!
|
2018-03-16 16:46:49 -04:00
|
|
|
MessageBus.publish('/i18n-flush', refresh: true)
|
2020-05-18 12:05:34 -04:00
|
|
|
end
|
2015-11-20 12:30:04 -05:00
|
|
|
|
2020-05-18 12:05:34 -04:00
|
|
|
def self.clear_cached_keys!(locale, keys)
|
|
|
|
should_clear_anon_cache = false
|
|
|
|
keys.each do |key|
|
|
|
|
should_clear_anon_cache |= expire_cache(locale, key)
|
2015-11-20 12:30:04 -05:00
|
|
|
end
|
2020-05-18 12:05:34 -04:00
|
|
|
Site.clear_anon_cache! if should_clear_anon_cache
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.i18n_changed(locale, keys)
|
|
|
|
reload_locale!
|
|
|
|
clear_cached_keys!(locale, keys)
|
2018-03-16 16:46:49 -04:00
|
|
|
end
|
2015-11-20 12:30:04 -05:00
|
|
|
|
2020-05-18 12:05:34 -04:00
|
|
|
def self.expire_cache(locale, key)
|
2018-03-16 16:46:49 -04:00
|
|
|
if key.starts_with?('post_action_types.')
|
2020-05-18 12:05:34 -04:00
|
|
|
ApplicationSerializer.expire_cache_fragment!("post_action_types_#{locale}")
|
2018-03-16 16:46:49 -04:00
|
|
|
elsif key.starts_with?('topic_flag_types.')
|
2020-05-18 12:05:34 -04:00
|
|
|
ApplicationSerializer.expire_cache_fragment!("post_action_flag_types_#{locale}")
|
2018-03-16 16:46:49 -04:00
|
|
|
else
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
true
|
|
|
|
end
|
2017-06-15 04:08:23 -04:00
|
|
|
|
2020-05-18 12:05:34 -04:00
|
|
|
private_class_method :reload_locale!
|
|
|
|
private_class_method :clear_cached_keys!
|
2018-03-16 16:46:49 -04:00
|
|
|
private_class_method :i18n_changed
|
|
|
|
private_class_method :expire_cache
|
2017-11-20 03:10:06 -05:00
|
|
|
|
2018-03-16 16:46:49 -04:00
|
|
|
private
|
2017-11-20 03:10:06 -05:00
|
|
|
|
2018-03-16 16:46:49 -04:00
|
|
|
def check_interpolation_keys
|
2019-10-17 12:34:07 -04:00
|
|
|
transformed_key = transform_pluralized_key(translation_key)
|
|
|
|
|
2018-03-16 16:46:49 -04:00
|
|
|
original_text = I18n.overrides_disabled do
|
2019-10-17 12:34:07 -04:00
|
|
|
I18n.t(transformed_key, locale: :en)
|
2018-03-16 16:46:49 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
if original_text
|
|
|
|
original_interpolation_keys = I18nInterpolationKeysFinder.find(original_text)
|
|
|
|
new_interpolation_keys = I18nInterpolationKeysFinder.find(value)
|
2017-11-20 03:10:06 -05:00
|
|
|
|
2018-03-16 16:46:49 -04:00
|
|
|
custom_interpolation_keys = []
|
2017-06-15 04:08:23 -04:00
|
|
|
|
2018-03-16 16:46:49 -04:00
|
|
|
CUSTOM_INTERPOLATION_KEYS_WHITELIST.select do |key, value|
|
2019-10-17 12:34:07 -04:00
|
|
|
if transformed_key.start_with?(key)
|
2018-03-16 16:46:49 -04:00
|
|
|
custom_interpolation_keys = value
|
2017-06-15 04:08:23 -04:00
|
|
|
end
|
|
|
|
end
|
2018-03-16 16:46:49 -04:00
|
|
|
|
|
|
|
invalid_keys = (original_interpolation_keys | new_interpolation_keys) -
|
|
|
|
original_interpolation_keys -
|
|
|
|
custom_interpolation_keys
|
|
|
|
|
|
|
|
if invalid_keys.present?
|
|
|
|
self.errors.add(:base, I18n.t(
|
|
|
|
'activerecord.errors.models.translation_overrides.attributes.value.invalid_interpolation_keys',
|
|
|
|
keys: invalid_keys.join(', ')
|
|
|
|
))
|
|
|
|
|
2019-12-09 19:48:27 -05:00
|
|
|
false
|
2018-03-16 16:46:49 -04:00
|
|
|
end
|
2017-06-15 04:08:23 -04:00
|
|
|
end
|
2018-03-16 16:46:49 -04:00
|
|
|
end
|
2017-06-15 04:08:23 -04:00
|
|
|
|
2019-10-17 12:34:07 -04:00
|
|
|
def transform_pluralized_key(key)
|
|
|
|
match = key.match(/(.*)\.(zero|two|few|many)$/)
|
|
|
|
match ? match.to_a.second + '.other' : key
|
|
|
|
end
|
2015-11-13 16:34:13 -05:00
|
|
|
end
|
2016-01-11 01:30:56 -05:00
|
|
|
|
|
|
|
# == Schema Information
|
|
|
|
#
|
|
|
|
# Table name: translation_overrides
|
|
|
|
#
|
|
|
|
# id :integer not null, primary key
|
|
|
|
# locale :string not null
|
|
|
|
# translation_key :string not null
|
|
|
|
# value :string not null
|
|
|
|
# created_at :datetime not null
|
|
|
|
# updated_at :datetime not null
|
2016-05-29 20:45:32 -04:00
|
|
|
# compiled_js :text
|
2016-01-11 01:30:56 -05:00
|
|
|
#
|
|
|
|
# Indexes
|
|
|
|
#
|
|
|
|
# index_translation_overrides_on_locale_and_translation_key (locale,translation_key) UNIQUE
|
|
|
|
#
|