日本語メッセージの文字化けに対応する
環境変数 LANG に「ja_JP.SJIS」を設定しているのに、Cygwin
のコマンドの出力が文字化けする…といった事態に困っているユーザも多いのではないでしょうか。
ここでは、この問題への対処方法について説明します。
手っ取り早くこの問題に対応するには
「ls や cat の出力メッセージが文字化けして困っています」という人は、次の手順に従えばこの問題を解決出来ます。
- nkf をインストールする(Cygwin JE でパッケージを公開しています)。
- moconv.sh というシェルスクリプトを入手する。
- 「sh ./moconv.sh」として、
moconv.shを実行する。
より詳細に理由を知りたい人は、この先を読み進めて下さい。
この問題が発生する理由
この問題は、gettext の日本語メッセージカタログに含まれている文字列が日本語
EUC-JP であることに起因しています。gettext が日本語メッセージカタログ(通常は
/usr/share/locale/ja 以下にあります)から取り出す日本語メッセージは日本語
EUC-JP ですが、Windows のコマンドプロンプトはそれらの文字列も
Shift_JIS エンコーディングとして表示してしまいます。従って、文字化けが発生してしまうというわけです。
解決策
有効な順に挙げていきます。
Shift_JIS のメッセージカタログを作成する
「Shift_JIS でメッセージが記述された日本語メッセージカタログ」が作成してしまえば、Shift_JIS
しか表示出来ないコンソールでも文字化けの問題は発生しなくなります。前述した
moconv.sh はこのためのスクリプトで、内部では次のような処理を行っています。
- 既存の日本語 EUC-JP のメッセージカタログ(mo 形式)を、po 形式に変換する。
- po 形式のメッセージカタログのエンコーディングを、Shift_JIS に変換する。
- Shift_JIS エンコーディングのメッセージカタログから、mo 形式を作成する。
- 作成された mo 形式のメッセージカタログを、
/usr/share/locale/ja_JP.SJIS以下に格納する。
Shift_JIS の日本語メッセージカタログが作成できたら、環境変数
LANG を「ja_JP.SJIS」に設定します(*1)。
これで、Shift_JIS の日本語メッセージカタログが利用されるようになります。
moconv.sh は /usr/share/locale/ja
以下に置かれているメッセージカタログに加え、vim のメッセージカタログも
Shift_JIS への変換対象としています。但し、vim のメッセージカタログの格納場所はバージョンに依存しているので、新しいバージョンの
vim が登場したときは、スクリプトを書き換える必要があります。
また、新しいメッセージカタログが追加された、或いは(パッケージのバージョンアップなどにより)
メッセージカタログが更新された場合は、moconv.sh
を再実行して下さい。変更されていないファイルは変換対象とはしないようにしていますので、毎回全てのメッセージカタログの変換が行われるようなことはありません(新しく追加された、或いは更新されたメッセージカタログのみが変換の対象となります)。
(*2)
環境変数 LANG に「ja_JP.SJIS」を設定したくない場合は、環境変数
LC_MESSAGES に「ja_JP.SJIS」を設定して下さい(後述)。
環境変数 OUTPUT_CHARSET に「sjis」を設定する
実は最も正しい対処方法なのですが、少なくとも Cygwin 上では確実性がありません。
gettext はバージョン 0.1.40 辺りから、「メッセージカタログ中に含まれるメッセージのエンコーディングと、 現在のロカールで期待されているエンコーディングが異なる場合、メッセージカタログ中のメッセージのエンコーディングを現在のロカールで期待されているエンコーディングに変換する」という機能を備えるようになりました。 この機能が正しく働くならそもそもこのような問題はなかったのですが、残念ながら Cygwin のロカール機構は偽物なので、この機能は利用出来ません。
このようなプラットフォームの存在を仮定してなのかどうかは分かりませんが、gettext
では環境変数 OUTPUT_CHARSET に出力エンコーディングを指定しておくと、メッセージカタログ中のメッセージを強制的に指定されたエンコーディングに変換して出力してくれます。しかし、これでもメッセージの一部が化ける(Shift_JIS に変換されず、日本語 EUC-JP のまま出力される)ことがあるため、確実ではありません。
環境変数 LC_MESSAGES に「C」を設定する
どうせ文字化けするのなら、日本語メッセージを諦めるという(後ろ向きな)考え方もあります。
このためには、メッセージの出力言語を既定する環境変数
LC_MESSAGES に「C」を設定して下さい。
これによってメッセージは翻訳されなくなり、英語のまま出力されるようになります。
勿論、環境変数 LANG は「ja_JP.SJIS」のままで構いません。
採用してはいけない方法
一部の書籍や Web サイトでは「/usr/share/locale/ja
を /usr/share/locale/_ja のようにリネームしてしまえば
OK」などと説明していますが、この方法を採用してはいけません。
この方法を採用すると日本語メッセージは出力されなくなりますが、それなら前述した環境変数
LC_MESSAGES を利用する方法のほうがスマートです。
この方法を採用すべきでないのは、日本語メッセージカタログが含まれたパッケージをインストール或いはアップデートすると、再び
/usr/share/locale/ja ディレクトリが作成されてしまうからです。
勿論、その都度 /usr/share/locale/ja 以下のファイルを
/usr/share/locale/_ja に移動しても構いませんが、態々そのような面倒な作業を増やす理由は何処にもないでしょう。