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



121
122
123
124
125
# File 'app/models/translation_override.rb', line 121

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



76
77
78
79
80
81
82
# File 'app/models/translation_override.rb', line 76

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



70
71
72
73
74
# File 'app/models/translation_override.rb', line 70

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.



116
117
118
119
# File 'app/models/translation_override.rb', line 116

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



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'app/models/translation_override.rb', line 50

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: ["data-auto-route"])
  original_translation =
    I18n.overrides_disabled { I18n.t(transform_pluralized_key(key), locale: :en) }

  data = { value: sanitized_value, original_translation: original_translation }
  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, sanitized_value)
  end

  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



159
160
161
# File 'app/models/translation_override.rb', line 159

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

#invalid_interpolation_keysObject



144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'app/models/translation_override.rb', line 144

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

#original_translation_deleted?Boolean

Returns:

  • (Boolean)


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

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)


138
139
140
141
142
# File 'app/models/translation_override.rb', line 138

def original_translation_updated?
  return false if original_translation.blank?

  original_translation != current_default
end