特定の文字エンコーディングのロケール名を見つけるには?

特定の文字エンコーディングのロケール名を見つけるには?

マニュアルページ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私のアプリケーションの機能のような機能が正しいコードページを使用したいだけです。

答え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()地域/国によって異なります。同じコードセットを使用しても、次のコードも同じです。

たとえば、使用されている文字マッピング(UTF-8、ISO-8859-9...)に関係なく、GNUトルコ語ロケールの小文字の形式を調べて、IUTF-8を使用する他のほとんどのロケールでも同様です。ıi

次のロケールソース定義を表示できます。

(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,

GNUシステムで特定のロケールカテゴリでサポートされているキーワードのリストも参照してくださいlocale -k LC_IDENTIFICATION(以前は機能していましたが、もう機能していないようです)。locale -k LC_CTYPElocale -kc LC_ALL

関連情報