在当前的C ++标准(C ++ 03)中,关于文本本地化的规范太少,这使得C ++开发人员在使用本地化文本时的生活比以往更加困难(当然,C ++ 0x标准稍后会有所帮助) )。
我去年调查了这个,我唯一确定的是你应该使用std::wstring
或std::basic_string<ABigEnoughType>
来操纵应用程序中的文本。我停止了我的研究,因为我正在更多地研究“文本显示”问题(在实时3D的情况下),但我想有一些最佳实践来管理原始C ++中的本地化文本,并且“使用Unicode”
所以,欢迎所有最佳实践,建议和信息(跨平台让我觉得很难)!
答案 0 :(得分:17)
在一家名为Black Lantern Studios的小型视频游戏公司,我是一款名为Lionel Trains DS的游戏的首席开发者。我们本地化为英语,西班牙语,法语和德语。我们事先了解所有语言,因此在编译时包含它们是唯一的选择。 (你看,它们被刻录成ROM)。
我可以向您提供有关我们所做的一些事情的信息。我们的字符串在启动时根据播放器的语言选择加载到数组中。每种语言都进入一个单独的文件,所有字符串的顺序相同。字符串1始终是游戏的标题,字符串2始终是第一个菜单选项,依此类推。我们将数组从enum
键入,因为integer
索引非常快,而在游戏中,速度就是一切。 (在其他一个答案中链接的解决方案使用string
查找,我倾向于避免。)当显示字符串时,我们使用printf()
类型函数将值替换为标记。 “ 3号火车正在离开1号城市。”
现在有一些陷阱。
1)在语言之间,短语顺序完全不同。 “ 3号火车正在离开城市1。”翻译成德语,后面的“从1号城市,3号火车正在起飞”。如果您使用的是printf()
,而且您的字符串是“火车%d正在离开城市%d。”,德国人最终会说“从城市3,火车1是离开。“这是完全错误的。我们通过强制翻译保留相同的单词顺序来解决这个问题,但我们最终得到了一些非常破碎的德语。如果我再次这样做,我会写一个函数,它接受字符串和一个从零开始的值数组。然后我会使用像%0
和%1
这样的标记,基本上将数组索引嵌入到字符串中。 更新:@Jonathan Leffler指出,符合POSIX的printf()
支持使用%2$s
类型标记,其中2$
部分指示printf()
填写该.h
标记与第二个附加参数。只要速度足够快,这将非常方便。自定义解决方案可能仍然更快,因此您需要确保并测试两者。
2)语言长度差异很大。英语中有30个字符,德语有时达到110个字符。这意味着它通常不适合我们所穿的屏幕。这可能不是PC / Mac游戏的关注点,但如果您正在进行任何文本必须适合定义框的工作,您将需要考虑这一点。为了解决这个问题,我们从其文本中删除了尽可能多的形容词用于其他语言。这缩短了句子,但保留了意义,如果失去了一点味道。我后来设计了一个我们可以使用的应用程序,它包含字体和框大小,并允许翻译人员进行自己的修改以使文本适合框。不确定他们是否实施过它。如果您遇到此问题,也可以考虑滚动文本区域。
3)就跨平台而言,我们为本地化系统编写了非常纯粹的C ++。我们编写了要加载的自定义编码二进制文件,以及一个自定义程序,用于将语言文本CSV转换为带有枚举和文件到语言映射的.lang
,以及每种语言的printf()
。我们使用的最平台特定的东西是字体和{{1}}函数,但是你会有适合你开发的地方的东西,或者如果需要可以自己编写。
答案 1 :(得分:7)
GNU Gettext做到这一切。
答案 2 :(得分:7)
我强烈不同意接受的答案。首先,关于使用静态数组查找来加速文本查找的部分仅显示the person doing the optimization is very inexperienced - 计算所述文本的布局并呈现所述文本比使用哈希查找多花费2-4个数量级。如果有人想要实现自己的语言库,它永远不应该基于静态数组。
但这并不是真正相关的,因为writing your own language library to use in your own game is even worse比无意义的过早优化。 never write your own localization library有一些非常好的理由:
规划使用本地化库的时间比计划编写本地化库的时间要容易得多。存在本地化库,它们起作用,并且许多人已经使用它们。
本地化很棘手,所以你会出错。每种语言都会添加一个新的怪癖,这意味着每当您向自己的本地化本地化库添加新语言时,您都需要再次更改代码以解决这些问题。您是否知道某些语言有多于2种复数形式,具体取决于相关项目的数量? 2个以上的性别(超过10个,甚至)?此外,数字和日期格式在不同语言的不同之间有很大差异。
当您的应用程序成功后,您将需要添加对更多语言的支持。您团队中没有人能说流利的语言。如果他们已经知道他们正在使用的工具,那么聘请某人撰写翻译将会相当便宜。
一个非常着名且完整的本地化库是GNU Gettext,它使用GPL,因此应该避免用于商业工作。您可以使用与Gettext文件一起使用的boost库boost.locale,并且可以免费使用和修改任何类型的商业和非商业项目。
答案 3 :(得分:0)
据我所知,C ++ 0x标准中没有任何其他功能。我怀疑委员会认为这是第三方图书馆的问题。