Class: TranslationOverride

Inherits:
ActiveRecord::Base
  • Object
show all
Includes:
HasSanitizableFields
Defined in:
app/models/translation_override.rb

Constant Summary collapse

ALLOWED_CUSTOM_INTERPOLATION_KEYS =

Allowlist i18n interpolation keys that can be included when customizing translations

{
  %w[
    user_notifications.user_
    user_notifications.only_reply_by_email
    user_notifications.reply_by_email
    user_notifications.visit_link_to_respond
    user_notifications.header_instructions
    user_notifications.pm_participants
    unsubscribe_mailing_list
    unsubscribe_link_and_mail
    unsubscribe_link
  ] => %w[
    topic_title
    topic_title_url_encoded
    message
    url
    post_id
    topic_id
    context
    username
    group_name
    unsubscribe_url
    subject_pm
    participants
    site_description
    site_title
    site_title_url_encoded
    site_name
    optional_re
    optional_pm
    optional_cat
    optional_tags
  ],
  %w[system_messages.welcome_user] => %w[username name name_or_username],
}

Class Method Summary collapse

Instance Method Summary collapse

Methods included from HasSanitizableFields

#sanitize_field

Class Method Details

.custom_interpolation_keys(translation_key) ⇒ Object



132
133
134
135
136
# File 'app/models/translation_override.rb', line 132

def self.custom_interpolation_keys(translation_key)
  ALLOWED_CUSTOM_INTERPOLATION_KEYS.find do |keys, value|
    break value if keys.any? { |k| translation_key.start_with?(k) }
  end || []
end

.reload_all_overrides!Object



89
90
91
92
93
94
95
# File 'app/models/translation_override.rb', line 89

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 { |locale, keys| clear_cached_keys!(locale, keys) }
end

.revert!(locale, keys) ⇒ Object



83
84
85
86
87
# File 'app/models/translation_override.rb', line 83

def self.revert!(locale, keys)
  keys = Array.wrap(keys)
  TranslationOverride.where(locale: locale, translation_key: keys).delete_all
  i18n_changed(locale, keys)
end

.transform_pluralized_key(key) ⇒ Object

We use English as the source of truth when extracting interpolation keys, but some languages, like Arabic, have plural forms (zero, two, few, many) which don’t exist in English (one, other), so we map that here in order to find the correct, English translation key in which to look.



127
128
129
130
# File 'app/models/translation_override.rb', line 127

def self.transform_pluralized_key(key)
  match = key.match(/(.*)\.(zero|two|few|many)\z/)
  match ? match.to_a.second + ".other" : key
end

.upsert!(locale, key, value) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'app/models/translation_override.rb', line 67

def self.upsert!(locale, key, value)
  params = { locale: locale, translation_key: key }

  translation_override = find_or_initialize_by(params)
  sanitized_value =
    translation_override.sanitize_field(value, additional_attributes: %w[data-auto-route target])
  original_translation =
    I18n.overrides_disabled { I18n.t(transform_pluralized_key(key), locale: :en) }

  data = { value: sanitized_value, original_translation: original_translation }

  params.merge!(data) if translation_override.new_record?
  i18n_changed(locale, [key]) if translation_override.update(data)
  translation_override
end

Instance Method Details

#current_defaultObject



170
171
172
# File 'app/models/translation_override.rb', line 170

def current_default
  I18n.overrides_disabled { I18n.t(transformed_key, locale: :en) }
end

#invalid_interpolation_keysObject



155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'app/models/translation_override.rb', line 155

def invalid_interpolation_keys
  return [] if current_default.blank?

  original_interpolation_keys = I18nInterpolationKeysFinder.find(current_default)
  new_interpolation_keys = I18nInterpolationKeysFinder.find(value)
  custom_interpolation_keys = []

  ALLOWED_CUSTOM_INTERPOLATION_KEYS.select do |keys, value|
    custom_interpolation_keys = value if keys.any? { |key| transformed_key.start_with?(key) }
  end

  (original_interpolation_keys | new_interpolation_keys) - original_interpolation_keys -
    custom_interpolation_keys
end

#make_up_to_date!Object



178
179
180
181
182
# File 'app/models/translation_override.rb', line 178

def make_up_to_date!
  return unless outdated?
  self.original_translation = current_default
  update_attribute!(:status, :up_to_date)
end

#message_format?Boolean

Returns:

  • (Boolean)


174
175
176
# File 'app/models/translation_override.rb', line 174

def message_format?
  translation_key.to_s.end_with?("_MF")
end

#original_translation_deleted?Boolean

Returns:

  • (Boolean)


143
144
145
146
147
# File 'app/models/translation_override.rb', line 143

def original_translation_deleted?
  !I18n.overrides_disabled { I18n.t!(transformed_key, locale: :en) }.is_a?(String)
rescue I18n::MissingTranslationData
  true
end

#original_translation_updated?Boolean

Returns:

  • (Boolean)


149
150
151
152
153
# File 'app/models/translation_override.rb', line 149

def original_translation_updated?
  return false if original_translation.blank?

  original_translation != current_default
end