在当前的C++标准(C++ 03)中,关于文本本地化的规范太少,这使得C++开发人员在使用本地化文本时比以往更加艰难(当然,C++ 0x标准稍后会有所帮助).
响应(实时)应用程序:应用程序必须将非响应时间最小化为"不明显",因此执行速度很重要.
本地化文本:显示的文本本地化为两种以上的语言,可能更多 - 不要指望固定数量的语言,应该易于扩展.
在运行时定义的语言:文本不应该在应用程序中编译(每种语言也没有一个应用程序),你在应用程序启动时获得所选的语言信息 - 这意味着某种文本加载.
跨平台:应用程序采用跨平台编码(Windows - Linux/Ubuntu - Mac/OSX),因此本地化文本系统也必须是跨平台的.
独立应用程序:应用程序提供运行它所需的所有内容; 它不会使用任何环境库或要求用户安装除操作系统之外的任何东西(例如大多数游戏).
去年我研究了这个,我唯一确定的是你应该使用std::wstring
或std::basic_string
操纵应用程序中的文本.我停止了我的研究,因为我的工作更多的"文本显示"的问题(在实时3D的情况下),但我想有管理的纯粹的C本地化的文本++不仅仅是这一点,"使用Unicode"的一些最佳做法.
所以,欢迎所有最佳实践,建议和信息(跨平台让我觉得很难)!
在一家名为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()
用第二个附加参数填充该标记.只要速度足够快,这将非常方便.自定义解决方案可能仍然更快,因此您需要确保并测试两者.
2)语言长度差异很大.英语中有30个字符,德语有时达到110个字符.这意味着它通常不适合我们所穿的屏幕.这可能不是PC/Mac游戏的关注点,但如果您正在进行任何文本必须适合定义框的工作,您将需要考虑这一点.为了解决这个问题,我们从其文本中删除了尽可能多的形容词用于其他语言.这缩短了句子,但保留了意义,如果失去了一点味道.我后来设计了一个我们可以使用的应用程序,它包含字体和框大小,并允许翻译人员进行自己的修改以使文本适合框.不确定他们是否实施过它.如果遇到此问题,您可能还会考虑滚动文本区域.
3)就跨平台而言,我们为本地化系统编写了非常纯粹的C++.我们编写了要加载的自定义编码二进制文件,以及一个自定义程序,用于将语言文本的CSV转换为.h
带有枚举和文件的语言映射,以及.lang
每种语言的a.我们使用的最平台特定的东西是字体和printf()
功能,但是你会有适合你开发的地方的东西,或者如果需要可以自己编写.
我非常不同意接受的答案.首先,关于使用静态数组查找来加速文本查找的部分仅表明进行优化的人非常缺乏经验 - 计算所述文本的布局并渲染所述文本比使用哈希查找多花费2-4个数量级的时间.如果有人想要实现自己的语言库,它永远不应该基于静态数组.
但这并不是真正相关的,因为在自己的游戏中编写自己的语言库比无意义的过早优化更糟糕.从不编写自己的本地化库有一些非常好的理由:
规划使用本地化库的时间比计划编写本地化库的时间要容易得多.存在本地化库,它们起作用,并且许多人已经使用它们.
本地化很棘手,所以你会弄错.每种语言都会添加一个新的怪癖,这意味着无论何时向自己的本地化本地化库添加新语言,都需要再次更改代码以解决这些问题.您是否知道某些语言有多于2种复数形式,具体取决于相关项目的数量?2个以上的性别(超过10个,甚至)?此外,数字和日期格式在许多语言的不同之间变化很大.
当您的应用程序成功时,您将需要添加对更多语言的支持.您团队中没有人能说流利的语言.如果他们已经知道他们正在使用的工具,那么聘请某人撰写翻译将会相当便宜.
一个非常着名和完整的本地化库是GNU Gettext,它使用GPL,因此应该避免用于商业工作.您可以使用与Gettext文件一起使用的boost库boost.locale,并且可以免费使用和修改任何类型的商业和非商业项目.
GNU Gettext做到了这一切.