Globalize::DbTranslate with :include and no base language patch
Globalize DB translations currently doesn't support a :select find option, which breaks hasmany :trough => atranslateable_model associations.
I've refactored the Globalize::DbTranslate module to an AR::Associations pattern, override Model.find to always preload translations whilst removing all of the custom finder SQL.
Benefits
- Supports all of the ActiveRecord::Base#find functionality
- Plugs in with existing globalize table structures (no migrations required)
- There is no Base Locale.Edit or create in any language, any other language always retrieves a valid facet, albeit not always in the active Locale.
- Retrieves all facet translations for a given model at once, thus Locale switching doesn't incur a database roundtrip overhead.
Caveats
I removed a tiny bit of functionality to allow me to focus on a initial prototype.
- Bidi strings temp. removed
- Removed piggy backing find option
- Works best with only one Locale per request, which is fine in most situations.
- The no Base Locale setup might not be ideal for all use cases.
- Only tested with Edge (production, test and development envs)
- Globalize unit test helper chokes with the Dependencies mechanism and I couldn't yet get the unit tests to run.
The rundown
AR association and Translateable.find
Setup an association in the translates() hook:
has_many :translations, :class_name => 'Globalize::ModelTranslation', :conditions => ['globalize_translations.table_name = ?', table_name], :foreign_key => 'item_id'
Override Translateable.find, scoped to always prefetch translations:
alias_method :old_find, :find
def find(*args)
options = args.last.is_a?(Hash) ? args.last : {}
if (options.has_key?(:untranslated) && options[:untranslated] == true)
old_find(*args)
else
with_scope( :find => { :include => :translations }) do
old_find(*args)
end
end
end
Cherry pick facet content
def find_translation_for_facet( facet )
translations ||= []
#highest priority, find for current language
translations << self.translations.detect{|tr| tr.facet == facet.to_s && tr.language_id == Locale.language.id }
#do we have a non-blank attribute in the model table?
translations << read_attribute(facet)
#find the first translation, for any language
translations << self.translations.detect{|tr| tr.facet == facet.to_s && !tr.text.nil? }
#we don't want nil or empty string
translations.reject!(&:blank?)
translations.empty? ? nil : (translations.first.respond_to?(:text) ? translations.first.text : translations.first)
end
The patch
Grab this patch and give it a whirl.
Feedback on this? Performance implications? Backwards compatibility?
1 comment
Jump to comment form | comments rss [?]