玩式草子─ソフトウェアとたわむれる日々

第70回Plamo LinuxをUTF-8で使う[その2]

前回は日本語を表示するための文字コードについて振り返り、JISに基づくShift-JISやEUC-JPから、Unicodeに基づくUTF-8へと移行してきた流れとそれに伴なって生じた不具合について紹介しました。

実のところEUC-JPやUTF-8は文字と数字を対応づけるためのルールに過ぎず、それをどう利用するかはソフトウェアの側に委ねられています。そこで今回は、これら文字コードを利用するための仕組みであるlocale(ロケール)について簡単に触れた後、実際にPlamo Linuxでロケール回りの設定を変更する方法を紹介しましょう。

ロケール機能とLANG環境変数

元々、コンピュータやソフトウェアは英語圏で発展したので、使う言語は英語しか考えられていませんでした。

printf("Hello World");

しかし、コンピュータやソフトウェアが英語圏以外にも普及していくにつれ、表示されるメッセージを自分たちが使っている言語にしたいという欲求が生じました。メッセージを変更するには、プログラムを改造し、コンパイル時の指定に応じて出力するメッセージを替えることが考えられます。

#ifdef JAPANESE
    printf("今日は、世界");
#else
    printf("Hello World");
#fi

英語と日本語の2言語程度ならこのような対応でも何とかなるでしょうが、世界中には他にもさまざまな言語があり、それらを一々プログラムの中の条件分岐で対応していたら大変です。そこでC言語では、プログラムの処理と表示すべきメッセージを分離して、表示すべきメッセージはプログラム本体とは独立に、指定に応じて変更できるようにしました。

その場合、プログラム本体では文字列そのものではなくmsg_01といった変数を表示するようにします。

printf(msg_01);

このmsg_01に入れるべき文字列は、言語ごとの設定ファイルとして用意します。

English.mo
msg_01:"Hello World"

Japanese.mo
msg_01:"今日は、世界"

Chinese.mo
msg_01:"你好、世界"

Russian.mo
msg_01:"привет мир"

