#include <locale.h>
char* setlocale (int category, const char* locale); // 区域设置(本地设置、地域设置)函数
struct lconv* localeconv (void); // 返回区域设置中与数字和货币有关的信息
struct lconv; //包含了与数字和货币有关的区域设置信息的结构体

struct lconv 与 localeconv

区域设置是与某个地区(或者说某个国家)的语言和文化相关的一系列内容,包含日期格式、数字格式、货币格式(例如货币符号、国际货币代码)、字符处理(例如字符分类)、字符比较(字符排序)等多个方面,其中数字和货币信息还包含了很多细节,为了便于管理,C语言将这些细节信息组织成一个结构体,它的名字就是 struct lconv。

也就是说,struct lconv 是一个包含了与数字和货币有关的区域设置信息的结构体。

localeconv() 函数会返回一个 struct lconv 类型的指针,从而让用户了解与数字和货币有关的地域信息,这也是获取 struct lconv 的唯一途径。

struct lconv 在visual c++ 2019 的定义

struct lconv
{
  /* Numeric (non-monetary) information. */

  char *decimal_point;		/* Decimal point character. */
  char *thousands_sep;		/* Thousands separator. */
  /* Each element is the number of digits in each group; elements with higher indices are farther left. An element with value CHAR_MAX means that no further grouping is done. An element with value 0 means that the previous element is used for all groups farther left. */
  char *grouping;

  /* Monetary information. */

  /* First three chars are a currency symbol from ISO 4217. Fourth char is the separator. Fifth char is '\0'. */
  char *int_curr_symbol;
  char *currency_symbol;	/* Local currency symbol. */
  char *mon_decimal_point;	/* Decimal point character. */
  char *mon_thousands_sep;	/* Thousands separator. */
  char *mon_grouping;		/* Like `grouping' element (above). */
  char *positive_sign;		/* Sign for positive values. */
  char *negative_sign;		/* Sign for negative values. */
  char int_frac_digits;		/* Int'l fractional digits. */
  char frac_digits;		/* Local fractional digits. */
  /* 1 if currency_symbol precedes a positive value, 0 if succeeds. */
  char p_cs_precedes;
  /* 1 iff a space separates currency_symbol from a positive value. */
  char p_sep_by_space;
  /* 1 if currency_symbol precedes a negative value, 0 if succeeds. */
  char n_cs_precedes;
  /* 1 iff a space separates currency_symbol from a negative value. */
  char n_sep_by_space;
  /* Positive and negative sign positions: 0 Parentheses surround the quantity and currency_symbol. 1 The sign string precedes the quantity and currency_symbol. 2 The sign string follows the quantity and currency_symbol. 3 The sign string immediately precedes the currency_symbol. 4 The sign string immediately follows the currency_symbol. */
  char p_sign_posn;
  char n_sign_posn;
#ifdef __USE_ISOC99
  /* 1 if int_curr_symbol precedes a positive value, 0 if succeeds. */
  char int_p_cs_precedes;
  /* 1 iff a space separates int_curr_symbol from a positive value. */
  char int_p_sep_by_space;
  /* 1 if int_curr_symbol precedes a negative value, 0 if succeeds. */
  char int_n_cs_precedes;
  /* 1 iff a space separates int_curr_symbol from a negative value. */
  char int_n_sep_by_space;
  /* Positive and negative sign positions: 0 Parentheses surround the quantity and int_curr_symbol. 1 The sign string precedes the quantity and int_curr_symbol. 2 The sign string follows the quantity and int_curr_symbol. 3 The sign string immediately precedes the int_curr_symbol. 4 The sign string immediately follows the int_curr_symbol. */
  char int_p_sign_posn;
  char int_n_sign_posn;
#else
  char __int_p_cs_precedes;
  char __int_p_sep_by_space;
  char __int_n_cs_precedes;
  char __int_n_sep_by_space;
  char __int_p_sign_posn;
  char __int_n_sign_posn;
#endif
};

