2008-10-08 27 views
20

这是一个普遍的问题,对于意见开放。我一直在想出一种设计Windows MFC应用程序和相关实用程序的字符串资源本地化的好方法。我的心愿是:设计字符串本地化的最佳方法

  • 必须在代码中保存字符串(而不是与宏的#define资源ID的替换),以使这些信息仍然可读的内联
  • 必须允许本地化的字符串资源(杜)
  • 不得强加额外的运行时环境的限制(例如:依赖于.NET等)
  • 应该有最小的obtrusion到现有的代码(改动较小越好)
  • 应该是调试的
  • 应该生成可由常用工具编辑的资源文件(例如:通用格式)
  • 不应该使用复制/粘贴注释块来保留代码中的文字字符串或其他任何可能导致不同步的文件
  • 会很高兴允许静态(编译时)检查每个“注释”字符串是否在资源文件中
  • 允许跨语言资源字符串池(适用于各种语言的组件,例如:native C++和.NET)

我有一种方式,除了静态检查,在一定程度上满足我所​​有的愿望,但我有h广告来开发一些自定义代码来实现它(并且它有局限性)。我想知道是否有人以特别好的方式解决了这个问题。

编辑: 的解决方案,我目前有看起来像这样:

ShowMessage(RESTRING(_T("Some string"))); 
ShowMessage(RESTRING(_T("Some string with variable %1"), sNonTranslatedStringVariable)); 

然后我有一个自定义工具从“RESTRING”块中解析出字符串,把它们放到一个.resx文件本地化以及一个单独的C#COM对象,以便从具有后备功能的本地化资源文件加载它们。如果C#对象不可用(或无法加载),我将回退到代码中的字符串。宏展开为一个模板类,它调用COM对象并进行格式化等。

无论如何,我认为添加我现在可以参考的内容会很有用。

回答

0

在一个项目中,我已经将其本地化为10多种语言,我将所有要本地化的资源都放入一个纯资源专用的dll中。在安装的时候,用户选择了与他们的应用程序一起安装的dll。

我只需将英文版dll发送给本地化团队。他们为我编译的每种语言都返回了本地化的dll。

我知道这不是完美的,但它的工作。

+0

你有没有想办法做到这一点,而不用代码中的资源ID替换字符串?你所描述的听起来像口语方法,这当然可以工作,但并不真正在寻找什么。 – Nick 2008-10-08 23:19:19

+0

不,我们不会将字符串硬编码到我们的应用程序中。我们所看到的是一个与资源ID相关的描述性常量。 – BoltBait 2008-10-08 23:26:16

1

我不太了解Windows通常如何实现这一功能,但本地化字符串在Apple的Cocoa framework中的处理方式非常有效。他们有一个非常基本的文本格式文件,您可以将其发送给翻译器,以及一些预处理器宏来从文件中检索值。

在你的代码中,你会看到你的母语中的字符串,而不是不透明的ID。

+0

这基本上是我在找的东西,但是在与纯C++(没有框架)协同工作的东西中。 – Nick 2008-10-08 23:29:12

+0

是的,我想它可能就像你要找的东西。不幸的是,我不知道这样的设计有任何纯C++版本,但对我来说似乎并不像写这样的程序很困难。关键的简化有一个“生成器”工具来扫描源文件和创建文件。 – 2008-10-08 23:32:49

3

我们使用英文字符串作为ID。

如果从国际资源对象(从安装的I18N DLL加载)查找失败,那么我们默认为ID字符串。

代码如下所示:

doAction(I18N.get("Press OK to continue")); 

作为构建过程的一部分,我们有一个分析所有源字符串常量Perl脚本。它构建应用程序中所有字符串的临时文件,然后将这些文件与每个本地资源字符串进行比较,以查看它们是否存在。任何缺少的字符串会生成电子邮件给相应的翻译团队。

我们可以为每个本地有多个dll。 DLL的名称是基于RFC 3066
语言[_territory] ​​[。代码集] [@修饰符]

我们尝试从机器中提取的语言环境和加载国际化DLL时要尽可能具体,但回落如果更具体的版本不存在,则将其应用于较不特定的本地变体。

例子:

在英国:如果本地是en_GB.UTF-8
(我用这个词松散DLL不是在特定的Windows意义上的)。

首先查找I18N.en_GB.UTF-8 dll。如果这个DLL不存在,请回退到I18N.en_GB。如果该DLL不存在回落到I18N.en如果该DLL不存在下跌贝克I18N.default

唯一的例外是: 简体中国(zh_CN的),其中回退是美国英语(en_US)。如果机器不支持简体中文,那么它不太可能支持全中文。

0

既然它是开放的意见,这里是我如何做到这一点。

我的本地化文本文件是一个简单的制表符分隔的文本文件,可以在Excel中加载和编辑。 第一列是用于定义和每一列到右边的是随后的语言,例如:

ID    ENGLISH  FRENCH GERMAN 
STRING_YES  YES   OUI  YA 
STRING_NO  NO   NON  NEIN 
在我生成文件

然后是一个cusom生成步骤,其生成strings.h文件和一个strings.dat 。在我的情况下,它为字符串ID构建一个枚举列表,然后为文本创建一个带有偏移量的二进制文件。由于在我的应用程序中,用户可以随时更改语言,我可以随时将它们全部存储在内存中,但如果需要,您可以轻松地让预处理器为每种语言生成不同的输出文件。

我喜欢这个设计的事情是,如果任何字符串丢失,那么我会得到一个编译错误,而如果在运行时查找字符串,那么你可能不知道在很少使用的部分代码,直到后来。

0

你想要一个我一直想写但从未有过的高级实用程序。 如果你没有找到这样的工具,你可能想要回退到我的CMsg()和CFMsg()包装类,这些类允许非常容易地从资源表中抽取字符串。(CFMsg甚至提供了一个FormatMessage单行包装 是的,如果没有你想要的工具,在注释中保留一个字符串的副本是一个很好的解决方法。关于注释的不同步,请记住字符串文字都很少改变。

http://www.codeproject.com/KB/string/stringtable.aspx

BTW,原生Win32程序和.NET程序有一个完全不同的资源存储管理。你将有一个很难找到两个共同的解决方案。

1

你解决方案与Unix/Linux“gettext”解决方案非常相似,实际上,您不需要编写提取routi网元。

我不知道你为什么要_RESTRING宏来处理多个参数。我的代码(使用wxWidgets对gettext的支持)如下所示:MyString.Format(_("Some string with variable %ls"), _("variable"));。也就是说,String :: Format(...)获取两个单独转换的参数。事后看来,升压::格式会更好,但它也将允许boost::format(_("Some string with variable %1")) % _("variable");

(我们使用_()宏简洁)

1

最简单的方法是在你的代码只使用字符串ID - 没有字面字符串。 然后,您可以为每种语言生成不同版本的.rc文件,并创建仅资源DLL或简单地构建不同的语言版本。

有一对夫妇共享utilstohelp其本地化调整处理与失踪的翻译不再言语和语言warnign对话框元素的RC文件。

一个更复杂的问题是语序,如果在printf中有几个数字,它必须按不同语言的语法顺序排​​列。 codeproject上有一些扩展的printf类,可以让您指定诸如printf(“word%1s和%2s”,var1,var2)之类的东西,以便在必要时切换%1s和%2s。