我做了一个简单的消息本地化。所有消息都存储在静态类Lng
public static partial class Lng
{
public static readonly string AppName = "My application";
public static class Category1
{
public static readonly string ConfirmDelete = "Are you sure want to delete?";
}
}
在代码中使用就像引用字段一样简单
MessageBox.Show(Lng.Category1.ConfirmDelete, ...
然后有一位经理,其中有以下内容:
这与语言文件的外观无关,但这里有一个反射部分
TranslateLng("Lng.", typeof(Lng));
...
private static void TranslateLng(string parent, Type type)
{
foreach (Type nested in type.GetNestedTypes())
{
string child = string.Format("{0}{1}.", parent, nested.Name);
TranslateLng(child, nested);
foreach (var field in nested.GetFields())
{
string key = child + field.Name;
DefaultAdd(key, (string)field.GetValue(null)); // store value in default language dictionary (if not created yet)
field.SetValue(null, GetValue(key)); // get value for currently selected language
}
}
这个系统有一个问题:所有消息都在一个类中定义,这需要手动管理(更新使用它们的代码时删除和更新消息)。
我正在考虑更改管理器以动态注册字符串并将使用简化为
MessageBox.Show(Lng.Text("Are you sure want to delete?"), ...
因此,文本定义在它使用的位置,重复的文本可以由经理处理等等。
但有两个问题:
我需要在应用程序运行结束时提供所有消息的完整列表,以导出完整的消息列表(对于当前选择的语言)。如果某些Lng.Text()
从未被调用过怎么办?有没有办法注册,因为它们在代码中使用(编译时?)?因此,即使从不使用代码的和平,所有呼叫都将以某种方式注册。
如何生成key
。我可以使用CallerMemberName
,但是右键更有用,因为它们正在说明确切的目的。例如,Lng.Configuration.Appearance.CaptionText
。我可以打电话给Lng.Text(key, message)
,但后来我必须管理钥匙,确保其独特性,这对我没有吸引力。
答案 0 :(得分:1)
我最近参与了一个国际化的项目,我们使用Resources
与Sisulizer计划的联合取得了巨大的成功。在提取资源时手动输入密钥时,资源可以解决您的关键问题。你也得到Resharper
的大力支持,这使整个过程变得轻而易举。
Sisulizer
然后用于提取资源以及在Win Forms和WPF类中硬编码的字符串。它可以导出CSV,您可以为您的译员提供,它也支持pseudo translation,这使得测试此类应用程序也非常容易。