struct lconv 成员变量说明

struct lconv 包含了如下的成员变量(不分先后顺序):

成员变量 类型 地域设置为"C"时的值 说明
decimal_point char* “.” 非货币数字的小数点,例如 100.25。

我们通常认为小数点就是点号.,在任何语言文化中都是固定的;其实不然,在法语、南非语、丹麦语、德语、希腊语、部分西班牙语中,小数点是逗号,
thousands_sep char* “” 非货币数字的千位分隔符,例如 12,172,390,000。

千位分隔符其实就是数字中的逗号。依西方的习惯,人们在数字中加入一个符号,以免因数字位数太多而难以看出它的值。所以人们在数字中,每隔三位数加入一个逗号,也就是千位分隔符,以便更加容易认出数值。
grouping char* “” 千位分隔符 thousands_sep 分隔非货币数字时,每一个分组包含的数字个数。

我们通常认为,每隔三位数加入一个千位分隔符(例如 12,172,390,000),但是这并不是固定的,也可以每隔两位数加入一个千位分隔符(例如 1,21,72,39,00,00),或者最开始的三位数加入一个分隔符,以后每隔两位数加入一个分隔符(例如12,17,23,90,000),或者是其他情况。grouping 成员就用来指定每隔几位加入一个千位分隔符。

grouping 包含一组以\为前导符的数字,每一个数字表示插入千位分隔符的位数,例如:
  • grouping 被设置为"\3",那么数字的分隔效果为 12,172,390,000;
  • grouping 被设置为"\1\2\3",那么数字的分隔效果为 12,172,390,00,0;
  • grouping 被设置为"\3\1",那么数字的分隔效果为 1,2,1,7,2,3,9,0,000;
  • grouping 被设置为"\1\3",那么数字的分隔效果为 1,217,239,000,0。

按照从左到右的顺序看 grouping 包含的数字,它们依次指明了从右到左(从低位到高位)插入千位分隔符的位置,这两者的顺序恰好是相反的。如果数字的位数过多,那么按照 grouping 最右边的数字(结束标志\0前面的数字)插入千位分隔符。

如果 grouping 包含了值为 CHAR_MAX 的数字,那么表示没有进一步的分组。
int_curr_symbol char* “” 国际货币符号(国际货币代码)。

国际货币符号由三个字母组成,遵循 ISO-4217 标准,例如,美元的国际符号是"USD",欧元的国际符号是"GBP",人民币的国际符号是"CNY"
注意,国际货币符号后面还会紧跟一个空格,用于分隔国际货币符号和货币量,例如 USD 29.86。最终,int_curr_symbol 由四个字符组成。
currency_symbol char* “” 本地货币符号。

适用于当前区域设置的当地流通的货币符号,例如,美元的货币符号为$,欧元的货币符号为,人民币的货币符号为
mon_decimal_point char* “” 货币量(表示货币的数字)的小数点,例如 ¥ 25.5。

mon_decimal_point 针对货币量,而 decimal_point 针对非货币量。
mon_thousands_sep char* “” 货币量的千位分隔符,例如 ¥ 25,000。

mon_thousands_sep 针对货币量,而 thousands_sep 针对非货币量。
mon_grouping char* “” 千位分隔符 mon_decimal_point 分隔货币量时,每一个分组包含的数字个数,细节请参考 grouping。

mon_grouping 针对货币量,而 grouping 针对非货币量。
positive_sign char* “” 用于表示非负(正数或者零)货币量的符号,一般为空字符串。
negative_sign char* “” 用于表示负的货币量的符号,一般为-,也就是负号。
frac_digits char CHAR_MAX 在当前的区域设置中(针对当地的货币格式),货币量的小数部分保留的位数,或者说货币量的小数点右侧的数字个数。
p_cs_precedes char CHAR_MAX 货币符号 currency_symbol 是否位于非负(正数或者零)货币量之前。例如,$ 26.3就是货币符号位于货币量之前,26.3 $就是货币符号位于货币量之后。

