作者:龙飞

自从开始研究SDL的文本显示,我就一直在思考在SDL中显示中文的问题。我们知道韦诺之战(Battle for Wesnoth)使用SDL开发的,并且支持多语言。所以,我一直相信Wesnoth的源代码里面一定有我所需要的答案。网络上是纵说纷纭啊,有些人干脆说,SDL不支持中文;有些人在困难面前回到了MFC的怀抱。而,既然我的目标是跨平台,并且我也相信一定能找到答案,所以,我坚持寻找。终于,完美解决了在SDL中显示中文,甚至多语言的问题。以下的几节,我将全面,详细的说明这些方法。

1.1:po,mo与gettext

线索从Wesnoth的发布游戏与源代码中开始,我们知道,在Wesnoth游戏中,有个名为po的文件夹,多国语言翻译都放在了这个文件夹下面。游戏程序中多为*.mo文件,源代码中多为*.po文件。通过搜索,po与mo的背景浮出水面——它们来自GNU项目gettext。

gettext项目是专门为多语言设计的。我们不需要修改源代码和程序的情况下,可以让程序支持多国语言。程序将根据系统所在的国家和区域选择相应的语言,当然,也可以在执行过程中让玩家自由的选择。既然是开放源代码的,自然也很容易的被移植到win32下。win32下的这个项目主页如下:

http://gnuwin32.sourceforge.net/packages/gettext.htm

为了方便的使用,我还是建议你下载完整的安装包(Complete package)。然后,你可以看英文说明,也可以凭着直觉去试验,找到哪些库和哪些DLL文件是编译和运行时必须的——当然,我也可以直接告诉你答案。

设置编译环境的问题就不再多说了,不清楚的请看前面的章节。反正都三部分:*.h文件,*.lib文件和*.dll文件,放到相应的文件夹下面并在编译时候指明就可以了。

我们下面将用到的文件有:

libintl.h:请在写源代码的时候#include进来;

libintl.lib:这是编译时候需要的库文件;

libintl3.dll和libiconv2.dll:这是程序运行时候需要的文件,放到*.exe文件可以找到的地方。

1.2:演示程序以及说明

#include#include#include#include"GNU/libintl.h"intmain(intargc,char*argv[])

{

setlocale(LC_ALL,"");

bindtextdomain("myText","E:/My Documents/Visual Studio 2008/po");

textdomain("myText");

std::stringtest=gettext("Hello, World!");

std::cout<

}

我们先说#include进来的,我用“<>”表示它是标准C++的一部分。它包含了函数setlocale()。这个函数在这里的两个参数——常量LC_ALL与空字符串""的意思是,在这个程序中的所有语言与区域,都设置为系统默认的语言与区域。

libintl.h是我们刚才加入的GNU的一部分,这意味着在Linux系统下,这个头文件是系统本身自带的。它包含了后面三个函数:bindtextdomain()将一个文件夹目录绑定到一个域名上,这个域名也是将来*.mo文件的文件名;textdomain()表明我们将使用的域名;gettext()中的字符串将是被多语言翻译替换的部分。

将这个程序编译,在没有多语言包的时候,程序也能正常的运行,显示“Hello, World!”。

1.3:为源程序制作po文件和mo文件

如果你已经安装了完整的安装包,找到相关文件夹的bin目录,这里有很多工具软件。你可以通过cmd的方式一步步的转换,也可以,偷点儿懒,因为有更加现成的工具可以用。但是,第一步,从源代码提取gettext()的文本,还得靠命令:xgettext。就跟用g++命令一样,假设我们的源文件名是main.cpp,我们把它先转换成一个模板文件a.pot:

xgettext-o a.pot main.cpp

你可以用vim之类的文本编辑器看看*.pot文件的内容,你会发现,一些说明,以及提取文本的详细信息被纪录了下来。

# SOME DESCRIPTIVE TITLE.

# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER# This fileisdistributed under the same licenseasthe PACKAGE package.

# FIRST AUTHOR, YEAR.

#

#, fuzzy

msgid""msgstr"""Project-Id-Version: PACKAGE VERSION\n""Report-Msgid-Bugs-To: \n""POT-Creation-Date: 2008-03-30 00:24+0800\n""PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n""Last-Translator: FULL NAME \n""Language-Team: LANGUAGE \n""MIME-Version: 1.0\n""Content-Type: text/plain; charset=CHARSET\n""Content-Transfer-Encoding: 8bit\n"#: main.cpp:11msgid"Hello, World!"msgstr""

下面,我们使用一个简单的小工具poedit。又一个跨平台的软件,主页在:

http://www.poedit.net/

安装运行后,选择“从POT文件更新类目”,然后打开我们刚才的a.pot,什么都不用修改(当然,你也可以把自己信息都写上去),确保“字符集”是UTF-8就可以了。然后,在英语下面也上替换的文字吧,保存的时候,相应的mo文件也就建立起来了。

msgid""msgstr"""Project-Id-Version: \n""Report-Msgid-Bugs-To: \n""POT-Creation-Date: 2008-03-30 00:24+0800\n""PO-Revision-Date: 2008-03-30 00:25+0800\n""Last-Translator: lf426 \n""Language-Team: \n""MIME-Version: 1.0\n""Content-Type: text/plain; charset=UTF-8\n""Content-Transfer-Encoding: 8bit\n"#: main.cpp:11msgid"Hello, World!"msgstr"浜茬埍鐨勪笘鐣岋紝鎴戞潵浜嗭紒"

