linux查看当前文化大小,Linux 的中文化问题简介(4)

Linux 的中文化问题简介(4)

2008-02-23 07:19:52来源:互联网 阅读 ()

c4468b3f4df77e96b0a416fa2a870fba.png

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

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com

特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

相关文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值