如果 p_cs_precedes 的值为 1,那么表示货币符号位于非负货币量之前;如果 p_cs_precedes 的值为 0,那么表示货币符号位于非负货币量之后。
n_cs_precedes char CHAR_MAX 货币符号 currency_symbol 是否位于负(正数或者零)的货币量之前。例如,$ -26.3就是货币符号位于货币量之前,-26.3 $就是货币符号位于货币量之后。

如果 n_cs_precedes 的值为 1,那么表示货币符号位于负的货币量之前;如果 n_cs_precedes 的值为 0,那么表示货币符号位于负的货币量之后。
p_sep_by_space char CHAR_MAX 货币符号 currency_symbol 与非负(正说或者零)货币量之间是否有空格。空格用来分隔货币符号和货币量,让货币的格式更加美观。

如果 p_sep_by_space 的值为 1,那么表示货币符号与非负货币量之间有空格;如果 p_sep_by_space 的值为 0,那么表示货币符号与非负货币量之间没有空格。
n_sep_by_space char CHAR_MAX 货币符号 currency_symbol 与负的货币量之间是否有空格。空格用来分隔货币符号和货币量,让货币的格式更加美观。

如果 n_sep_by_space 的值为 1,那么表示货币符号与负的货币量之间有空格;如果 n_sep_by_space 的值为 0,那么表示货币符号与负的货币量之间没有空格。
n_sign_posn char CHAR_MAX 负的货币量中 negative_sign 的位置:
  • 0:货币符号 currency_symbol 和数字放在括号中,例如( $-26.3)(-26.3 $)
  • 1:negative_sign 位于货币符号 currency_symbol 和数字之前,例如-$26.3-26.3 $
  • 2:negative_sign 位于货币符号 currency_symbol 和数字之后,例如$ 26.3-26.3 $-
  • 3:negative_sign 紧挨着放在货币符号 currency_symbol 之前,例如-$ 26.326.3 -$
  • 4:negative_sign 紧挨着放在货币符号 currency_symbol 之后,例如$- 26.326.3 $-

n_sign_posn 为 CHAR_MAX 表示未定义。
p_sign_posn char CHAR_MAX 非负(正数或者零)货币量中 positive_sign 的位置,请参照 n_sign_posn。
int_frac_digits char CHAR_MAX 和 frac_digits 类似。不过 frac_digits 针对的是当地(当前区域设置)的货币格式,而 int_frac_digits 针对的是国际货币格式。
int_p_cs_precedes char CHAR_MAX 和 p_cs_precedes 类似。不过 p_cs_precedes 针对的是当地(当前区域设置)的货币格式,而 int_p_cs_precedes 针对的是国际货币格式。
int_n_cs_precedes char CHAR_MAX 和 n_cs_precedes 类似。不过 n_cs_precedes 针对的是当地(当前区域设置)的货币格式,而 int_n_cs_precedes 针对的是国际货币格式。
int_p_sep_by_space char CHAR_MAX 和 p_sep_by_space 类似。不过 p_sep_by_space 针对的是当地(当前区域设置)的货币格式,而 int_p_sep_by_space 针对的是国际货币格式。
int_n_sep_by_space char CHAR_MAX 和 n_sep_by_space 类似。不过 n_sep_by_space 针对的是当地(当前区域设置)的货币格式,而 int_n_sep_by_space 针对的是国际货币格式。
int_p_sign_posn char CHAR_MAX 和 p_sign_posn 类似。不过 p_sign_posn 针对的是当地(当前区域设置)的货币格式,而 int_p_sign_posn 针对的是国际货币格式。
int_n_sign_posn char CHAR_MAX 和 n_sign_posn 类似。不过 n_sign_posn 针对的是当地(当前区域设置)的货币格式,而 int_n_sign_posn 针对的是国际货币格式。

