アプリの多言語化

10月に韓国である国際学会でセミナーをやることになった。セミナーで某ソフトウェア(研究室謹製、日本語版のみ)を使うらしいので、そのソフトを多言語化しなくてはならなくなった。もちょっと具体的に言うと、日本語の環境下では日本語で、それ以外は英語で表示されるように変更しなくてはならなくなった。
問題のソフトは多言語対応しない設定で、日本語でフォーム等をデザインしていたので、

  • 多言語対応するように変更(スイッチを入れるだけ)
  • 既定の言語として、英語でデザインし直し
  • 日本語環境用に、日本語でデザイン

というステップを踏まねばならないようだ。ここでは、本格的に多言語化する前に、確認用として作った簡単なアプリを例示しながらまとめてみた。とりあえず研究室で買っているMSDN AAから、英語版と韓国語版のWindows XPをありがたく頂戴して、VirtualPC上で動かすことにした。

バーチャルな環境作り終わってから気づいたけど、わざわざ各言語のWindowsを用意しなくても、Thread.CurrentThread.CurrentUICultureを変更すればいいらしい...。

参考にしたサイト

1. 英語に置き換えていく

デザイナでフォームを開き、日本語だったラベル等を全て英語化。
量が多い場合は、元の日本語を控えておくと、後々思い出せて良いかもしれない。

2. 日本語環境での有効となる要素を設定

フォームのプロパティLocalizableをTrueに変更する。ちなみに、このプロパティはデザイナからしかアクセスできないようようだ。つまり、コードでForm1.Localizable = true;って書いてもコンパイルエラーになる。さらに、フォームのプロパティのLanguageを"日本語"にする*1

あとは日本語環境でのlabel1.Textなんかを日本語で書いていく。Languageプロパティを"(既定値)"に戻すとデザイナ上で英語に戻るが、日本語の情報もちゃんと保持されている。
英語に書き換える前の日本語を丸ごとコピーできれば、かなり手間が省けるはずなので、その方法があれば良いけど、ちょっと調べただけだと見つけきれなかった。方法をご存じの方がいらっしゃいましたら、ぜひ教えてください。
ビルドすると、exeと同じ位置に「ja」というフォルダがあって、その中にある「<アプリの名前>.resources.dll」というDLLが入っている。おそらくこの中に日本語の情報が入っているのだろう。
普通に自分の環境(Windows7Proの日本語版)実行してみるとこんな感じ。

韓国語版のWindows XPで実行したらこんな感じ。

英語版XPではこんな感じ。

フォームのサイズや各コントロールのLocationもLanguageごとに変えられるらしい。これはすごい。既定の言語でのフォームのWidthは300のはずなのに、なぜか韓国語版では幅が広くなった。理由はよくわからん。
あと、アカデミックアライアンス様々だなぁ。

コード中にベタ書きした文字列たち1

例えば、このアプリでボタンを押したらメッセージボックスで適当な文字列を表示したいとしよう。いままでは日本語だけだったので以下のように

private void button1_Click(object sender, EventArgs e)
{
	MessageBox.Show("こんにちは");
}

表示される文字列をリテラルでベタ書きしていた。これと同様に、多言語化すべきソフトにも、コード中に文字列をベタ書きしている個所が相当ある。これも環境に合わせて可変にする必要がある。ってことで初めに書いたコードは

private void button1_Click(object sender, EventArgs e)
{
	bool isJpn = Application.CurrentCulture.TwoLetterISOLanguageName == "ja";
	string msg = isJpn ? "こんにちは" : "Hello";
	MessageBox.Show(msg);
}

こんなん。確かに動いた。

現在の言語が何かを調べるにはどうしたらよいか分からなかったけど、試行錯誤で上記のコードにたどりついた。
でも "ja" って書いててかなり気持ち悪かった。TwoLetterISOLanguageNameというくらいだから標準化されてて変更はそう無いのだろうけど。そうでなくても、言語が増えたらまたソースコード書き直しになってしまう。まぁ、英語と日本語以外は無いだろうけど*2
...ってことで、調べたら他のやり方があった。

コード中にベタ書きした文字列たち2

プロジェクトにアセンブリリソースファイルを2個追加する。なんで2個かというと、既定の言語用と、日本語用。ここでは以下のファイル名にした。

既定の言語用
MessageBoxResource.resx
日本語用
MessageBoxResource.ja.resx

ファイル名でどの言語用のリソースか勝手に判断されるっぽい?詳しくは知らん。ファイルを追加できたら、各resxファイルに以下の情報を追記する。

resxファイル 名前
MessageBoxResource.resx message Hello
MessageBoxResource.ja.resx message こんにちは

「名前」は必ず同じもの(ここではmessage)にする。詳しくは知らん。resxファイルが編集できたら、コードを以下のように書き換える。

private void button1_Click(object sender, EventArgs e)
{
	MessageBox.Show(MessageBoxResource.message);
}

実行してみると、if文で書いたときと同じ結果になった。めでたし、めでたし。

Form1.resxとForm1.ja.resxに追記させてくれれば、ファイルが増えなくていい気がするけど、できないみたい。
アプリを配布するときは、前述の「ja」フォルダが実行ファイルと同じ場所にないとダメみたい。日本語環境下で「ja」フォルダがないと、既定の言語として動くっぽい。以下は日本語版のWindows7で動かした様子。

なんとかならんもんか

上記の方法だと

  1. 既存の日本語を英語に翻訳
  2. 言語を日本語に切り替えて、再度、元の日本語を入力

というアホみたいなことになる。英語に翻訳する前の日本語を、日本語環境用にそっくりそのままコピーできて欲しい。
しかも、途方もない量の日本語があるので、かなり切実。

*1:"日本語(日本)"というのもあったけど、違いがよくわからない。そして、このプロパティもデザイナからしかいじれないっぽい。

*2:いや、もしかしたらこのセミナーでこのアプリを気に入ってくれる韓国の方がいて、「ぜひ自分に韓国版を作らせて」とか...無いか。