こうしておけばプログラム本体は同じままで、⁠英語で表示せよ(="English.moを使え"⁠⁠」と指示すればmsg_01として "Hello World"が、⁠ロシア語で表示せよ」と指示すれば"привет мир"が表示されることになります。

Unix/Linuxの場合、C言語で書かれたソフトウェアは実行時にCライブラリ(libc)を利用するので、このような多言語の切り替え機能はlibcに実装されており、locale(ロケール、あるいはロカール)と呼ばれています。

libc(Linuxの場合はglibc)がどのロケールを利用するか(=どの言語で表示するか)は、コマンドで直接指定することもできるものの、通常はLANGという環境変数経由で設定することになっています。

ロケールやLANG環境変数では、どの言語を使用するかを"言語名_使用地域"の形で指定し、必要に応じて"使用する文字コード"の指定を追加することになっています。

日本語の場合、⁠言語名」は日本語ja⁠、⁠地域名」は日本JPなので"ja_JP"となり、文字コードとしてEUC-JPを使う場合は"ja_JP.eucJP"、UTF-8を使う場合は"ja_JP.UTF-8"となります。

すなわち「日本語の文字コードをEUC-JPからUTF-8に変更する」には、"ja_JP.euc-JP"と設定されているLANG環境変数を"ja_JP.UTF-8"に変更すればいい、ということになります。

環境変数の設定方法

Plamo Linuxではコンソールでも日本語が使えるように、カーネルのコンソール用ドライバに"unicon"と呼ばれる機能を追加するパッチをあてています。uniconはfbterm等のアプリを不要にする便利な機能なものの、開発時期が古いこともありUTF-8には対応していません。

そのためLANG環境変数の設定も、⁠ログインした段階ではja_JP.eucJP⁠⁠、⁠Xを起動するとja_JP.UTF-8」という2段階にしておく方が便利でしょう。

Plamo Linuxの場合、デフォルトの状態ではLANG環境変数を/etc/profile~/.bashrc~/.xinitrcの3ヵ所で設定しています。

これらの設定のうち、/etc/profileはログインした際に一度だけ実行される設定で、~/.bashrcはシェル(bash)を起動するごとに実行される設定、~/.xinitrcはX Window Systemを起動する際に実行される設定です。

/etc/profileは、前述した「ログインした段階ではja_JP.eucJP」を実現する設定になっているのでこのままにしておきます。

一方、⁠Xを起動するとja_JP.UTF-8」という設定は~/.xinitrc に指定することになります。この際、LANG以外にも、OUTPUT_CHARSETJLESSCHARSETという変数にUTF-8を使う指定を追加し、それらをexportしておきます。

 37  # LANG=ja_JP.eucJP
 38  # export LANG
 39  LANG=ja_JP.UTF-8
 40  OUTPUT_CHARSET=UTF-8
 41  JLESSCHARSET=japanese-utf8
 42  export LANG OUTPUT_CHARSET JLESSCHARSET

この例では、元々は37~38行で設定していたLANGをコメントアウトし、新たに39~42行でLANGOUTPUT_CHARSETJLESSCHARSETを設定しています。

40行めのOUTPUT_CHARSETはglibcが各アプリのメッセージカタログを出力する際の文字コード指定、41行めのJLESSCHARSETはlessがファイルを読む際と出力する際の変換の指定です。それぞれの環境変数で指定の仕方が少しずつ違っているのでご注意ください。

最後に ~/.bashrcから、これらの設定と重なる部分を削除します。具体的には、29~35行をコメントアウトしてしまえばいいでしょう。

 29  # LANG=ja_JP.eucJP
 30  # export LANG
 31  
 32  # JISで表示できない端末はEUCにする
 33  # if [ "$TERM" = "xterm" -o "$TERM" = "dtterm" ] ; then
 34  #   JLESSCHARSET=japanese-euc
 35  # fi

これらの設定を削除しておかないと、X Window System上でターミナルソフト等を起動すると、そこで動作するbashがLANGやJLESSCHARSETの設定を上書きしてしまいます。

以上の変更を加えた後、いったんログアウトして再度ログインし、X Window Systemを立ちあげると、LANGはja_JP.UTF-8に設定され、前回指摘した文字コードがらみの問題は発生しなくなりました。

図1 VLCが正しくファイル名を読める
図1 VLCが正しくファイル名を読める

なお、今回紹介した方法で文字コードを切り替えて使えるのは、XfceやKDE、Mateといった最近の統合デスクトップ環境のみで、多言語化に対応していないAfterStepClassicやQvwmといった古いウィンドウマネージャはUTF-8環境で利用することはできません。

ファイルシステムの文字コード問題

前節で紹介したように、Plamo Linuxで日本語の文字コードをUTF-8にするのは、2つの設定ファイルを変更するだけの簡単な作業です。しかし、動作環境の文字コードをUTF-8にすると、今度はファイルシステム上にある過去に作ったEUC-JPな日本語ファイル名が正しく読めなくなります。

図2 EUC-JPな日本語ファイル名が正しく表示されない
図2 EUC-JPな日本語ファイル名が正しく表示されない

ファイル名の文字コードを変換するのはそれほど難しい作業ではないものの、UTF-8にしてしまうと、今度はEUC-JPな環境が必要になった時に不便です。

さて何かいい方法はないかなぁ…、と考えているうち、sambaにはファイルシステムの文字コードを変換して、LinuxのEUC-JPなファイル名をWindows環境に正しく見せる機能があったことを思いだしました。

sambaにはLinux用のmount.cifsというコマンドもあるし、この機能を使えば、EUC-JPなファイル名をUTF-8として見せることができるんじゃないかしらん、mount.cifsのmanページを調べてみると、iocharsetというオプションがありました。

iocharset
    Charset used to convert local path names to and from Unicode.
    Unicode is used by default for network path names if the server
    supports it. If iocharset is not specified then the nls_default
    specified during the local client kernel build will be used.
    If server does not support Unicode, this parameter is unused.

ro
    mount read-only
...

考えてみると、mount.cifsはWindowsサーバが提供しているSMBなリソースをLinux環境にマウントするためのツールなので、Windows環境の文字コードをLinux環境用に変換するのは必須の機能です。だとすると、ローカルなsambaサーバを経由して必要なディレクトリをmount.cifsでマウントすることにすれば、文字コードはマウント時に指定できそうです。

さっそく/etc/samba/smb.confにMP3ファイルの置き場を追加して、mount.cifsでマウントしてみることにしました。

$ sudo vi /etc/samba/smb.conf
....
[MP3]
comment = MP3 archives
path = /mnt3/MP3
read only = no
create mask = 0755
...
$ sudo /etc/rc.d/init.d/samba restart
Stopping Samba Server..
Starting Samba server..

マウント先として./MP3-utf8というディレクトリを作り、mount.cifsを使って先に公開したリソースをマウントします。

$ mkdir ./MP3-utf8
$ sudo mount -t cifs //localhost/MP3 ./MP3-utf8 -o user=kojima,iocharset=utf8
Password: *****

この設定で./MP3-utf8/以下に、ディスク上にはEUC-JPで保存されている/mnt3/MP3/の内容が、UTF-8に変換されて見えるようになりました。

$ ls ./MP3-utf8/NHK
2013-03-31-20-05_エレうた最終回.mp3                                            カルチャーラジオ/          歌謡スクランブル/
2013-04-15-20-30_NHKラジオアーカイブス「江戸川乱歩」(3).mp3              ガットの調べ/              漢詩を読む/
2013-05-03-09-05_みんなのうた「フリクリ フニクラ(登山電車)」「感謝状」.mp3  クラシック/                古楽の楽しみ/
2013-08-17-12-55_みんなの歌.mp3                                                クラシックの迷宮/          高校講座/
  ...

このディレクトリは、UTF-8しか読めないVLCからでも正しく見えます。

図3 VLCからSMBなリソースにアクセス
図3 VLCからSMBなリソースにアクセス

また、このディレクトリ(./MP3-utf8)UTF-8で書き込んだ日本語ファイル名は、元のディレクトリ(/mnt3/MP3)上ではEUC-JPで保存されます。

$ mkdir -p MP3-utf8/日本語テスト/
$ touch MP3-utf8/日本語テスト/日本語のファイル名
図4 UTF-8で書き込んだファイル名もEUC-JPに変換される
図4 UTF-8で書き込んだファイル名もEUC-JPに変換される

上図左側のターミナルが文字コードをEUC-JPにしたxfce4-terminal、右が文字コードをUTF-8にしたxfce4-terminalです。右側(UTF-8環境)で、~/MP3-utf8/以下に作った日本語のディレクトリやファイル名は、samba経由で元の/mnt3/MP3/上にEUC-JPとして書き込まれ、左側(EUC-JP環境)からも正しく参照できています。

このようにsambaとmount.cifsを組み合わせることで、ローカルなファイルシステムの文字コードも透過的に変換でき、EUC-JPな環境とUTF-8の環境が共存できるようになりました。

なお、mount.cifsのオプションとして指定する場合は"iocharset=utf8"(utf8は小文字でハイフン無し)となることにご注意ください。カーネルでは"nls-utf8.ko"モジュールドライバがこの機能を担っているので、"utf-8"や"UTF8"という指定ではエラーになるようです。


今回、この原稿自体をUTF-8化したXfce-4.12環境で書いてみました。前回も触れたように、最近の統合デスクトップ環境はUnicode/UTF-8を基盤に構築されているので、LANGをja_JP.UTF-8にする方が、アプリとの相性もいいようです。

実際に試してみたところ、文字コードの設定を替えるだけなら今回紹介した程度の変更で済むものの、日本語manページがEUC-JPで生成されているのでUTF-8環境からは読めなかったり、EUC-JPで記述されている各種設定ファイルの日本語コメントが文字バケしたり、viエディタとして(vimではなく)nviを採用しているためUTF-8には対応できない等、いくつかの不具合も見つかりました。

今後、これらの問題点を整理、修正した上で、次のバージョンアップではユーザアカウント作成時に使用するロケールを選択できるようにしようと思っています。

おすすめ記事

記事・ニュース一覧