如果 char * 类型的成员变量的值为 "",或者 char 类型的成员变量的值为 CHAR_MAX,那么表示(在当前的区域设置中)该成员变量的值不可用(无效)。

int_pint_n开头的成员变量(最后六个)是 C99 标准新加入的,请确认您的编译器是否支持。

实例

下表给出了依照当地习惯对货币量$-3.00格式化的各种方式,它们由 struct lconv 中的三个成员的值决定,分别是 n_sep_by_space、n_sign_posn 和 n_cs_precedes。

n_sep_by_space: 0
n_sign_posn 0 1 2 3 4
n_cs_precedes: 0 (3.00$) -3.00$ 3.00$- 3.00-$ 3.00$-
n_cs_precedes: 1 ($3.00) -$3.00 $3.00- -$3.00 $-3.00
n_sep_by_space: 1
n_sign_posn 0 1 2 3 4
n_cs_precedes: 0 (3.00 $) -3.00 $ 3.00 $- 3.00 -$ 3.00 $-
n_cs_precedes: 1 ($ 3.00) -$ 3.00 $ 3.00- -$ 3.00 $- 3.00

setlocale

setlocale() 函数既可以用来对当前程序进行地域设置(本地设置、区域设置),也可以用来获取当前程序的地域设置信息。

通过 setlocale() 函数进行地域设置,改变程序的语言环境。地域设置是与某个地区(或者说某个国家)的语言和文化相关的一系列内容,包含字符集(字符编码)、日期格式、数字格式、货币格式(例如货币符号、国际货币代码)、字符处理(例如字符分类)、字符比较(字符排序)等。

参数说明

  • category

    地域设置的影响范围。地域设置包含日期格式、数字格式、货币格式、字符处理、字符比较等多个方面的内容,当前的地域设置可以只影响某一方面的内容,也可以影响所有的内容,通过 category 参数就可以指明地域设置的影响范围。

    category 的值不能随便设置,必须使用 <locale.h> 中定义的宏,下表列出了宏名及其说明。

    宏(展开为常量) 本地设置的影响范围
    LC_ALL 影响所有内容。
    LC_COLLATE 影响字符比较(字符排序),具体来说就是影响 <string.h> 头文件中的 strcoll() 和 strxfrm() 函数。

    在默认的地域设置中(设置为"C"),比较字符大小其实比较的是字符的内码,C语言一般使用 ASCII 编码,此时比较的就是字符的 ASCII 码值;但是在其它的地域设置中,可能会有不同的比较方式,例如在中文环境下就可以按照拼音来对字符进行比较和排序。
    Windows 和 Linux 都支持按拼音排序,但是 Mac OS 不支持;Windows 甚至还支持按照笔画来排序,不过需要修改“控制面板 --> 区域和语言”里面的设置。
    LC_CTYPE 1) 影响字符分类和字符转换,具体来说就是影响 <ctype.h> 和 <wctype.h> 头文件中的函数。

    例如,在默认的地域设置中(设置为"C"),只有"abc…xyzABC…XYZ"才被认为是字母;但是在其它的地域设置中,可能会包含更多的字母,例如在中文环境下,拼音ü、拉丁文àáâãäåçö、希腊文σωδψφ(数学物理公式中常用希腊字母)等都将成为字母。
    即使在特定的地域设置下,一个字符是否是字母还跟操作系统有关系,例如在中文环境下,罗马数字 ⅢⅥⅦⅨ将被 Windows 和 Linux 视为字母,但是 Mac OS 就不认为它们是字母。
    2) 还会影响某些多字节字符和宽字符处理函数,例如 mbtowc()、mbstowcs() 等。
    不过在实际测试中,暂时未发现这些函数会受到 LC_CTYPE 的影响。
    <mark>LC_CTYPE 的影响范围最大,可以说是地域设置中最重要的一项内容。</mark>
    LC_MONETARY 影响货币信息,包括货币符号、国际货币代码等;货币信息可以从 localeconv() 返回的 lconv 结构体中取得。

    例如,美元的货币符号是$,国际代码是USD;人民币的货币符号是,国际代码是CNY;英镑的货币符号是£,国际代码是GBP
    LC_NUMERIC 影响数字格式,包括小数点(用哪个字符来表示小数点)、数字分组等。

    世界上大部分地区都使用.表示小数点,例如 12.45、0.88 等;但是在法语地区却使用,表示小数点,此时printf("%f", 12.45);的输出结果就是12,450000。
    LC_TIME 影响日期时间的格式,具体来说就是影响 strftime() 函数的行为。

    例如,美国地区书写日期的格式是月/日/年,比如08/31/2017;而大陆地区书写日期的格式是年/月/日,比如2017/08/31
  • locale
    地域设置的名称(字符串),也就是设置为哪种地域,或者说哪种语言文化。

    对于不同的平台和不同的编译器,地域设置的名称可能会不同,C语言标准没有干预太多。C语言标准只是规定,各个组织在实现编译器时至少要支持以下三个名称:

    地域设置名称 说明
    “C” 默认的地域设置,C语言程序启动时就使用"C"地域设置,也就是相当于调用setlocale(LC_ALL,“C”)

    "C"是一种非常中立的地域设置,不偏向于任何一个地区,它会尽量少地包含地域设置信息,这些信息只是让C语言程序能够正常运行。大多数情况下,"C"仅仅是对小数点进行了设置(设置为.),其它的信息都被置空。
    “” 使用当前操作系统默认的地域设置。这点很容易理解,如果操作系统是英文版的,那就使用英文环境,如果操作系统是中文版的,那就使用中文环境,这样做提高了C程序的兼容性,可以根据操作系统的版本自动地选择语言。
    并不是所有的编译器都能很好的支持 "",例如,Xcode 下的 LLVM 编译器就不支持 ""(设置为 ""无效)。
    NULL 不指定任何名称。此时 setlocale() 不会对地域设置进行任何修改,仅仅是返回当前地域设置的名称。换句话说,如果我们仅仅想知道当前使用的是哪种地域设置,而不想修改它,那么就可以将 locale 参数置为 NULL。

