1. 什么是计算机的Locale

关于locale我不知道该怎么样翻译(直译就是地区、地域)才算准确,干脆就叫locale吧,反正它与我们的操作系统的语言环境有着很大的关系。Locale 是软件在运行时的语言环境, 它包括语言(Language), 地域 (Territory)字符集(Codeset)。一个locale的书写格式为: 语言_地域.字符集,比如en_US.UTF-8、zh_CN.GB2312。

在你的Linux系统上面输入locale命令,就可以显示出你当前的locale配置,加上-a参数,就可以显示出你的系统当前可用的locales。比如下面是我的系统的输出:

allan@ubuntu:data$ locale
LANG=en_US.UTF-8
LANGUAGE=
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=

allan@ubuntu:data$ locale -a
C
C.UTF-8
en_AG
en_AG.utf8
en_AU.utf8
en_BW.utf8
en_CA.utf8
en_DK.utf8
en_GB.utf8
en_HK.utf8
en_IE.utf8
en_IN
en_IN.utf8
en_NG
en_NG.utf8
en_NZ.utf8
en_PH.utf8
en_SG.utf8
en_US.utf8
en_ZA.utf8
en_ZM
en_ZM.utf8
en_ZW.utf8
POSIX

locale被分为12类

  • 语言符号及其分类(LC_CTYPE)
  • 数字(LC_NUMERIC)
  • 比较和排序习惯(LC_COLLATE)
  • 时间显示格式(LC_TIME)
  • 货币单位(LC_MONETARY)
  • 信息主要是提示信息,错误信息, 状态信息, 标题, 标签, 按钮和菜单等(LC_MESSAGES)
  • 姓名书写方式(LC_NAME)
  • 地址书写方式(LC_ADDRESS)
  • 电话号码书写方式(LC_TELEPHONE)
  • 度量衡表达方式(LC_MEASUREMENT)
  • 默认纸张尺寸大小(LC_PAPER)
  • 对locale自身包含信息的概述(LC_IDENTIFICATION)

还有两个变量:LC_ALL和LANG。它们之间有一个优先级的关系:LC_ALL > LC_* > LANG ,高优先级的设置会覆盖低优先级的设置

更多有关locale的信息可以查看http://wiki.ubuntu.org.cn/Locale

2. setlocale函数

函数原型:

#include <locale.h>

char *setlocale(int category, const char *locale);

有了上面的概念,理解这个函数就很容易了。setlocale函数用来设置或查询我们程序当前的locale(The setlocale() function is used to set or query the program's current locale.)。

第一个参数category是一个整型值,可取的值为上边locale的十二个类;

第二个参数locale是一个char型的字符串,可取的值为locale -a命令的输出:

  • 如果locale参数为NULL,则返回当前指定类别的locale值,即只查询;
  • 如果locale为一个合法的参数值(对于某个特定系统,其合法的值即为系统上面locale -a命令的输出),则将指定的locale类别设定为该值
  • 如果locale为空字符串"",则每个类别会被设置成系统环境变量所设置的值,依次设置LC_ALL、LC_*、LANG。如果某个参数非法,则函数返回NULL。

对于C程序来说,程序刚启动的时候,“C”会被设置为默认的locale。为了程序的通用性和可移植性,我们调用setlocale(LC_ALL, ""); 语句,将locale设置为当前系统上面locale相关环境变量所设置的值。

看下面的例子:

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>

int main()
{

    puts("On startup of the main program, the portable "C" locale is selected as default:");
    printf("LC_ALL=%sn", setlocale(LC_ALL, NULL));
    printf("LC_CTYPE=%sn", setlocale(LC_CTYPE, NULL));
    printf("LC_NUMERIC=%sn", setlocale(LC_NUMERIC, NULL));
    printf("LC_COLLATE=%sn", setlocale(LC_COLLATE, NULL));
    printf("LC_TIME=%sn", setlocale(LC_TIME, NULL));
    printf("LC_MONETARY=%sn", setlocale(LC_MONETARY, NULL));
    printf("LC_MESSAGES=%sn", setlocale(LC_MESSAGES, NULL));
    printf("LC_NAME=%sn", setlocale(LC_NAME, NULL));
    printf("LC_ADDRESS=%sn", setlocale(LC_ADDRESS, NULL));
    printf("LC_TELEPHONE=%sn", setlocale(LC_TELEPHONE, NULL));
    printf("LC_MEASUREMENT=%sn", setlocale(LC_MEASUREMENT, NULL));
    printf("LC_PAPER=%sn", setlocale(LC_PAPER, NULL));
    printf("LC_IDENTIFICATION=%snn", setlocale(LC_IDENTIFICATION, NULL));
    //printf("LANG=%sn", setlocale(LANG, NULL));


    setlocale(LC_ALL,"");
    puts("After execute setlocale(LC_ALL, ""); setence:");
    printf("LC_ALL=%sn", setlocale(LC_ALL, NULL));
    printf("LC_CTYPE=%sn", setlocale(LC_CTYPE, NULL));
    printf("LC_NUMERIC=%sn", setlocale(LC_NUMERIC, NULL));
    printf("LC_COLLATE=%sn", setlocale(LC_COLLATE, NULL));
    printf("LC_TIME=%sn", setlocale(LC_TIME, NULL));
    printf("LC_MONETARY=%sn", setlocale(LC_MONETARY, NULL));
    printf("LC_MESSAGES=%sn", setlocale(LC_MESSAGES, NULL));
    printf("LC_NAME=%sn", setlocale(LC_NAME, NULL));
    printf("LC_ADDRESS=%sn", setlocale(LC_ADDRESS, NULL));
    printf("LC_TELEPHONE=%sn", setlocale(LC_TELEPHONE, NULL));
    printf("LC_MEASUREMENT=%sn", setlocale(LC_MEASUREMENT, NULL));
    printf("LC_PAPER=%sn", setlocale(LC_PAPER, NULL));
    printf("LC_IDENTIFICATION=%sn", setlocale(LC_IDENTIFICATION, NULL));
    //printf("LANG=%sn", setlocale(LANG, NULL));

    return 0;
}

程序执行结果:

allan@ubuntu:temp$ ./a.out 
On startup of the main program, the portable "C" locale is selected as default:
LC_ALL=C
LC_CTYPE=C
LC_NUMERIC=C
LC_COLLATE=C
LC_TIME=C
LC_MONETARY=C
LC_MESSAGES=C
LC_NAME=C
LC_ADDRESS=C
LC_TELEPHONE=C
LC_MEASUREMENT=C
LC_PAPER=C
LC_IDENTIFICATION=C

After execute setlocale(LC_ALL, ""); setence:
LC_ALL=en_US.UTF-8
LC_CTYPE=en_US.UTF-8
LC_NUMERIC=en_US.UTF-8
LC_COLLATE=en_US.UTF-8
LC_TIME=en_US.UTF-8
LC_MONETARY=en_US.UTF-8
LC_MESSAGES=en_US.UTF-8
LC_NAME=en_US.UTF-8
LC_ADDRESS=en_US.UTF-8
LC_TELEPHONE=en_US.UTF-8
LC_MEASUREMENT=en_US.UTF-8
LC_PAPER=en_US.UTF-8
LC_IDENTIFICATION=en_US.UTF-8