Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 设计字符串本地化的最佳方法_C++_Windows_Mfc_Localization - Fatal编程技术网

C++ 设计字符串本地化的最佳方法

C++ 设计字符串本地化的最佳方法,c++,windows,mfc,localization,C++,Windows,Mfc,Localization,这是一个一般性的问题,可以发表意见。我一直在尝试为Windows MFC应用程序和相关实用程序的字符串资源本地化设计一种好方法。我的愿望是: 必须在代码中保留字符串文字(而不是替换为宏#define resource ID),以便消息仍然可以内联读取 必须允许本地化字符串资源(duh) 不得施加额外的运行时环境限制(例如:对.NET的依赖性等) 应尽量减少对现有代码的干扰(修改越少越好) 应该是可调试的 应生成可通过通用工具编辑的资源文件(即:通用格式) 不应使用复制/粘贴注释块来保留代码中的

这是一个一般性的问题,可以发表意见。我一直在尝试为Windows MFC应用程序和相关实用程序的字符串资源本地化设计一种好方法。我的愿望是:

  • 必须在代码中保留字符串文字(而不是替换为宏#define resource ID),以便消息仍然可以内联读取
  • 必须允许本地化字符串资源(duh)
  • 不得施加额外的运行时环境限制(例如:对.NET的依赖性等)
  • 应尽量减少对现有代码的干扰(修改越少越好)
  • 应该是可调试的
  • 应生成可通过通用工具编辑的资源文件(即:通用格式)
  • 不应使用复制/粘贴注释块来保留代码中的文字字符串,或任何可能导致去同步的其他内容
  • 最好允许静态(编译时)检查资源文件中是否有每个“notated”字符串
  • 允许跨语言资源串池(对于各种语言的组件,例如:本地C++和.NET)
  • 是很好的。
除了静态检查之外,我有一种在某种程度上满足我所有愿望的方法,但是我不得不开发一些自定义代码来实现它(而且它有局限性)。我想知道是否有人以特别好的方式解决了这个问题

编辑: 我目前拥有的解决方案如下所示:

ShowMessage( RESTRING( _T("Some string") ) );
ShowMessage( RESTRING( _T("Some string with variable %1"), sNonTranslatedStringVariable ) );
然后,我有一个自定义实用程序来解析“RESTRING”块中的字符串,并将它们放入.resx文件中进行本地化,还有一个单独的C#COM对象用于从本地化的资源文件中加载它们,并使用回退。如果C#对象不可用(或无法加载),我将返回代码中的字符串。宏扩展为一个模板类,该类调用COM对象并进行格式化等操作


无论如何,我认为添加我现在的参考资料会很有用。

在一个我已本地化为10多种语言的项目中,我将所有要本地化的内容都放在一个仅限资源的dll中。在安装时,用户选择了与应用程序一起安装的dll

我只需要将英文dll交付给本地化团队。他们为我在构建中包含的每种语言返回了一个本地化的dll


我知道它并不完美,但它确实有效。

我不太清楚Windows上通常是如何实现的,但苹果的本地化字符串处理方式非常好。它们有一个非常基本的文本格式文件,可以发送给转换器,还有一些预处理器宏,用于从文件中检索值


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

我们使用英语字符串作为ID

如果从国际资源对象(从安装的I18N dll加载)查找失败,则默认为ID字符串

代码如下所示:

doAction(I18N.get("Press OK to continue"));
作为构建过程的一部分,我们有一个perl脚本,可以解析字符串常量的所有源代码。它构建应用程序中所有字符串的临时文件,然后将这些字符串与每个本地文件中的资源字符串进行比较,以查看它们是否存在。任何缺少的字符串都会生成一封电子邮件,发送给相应的翻译团队

我们可以有多个dll为每个本地。dll的名称基于RFC 3066
语言[_territory][.codeset][@modifier]

我们尝试从机器中提取区域设置,并在加载I18N 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)。如果机器不支持简体中文,那么它就不可能支持全中文。

因为它可以接受意见,下面是我的操作方法

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

ID              ENGLISH      FRENCH    GERMAN
STRING_YES      YES          OUI       YA
STRING_NO       NO           NON       NEIN
然后在我的makefile中是一个cusom构建步骤,它生成一个strings.h文件和一个strings.dat。在我的例子中,它为字符串ID构建一个枚举列表,然后为文本构建一个带有偏移量的二进制文件。由于在我的应用程序中,用户可以随时更改语言,我将它们全部存储在内存中,但如果需要,您可以很容易地让预处理器为每种语言生成不同的输出文件


我喜欢这种设计的一点是,如果缺少任何字符串,那么我会得到一个编译错误,而如果在运行时查找字符串,那么您可能直到稍后才知道代码中很少使用的部分缺少字符串。

您想要一个高级实用程序,我一直想编写,但从来没有时间编写。 如果找不到这样的工具,您可能希望使用我的CMsg()和CFMsg()包装类,它们允许非常轻松地从资源表中提取字符串。(CFMsg甚至提供一个FormatMessage一行程序包装器。 是的,如果没有您正在寻找的工具,在注释中保留字符串的副本是一个很好的解决方案。关于注释的取消同步,请记住字符串文本很少更改


顺便说一句,本机Win32程序和.NET程序具有完全不同的资源存储管理。您将很难找到两者的通用解决方案。

您的解决方案与Unix/Linux“
gettext
”解决方案非常相似。事实上,您不需要编写解压缩程序