除了以上三个强制要求的名称,其他名称在 Windows 和 Linux 下的写法一般不同,读者可以猛击下面的链接了解更多细节:

返回值

如果 setlocale() 执行成功,那么返回一个指向字符串的指针,该字符串包含了当前地域设置的名称。也就是说,setlocale() 会将当前地域设置的名称返回。

如果 setlocale() 执行失败(例如为 locale 指定的名称不存在,就会导致地域设置失败),那么返回空指针 NULL。

Linux setlocale() 区域设置格式说明以及名称汇总

refer : linux下 locale 的格式

在 Linux 下,locale 的命名格式为:

language_area.charset

language 表示语言,例如英语或中文;area 表示使用该语言的地区,例如美国或者中国大陆;charset 表示字符集编码,例如 UTF-8 或者 GBK。

举一个简单的例子:

zh_CN.UTF-8

zh 代表中文,CN 代表大陆地区,UTF-8 表示字符集编码。

charset 可以省略,此时会选择当前语言的默认 charset。Linux 发行版大都使用 UTF-8 编码,它是 Unicode 字符集的一种编码方式,能够支持世界上的所有语言;省略 charset,也就意味使用 UTF-8。

<caption> locale 名称及其说明 </caption>
locale 名称 说明
af_ZA 南非语
ar_AE 阿拉伯语(阿联酋)
ar_BH 阿拉伯语(巴林)
ar_DZ 阿拉伯语(阿尔及利亚)
ar_EG 阿拉伯语(埃及)
ar_IQ 阿拉伯语(伊拉克)
ar_JO 阿拉伯语(约旦)
ar_KW 阿拉伯语(科威特)
ar_LB 阿拉伯语(黎巴嫩)
ar_LY 阿拉伯语(利比亚)
ar_MA 阿拉伯语(摩洛哥)
ar_OM 阿拉伯语(阿曼)
ar_QA 阿拉伯语(卡塔尔)
ar_SA 阿拉伯语(沙特阿拉伯)
ar_SY 阿拉伯语(叙利亚)
ar_TN 阿拉伯语(突尼斯)
ar_YE 阿拉伯语(也门)
az_AZ 阿塞拜疆语(拉丁文)
az_AZ 阿塞拜疆语(西里尔文)
be_BY 比利时语
bg_BG 保加利亚语
bs_BA 波斯尼亚语(拉丁文,波斯尼亚和黑塞哥维那)
ca_ES 加泰隆语
cs_CZ 捷克语
cy_GB 威尔士语
da_DK 丹麦语
de_AT 德语(奥地利)
de_CH 德语(瑞士)
de_DE 德语(德国)
de_LI 德语(列支敦士登)
de_LU 德语(卢森堡)
dv_MV 第维埃语
el_GR 希腊语
en_AU 英语(澳大利亚)
en_BZ 英语(伯利兹)
en_CA 英语(加拿大)
en_CB 英语(加勒比海)
en_GB 英语(英国)
en_IE 英语(爱尔兰)
en_JM 英语(牙买加)
en_NZ 英语(新西兰)
en_PH 英语(菲律宾)
en_TT 英语(特立尼达)
en_US 英语(美国)
en_ZA 英语(南非)
en_ZW 英语(津巴布韦)
es_AR 西班牙语(阿根廷)
es_BO 西班牙语(玻利维亚)
es_CL 西班牙语(智利)
es_CO 西班牙语(哥伦比亚)
es_CR 西班牙语(哥斯达黎加)
es_DO 西班牙语(多米尼加共和国)
es_EC 西班牙语(厄瓜多尔)
es_ES 西班牙语(传统)
es_ES 西班牙语(国际)
es_GT 西班牙语(危地马拉)
es_HN 西班牙语(洪都拉斯)
es_MX 西班牙语(墨西哥)
es_NI 西班牙语(尼加拉瓜)
es_PA 西班牙语(巴拿马)
es_PE 西班牙语(秘鲁)
es_PR 西班牙语(波多黎各(美))
es_PY 西班牙语(巴拉圭)
es_SV 西班牙语(萨尔瓦多)
es_UY 西班牙语(乌拉圭)
es_VE 西班牙语(委内瑞拉)
et_EE 爱沙尼亚语
eu_ES 巴士克语
fa_IR 法斯语
fi_FI 芬兰语
fo_FO 法罗语
fr_BE 法语(比利时)
fr_CA 法语(加拿大)
fr_CH 法语(瑞士)
fr_FR 法语(法国)
fr_LU 法语(卢森堡)
fr_MC 法语(摩纳哥)
gl_ES 加里西亚语
gu_IN 古吉拉特语
he_IL 希伯来语
hi_IN 印地语
hr_BA 克罗地亚语(波斯尼亚和黑塞哥维那)
hr_HR 克罗地亚语
hu_HU 匈牙利语
hy_AM 亚美尼亚语
id_ID 印度尼西亚语
is_IS 冰岛语
it_CH 意大利语(瑞士)
it_IT 意大利语(意大利)
ja_JP 日语
ka_GE 格鲁吉亚语
kk_KZ 哈萨克语
kn_IN 卡纳拉语
ko_KR 朝鲜语
kok_IN 孔卡尼语
ky_KG 吉尔吉斯语(西里尔文)
lt_LT 立陶宛语
lv_LV 拉脱维亚语
mi_NZ 毛利语
mk_MK 马其顿语(FYROM)
mn_MN 蒙古语(西里尔文)
mr_IN 马拉地语
ms_BN 马来语(文莱达鲁萨兰)
ms_MY 马来语(马来西亚)
mt_MT 马耳他语
nb_NO 挪威语(伯克梅尔)(挪威)
nl_BE 荷兰语(比利时)
nl_NL 荷兰语(荷兰)
nn_NO 挪威语(尼诺斯克)(挪威)
ns_ZA 北梭托语
pa_IN 旁遮普语
pl_PL 波兰语
pt_BR 葡萄牙语(巴西)
pt_PT 葡萄牙语(葡萄牙)
qu_BO 克丘亚语(玻利维亚)
qu_EC 克丘亚语(厄瓜多尔)
qu_PE 克丘亚语(秘鲁)
ro_RO 罗马尼亚语
ru_RU 俄语
sa_IN 梵文
se_FI 北萨摩斯语(芬兰)
se_FI 斯科特萨摩斯语(芬兰)
se_FI 伊那里萨摩斯语(芬兰)
se_NO 北萨摩斯语(挪威)
se_NO 律勒欧萨摩斯语(挪威)
se_NO 南萨摩斯语(挪威)
se_SE 北萨摩斯语(瑞典)
se_SE 律勒欧萨摩斯语(瑞典)
se_SE 南萨摩斯语(瑞典)
sk_SK 斯洛伐克语
sl_SI 斯洛文尼亚语
sq_AL 阿尔巴尼亚语
sr_BA 塞尔维亚语(拉丁文,波斯尼亚和黑塞哥维那)
sr_BA 塞尔维亚语(西里尔文,波斯尼亚和黑塞哥维那)
sr_SP 塞尔维亚(拉丁)
sr_SP 塞尔维亚(西里尔文)
sv_FI 瑞典语(芬兰)
sv_SE 瑞典语
sw_KE 斯瓦希里语
syr_SY 叙利亚语
ta_IN 泰米尔语
te_IN 泰卢固语
th_TH 泰语
tl_PH 塔加路语(菲律宾)
tn_ZA 茨瓦纳语
tr_TR 土耳其语
tt_RU 鞑靼语
uk_UA 乌克兰语
ur_PK 乌都语
uz_UZ 乌兹别克语(拉丁文)
uz_UZ 乌兹别克语(西里尔文)
vi_VN 越南语
xh_ZA 班图语
zh_CN 中文(简体)
zh_HK 中文(香港)
zh_MO 中文(澳门)
zh_SG 中文(新加坡)
zh_TW 中文(繁体)
zu_ZA 祖鲁语