这是po文件。怎么是乱码?那是因为windows不是用UTF-8保存的文本文件(默认一般是GB2312)。用poedit打开时候是正确显示的。我的文本内容是:“亲爱的世界,我来了!”。

如果你用的是vim,可以通过设置环境变量解决显示乱码的问题,在_vimrc文件中添加这一句:

setfileencodings=gb2312,ucs-bom,utf-8,chinese

1.4:设置mo文件的目录

下面的工作可能就有些教条了。还记得我们绑定域名的路径吧,我用的是

E:\My Documents\Visual Studio 2008\po

(请注意在C++程序里面把斜杠反过来!)

*.mo文件并不是直接放到这个路径下,而是这个路径下的./LL/LC_MESSAGES或者./LL_CC/LC_MESSAGES。其中LL表示语种,CC表示国家或区域。具体的请参考Wesnoth。就我们的中文来说,这个例子放mo文件的路径是:

E:\My Documents\Visual Studio 2008\po\zh_CN\LC_MESSAGES

现在运行程序就可以看到文本已经被替换了。如果我们删除mo文件或修改mo文件名(与绑定域名不一致),程序会继续显示原来的英文。如果我们改变系统环境,只要不是中国中文,程序都还是显示英文。如果我们要更新替换内容,直接用poedit更新po和mo文件就可以了。

1.5:构建StringData类

我们希望字符串的数据单独的保存在一个文件里,这样既方便被gettext提取,也方便修改。而且,在程序里面,我们尽量把gettext涉及到的一些特殊的设置隐藏了。所以,我们构建StringDada类,在程序中需要用到的地方,直接调用它的对象就可以了。

//FileName: string_data.h#ifndef STRING_DATA_H#defineSTRING_DATA_H#include#include#include#include"GNU/libintl.h"classStringData

{private:

std::vector<:string>data;public:

StringData();

std::stringoperator[](constunsignedint&n)const;

};#endif

我重载了[],这样在调用数据的时候更加直观。我们将数据都写在StringData的构造函数中,将来gettext也只需要提取StringData的实现文件就可以了。

#include"string_data.h"StringData::StringData()

{

setlocale(LC_ALL,"");

bindtextdomain("StringData","./po");

textdomain("StringData");//0data.push_back(gettext("Up was pressed."));//1data.push_back(gettext("Down was pressed."));//2data.push_back(gettext("Left was pressed."));//3data.push_back(gettext("Right was pressed."));//4data.push_back(gettext("Other key was pressed."));

}

std::stringStringData::operator[](constunsignedint&n)const{if( n>=data.size() )

return 0;returndata[n];

}

1.6:做个gettext的批处理

如果你按照我全面介绍的,安装了Poedit,也安装了GnuWin32,那么,我们做个批处理文件让从string_data.cpp到StringData.mo的转换更加简单吧。(如果安装路径不一样请做相应的修改)。

@set path=C:\Program Files\GnuWin32\bin;%PATH%;

xgettext--force-po-o string_data.pot string_data.cpp

msginit-l zh_CN-o StringData.po-i string_data.pot

@set path=C:\Program Files\Poedit\bin;%PATH%;

poedit StringData.po

del string_data.pot

del StringData.po

Poedit打开StringData.po的时候会报错,那是因为文件指明的编码不可用,请在“字符集”中选择UTF-8,另外,在“工程名称以及版本”中写点信息,不要使用默认值就可以了。然后翻译并保存,StringData.mo文件就生成了。

posted on 2008-03-30 02:02 lf426 阅读(4692) 评论(3)  编辑 收藏 引用 所属分类: SDL入门教程 、跨平台与GNU

