EF Code First多语言支持

2 multilingual ef-code-first

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

通过多语言支持,我的意思是不仅要在UI的某些资源文件中进行标签转换,而且还需要为数据库中的给定域实体存储名称,描述等.

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

Jav*_*Ros 8

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

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

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

这里的代码:

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; }
}
Run Code Online (Sandbox Code Playgroud)

您可以构建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();


        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我只想结束它,我希望这工作正常;)

最好的祝福!

UPDATE

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

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

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

public class MultilingualContext : DbContext
{
    public DbSet<Product> Products { get; set; }
    public DbSet<MultilingualString> MultilingualStrings { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

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

context.MultilingualStrings.Where(s => s.Translation.StartsWith(ProductNameTextBox.Text));
Run Code Online (Sandbox Code Playgroud)

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