Windows setlocale() 区域设置格式说明以及名称汇总

refer: Windows 下 locale 的格式

Linux 下的 locale 只有一种格式,而 Windows 下的 locale 有三种格式。

1) 专有名称

Windows 定义了一组专有的地域设置名称供 setlocale() 使用,这些名称包含了地域设置的所有信息,例如:

setlocale ("LA_ALL", "en-US");  //en-US就是一个专有名称,它对应的是美国英语
setlocale ("LC_CTYPE", "zh-CN");  //zh-CN就是一个专有名称,它对应的是大陆汉语

不同的 Windows 版本支持不同的专有名称,大家在使用时注意查看手册。Windows 各个版本支持的所有名称请猛击: https://msdn.microsoft.com/en-us/library/cc233982.aspx

2) 语言 + 地区 + 代码页

使用 setlocale() 进行地域设置时,还可以按照下面的格式来设置 locale 参数:

请求设定的 locale 名可以为以下格式(参考MSDN:Language and Country/Region Strings):

locale :: “locale-name”
| “language[_country-region[.code-page]]”
| “.code-page”
| “C”
| “”
| NULL

虽然形式与 glibc 的相同,当 Windows 的 locale 名并不符合 POSIX 的规范,比如采用 GBK 字符集的大陆中文,POSIX 的名字为:zh_CN.GBK,而在 Windows CRT 中要用:Chinese_People’s Republic of China.936。

