Locale

如何查找給定字元編碼的語言環境名稱?

  • January 31, 2022

的手冊頁setlocale似乎說語言程式碼和字元編碼名稱足以設置適當的語言環境:

語言環境名稱通常採用語言形式

$$ _territory $$$$ .codeset $$$$ @modifier $$,其中語言是 ISO 639 語言程式碼,地區是 ISO 3166 國家程式碼,程式碼集是字元集或編碼標識符,如 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我的應用程序中的功能使用正確的程式碼頁。

我認為您將不得不遍歷它們。在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 作為charmap 的可用語言環境。

但請注意,LC_CTYPE指定charmap / codeset 的類別還包括字元分類:什麼是小寫字母,什麼是標點符號等以及音譯(如 所使用的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類別跨區域設置的差異。您不會在其中找到charmap,這些文件和charmaps 組合的區域設置是使用生成的localedef -i thosefiles -f charmap,儘管只有一些組合有意義,請參閱/usr/share/i18n/SUPPORTED列表。

例如,en_GB您系統上的語言環境可能是使用 生成的,localedef -i locales/en_GB -f charmaps/ISO-8859-1.gzen_GB.UTF-8使用localedef -i locales/en_GB -f charmaps/UTF-8.gz.

因此,在這裡,也許您需要找到一個ISO-8859-1用作charmap 的語言環境,但還需要具有在英國大陸對英國英語或在意大利/德國等講德語的人有意義的音譯規則和字元分類,例如滿足:

[[ $(locale language)  = 'British English' &&
  $(locale territory) = 'United Kingdom' &&
  $(locale charmap)   = ISO-8859-1 ]]

這應該會稍微縮小選擇範圍。

請注意,languageandterritory是非標準的 GNU 擴展,這就解釋了為什麼你不會在 zsh 中找到它們$langinfo。GNU libc 文件 ( info libc langinfo) 僅提及:

文件“langinfo.h”定義了更多的符號,但沒有一個是官方的。使用它們是不可移植的,並且返回值的格式可能會改變。因此,我們建議(原文如此)您不要使用它們。

/usr/include/langinfo.h在我的系統上有:

 _NL_IDENTIFICATION_LANGUAGE,
 _NL_IDENTIFICATION_TERRITORY,

另請參閱locale -k LC_IDENTIFICATIONlocale -k LC_CTYPE以獲得 GNU 系統上給定語言環境類別支持的關鍵字列表(locale -kc LC_ALL過去可以使用,但現在顯然不再使用)。

引用自:https://unix.stackexchange.com/questions/688760