一种locale表示一种文化的各种数据的表示或显示方式,一种locale分成多个部分,不同的部分由category表示,每一种category下面定义了很多关键字keyword
locale -a 查看所有支持的locale,
locale 不带参 查看当前locale的各个category
locale -ck LC_TIME 输出LC_TIME这个category下面的所有keyword
改变category的locale,在输出这个category下面的所有keyword,会发现locale不同keyword会有什么变化
LC_TIME=zh_CN.utf8 locale -ck LC_TIME;
LC_TIME=en_US.utf8 locale -ck LC_TIME
改变category的locale,会发现locale不同date命令输出的时间不同了,这就是locale的直观的影响
LC_TIME=zh_CN.utf8 date
LC_TIME=en_US.utf8 date
locale格式 language[_territory][.codeset][@modifier]
language是 ISO 639 语言代码
Chinese zh
English en
Japanese ja
Korean ko
territory是 ISO 3166 国家/地区代码China CN
Hong Kong HK
Taiwan TW
United States of America US
Japan JP
Korea KR
codeset 字符编码 ISO-8859-1 or UTF-8
man 5 locale 查看locale definition file
man 7 locale 查看国际化多语言编程方面的信息支
Locale category有哪些
posix定义的
* LC_CTYPE
* LC_COLLATE
* LC_MESSAGES 影响与语言翻译相关的函数gettext, ngettext, rpmatch
* LC_MONETARY
* LC_NUMERIC
* LC_TIME 影响时间输出函数strftime,strptime
非标准
* LC_ADDRESS
* LC_IDENTIFICATION
* LC_MEASUREMENT
* LC_NAME
* LC_PAPER
* LC_TELEPHONE
LC_ALL 包含以上所有LC_*
编程接口方面
相关头文件#include <locale.h>
setlocale函数设置当前locale
setlocale(LC_ALL,"")初始化LC_MESSAGES根据下面3个环境变量得第一个非空值
LC_ALL, LC_MESSAGES, LANG
linux c编程字符串国际化gettext系得函数
通过查找message目录将指定字符串根据当前locale翻译得到locale相对于得字符串
#include <libintl.h>
char * gettext (const char * msgid);
char * dgettext (const char * domainname, const char * msgid);
char * dcgettext (const char * domainname, const char * msgid,
int category);
msgid表示消息目录中的消息,消息目录由.po文件定义,用msgfmt生成.mo并安装到指定目录
xgettext工具
抽取源码中的字符串,生成message目录,然后可以针对每个字符串翻译
xgettext [OPTION] [INPUTFILE]...
[INPUTFILE]... 源码文件
-f, --files-from=FILE 通过FILE指定源码文件列表
-D, --directory=DIRECTORY 通过DIRECTORY指定查找目录
-d, --default-domain=NAME 输出文件为NAME.po,不指定默认为messages.po
-o, --output=FILE 输出文件为FILE,指定 - 输出到标准输出
-p, --output-dir=DIR 指定输出文件所在目录
-j, --join-existing 与存在得输出文件合并,相当于更新
-k, --keyword 不使用默认关键字,查找字符串
-kWORD, --keyword=WORD,用WORD作为额外得关键字
main.c 代码如图
执行命令
xgettext -k_ -o hello.po main.c
生成得hello.pot如图
hello.pot只是一个模板
cp hello.pot hello.po
然后修改Language: zh_CN
CHARSET为UTF-8
其它黄色部分改成自己需要得文字
发布应用时
msgfmt -o 特定规则的目录/xxx.mo xxx.po
把消息目录文件也就是mo文件放到 特定规则的目录
规则是这样的
dirname/locale/category/domainname.mo
dirname由bindtextdomain函数指定,默认值与系统相关,典型值是prefix/share/locale,prefix是包的安装前缀
locale是当前的locale名,对应GNU实现来说一般是没有国家的语言名,ubuntu实现zh_CN 和 zh
category 对与gettext dgettext两个函数来说是LC_MESSAGES,对dcgettext函数来说就是对应参数
domainname gettext由之前调用的textdomain指定,如果未调用textdomain,domainname默认为messages;dgettext 和dcgettext,domainname 传对应参数指定
从ubuntu18.04系统,使用的翻译函数角度
gettext
dirname为系统目录,/usr/share/locale、/usr/share/locale-langpack
locale 由LC_MESSAGES locale指定,它又是由之前调用的setlocale指定,中文环境通常为zh_CN、zh
category 固定LC_MESSAGES
domainname 由之前调用的textdomain指定,如果未调用textdomain,domainname默认为messages,
所以mo查找的顺序是
1、/usr/share/locale/zh_CN/LC_MESSAGES/messages.mo
2、/usr/share/locale/zh/LC_MESSAGES/messages.mo
3、/usr/share/locale-langpack/zh_CN/LC_MESSAGES/messages.mo
4、/usr/share/locale-langpack/zh/LC_MESSAGES/messages.mo
dgettext,指定的路径找不到还会找系统路径
dirname由bindtextdomain函数指定,如果是相对路径,前面还要加上当前工作目录(getcwd获取),
locale 为zh_CN、zh
category 固定LC_MESSAGES串,注意不是LC_MESSAGES的值
domainname dgettext传对应参数指定,参数为NULL,由之前调用的textdomain指定
当dirname为相对路径c/d,工作目录为/a/b,domainname为hello,时mo查找的顺序是
1、/a/b/c/d/zh_CN/LC_MESSAGES/hello.mo
2、/a/b/c/d/zh/LC_MESSAGES/hello.mo
3、/usr/share/locale-langpack/zh_CN/LC_MESSAGES/hello.mo
4、/usr/share/locale-langpack/zh/LC_MESSAGES/hello.mo
dcgettext
基本同上dgettext,除了
1、没有搜索系统路径/usr/share/locale-langpack
2、locale 由dcgettext的参数指定,此参数必须为<locale.h>中的LC_XXX常量
如果指定LC_NAME,那么dgettext查找目录里面的LC_MESSAGES串换成LC_NAME串,mo查找的顺序是
1、/a/b/c/d/zh_CN/LC_NAME/hello.mo
2、/a/b/c/d/zh/LC_NAME/hello.mo
另外对于翻译时存在字符编码转换的需要,LC_CTYPE locale 会用到
mo文件根据调用的翻译函数,复制到响应的查找目录就可以得到