设计可以具有多语言字段的Domain对象的最佳方法是什么。一个示例可以是Product类,其中Description是多语言的。
我找到了很少的链接,但无法确定哪一个是最好的方式。
http://fabiomaulo.blogspot.com/2009/06/localized-property-with-nhibernate.html
(这会将所有本地化语言数据存储在一个字段中。如果我们从Sql查询,则可能会出现问题)
http://ayende.com/Blog/archive/2006/12/26/LocalizingNHibernateContextualParameters.aspx
(这个开头有一个警告,它是一个黑客,不再支持)
http://www.webdevbros.net/2009/06/24/create-a-multi-languaged-domain-model-with-nhibernate-and-c/
(这没有描述如何在数据库中构建多语言数据。)
任何有使用NHibernate和多语言数据经验的人。还有更好的方法吗?
答案 0 :(得分:2)
第三种选择看起来很棒。给出了hibernate映射,但没有给出数据库模式 - 如果这是你缺少的,那么我将在这里草拟它:
dictionary
----------
ID: int - identity
name: nvarchar(255)
phrase
------
dictionary_id:int (fkey dictionary.ID)
culture_id:int (LCID)
phrase:nvarchar(255) - this is the default size - seems too small
根据this blog entry,255是String值的默认字符串长度。要克服短语文本中的短字符串长度,您可以将<element>
标记更改为
<element column="phrase" type="String" length="4001"></element>
要在您的域模型中使用此功能,请向您想要可翻译文本的实体添加PhraseDictionary
属性。例如。 title属性或decription属性。
我认为这篇文章描述了一个很好的方法,而且是我要去的方法 对于。
编辑:在回复评论时,如果您知道绝对最大尺寸小于该值,则使长度小于4001,因为这通常会更快。此外,NHibernate将懒惰地获取集合,但它可以一次获取所有项目。您可以进行分析以确定这是否具有任何性能影响。 (如果您只有少数几种语言,那么我怀疑您会发现不同之处。)如果您有多种语言(Say 50+),那么创建自定义属性以获取本地化文本可能是值得的。这些将发出查询以专门获取所需的文本。更重要的是,您可以在一个查询中获取给定实体的所有文本,而不是将每个本地化文本属性作为单独的查询。
请注意,只有在分析表明您有理由关注性能时才需要额外的努力。有可能本文中的实施将充分发挥作用。
答案 1 :(得分:1)
我只有Hibernate的经验,但是因为nHibernate非常相似:
一个选项是定义一个组件类型MultilingualString,其中包含每种语言的成员(假设编码时已知这组语言)。此类型也是通过语言ID为字符串放置getter的便捷位置。
class MultiLingualString {
String english;
String chinese;
String klingon;
String forLanguage(Language lang) {
switch (lang) {
// you can guess what goes here
}
}
}
这导致所有语言的字符串存储在数据库的单独列中,而对象世界中的表示保留了精细的粒度。
优点是不需要连接来获取字符串。另一方面,不使用这种方法获取字符串的唯一方法是使用投影,如果字符串很大,很多且很少需要,这是一个严重的限制。
如果你这么做,写一个UserType可能是值得的。
答案 2 :(得分:1)
从SQL Server的严格数据库角度来看,您应该拥有一个包含所有基本数据(记录密钥,日期,数字等)的表和一个包含所有可翻译字符串数据的表。让我们调用两个表Base和Base_Description。
Base确保每条记录都有一个密钥,密钥可能是字符串或自动生成的id,具体取决于您的特定用例。
Base_Description表与Base表相关,但也包含一个值,用于选择数据所在的语言。在我的项目中,我们使用sys.languages中的langid列,因为我们可以设置语言与连接,然后使用@@ LANGID获取大多数操作。
在我们的测试中,我们发现这比每种语言有多个字段要快得多,它还允许您更轻松地添加其他语言。我们还使用SQL Server全文索引,它完全适用于此方法。您应该使用中性语言进行索引,然后您可以选择要在运行时搜索的语言(也可以过滤Base_Description中的LangID列)。
答案 3 :(得分:1)
您的要求是否包含在同一对象中实际具有多语言属性的域对象?并且,如果是这样,是否存储在对象中的无限翻译(在集合中,比如说 - 在这种情况下我会说它需要像任何主/细节或父/子集合)或固定的翻译,其中案例语言(以及因此映射到存储过程或其他的结果)必须以静态方式确定?
在我工作的许多国际化应用程序中,数据只有一种语言 - 客户名称,产品名称(将一个国家使用的相同产品映射到另一个国家/地区的产品没有任何意义,它们都有不同的分销商和不同的SKU,当然还有本地化的定价)。界面也只有一种语言(一次)。因此,所有域对象一次只需要一种语言。因此,当对象被实例化时,将确定翻译的语言。
我们有翻译用户界面,允许用户更新翻译的文本,但这些只需要一次两种语言(本地和默认)。我可以看到这与你所说的最接近。我猜你会为每个可翻译的属性设置子集合,并在集合中包含所有可能的翻译。这可能与您链接的第三篇文章中的第二个解决方案最接近。当然,此时您还需要查看是否需要急切/延迟加载等。