如何创建多语言域模型

Ces*_*Gon 5 multilingual domain-driven-design

我正在使用域驱动设计,我对我的域模型有一个非常清晰的描述.它包含120多个类,非常稳定.我们将在.NET 4和C#中实现它.问题是,我们需要模型多语言; 某些属性需要以多种语言存储.例如,Person类具有类型的Position属性,string该属性应该以英语(例如"Librarian")和西班牙语(例如"Bibliotecario")存储值.此属性的getter应根据某些语言参数返回英语或西班牙语版本.

在这里开始我的问题.我不知道如何参数化.我有两种主要方法可以做到:

  1. 使用属性集合.位置不是一个string而是一个Dictionary<Language, string>,它可以让客户通过语言检索人的位置.
  2. 保持简单的标量属性,但要根据全局已知的"当前语言"设置返回(或设置)一种或多种语言的值.客户端代码将设置工作语言,然后所有对象将设置并获取该语言的值.

选项1避免了全局状态,但它弄乱了我模型中几乎每个类的接口.另一方面,选项2的表达力较差,因为如果不查看全局设置,您无法分辨出将要获得的语言.此外,它还为全局设置中的每个类引入了依赖项.

请注意,我对数据库或ORM实现不感兴趣; 我只在域模型级别工作.

那我有两个具体的问题:

  • 哪个是实现我的多语言域模型目标的最佳选择(1或2)?
  • 还有其他我没有考虑的选择,它们是哪些?

谢谢.

编辑.有人建议这是一个与用户界面相关的问题,因此可以通过.NET中的全球化/本地化支持来解决.我不同意.只有当您知道在编译时必须向用户显示的本地化文字时,UI本地化才有效,但这不是我们的情况.我的问题涉及在编译时未知的多语言数据,因为它将在运行时作为用户数据提供.这不是与UI相关的问题.

编辑2.请记住,Person.Position只是一个说明问题的玩具示例.它不是真实模型的一部分.不要试图批评或改进它; 这样做没有意义.我们的业务需求涉及许多无法编码为枚举类型或类似的属性,并且必须保留为自由文本.因此困难.

小智 5

鉴于以下内容:

一些用例涉及在所有支持的语言中设置对象的值; 其他人则涉及在一种给定语言中查看价值观.

我建议两种选择.这意味着Person和所有持有多语言内容的类应该将该内容保持在其状态,并且:

  • Position属性应以当前用户的语言设置/获取人员的位置 .

  • 所有 语言设置/获取应该有相应的属性或方法.

  • 应该有一种方法来设置(甚至切换,如果需要)用户语言.我将使用抽象的SetLanguage(语言lang)方法和CurrentLanguage getter创建一个抽象类(例如BaseMultilingualEntity).您需要在某种类型的注册表中跟踪从BaseMultilingualEntity派生的所有对象,这些注册表将公开语言设置.

使用某些代码编辑

public enum Language {
    English,
    German
}

// all multilingual entity classes should derive from this one; this is practically a partly implemented observer
public abstract class BaseMultilingualEntity
{
    public Language CurrentLanguage { get; private set; }

    public void SetCurrentLanguage(Language lang)
    {
        this.CurrentLanguage = lang;
    }
}

// this is practically an observable and perhaps SRP is not fully respected here but you got the point i think
public class UserSettings
{
    private List<BaseMultilingualEntity> _multilingualEntities;

    public void SetCurrentLanguage(Language lang)
    {
        if (_multilingualEntities == null)
            return;

        foreach (BaseMultilingualEntity multiLingualEntity in _multilingualEntities)
            multiLingualEntity.SetCurrentLanguage(lang);
    }

    public void TrackMultilingualEntity(BaseMultilingualEntity multiLingualEntity)
    {
        if (_multilingualEntities == null)
            _multilingualEntities = new List<BaseMultilingualEntity>();

        _multilingualEntities.Add(multiLingualEntity);
    }
}

// the Person entity class is a multilingual entity; the intention is to keep the XXXX with the XXXXInAllLanguages property in sync
public class Person : BaseMultilingualEntity
{
    public string Position
    {
        set
        {
            _PositionInAllLanguages[this.CurrentLanguage] = value;
        }
        get
        {
            return _PositionInAllLanguages[this.CurrentLanguage];
        }
    }

    private Dictionary<Language, string> _PositionInAllLanguages;

    public Dictionary<Language, string> PositionInAllLanguages {
        get
        {
            return _PositionInAllLanguages;
        }
        set
        {
            _PositionInAllLanguages = value;
        }
    }
}

public class Program
{
    public static void Main()
    {

        UserSettings us = new UserSettings();
        us.SetCurrentLanguage(Language.English);

        Person person1 = new Person();
        us.TrackMultilingualEntity(person1);

        // use case: set position in all languages
        person1.PositionInAllLanguages = new Dictionary<Language, string> {
            { Language.English, "Software Developer" }, 
            { Language.German, "Software Entwikcler" }
        };

        // use case: display a person's position in the user language
        Console.WriteLine(person1.Position);

        // use case: switch language
        us.SetCurrentLanguage(Language.German);
        Console.WriteLine(person1.Position);

        // use case: set position in the current user's language
        person1.Position = "Software Entwickler";

        // use case: display a person's position in all languages
        foreach (Language lang in person1.PositionInAllLanguages.Keys)
            Console.WriteLine(person1.PositionInAllLanguages[lang]);


        Console.ReadKey();

    }
}
Run Code Online (Sandbox Code Playgroud)