的手册页setlocale
似乎是说语言代码和字符编码名称足以设置适当的区域设置:
区域设置名称通常采用 language[_territory][.codeset][@modifier] 形式,其中 language 是 ISO 639 语言代码,region 是 ISO 3166 国家/地区代码,codeset 是字符集或编码标识符,例如 ISO- 8859-1 或 UTF-8。
然而,快速测试表明,只有区域设置名称的“修饰符”部分是可选的:
void tryLocale(const char * locid)
{
char * result = std::setlocale(LC_CTYPE, locid);
std::cout << locid << " = " << (result ? result : "fail") << std::endl;
}
int main()
{
tryLocale("de"); // de = fail
tryLocale("de_DE"); // de_DE = fail
tryLocale("de_DE.CP1252"); // de_DE.CP1252 = de_DE.CP1252
tryLocale("de.CP1252"); // de.CP1252 = fail
tryLocale(".CP1252"); // .CP1252 = fail
}
我的问题是我只知道所需的编码名称(例如ISO-8859-1
),并且我可能会想出语言代码(例如en
)。我不知道如何找到合适的国家/地区名称(例如US
),而且我对国家/地区不感兴趣:我只想像tolower
我的应用程序中那样的功能使用正确的代码页。
答案1
我想你必须循环浏览它们。在zsh
:
for l (${(f)"$(locale -a)"})
[[ $(LC_ALL=$l locale charmap) = ISO-8859-1 ]] && print -r -- $l
或者在模块$langinfo
中使用其特殊关联数组进行相同的操作zsh/langinfo
:
zmodload zsh/langinfo
for LC_ALL (${(f)"$(locale -a)"})
[[ $langinfo[CODESET] = ISO-8859-1 ]] && print -r -- $LC_ALL
将列出使用 ISO-8859-1 作为字符映射的所有可用区域设置。
但请注意,LC_CTYPE
指定字符映射/代码集的类别还涵盖字符分类:什么是小写字母,什么是标点符号等,以及音译(如 所使用的tolower()
),两者都可能因地区/国家而异。即使使用相同的代码集,下一个也是如此。
例如,查看 GNU 土耳其语语言环境中的小写形式I
,ı
无论使用什么字符映射(UTF-8、ISO-8859-9...),而i
在大多数其他也使用 UTF-8 的语言环境中也是如此。
您可以查看区域设置源定义,例如:
(cd /usr/share/i18n/locales && pcregrep -Me '(?ms)^LC_CTYPE.*?^END' -- *)
在 GNU 系统上查看该LC_CTYPE
类别跨区域设置的差异。您不会在那里找到字符映射,这些文件和字符映射的组合的区域设置是使用 生成的localedef -i thosefiles -f charmap
,尽管只有某些组合有意义,请参阅/usr/share/i18n/SUPPORTED
参考资料 的列表。
例如,en_GB
您系统上的区域设置可能是使用localedef -i locales/en_GB -f charmaps/ISO-8859-1.gz
和生成en_GB.UTF-8
的localedef -i locales/en_GB -f charmaps/UTF-8.gz
。
因此,在这里,也许您需要找到一个用作ISO-8859-1
字符映射的语言环境,但也需要具有在英国大陆对于英国英语或意大利/德国等德语使用者有意义的音译规则和字符分类,例如满足:
[[ $(locale language) = 'British English' &&
$(locale territory) = 'United Kingdom' &&
$(locale charmap) = ISO-8859-1 ]]
这应该会稍微缩小选择范围。
请注意,language
和territory
是非标准 GNU 扩展,这解释了为什么您在 zsh 的$langinfo
. GNU libc 文档 ( info libc langinfo
) 仅提到:
文件“langinfo.h”定义了更多符号,但它们都不是官方的。使用它们是不可移植的,并且返回值的格式可能会改变。因此我们建议(原文如此)您不要使用它们。
/usr/include/langinfo.h
我的系统上有:
_NL_IDENTIFICATION_LANGUAGE,
_NL_IDENTIFICATION_TERRITORY,
另请参阅locale -k LC_IDENTIFICATION
,locale -k LC_CTYPE
了解 GNU 系统上给定语言环境类别支持的关键字列表(locale -kc LC_ALL
过去可以工作,但现在显然不再有效)。