EF Code First 多语言支持

发布于 2024-12-19 11:29:31 字数 295 浏览 0 评论 0原文

假设您必须使用 EF Code First 和 POCO 类开发一个支持多种语言的网站,您将如何对 POCO 类进行建模来支持这种情况?

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

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

Assuming you have to develop a website supporting multiple languages with EF Code First and POCO classes how would you model your POCO classes to support this scenario?

By multi-language support I meant not only having e.g. labels translation in some resource files for your UI, but also you'd need to store Name, Description, etc for a given domain entity in your database.

E.g.: Let's say your Domain model has an entity Product. In your database you need to store the Product' Name & Description (2 fields for simplicity) for 2 languages(but more languages can be added in the future).
Based on the current culture, the UI needs to pick up the labels' text from the resource files(this is easy to implement) but you also need to display the Product' Name & Description that comes from the database.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

同展鸳鸯锦 2024-12-26 11:29:31

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

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

  1. 您有一个 Product 类,它的 ProductName 属性为 MultilingualString 类型
  2. MultilingualString 类对每种未知语言都有一个默认文本,并有一个列表这段文字的翻译。它具有设置不同翻译的方法(SetTranslation)和翻译为特定语言的方法。最后,这个类有一个属性 tu 翻译为当前线程区域性(翻译)
  3. 你有一个包含语言和翻译文本的 Translation 类

这里的代码:

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));

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

Finally I have made my own classes to support multilingual in my database data.

I'm Spanish and I have translated my code for post here, Maybe it have simple syntax errors,

  1. You have a Product class that have a ProductName property as a MultilingualString type
  2. MultilingualString class have a default text for every unknown language and have a list of translations of this text. It have methods for set the different translations (SetTranslation) and methods to translate to specific language. By the end this class have a property tu translate to the current thread culture (Translation)
  3. You have the Translation class which have the language and the translated text

Here the code:

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; }
}

You can build the DbContext class and make some test like this:

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();


        }
    }
}

I have just to end it, I hope this works fine ;)

Best regards!

UPDATE

One more thing, when you remove the product don't remove the multilingual string entry. You can add bussines logical to your services and remove the multilingual entry when you remove the product.

Or not!. if you don't remove the multilingual entry you will have more and more MultilingualStrings entries and you could take advantage of this repository to offer translated products names for the future products.

You can add MultilingualStrings set to the context:

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

Then you can search MultilingualStrings in the ProductNameTextBoxOnChange event for example:

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

And you can using this repository for other properties of other entities that have multilingual strings.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文