C++ 国際化

C, C++ で使われている国際化(initialization, i18n)について書いてみたいと思います。
細かいところは結構はしょって書いたのですが、いろいろ書いてしまって結構長いです。

国際化というのは主に言語(地域)ごとにメッセージを切り替えることを言います。 他にも通貨記号($)や時間の表し方も言語ごとに違いますし、少数点などはヨーロッパでは, . の使い方が逆だったりしてそれにあわせることなども含みますが、 今回はメッセージの切り替え中心です。

Un*x


C ではこの国際化は標準ライブラリにローケルという名前で古くからあります。
これはメッセージファイルに番号ごとのメッセージを書いておいて、 コード中では最初に言語を設定し、この番号を指定すると設定した言語のメッセージが取得できる という仕組みです。 普通はコード中に番号を直接書くことはしないでしょうから、 番号に対して define や列挙型をヘッダに記述しておいてそれを使うことになります。

この標準ライブラリはそのまま使おうとするとすごくめんどくさいです。 そのため、せっかくあるのになかなか使われず、国際化が進みませんでした。 そこでで出てきたのが GetText です。
これはベースは標準ライブラリを使用しますが、使いやすくなります。
プログラムを作る側は今まで英語メッセージを文字リテラルとして書いていたところを次のように _で囲むだけで済みます。
printf(_("Helow World.!!\n"));
このように書いたソースに対してツールを通すとメッセージファイルを作ってくれます。
訳す人はツールでメッセージが抜き出されたものができるので、それに対応する訳を書いて、 また、ツールを通すとその言語用のメッセージファイルが出来ます。

これで国際化が進んで、普通に日本語でアプリケーションが使えるようにとても良かったのですが、 個人的にはこの GetText はあまり好きではありません。
というのも、メッセージやアイコンなどはリソースというのですが、 このリソースはソースと分けて一括で管理したいためです。
翻訳用のメッセージはまとまっているのですが、デフォルトの言語(大抵は英語) はソースコードのあちこちに散らばることになりますし、修正する度にビルドのしなおしが必要となります。

今は国際化するのが当たり前になってきたので、もう GetText はいいんじゃないかと思うのですが、 Linux ではこれが主流です。
統合デスクトップ環境である gnome で使われえている GTK+ は GetText を使っていますし、 KDE の Qt は GetText ではなく独自の国際化を持っているのですが、これも GetText 方式です。

Linux ではない商用 Un*x の世界はというと、こちらの GUI は Motif というライブラリが古くから使われていて、これで CDE (gnome や KDE のもとになっているもの) も作られています。 Motif はさらに古い GUI ツールキットである Xt ライブラリの上に出来ているのですが、 こちらはきちんとリソースが分けられています。
Xt ではテキストファイルであるリソースファイルに以下のような行を書きます。
FooApp.FooDialog.OkButton.label : 了解 
キーになる方は親子関係で書くことができ、これを Widget の部品の名前とあわせておきます。 そうすると、アプリケーションは起動時にリソースファイルをロードして言語にあわせたラベルになります。
ただ、これは GUI 専用のところがあって、 エラーメッセージのようなコード中で決める文字列は C の国際化を使用する必要があります。

他に有名な国際化ライブラリで ICU というものがあります。
これはリソースの国際化だけではなく、文字コード変換などの機能も含んだ大掛かりなもので、 クロスプラットホームで動作します。 しかし、文字コード変換などは Boost からも使われるようになって、広く使われているのですが、 リソース管理という面ではそれほど使われていない気がします。
これもリソースを分離するタイプでよく考えられていると思うのですが、 やはり、 GUI ツールキットとセットではないと広まりにくいのかも知れません。

Windows


Windows の場合、 .NET 以前は基本的に C の標準ライブラリのようなもので、 番号(ID)に対して文字列を指定し、 ID を指定して文字列を取得します。
ただ、 Visual Studio のような IDE で作るのが普通なので、 メッセージファイルの作成と番号の define 定義が同時にできるような感じになっていて、 そんなに使いづらくもないかなと思います。
.NET では番号を define したものではなく、 'Foo.Bar.Ok' のような文字列で取得できるようになっています。

Windows ではリソースは exe や dll などのバイナリファイルに埋め込んでしまいます。 なので、翻訳がない場合に問題が出てきます。
Un*x 系では言語の指定は環境変数 LANG で行いますが、 Windows では WIN32API などの OS が提供するライブラリでユーザーが設定している言語を取得してきます。
商用アプリなど売るところが決まっている場合は問題ないのですが、 フリーウェアなどの場合はリソース用の dll などで追加して、 言語の設定を自動で行うのではなく、アプリの設定でユーザーがどの言語を選択するかを指定するといった工夫が必要になります。

Un*x 系はというと翻訳ファイルやリソースは分かれているのが普通なので、 翻訳ファイルの置き場所に翻訳ファイルおいてなければデフォルト言語(英語)で表示して、 翻訳を追加したければ、そこにファイルを置くという方式が多いと思います。

ちなみに Qt はクロスプラットホームなので、アイコンなどのリソースを Un*x でも、がんばって取り込む仕組みを持っています。 ただ、翻訳ファイルは別ファイルになっていて、 Un*x のような追加方式にすることもできなくはありません。
できなくはないというのは、見つからなかったら英語にする仕組みはないので、 その辺はアプリ側で実装する必要があったりします。


といった感じが C++ での基本的な国際化の方法じゃないかと思います。
どれも一長一短といった感じで、これだっと言うものはないです。 強いて言えば、 .NET が良いと思うのですが、クロスプラットホームではないです。
(Linux でも動くんじゃないかって話はありますが)

それでクロスプラットホームの大規模のアプリの中には自前で国際化の仕組みをもったものもあります。
例えば、 firefox, thunderbird の Mozilla では テキストファイルである プロパティファイルや DTD を使った Java っぽい国際化ができるようになっています。

関連記事
スポンサーサイト
Prev.    Category    Next 

Facebook コメント


コメント

コメントの投稿

Font & Icon
非公開コメント

このページをシェア
アクセスカウンター
アクセスランキング
[ジャンルランキング]
コンピュータ
35位
アクセスランキングを見る>>

[サブジャンルランキング]
プログラミング
6位
アクセスランキングを見る>>
カレンダー(アーカイブ)
プルダウン 降順 昇順 年別

05月 | 2017年06月 | 07月
- - - - 1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 -


はてな新着記事
はてな人気記事
ブロとも申請フォーム
プロフィール

yohshiy

Author:yohshiy
職業プログラマー。
仕事は主に C++ ですが、軽い言語マニアなので、色々使っています。

はてブ:yohshiy のブックマーク
Twitter:@yohshiy

サイト紹介
プログラミング好きのブログです。プログラミング関連の話題や公開ソフトの開発記などを雑多に書いてます。ただ、たまに英語やネット系の話になることも。