Module: Models::Translatable
- Extended by:
- ActiveSupport::Concern, Mobility
- Included in:
- CatalogItem, Item, ProductLine, ProductSpecification, Video
- Defined in:
- app/concerns/models/translatable.rb
Overview
Mobility-based translation handling for translated models: guards against
NULL translations containers and compacts redundant sub-locale values
(e.g. en-US identical to en) into the base locale before validation.
Instance Attribute Summary collapse
-
#do_not_compact_translation_container ⇒ Object
Returns the value of attribute do_not_compact_translation_container.
Class Method Summary collapse
-
.skip_compaction_for(*attributes) ⇒ void
Marks attributes whose regional translations must never be folded into the base locale during compaction.
Instance Method Summary collapse
-
#compact_translation_container ⇒ void
This method cleans up the translation container, prevents blanks from saving Also if a locale and its fallback are the same, only keep the fallback e.g if you have en-US and an en translation which are the same, we don't need to store and maintain en-US.
Instance Attribute Details
#do_not_compact_translation_container ⇒ Object
Returns the value of attribute do_not_compact_translation_container.
14 15 16 |
# File 'app/concerns/models/translatable.rb', line 14 def do_not_compact_translation_container @do_not_compact_translation_container end |
Class Method Details
.skip_compaction_for(*attributes) ⇒ void
This method returns an undefined value.
Marks attributes whose regional translations must never be folded into
the base locale during compaction.
40 41 42 |
# File 'app/concerns/models/translatable.rb', line 40 def skip_compaction_for(*attributes) self.attributes_to_skip_compaction = attributes.map(&:to_s) end |
Instance Method Details
#compact_translation_container ⇒ void
This method returns an undefined value.
This method cleans up the translation container, prevents blanks from saving
Also if a locale and its fallback are the same, only keep the fallback
e.g if you have en-US and an en translation which are the same, we don't need
to store and maintain en-US
This works with column_fallback by moving values from sub-locales (en-US, en-CA)
to their base locale (en) and then removing the sub-locale.
A regional value that genuinely DIFFERS from its base is left alone: folding
it would overwrite the base with regional copy and lose the distinction.
Only the base locale is affected — I18n.fallbacks[:fr] is [:fr], so fr
and en are never compaction candidates in the first place.
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'app/concerns/models/translatable.rb', line 61 def compact_translation_container return if translations.blank? translations.dup.each do |translation_locale, translated_values| locale_sym = translation_locale.to_sym _, locale_fallback = I18n.fallbacks[locale_sym] # Skip if there's no fallback or if this is already a base locale next unless locale_fallback.present? && locale_sym != locale_fallback # For sub-locales like en-US, en-CA that fall back to en: # Move their values to the fallback locale and remove the sub-locale moved_keys = translated_values.filter_map do |key, value| # Skip if this attribute is marked to skip compaction next if attributes_to_skip_compaction.include?(key.to_s) backend_accessor = begin send(:"#{key}_backend") rescue StandardError nil end next if backend_accessor.nil? # Only fold a REDUNDANT regional value into its base. This used to write # unconditionally, so a genuinely distinct regional value (a Canadian # name differing from the US one) silently overwrote the base — the # opposite of the "if a locale and its fallback are the same, only keep # the fallback" intent documented above, and the reason callers reach # for do_not_compact_translation_container. base_value = backend_accessor.read(locale_fallback) next unless base_value.blank? || base_value == value # Write the value to the fallback locale (this will use column_fallback if configured) backend_accessor.write(locale_fallback, value) # Clear the sub-locale value backend_accessor.write(locale_sym, nil) key end # Remove the now-empty sub-locale from translations, but only once every # key really moved — a key retained above because it differs from its base # still needs its container entry. if moved_keys.size == translated_values.keys.size Rails.logger.info "Compacting translation locale: #{translation_locale} from #{self.class.name} #{id} (moved to fallback #{locale_fallback})" translations.delete(translation_locale) end end @do_not_compact_translation_container = true end |