How to create this MongoMapper custom data type?
I'm trying to create a custom MongoMapper data type in RoR 2.3.5 called Translatable:
class Translatable < String
def initialize(translation, culture="en")
end
def languages
end
def has_translation(culture)?
end
def self.to_mongo(value)
end
def self.from_mongo(value)
end
end
I want to be able to use it like this:
class Page
include MongoMapper::Document
key :title, Translatable, :required => true
key :content, String
end
Then implement like this:
p = Page.new
p.title = "Hello"
p.title(:fr) = "Bonjour"
p.title(:es) = "Hola"
p.content = "Some content here"
p.save
p = Page.first
p.languag开发者_StackOverflow社区es
=> [:en, :fr, :es]
p.has_translation(:fr)
=> true
en = p.title
=> "Hello"
en = p.title(:en)
=> "Hello"
fr = p.title(:fr)
=> "Bonjour"
es = p.title(:es)
=> "Hola"
In mongoDB I imagine the information would be stored like:
{ "_id" : ObjectId("4b98cd7803bca46ca6000002"), "title" : { "en" :
"Hello", "fr" : "Bonjour", "es" : "Hola" }, "content" : "Some content
here" }
So Page.title is a string that defaults to English (:en) when culture is not specified.
I would really appreciate any help.
You haven't told us how Translatable stores its internal representation of the various translated versions. Aside from the MongoMapper integration, do you have a working Translatable class? If so, could you post the full source?
I'll assume, for argument's sake, Translateable has a Hash instance variable called @translated_versions, which maps from culture Symbols to translated Strings. You could then implement the MongoMapper integration as:
class Translatable < String
attr_reader :translated_versions
def initialize(value)
@translated_versions = value
end
def self.to_mongo(value)
value.translated_versions
end
def self.from_mongo(value)
self.new(value)
end
end
This would get you far enough to store your Translatable instances as MongoMapper keys. Note that p.languages and p.has_translation(:fr) would still not work, as you only defined those methods on Translatable, not Page. You'd either need to call p.title.languages and p.title.has_translation(:fr), or add code to Page to delegate those methods to title for you.
it's better to use the i18n gem to handle + store the translations! and to just specify a I18N-lookup-key in your model, which then uses the I18N translate() method to lookup the correct translation based on the user's locale..
In your case, I'd suggest to just store a symbolic page title, which is then used as a lookup-key for I18N
The I18N-keys are looked up in the static translation files under ./config/locales/
See:
http://guides.rubyonrails.org/i18n.html
Exception:
only if you want have users be able to dynamically specify translations within your web-app, you might want to store the translations in a database.
After a bit of digging, I found this gem, which stores the translations in ActiveRecord:
This can probably get adapted for MongoDB pretty easily:
https://github.com/grosser/fast_gettext
https://github.com/grosser/fast_gettext/blob/master/examples/db/migration.rb
Also:
http://groups.google.com/group/rails-i18n/browse_thread/thread/6b7ba3c401890a7e
https://github.com/svenfuchs/i18n/blob/df498763cd1968c58900d66a322325d9db8b0d06/lib/i18n/backend/active_record/translation.rb#L18
精彩评论