language字段的可用值参考:Language Strings
country_region 字段的可用值参考:Country/Region Strings
code_page 字段的可用值是 Windows 系统支持的代码页编号,参考:Code Page Identifiers
https://www.science.co.il/language/Locale-codes.php?s=codepage

.code_page:可以直接使用代码页来设定 locale,而且可以使用 .OCP、.ACP 两个伪代码页,.OCP 表示从系统获得的当前活动的 OEM 代码页,.ACP 表示从系统获得的活动 ANSI 代码页。

“”:根据 Windows 系统环境的活动 ANSI 代码页来设定 locale。.OCP、.ACP、和环境代码页都受控制面板中“区域与语言选项”的设置影响。默认装完简体中文版 Windows 后,活动的 ANSI 代码页为:936(即 GBK),可用chcp 控制台程序查看活动代码页。

language 表示语言,例如英语或中文;area 表示使用该语言的地区,例如美国或者中国大陆;codepage 表示代码页,例如 GBK 编码的代码页是936


举一个简单的例子:

chs_china.936

chs 是“chinese-simplified”的简写,表示简体中文,china 表示中国大陆,936 是 GBK 编码的代码页。

可以省略 area 和 codepage,只写 language,此时会选择当前 language 的默认 area 和 codepage;如此一来,上例就可以简写为chs。GBK 是简体中文版 Windows 默认的编码,它的代码页就是 936。

