软件本地化(国际化)步骤

增加本地化代码实例

#define LOCALE_DIR “/usr/share/locale”

#define LOCALE_DIR “”//如果设置当前目录

#define _(string) gettext(string)

int main()

{

setlocale(LC_ALL, ""); //配置地域化信息

bindtextdomain("test",LOCALE_DIR); //指定包里包含消息条目的目录(mo目录)

bind_textdomain_codeset("test","UTF-8")//指定域消息条目(mo)中消息的字符编码

textdomain("test"); //指定域名(test.mo)

printf(_("Hello world!\n"));//gettext函数,用于xgettext导出pot文件

...

}

#Makefile

src=test.c

exe=test

filename=test

CC = gcc

zh = zh_CN/LC_MESSAGES

LOCALE_DIR = /usr/share/locale

all:

$(CC) $(src) -o $(exe)

po:

xgettext --keyword=_ $(src) -o $(filename).pot

msginit -l zh_CN.UTF-8 -i $(filename).pot -o $(filename).po

mo:

msgfmt $(filename).po -o $(filename).mo

dir:

mkdir -p zh_CN/LC_MESSAGES

cp:

cp test.mo $(zh)

cp test.mo $(LOCALE_DIR)/$(zh)

#end Makefile

详细说明

函数setlocale()

原型: char* setlocale(const char* category, const char* locale);

内容说明

本函数用来配置地域的信息。参数 category 有下列的选择:

  • LC_ALL 包括下面的全项选项都要。

  • LC_COLLATE 配置字符串比较

  • LC_CTYPE 配置字符类别及转换

  • LC_MONETARY 配置金融货币

  • LC_NUMERIC 配置小数点后的位数。

  • LC_TIME 配置时间日期格式

而参数 locate 若是空字符串 "",则会使用系统环境变量的 locate 或是 LANG 的值。若 locate 为零,则不会改变地域化配置。返回新的地域,若系统尚未实现则返回 false

//===

函数 bindtextdomain()

原型: char * bindtextdomain (const char * domainname, const char * dirname);

函数功能:函数的作用是设置指定消息域(mo)里包含消息条目的位置。

bindtextdomain 告诉程序域 domainname 的文件是在 locale 目录下。所以 gettext 最终会选择从 locale/$LANG/LC_MESSAGES/helloworld.mo 文件中得到翻译的字符串。$LANG 是由 locale环境变量的值所决定。

//===

函数 bind_textdomain_codeset()

原型:bind_textdomain_codeset(const char* Domain,const char* encoding)

用法:bind_textdomain_codeset(“test”, “UTF-8”);

函数功能:指定域消息条目中消息的字符编码

//===

函数 textdomain()

原型:textdomain(const char* Domain);

用法:textdomain(“test”);

函数功能:textdomain 告诉程序要全局使用的 domain 名字叫 test。一个域实际上对应的是一个文件名。比如这里就是 test.mo 文件


