Dmi*_*yev 2 character-encoding locale
的手册页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
}
Run Code Online (Sandbox Code Playgroud)
我的问题是我只知道所需的编码名称(例如ISO-8859-1
),并且我可能会想出语言代码(例如en
)。我不知道如何找到合适的国家/地区名称(例如US
),而且我对国家/地区不感兴趣:我只想像tolower
我的应用程序中那样的功能使用正确的代码页。
我想你必须循环浏览它们。在zsh
:
for l (${(f)"$(locale -a)"}) \n [[ $(LC_ALL=$l locale charmap) = ISO-8859-1 ]] && print -r -- $l\n
Run Code Online (Sandbox Code Playgroud)\n$langinfo
或者在模块中使用其特殊关联数组进行相同的操作zsh/langinfo
:
zmodload zsh/langinfo\nfor LC_ALL (${(f)"$(locale -a)"})\n [[ $langinfo[CODESET] = ISO-8859-1 ]] && print -r -- $LC_ALL\n
Run Code Online (Sandbox Code Playgroud)\n将列出使用 ISO-8859-1 作为字符映射的所有可用区域设置。
\n但请注意,LC_CTYPE
指定字符映射/代码集的类别还涵盖字符分类:什么是小写字母,什么是标点符号等,以及音译(如 所使用的tolower()
),两者都可能因地区/国家而异。即使使用相同的代码集,下一个也是如此。
例如,查看 GNU 土耳其语语言环境中的小写形式I
,\xc4\xb1
无论使用什么字符映射(UTF-8、ISO-8859-9...),而i
在大多数其他也使用 UTF-8 的语言环境中也是如此。
您可以查看区域设置源定义,例如:
\n(cd /usr/share/i18n/locales && pcregrep -Me '(?ms)^LC_CTYPE.*?^END' -- *)\n
Run Code Online (Sandbox Code Playgroud)\n在 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' &&\n $(locale territory) = 'United Kingdom' &&\n $(locale charmap) = ISO-8859-1 ]]\n
Run Code Online (Sandbox Code Playgroud)\n这应该会稍微缩小选择范围。
\n请注意,language
和territory
是非标准 GNU 扩展,这解释了为什么您在 zsh 的$langinfo
. GNU libc 文档 ( info libc langinfo
) 仅提到:
\n\n文件 \xe2\x80\x98langinfo.h\xe2\x80\x99 定义了更多符号,但它们都不是官方的。使用它们是不可移植的,并且返回值的格式\n可能会改变。因此我们建议(原文如此)您不要使用它们。
\n
/usr/include/langinfo.h
我的系统上有:
_NL_IDENTIFICATION_LANGUAGE,\n _NL_IDENTIFICATION_TERRITORY,\n
Run Code Online (Sandbox Code Playgroud)\n另请参阅locale -k LC_IDENTIFICATION
,locale -k LC_CTYPE
了解 GNU 系统上给定语言环境类别支持的关键字列表(locale -kc LC_ALL
过去可以工作,但现在显然不再有效)。