3) 代码页

字符编码就是使用某种语言的某个地区定义的文字在计算机内部的表示方式,代码页就是字符编码在计算机中的 ID,知道了代码页也就知道使用哪个地区的哪种语言了。

使用代码页的格式为:

.codepage

例如, setlocale("LC_ALL", ".936");就表示使用 GBK 编码,对应的是使用汉语的中国大陆地区。

例如,setlocale("LC_ALL", ".65001");就表示使用UTF-8 编码

Windows 下可用的所有代码页列表请猛击:https://msdn.microsoft.com/en-us/library/dd317756(VS.85).aspx

关于代码页使用的注意事项:

ANSI code pages can be different on different computers, or can be changed for a single computer, leading to data corruption. For the most consistent results, applications should use Unicode, such as UTF-8 or UTF-16, instead of a specific code page.

译文:

ANSI代码页可以在不同的计算机上不同,也可以针对单台计算机进行更改,从而导致数据损坏。 为了获得最一致的结果,应用程序应使用Unicode,例如UTF-8或UTF-16,而不是特定的代码页。

Windows/Linux查看系统代码页/locale,修改系统或终端的代码页/locale方法

Linux系统查看locale的方法:在终端输入locale
windows查看代码页方法:在cmd.exe输入chcp,或者右键cmd.exe属性查看。

修改locale:
Linux系统修改配置文件/etc/sysconfig/i18n/etc/sysconfig/language
Windows在开始-控制面板-区域和语言选项-选择一个语言

修改session local的方法:
windows在CMD命令行输入 mode con cp select=437
linux在终端export LANG=zh_CN.UTF8

C:\Windows\system32>mode con cp select=65001

Status for device CON:
----------------------
    Lines:          300
    Columns:        80
    Keyboard rate:  31
    Keyboard delay: 1
    Code page:      65001

C:\Windows\system32>chcp
Active code page: 65001

C:\Windows\system32>

Note:

  • mode con cp select=65001 设置的代码页,在当前命令行有效,命令行关闭,将不再有效。
  • 要想永久生效,需要修改注册表:HKEY_CURRENT_USER ——> Console——>%SystemRoot%_System32_cmd.exe——>修改codePage的值。但是这个值需要***作系统支持,如果不支持,即使设置了,也没有效果。
  • 如windows 7操作系统,不支持UTF-8(65001)代码页,即使设置了,查询显示为Active code page: 65001,但实际上使用时并不会生效。

refer to:
Windows命令行修改代码页,显示特定国家语言
Linux与Windows编码不一致的解决方案
windows修改默认代码页
Windows的CRT中的setlocale()

总结

以上三种格式中,第一种是微软官方推荐使用的,这种格式和 Linux 下的非常类似。