插件程序中的 i18n
GNU 程序及插件中如何支持 i18n
插件
现在的大多数 GNOME 环境下的程序都使用了基于插件的结构来使得程序自身的功能能方便的得到扩展,添加新的功能只需要增加新的插件即可,程序默认提供的功能也大都是以插件方式实现的。
Evolution: EPlugin
Anjuta 2.x: AnjutaPlugin
Gedit: GeditPlugin
Xchat-gnome: Plugins
它他们都基于 GLib 提供的 GModule 来实现的。
i18n
如想让你的程序支持国际化,你只需要参照 ”国际化 GNOME 应用程序“ 中的说明做就可以了,如果你使用 Anjuta 等 IDE 来新建一个项目,那么会有是否支持 i18n 的选项供你选择,然后你的程序就可以根据语言环境显示不同语言的界面。GNU 程序中使用 gettext 程序库来实现国际化,这里有一个必须要请的概念就是“域“(domain),一个程序中只有一全局的域,用来获取界面字符串的国际化字串,这个域一般与和序名字相同,在 configure 脚本中指定,这个名字还对应于程序安装后的 $PREFIX/share/locale/$LANG/LC_MESSAGES/domain.mo 文件。
普通程序中的 i18n
除在编译脚本需要做的改动外,在代码中要做的就是引入 gi18n.h ,只要引用了 glib.h/gtk.h/gnome.h 就已经隐含地引入了。 gi18n.h 中定义了一组宏, _() , N_() 用来标记程序需要国际化的字符串,其中 _() 用于普通字串,而 N_() 用于数组中的字符串并在代码中使用 _() 来引用。
还需要在 main 函数做初始化工作:
#ifdef ENABLE_NLS
bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
#endif
插件中的 i18n
插件中你需要明确地引入 gi18n-lib.h,而不是 gi18n.h。gi18n-lib.h 是专为类似插件这样需要在主程序之外装入的库而准备的 i18n 宏。
#include <glib/gi18n-lib.h>
这个头文件自动把使用了 dgettext 而不是 gettext,参见文末的代码片段。
另外需要在插件初始化代码中加入
bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
注意,这里没有 textdomain () 的调用,调用 textdomain 所设置的 gettext 域为主程序中的全局的域,因此你不能在这里设置这个域,不然主程序中的界面就无法获正确的 i18n 字符串了。
gi18n.h
#define _(String) gettext (String)
#define Q_(String) g_strip_context ((String), gettext (String))
#ifdef gettext_noop
#define N_(String) gettext_noop (String)
#else
#define N_(String) (String)
#endif
gi18n-lib.h
#ifndef GETTEXT_PACKAGE
#error You must define GETTEXT_PACKAGE before including gi18n-lib.h.
#endif
#define _(String) dgettext (GETTEXT_PACKAGE, String)
#define Q_(String) g_strip_context ((String), dgettext (GETTEXT_PACKAGE, String))
#ifdef gettext_noop
#define N_(String) gettext_noop (String)
#else
#define N_(String) (String)
#endif
参考: http://mail.gnome.org/archives/desktop-devel-list/2006-May/msg00036.html
EPlugin 的国际化
(待续)
实例:
* Anjuta 2 plugin foobar 利用上述方法实现了插件中提供的界面的国际化。
* EPlugin: 删除重复邮件插件 尚未实现国际化(研究中)


要是能举个例子