システムワイドなロケール設定 〜 Cygwin
Cygwin でのシステムワイドなロケール設定の取り扱いに関して、調べた結果を備忘録代わりにまとめておきます。
表題で「システムワイド」と謳いつつ「ユーザ毎」の設定について書いている点は、前回のWindows のエントリと同様です(笑)。
設定更新方法
Cygwin でのシステムワイドなロケール設定は、Windows でのロケール設定を参照しているので、「コントロールパネル」⇒「地域と言語」で表示されるダイアログ経由で変更します。
「地域と言語」での設定変更は、Cygwin のパスで言う /etc/profile.d/lang.sh
中の以下の記述によって、環境変数に反映されます。
# if no locale variable is set, indicate terminal charset via LANG test -z "${LC_ALL:-${LC_CTYPE:-$LANG}}" && export LANG=$(/usr/bin/locale -uU)
Windows の環境変数として、 LC_ALL
や LC_CTYPE
、LANG
のいずれも定義されていない場合、"locale -uU
" の実行結果が LANG
環境変数に設定されます。
"locale -uU
" は、オプション指定に対応する以下の機能によって、"ja_JP.UTF-8
" 形式の情報を表示します。
-u
: 「地域と言語」で設定された地域/言語の表示-U
: 末尾に ".UTF-8
" を追加
設定を実施するファイルが /etc/profile.d
配下のファイルであることから、ログインシェル以外では設定されないことがわかります。
「スタート」メニューに追加される「Cygwin bash shell」の実体である Cygwin.bat
などは、以下のように「ログインシェル」であることを明示して bash
を起動しています。
bash --login -i
その一方で、他の Windows プログラムから bash
が起動されるケースでは、「ログインシェル」扱いにはなりません。また、Emacs のシェルバッファでのシェル起動の様なケースを除けば、「対話的実行」になることも無いでしょう。
「ログインシェル」でも「対話的実行」でもない場合は、.bashrc
は読み込まれませんから、いくら .bashrc
にロケール設定を書いても役に立ちません。
そのため、必要であれば、Windows の環境変数として、ロケール系環境変数を明示的に設定しておいた方が良いでしょう。
あるいは、Windows の環境変数 BASH_ENV
を使い、 bash
の「非ログイン」且つ「非対話的実行」時限定の設定ファイル読み込み挙動として、"${HOME}/.bashrc
" を読み込ませる、という手もありますね。
ただ、こちらの方法だと、コマンドラインでの bash -c "コマンド"
実行等でも、都度設定ファイルの読み込みが実施されてしまうので、個人的にはあまりお勧めしません
Cygwin のファイル名文字コード
Cygwin のファイル API におけるファイル名の符号化方式は、Cygwin 1.7 からロケール設定の影響を受けるように変更されました。デフォルト値は "LC_CTYPE=C.UTF-8
" 相当になります。
Cygwin 上で全てが完結するのであれば、UTF-8 でも全然構わないでしょう。むしろ、Mercurial のファイル名文字コードの問題も解決するので、歓迎したいくらいです。
しかし、Cygwin コマンドと他の Windows プログラムの併用/連携が必要なケースなどでは、使用する文字コードの差異によって、連携が上手く行かない可能性が出てきます。
そのため私個人は、Windows の環境変数として "LC_CTYPE=ja_JP.cp932
" を明示的に設定することで、ファイル名文字コードには常時 Shift-JIS を使用する運用を続けています。
ちなみに、インストール時の環境設定由来なのか、私の環境では Meadow 起動時の環境変数設定に "LANG=JPN
" が追加されてしまうのですが、この設定が Cygwin のロケール判定処理を混乱させるらしく、Meadow から起動したシェルでは、"LC_CTYPE=ja_JP.UTF-8
" が設定されていても、Cロケール設定相当とみなされる (locale
コマンド出力での確認)、という残念な状況になっていました。
$ env | grep LANG LANG=JPN $ env | grep LC_ LC_CTYPE=ja_JP.cp932 $ locale LANG=JPN LC_CTYPE="C" LC_NUMERIC="C" LC_TIME="C" LC_COLLATE="C" LC_MONETARY="C" LC_MESSAGES="C" LC_ALL=
国際化周りの elisp ライブラリをザックリと検索した限りでは、set-language-environment
関数に明示的に言語環境名を指定する前提であれば、LANG
環境変数が未設定でも大丈夫そうなので、Emacs の個人設定ファイルに以下の記述を追加して凌いでいます。
(setenv "LANG" nil)