为gtk程序实现国际化和本地化
添加评论
2009年12月22日
这是一个学习笔记,内容是在Linux系统下以一个简单的gtk程序为基础,为其添加对i18n和l10n的支持。从而了解怎么实现gtk程序的国际化和本地化。
基本的概念
- 什么是i18n,i18n是internationalization的简称,指程序能提供不同语言显示的国际化支持。
- 什么是l10n,l10n是localization的简称,指程序的能拥有某一特定语言支持的本地化。
更多的信息可以自行google或者参看一下这里 http://www.linuxforum.net/doc/i18n-new.html
- 基本原则:标记代码中用户在程序使用过程可见的字符串。
- 基本原理:整个过程是代码中使用 _()和N_()的方式来标记你需要翻译的字符串(即用户在使用过程可见的字符串),提取并翻译这些字符串后,将其单独格式化,存放到语言文件夹。
国际化
- 首先寻找你要翻译的字符串
- 然后gettext()函数将需要翻译的字符串进行标记
- 进行编译
本地化
- 提取被比较的字符串
- 进行翻译
- 格式化
- 将文件存放到本地文件夹
国际化具体过程
我们先来看看gtk程序的国际化。
首先是在需要提供国际化的程序代码里增加一些我们将要用到的库和申明。
//要包含一个头文件。 #include <glib/gi18n.h> //versions 2.4及更高版本使用 //同时需要一些基本的申明。 #define GETTEXT_PACKAGE "Hello_I18n" // 可以换成你需要的名字 #define LOCALEDIR "mo" //定义本地语言文件存放路径 //以及对gettext()进行初始化 bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR); bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); textdomain(GETTEXT_PACKAGE);
现在可以对我们代码中需要翻译的字符串进行标记了。
例:
原代码如下
gtk_window_set_title(GTK_WINDOW(window), "Hello I18n!");
需要标记的字符串为“Hello I18n!”,上面的语句说明了在程序的标题栏里要显示的字符串为“Hello I18n!”,那么需要将上面的语句改为下面这样:
gtk_window_set_title(GTK_WINDOW(window), _("Hello I18n!"));
但是如果我们要对静态字符串进行标记的话,就要使用另一种方式N_().
例:
const char *warning = "The alien is behind you! \n";
我们需要将其改为:
const char *warning = N_("The alien is behind you! \n");
就这样我们完成了程序的国际化,你可以编译你的程序。
本地化具体过程
而做完国际化后,我们需要做的是本地化。
在终端下面通过xgettext命令,我们可以将我们代码test.c中标记的字符串提取出来并保存在test.po里:
xgettext -a -o test.po test.c
我们打开test.po可以看见一些信息
例如:
msgid "test.\n" msgstr ""
那么我们本地化就是对这样的字符串根据不同的地区语言进行翻译,例如我们的中文:
msgid "test.\n" msgstr "测试。\n"
并且修改
charset=CHARSET\n
为
charset=utf-8\n
然后保存。
接下来格式化文件:
msgfmt -o test.mo test.po
然后将test.mo文件复制到LOCALEDIR下面对应的文件夹里。例如,我们在前面的例子里定义LOCALEDIR为mo。
cp test.mo mo/zh_CN/LC_MESSAGES
现在如果我们的LC_ALL为zh_CN,那么我们如果执行这个程序,就可以看见中文了。而不是原来的英文或者其他语言。
一个国际化以后的简单例子:
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#define GETTEXT_PACKAGE "Test"
#define LOCALEDIR "mo"
int main ( int argc,
char *argv[] )
{
GtkWidget *frame;
GtkWidget *label;
bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
textdomain(GETTEXT_PACKAGE);
window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), _("Hello I18n!"));
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
g_signal_connect(G_OBJECT(window), "destroy",
G_CALLBACK(gtk_main_quit),
NULL);
gtk_container_set_border_width(GTK_CONTAINER(window), 10);
frame = gtk_frame_new(_("WARNING"));
label = gtk_label_new(_("\n The alien is behind you!\n"));
gtk_container_add(GTK_CONTAINER(frame), label);
gtk_container_add(window, frame);
gtk_widget_show_all(window);
}
清理电脑里的文件时发现的笔记,写了有些年头了,而现在,似乎大家都用python在写gtk的程序了。
P.S 有时做一些贡献很简单,比如为自己喜欢的软件实现本地化。
[...] 最近给自己找了很多事来做,把自己的schedule填满,不管什么时候能做完,或者能不能做到,至少自己的时间很紧凑,也让自己的生活很充实。 还有几件事,是没有排上的,比如说把最近的笔记整理成一个简单的howto来说明如何让GTK的程序实现简单的i18n和l10n支持。 [...]