Translating shared attributes

by ewout

ActiveRecord can translate the attribute names of a model when the translation is in a predefined path in the locale file. This is more powerful than I18n.translate, since functionality like form helpers can build on top of that. However, there are attribute names that are shared between multiple or all models. Translating them over and over again for every model is not DRY. One solution:

en:
  activerecord:
    attributes:
      shared:
        created_at: Date created
        updated_at: Date updated

Given this locale file, we can find the attribute name of a model, even if it is shared:

Person.human_attribute_name(:created_at, :default => :'shared.created_at')

This requires the caller to know about the shared attributes and violates encapsulation. Instead, ActiveRecord can be extended to look for shared attributes.

# Allow shared attributes to be defined in the locale file.
# active_record > attributes > shared
class ActiveRecord::Base
  class << self
    def human_attribute_name_with_default(attribute_key_name, options = {})
      (options[:default] ||= []) << :"shared.#{attribute_key_name}"
      human_attribute_name_without_default(attribute_key_name, options)
    end

    alias :human_attribute_name_without_default :human_attribute_name
    alias :human_attribute_name :human_attribute_name_with_default
  end
end
Fork me on GitHub