Linux中文化之Linux的中文化问题简介[3]

[入库:2005年9月19日] [更新:2007年3月25日]

本文简介:

  (PS. xedit 还有点问题,所以用这个方式用 xedit 读取档案可能会不正常)
  六、撰写 I18N 的程式:
  在此我将我的一些心得与大家分享。由於这个问题牵涉的层面很广,而我只有针对部分 子题稍微摸索一下,因此本文的目的不在於成为一个「完整」的文件说明,也许做为入 门导引来得好些,希望能对 I18N 程式写作有兴趣的朋友提供一个方向。有兴趣的朋友 同时也可以参考 info libc 的 Locale 章节,以及
  ftp.nctu.edu.tw:
  /documents/FAQ/comp/answers/internationalization/programming-faq.gz
  (感谢 stevel 兄提供)
  □头有更完整的说明。
  除此之外,在这□我也会参杂一些我个人的理念,不一定是对的,仅供参考,也请各位 多多给予我批评与指教。
  第一步: setlocale (详见 man setlocale 与其他相关 man page) 程式的第一步必须要设定 locale, 而一般的写法是 locale 资料是经由环境变数取 得,而不要写死在程式□头,例如:
  #include
  main()
  {
  setlocale(LC_ALL, "");
  .....
  }
  或分别设定:
  setlocale(LC_CTYPE, "");
  setlocale(LC_MESSAGES, "");
  .....
  我个人的建议是,在 setlocale() 时只要设我们程式中需要的项目即可,而不要设
  LC_ALL, 原因是在某些 locale 下 (如我们的 zh_TW.Big5), 并非所有的项目都能正确 运作。我想对大部分的程式而言,设好 LC_CTYPE 与 LC_MESSAGES 就差不多了,故以
  下我针对这两个做说明。
  wcs. vs. mbs. (详见 man mbstowcs 与相关 man page)
  "wcs" 是 "wide-chararater string" 的缩写,而 "mbs" 是 "multi-byte string" 的
  缩写,二者分别代表字串的表现方式。所谓的 multi-byte 是指数个 char 组成一个字 (如全形字或中文字是由两个 char 组成),而 wide-char 是指一个 wchar_t type 就
  是一个字, 而 sizeof(wchar_t) 的大小与系统有关,一般而言是 4 bytes。一般我们 可以直接看、输出输入等都是 multi-byte, 如:
  char *str = "这是一个句子: abcd";
  但我们会建议在程式内部,用 mbstowcs() 将它转成 wchar_t 来统一处理,这个转换 其实是根据 locale 中的 LC_CTYPE 的机制,它定义了 multi-byte 与 wide- char 值 二者间的对应关系。做这样转换的好处是,您不用担心全形、半形的问题,因为一个 wchar_t 矩阵元就是一个字。 wchar_t 有一组与 string.h 中相对应的字串处理函式 (目前在 Linux 中可能还没有 man page 说明),就定义在 wchar.h 中,让我们可以如同处理 (char *) 那样地处理 (wchar_t *), 其部分的对应关系如下,其他的可以直接看 wchar.h 的内容:
  wcscpy() <====> strcpy()
  wcsncpy() <====> strncpy()
  wcslen() <====> strlen()
  wcsdup() <====> strdup()
  wcscmp() <====> strcmp()
  wcsncmp() <====> strncmp()
  ........................................
  由於 mbs 码与 wcs 码的对应关系是由该 locale 的 LC_CTYPE 来决定的,也就是不同 的 locale 写法其对应关系可能会不一样。就我们的 glibc2, zh_TW.Big5 locale 而 言,由 mbs 转成的 wcs 即为 unicode (有关 unicode 的资讯可以在 http://www.unicode.org/ 中找到),但不能保证在其他的系统或环境下也是如此。故 最保险的做法,是将字串储存成 multi-byte, 然後在 run-time 时才用 mbstowcs() 转成 wide-char 来运作。
  讯息输出 (详见 info gettext):
  一般我们程式的讯息输出,是经由 stdio.h □头的函式,直接输出到 stdout 或 stderr, 而输出的内容是直接写死在程式码中。这样的程式要做多国语文化会造成困 扰,因为我们必须要修改原始码,将所有的讯息字串翻译成另一种语文。因此,我们必 须透过 locale 的 LC_MESSAGES 来处理讯息输出。其原理很简单,就是将程式中的所
  有讯息抽离出来,为每一个locale 分别做好一个讯息档,当程式要输出讯息时,则透 过 libc 的函式依目前的 locale 去正确的讯息档中抓取讯息。
  在此我用 GNU gettext 为例,简单说明其原理。在 /usr/share/locale 中,□头有各 种 locale 的资料目录。而每个目录下,都会有一LC_MESSAGES 的目录,而这些目 录就是用来放各别程式的讯息档。例如:
  /usr/share/locale/ja/LC_MESSAGES/prog.mo (日文)
  /usr/share/locale/zh_TW.Big5/LC_MESSAGES/prog.mo (Big5)
  其中在 ja/ 目录下的 prog.mo 就是 prog 这个程式的日文讯息,而 zh_TW.Big5/ 下
  的 prog.mo 就是 prog 这个程式的中文讯息。假设在还没加入 LC_MESSAGES 支援之
  前, prog.c 长得像这样:
  #include
  main()
  {
  printf("This is a test string.\n");
  }
  现在我们要用 gettext 来加入支援,则程式只要改成:
  #include
  #include
  #define _(STRING) gettext(STRING)
  #define PACKAGE "prog"
  main()
  {
  setlocale(LC_MESSAGES, "");
  textdomain(PACKAGE);
  /* 这□就是指定用
  /usr/share/locale/$LOC/LC_MESSAGES/prog.mo
  作为讯息档。其中 $LOC 是在 setlocale 中设定的 */
  printf(_("This is a test string.\n"));
  /* 使用 gettext 来抓出讯息,再交给 printf 来印 */
  }
  如果在指定的 locale 下找不到 prog.mo 档,则程式就直接以原英文讯息印出。因
  此,加入 LC_MESSAGES 的支援,原 source code 修改并不多,其实相当方便。
  比较麻烦的是各 locale 下的讯息档制作,而这些步骤可以经由 GNU gettext 套件很
  容易地达成,其步骤简述如下 (详见 info gettext):
  xgettext editor msgfmt (install)
  source code --> .pot --> .pox --> .gmo --> .mo -->
  (节录自 Platin.bbs@csie.nctu.edu.tw 的文章:
  [REF] 关於 gettext (一、简介))
  使用 xgettext 产生 .pot 档:
  xgettext -a -o prog.pot prog.c
  而 prog.pot 档的内容如下:
  # SOME DESCRIPTIVE TITLE.
  # Copyright (C) YEAR Free Software Foundation, Inc.
  # FIRST AUTHOR , YEAR.
  #
  #: prog.c:8
  #, fuzzy
  msgid ""
  msgstr ""
  "Project-Id-Version: PACKAGE VERSION\n"
  "POT-Creation-Date: 1999-02-28 19:18+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: ENCODING\n"
  #: prog.c:10
  msgid "This is a test string.\n"
  msgstr ""
  各位可以注意到倒数两行, msgid 就是原来 source □头的英文讯息,而我 们可以直
  接在 msgstr 中将原讯息翻译成中文。所以,接下来的工作其实就 是翻译,我们可以
  用任意的编辑器编辑这个档案,并将翻译好的档案存成 prog.pox 档。
  将 prog.pox 编译成 prog.gmo:
  msgfmt -o prog.gmo prog.pox
  其中 prog.gmo。就是我们要的讯息档,等到我们把它安装到
  /usr/share/locale/..../LC_MESSAGES/

本文关键:Linux中文化之Linux的中文化问题简介
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top