linux sdl windows.h,SDL入门教程(十):1、多语言支持,Win32下的GetText相关推荐

  1. Wix 安装部署教程(十四) -- 多语言安装包之用户许可协议

    Wix 安装部署教程(十四) -- 多语言安装包之用户许可协议 原文:Wix 安装部署教程(十四) -- 多语言安装包之用户许可协议 在上一篇中,留下了许可协议的问题,目前已经解决.感谢网友武全的指点 ...

  2. SpringCloud 入门教程(十):和RabbitMQ的整合 -- 消息总线Spring Cloud Netflix Bus

    在本教程第三讲Spring Cloud 入门教程(三): 配置自动刷新中,通过POST方式向客户端发送/refresh请求, 可以让客户端获取到配置的最新变化.但试想一下, 在分布式系统中,如果存在很 ...

  3. linux 没有windows.h头文件_宋宝华: Linux内核编程广泛使用的前向声明(Forward Declaration)...

    本文系转载,著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 作者:宋宝华 来源: 微信公众号linux阅码场(id: linuxdev) 前向声明 编程定律 先强调一点:在一切可 ...

  4. PostgreSQL在Linux和Windows安装和入门基础教程

    StackOverflow 2022 开发者报告:总体而言,MySQL 依然是最受欢迎的的数据库.但在专业开发者群体中,PostgreSQL(46.48%)已经超越 MySQL(45.68%)夺得了第 ...

  5. php十天入门教程,十天学会php之第十天_PHP教程

    学习目的:学会用PHP上传文件和发邮件 上传文件表单必须加上 enctype="multipart/form-data" 和 下面看一下代码: $f=&$HTTP_POST ...

  6. 大白菜linux系统安装步骤,GRUB简单入门教程

    一.什么是多重操作系统引导管理器,什么是GRUB: 1.什么是多重操作系统引导管理器及工作原理: 系统启动引导管理器,是在计算机启动后运行的第一个程序,他是用来负责加载.传输控制到操作系统的内核,一旦 ...

  7. linux 切换目录技巧,Lnux入门教程:Linux目录切换技巧

    在Linux的多目录命令提示符中工作是一种痛苦的事情,但以下这些利用cd和pushd切换目录的技巧有助于你节省时间和精力. 在Linux命令提示中,用cd命令来改变当前目录.这是cd命令的一些基本用法 ...

  8. OPENCV入门教程十四:medianBlur中值平滑

    一.目标 学习如何使用opencv中的函数,学习对图像的中值平滑操作,学习medianBlur()函数的使用 二.函数说明 函数原型: void medianBlur(InputArray src, ...

  9. Linux的内网渗透入门教程:第一节 通过arp欺骗进行网关劫持,截获别人手机的图片(VMware环境)

    免责声明:本人提供的任何工具.文章和知识,只可研究学习,本人对使用这些工具.文章和知识而导致的一切后果,不承担任何法律责任.请大家文明上网,远离网络非法行为! 一.引言 这是本人第一次写博客,据我一位 ...

  10. SpringBoot入门教程(十)应用监控Actuator

    Actuator可能大家非常熟悉,它是springboot提供对应用自身监控,以及对应用系统配置查看等功能.spring-boot-starter-actuator模块的实现对于实施微服务的中小团队来 ...

最新文章

  1. python ggplot为什么不能取代matplotlib_Matplotlib vs ggplot2
  2. 计算机导航辅助教程,计算机导航辅助下微创人工全膝关节置换的初步经验
  3. Android/Java 获取一个byte[]的真实编码,用于解决乱码问题
  4. 优秀设计师必备:视觉传达设计与视觉思维
  5. 传统企业建模原理及建模体系介绍
  6. JDBC连接mysql、创建表、操作数据、PreparedStatement防注入、sql语句返回值类型知识汇总
  7. 永远的GetLong
  8. 第三次学JAVA再学不好就吃翔(part56)--StringBuffer的替换反转和截取功能
  9. 面试官:AtomicInteger是如何保证线程安全?
  10. Struts2中的图片验证码
  11. 复盘:图像饱和度计算公式和图像信噪(PSNR)比计算公式
  12. ARM嵌入式系统的问题分析与总结
  13. excel常用快捷键详解
  14. html 链接长宽,CSS实现长宽比的几种方案【转载】
  15. 动物识别系统代码python_人工智能-动物识别专家系统算法Python + Pyqt 实现
  16. Android studio一直卡在Gradle:Build Running的解决方法
  17. Linux中samba配置和windows映射Linux驱动盘
  18. MCU基础以及RTOS原理知识分享
  19. Excel学习笔记(简单到记到后来不想记)
  20. Android 官方现代 App 架构解读 - 启程

热门文章

  1. 人到中年,没事多休息,有空多赚钱!
  2. 计算机粘贴复制快捷键,电脑粘贴复制快捷键ctrl加什么(电脑快捷键方法大全)...
  3. AM使用指南之一:Transaction和DBTransaction的区别与联系
  4. Steven H. Simon《The Oxford Solid State Basics》(史蒂文·H·西蒙《牛津固态物理学基础》)中文目录
  5. 根据显示屏分辨率调试html 样式
  6. Win10将用户名修改为英文
  7. Java程序设计基础——setSize()和setBounds()的区别
  8. 信号与系统——卷积和
  9. MATLAB-数字图像处理 量化
  10. peoplesoft笔记