>国际化(Internationalization,简写为I18N)是指软件在设计结构和机制上支持多语言的扩展特性,其功能和代码设计不针对某一特定语言和地域。
>
>一:基本实现步骤
>1 编辑源程序
>用 vim编辑器编辑源程序。注意:要顺利实现程序国际化,源程序应当包含相应的标准头文件,主函数中要调用相关的函数,如库libintl,函数setlocale(),bindtextdomain(),textdomain()等。
>如下程序为简单的示例:
>
>#include<stdio.h>
>#include<locale.h>
>#include<libintl.h>
>#include<stdlib.h>
>
>#define _(String) gettext (String)
>int main(int argc,char**argv)
>{
> setlocale(LC_ALL,"");
> bindtextdomain("gettext",".");
> textdomain("gettext");
> printf("%s\n",_("on e world,on e dream!"));
> return 0;
>
}
>
>
>2 编译源程序
>用gcc命令对源程序进行编译,生成可执行文件。执行后,可以显示源程序中的输入函数的字符。命令示例:
>gcc -o gettext gettext.c
>
>3 创建翻译文件模板pot
>用xggetxt命令提取源程序中的翻译信息,创建翻译文件模板pot(Portable Object Template可移植的对象模板)文件。命令示例:
>xgettext --keyword=_ gettext.c -o gettext.pot
>
>4 由pot生成可移植对象po文件
>每一种语言都有其可移植的对象文件,即po(Portable Object )文件。该文件是由一对对的msgid和msgstr组成的,其中,msgid表示从程序中提取的信息,msgstr表示译文。命令示例:
>cp gettext.pot gettext.po
>
>5 编辑po文件中的翻译字符,修改字符的编码
>用gedit或vim编辑器编辑po文件,翻译相关信息,并将charset改为UTF-8,否则不可编码。完成后,保存文件。注意:如果要实现多种语言,此时应复制多分po文件,并分别进行翻译。命令示例:
>gedit gettext.po或vim gettext.po
>
>6 由po文件生成二进制mo文件
>用msgfmt命令将po文件转为二进制mo(MachineObject)文件,供计算机读取执行。命令示例:
>msgfmt gettext.po -o gettext.mo
>
>7 将mo文件放在正确的目录结构下
>mo文件存放位置是否正确是能否实现程序国际化的关键。一般情形下,应将其放在相应地区的locale下相应的子目录中。通常默认目录结构为/usr/share/local,因此本例中生成的mo应放在该目录下相应的子目录中。但是,由于程序中setlocale()函数设定在当前目录结构下查找翻译信息,因此只需在当前目录(即源程序所在目录)下新建相应的地区目录即可。如本例中,可以创建如下目录结构:
> zh_CN/LC_MESSAGES/和en_US/LC_MESSAGES/
>建好目录后,分别将两个不同的mo文件放在这两目录下
>
>8 设置环境变量
>本示例程序会从当前的环境设定LANG来读取地区信息,因此需要设置LANG,如下。注意:每次只能设置一个地区。
>LANG=zh_CN.UTF-8
>LANG=en_US.UTF-8
>
>9 执行程序,得到结果
>在终端界面运行 ./gettext 即可得到所要显示的结果。
>
>二:国际化程序的升级
>调试程序的过程中,对源程序进行相应的修改是不可避免的。如何在源程序修改之后,仍能正确的显示当前新修改的翻译,同时又有效利用原来的翻译信息以提高效率,即如何对国际化程序进行“升级”呢?
>采用如下步骤可以解决此问题。
>
>1 修改(增、删)源程序
>
>2 运行xgettext生成新的pot文件
>命令示例:
>xgettext --keyword=_ gettext.c -o gettext.pot
>
>3 将原程序的po文件更名,以区分新pot文件将生成的po文件
>命令示例:
>mv gettext.po old_gettext.po
>
>4 运行msgmerge将新、旧pot文件进行比较、合并,生成升级版本的po文件
>命令示例:
>msgmerge old_gettext.po gettext.pot --output-file gettext.po
>
>5 为了记录新旧pot的区别,可以用diff命令记录下,两次pot文件中的异同。
>命令示例:
>diff -u old_gettext.po gettext.po > old_gettext.diff
>
>6 在第4步生成新的po文件生成后,可以删除原来的po文件,以免干扰。
>命令示例:
>rm -f old_gettext.po
>
>7 将新生成的po文件生成mo文件
>命令示例:
>msgfmt gettext.po -o gettext.mo
>
>8 将新生成的mo文件放在正确的目录结构下
>
>9 设置环境变量
>
>10 执行程序,得到新的结果
>
>三:注意的一些问题
>1 源程序中的setlocale()函数与mo文件的目录结构应相一致,否则不能得到正确的结果。
>
>2 编辑po文件时,注意要将字符调整为可移植的编码UTF-8,才可以得到正确结果。否则会有如下警告:
>(gettext.po:警告:字符集“CHARSET”不是可移植的编码名称。将消息转换为用户字符集可能不工作。)
>
>3 设置多个环境变量(地区)时,要拷贝多份po并分别进行编辑,并将各自生成的mo文件放在正确的目录下。
>
>4 修改源程序对其进行国际化升级后,应删除原程序(修改前)的可执行文件,否则不能得到修改后的程序的运行结果
>
>四:对源程序的一些解释
>
>#include<stdio.h>
>#include<locale.h> //定义本地化函数。
>#include<libintl.h>//包含gettext库,gettext是GUN为解决程序国际化问题专门建立的一套工具和库。
>#include<stdlib.h>
>
>#define _(String) gettext (String)
>int main(int argc,char**argv)
>{
> setlocale(LC_ALL,"");//设置本程序的环境变量(即指特定地区locale),第一参数是命令的作用域,可以指日期、货币、数字、文本的显示样式;第二参数是一个文本字符串,标志你希望使用哪个地区。若设置成一个空的字符串,则程序会从LANG环境变量获取地区信息。
> bindtextdomain("gettext",".");//告诉gettext最终的生成的翻译文件mo的位置,“.”表示在当前目录下寻找mo文件。
> textdomain("gettext");//设定翻译环境,即指定使用gettext的翻译。
> printf("%s\n",_("on e world,on e dream!"));
> return 0;
>}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值