EF Code First多语言支持

时间:2011-12-03 12:01:19

标签: ef-code-first multilingual

假设您必须使用EF Code First和POCO课程开发支持多种语言的网站,您将如何为POCO类建模以支持此方案?

通过多语言支持我的意思不仅仅是在UI的某些资源文件中标记翻译,但您还需要为数据库中的给定域实体存储名称,描述等。

例如:假设您的域模型有实体产品。在您的数据库中,您需要存储产品名称& 2种语言的描述(简单2个字段)(但将来可以添加更多语言)。 根据当前的文化,用户界面需要从资源文件中获取标签的文本(这很容易实现),但您还需要显示产品的名称和名称。来自数据库的描述。

1 个答案:

答案 0 :(得分:7)

最后,我已经创建了自己的类来支持我的数据库数据中的多语言。

我是西班牙语,我已经在这里翻译了我的代码,也许它有简单的语法错误,

  1. 您的Product类具有Productling属性作为MultilingualString类型
  2. MultilingualString类具有每种未知语言的默认文本,并具有此文本的翻译列表。它有设置不同翻译(SetTranslation)的方法和翻译成特定语言的方法。到最后,这个类有一个属性tu转换为当前的线程文化(翻译)
  3. 您拥有包含语言和翻译文本的翻译课程
  4. 这里是代码:

    public class Product
    {
        public int Id { get; set; }
        public MultilingualString ProductName { get; set; }
    }
    
    public class MultilingualString
    {
        // You need it only to make the class persistent
        public int Id { get; set; }
    
        public string Text { get; set; }
        public virtual ICollection<Translation> Translations { get; set; }
    
        public string Translation { get { return Translate(); } }
    
        public void SetTranslation(string language, string text)
        {
            if (Translations == null)
                Translations = new List<Translation>();
    
            var found = Translations.Where(t => t.Language.ToUpper() == language.ToUpper()).FirstOrDefault();
            if (found == null)
                Translations.Add(new Translation() { Language = language, Text = text });
            else
                found.Text = text;
        }
    
        public string Translate(string cultureName)
        {
            return Translate(new CultureInfo(cultureName));
        }
    
    
        public string Translate(CultureInfo culture = null)
        {
            if (culture == null)
                culture = Thread.CurrentThread.CurrentCulture;
    
            var translation = Translations == null
                                 ? null
                                 : Translations.Where(
                                     t =>
                                     culture.Name.ToUpper(CultureInfo.InvariantCulture).StartsWith(
                                         t.Language.ToUpper(CultureInfo.InvariantCulture))).FirstOrDefault();
    
            return translation == null ? Text : translation.Text;
        }
    }
    
    public class Translation
    {
        // You need it only to make the class persistent
        public int Id { get; set; }
        public string Language { get; set; }
        public string Text { get; set; }
    }
    

    您可以构建DbContext类并进行如下测试:

    public class MultilingualContext : DbContext
    {
        public DbSet<Product> Products { get; set; }
    }
    
    [TestClass]
    public class Tests
    {
        [TestMethod]
        public void ThisWorksFine()
        {
            using (var context = new MultilingualContext())
            {
                var product = new Product();
                context.Products.Add(product);
    
                product.ProductName = new MultilingualString() { Text = "Beer (default language)" };
                product.ProductName.SetTranslation("en", "Beer");
                product.ProductName.SetTranslation("es", "Cerveza");
                product.ProductName.SetTranslation("fr", "Bière");
                product.ProductName.SetTranslation("de", "Bier");
    
                var spanishProductName = product.ProductName.Translate(new CultureInfo("es"));
                Assert.AreEqual(spanishProductName, "Cerveza");
    
                var culture = Thread.CurrentThread.CurrentCulture;
    
                Thread.CurrentThread.CurrentCulture = new CultureInfo("en");
                Assert.AreEqual(product.ProductName.Translation, "Beer");
                Thread.CurrentThread.CurrentCulture = new CultureInfo("es");
                Assert.AreEqual(product.ProductName.Translation, "Cerveza");
                Thread.CurrentThread.CurrentCulture = new CultureInfo("fr");
                Assert.AreEqual(product.ProductName.Translation, "Bière");
                Thread.CurrentThread.CurrentCulture = new CultureInfo("de");
                Assert.AreEqual(product.ProductName.Translation, "Bier");
                Thread.CurrentThread.CurrentCulture = new CultureInfo("it");
                Assert.AreEqual(product.ProductName.Translation, "Beer (default language)");
    
                Thread.CurrentThread.CurrentCulture = culture;
    
                context.SaveChanges();
    
    
            }
        }
    }
    

    我只想结束它,我希望这很好用;)

    祝你好运!

    <强>更新

    还有一件事,当您删除产品时,请不要删除多语言字符串条目。您可以在服务中添加逻辑,并在删除产品时删除多语言条目。

    或不!如果您不删除多语言条目,您将拥有越来越多的MultilingualStrings条目,您可以利用此存储库为未来产品提供已翻译的产品名称。

    您可以将MultilingualStrings设置为上下文:

    public class MultilingualContext : DbContext
    {
        public DbSet<Product> Products { get; set; }
        public DbSet<MultilingualString> MultilingualStrings { get; set; }
    }
    

    然后您可以在ProductNameTextBoxOnChange事件中搜索MultilingualStrings,例如:

    context.MultilingualStrings.Where(s => s.Translation.StartsWith(ProductNameTextBox.Text));
    

    您可以将此存储库用于具有多语言字符串的其他实体的其他属性。