Some more info after yesterdays trial and errors...
package models
import collection.immutable.Map
import collection.immutable.MapProxy
import play.api.i18n.Lang
/**
* Used to store a map of lang code -> translation
* {{{
* case class MyModel(
* name: LocalizedString,
* description: LocalizedString
* )
*
* val myModel = MyModel(
* name = LocalizedString("the name in my current locale"),
* description = LocalizedString("en" -> "An English description", "sv" -> "En Svensk beskrivning")
* )
*
* myModel.name = the name in my current locale
*
* myModel.name("default name") = if the LocalizedString doesn't contain the Lang it will use "default name"
*
* // We could also have the default message in a lang file
* import play.api.i18n.Messages
* myModel.name(Messages("name.default"))
*
* // And since the LocalizedString is also a map we have all the goodies from the Map API
* myModel.description.map((code, desc) => println("Description in: " + code + ": " + desc))
*
* }}}
* @param self
*/
class LocalizedString(val self: Map[String, String]) extends MapProxy[String, String] {
// Get localized string or fallback to if there is a string at all or fallback even further to an the default argument specified.
def apply(default: String = "")(implicit lang: Lang): String = self.get(lang.code).getOrElse(self.headOption.map(_._2).getOrElse(default))
// Get localized string or fallback to if there is a string at all and fallback even further to an empty string.
def toString()(implicit lang: Lang): String = apply()(lang)
}
object LocalizedString {
// Allow implicit conversions
def apply(foo: Map[String, String]) = new LocalizedString(foo)
implicit def map2LocalizedString(map: Map[String, String]): LocalizedString = LocalizedString(map)
implicit def localizedString2Map(localizedString: LocalizedString): Map[String, String] = localizedString.self
// Factory methods
def apply(): LocalizedString = new LocalizedString(Map.empty)
def apply(value: String)(implicit lang: Lang): LocalizedString = LocalizedString(lang.code -> value)
def apply(keys: (String, String)*): LocalizedString = new LocalizedString(Map(keys:_*))
}
The problem is that salat doesn't understand that LocalizedString is a sub type of Map and thus doesn't deserialize it.
It does serialize it though.
---------- CONSTRUCTOR EXPECTS FOR PARAM [1] --------------
NAME: name
TYPE: models.LocalizedString
DEFAULT ARG [Missing, but unnecessary because input value was supplied]
@Ignore false
---------- CONSTRUCTOR INPUT ------------------------
TYPE: com.mongodb.BasicDBObject
VALUE:
{ "en" : "English string" , "sv" : "Swedish string"}
------------------------------------------------------------
So my question is, can i force salat to use my LocalizedString or get it to understand subtypes of Map?