discourse/app/models/translation_override.rb
Sam Saffron 30990006a9 DEV: enable frozen string literal on all files
This reduces chances of errors where consumers of strings mutate inputs
and reduces memory usage of the app.

Test suite passes now, but there may be some stuff left, so we will run
a few sites on a branch prior to merging
2019-05-13 09:31:32 +08:00

118 lines
3.3 KiB
Ruby

# frozen_string_literal: true
require "i18n/i18n_interpolation_keys_finder"
class TranslationOverride < ActiveRecord::Base
# 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
}
}
validates_uniqueness_of :translation_key, scope: :locale
validates_presence_of :locale, :translation_key, :value
validate :check_interpolation_keys
def self.upsert!(locale, key, value)
params = { locale: locale, translation_key: key }
data = { value: value }
if key.end_with?('_MF')
_, filename = JsLocaleHelper.find_message_format_locale([locale], fallback_to_english: false)
data[:compiled_js] = JsLocaleHelper.compile_message_format(filename, locale, value)
end
translation_override = find_or_initialize_by(params)
params.merge!(data) if translation_override.new_record?
i18n_changed([key]) if translation_override.update(data)
translation_override
end
def self.revert!(locale, *keys)
TranslationOverride.where(locale: locale, translation_key: keys).delete_all
i18n_changed(keys)
end
def self.i18n_changed(keys)
I18n.reload!
MessageBus.publish('/i18n-flush', refresh: true)
keys.flatten.each do |key|
return if expire_cache(key)
end
end
def self.expire_cache(key)
if key.starts_with?('post_action_types.')
ApplicationSerializer.expire_cache_fragment!("post_action_types_#{I18n.locale}")
elsif key.starts_with?('topic_flag_types.')
ApplicationSerializer.expire_cache_fragment!("post_action_flag_types_#{I18n.locale}")
else
return false
end
Site.clear_anon_cache!
true
end
private_class_method :i18n_changed
private_class_method :expire_cache
private
def check_interpolation_keys
original_text = I18n.overrides_disabled do
# lookup is protected
I18n.backend.send(:lookup, self.locale, self.translation_key)
end
if original_text
original_interpolation_keys = I18nInterpolationKeysFinder.find(original_text)
new_interpolation_keys = I18nInterpolationKeysFinder.find(value)
custom_interpolation_keys = []
CUSTOM_INTERPOLATION_KEYS_WHITELIST.select do |key, value|
if self.translation_key.start_with?(key)
custom_interpolation_keys = value
end
end
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(', ')
))
return false
end
end
end
end
# == 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
# compiled_js :text
#
# Indexes
#
# index_translation_overrides_on_locale_and_translation_key (locale,translation_key) UNIQUE
#