● ToolBox API徒然草(2007/01/07)

  このニュースは、MOSAの会員にのみ配布されているデベロッパー向けの
  デジタルマガジンMOSADeNのに掲載された記事です。ほぼ一ヶ月遅れで
  ここに掲載されて行きます

 〜 Carbonモダンアプリケーションへの道(その7) 〜


アプリケーションを多国語対応にする場合、Shift-JISコードで表記できない文字列を用意する必要が出てきます。そこで登場するのがユニコードです。今回はユニコードを操作するAPIについて、その特徴や活用方法などを解説したいと思います。

まずはソースコード内で頻繁に使うユニコードデータの保存用構造体を決めます。つまりPascalストリングスならStr255、Cストリングスなら前回紹介したCStr255構造体に相当するものです。独自に定義してもよいのですが、筆者はFile ManagerのAPIで利用されているHFSUniStr255構造体を用いています。この構造体はFiles.hヘッダーファイルで定義されています。



構造体で利用されているUniCharは別の場所でUInt16として定義されています。ここに記載されているUInt16はunsigned shortの事です。つまり1文字のデータが2バイトということになります。また、長さは655365文字まで設定できますが、UniCharの配列が255しか確保されていませんので、文字列長のオーバーフローには注意が必要です。この構造体のサイズ(sizeof(HFSUniStr255))は512バイトとなります。今回も、CStr255を定義した場合と同様に、以下のように格納文字長だけが異なる構造体(HFSUniStr63、HFSUniStr31、HFSUniStr15など)をいくつか用意しておくと便利です。



HFSUniStr255にユニコード文字列を格納し、各種APIや自作ルーチンに渡す場合に注意することがあります。HFSUniStr255のワードデータはPowerPC環境ではビッグエンディアンで、X86環境ではリトルエンディアンで保存されています。よって、この構造体を一度外部ファイルへ書き出し、異なるエンディアン環境のユニバーサル・アプリケーションで読み込む場合には、エンディアンをひっくり返す必要があります。もしアプリケーションのネイティブ・ファイルフォーマットをビッグエンディアン(PowerPC)とするならば、x86環境で読み込んだ場合には、以下のようなスワップルーチンを通すことになります。



文字の処理中に、ユニコード文字列をCFStringRefに変換したり、CFStringRefをユニコード文字列に変換したりする作業が発生した場合には、以下の2つのFile Manager APIを用いると便利です。ユニコードからCFStringRefを得るにはFSCreateStringFromHFSUniStr()を...

CFStringRef FSCreateStringFromHFSUniStr( CFAllocatorRef alloc,const HFSUniStr255 *uniStr);

逆に、CFStringRefからユニコードを得るにはFSGetHFSUniStrFromString()を使います。

OSStatus FSGetHFSUniStrFromString( CFStringRef theString,HFSUniStr255 *uniStr);

また、これらのAPIと同じ働きを持つルーチンをCore FoundationのAPIを利用し作成すると、以下のような感じになります。cfToUnicodeString()がCFStringRefからユニコード文字列への変換、unicodeToCFString()がユニコード文字列からCFStringRefへの変換を行います。



さて、話をアプリケーションの多国語対応に戻しましょう。Core Foundationには、ユニコード文字列を外部ファイルから読み込み自作アプリケーションで利用するのに最適なAPIが用意されています。以下のCFCopyLocalizedString()です。このAPIはCFBundle.hヘッダーファイルに定義されています。

CFStringRef CFCopyLocalizedString( CFStringRef key,const char *comment );

CFCopyLocalizedString()を利用するには、先んじて、アプリケーションで使うユニコード文字列を列記した「Localizable.strings」というファイルを、アプリケーションパッケージの「Resouces」フォルダ内の各言語対応フォルダに入れておく必要があります。例えば、英語用であれば「English.lproj」、日本語用ならば「Japanese.lproj」フォルダ内です。Finderの情報ウィンドウに各国語でバージョン番号等を表示させるために用意する「InfoPlist.strings」ファイルと同じ仕組みです。このAPIが、CFString.hではなくCFBundle.hに定義されているのは、利用形態が「パッケージ」の仕組みに深く関わっているのが理由です。

各国語用のLocalizable.stringsファイルは、Xcodeプロジェクトのファイル一覧に登録しておくことにより、リンク時にアプリケーションパッケージ内の適切なフォルダに格納されます。まず最初のサンプルとして、Apple社から提供されている「iPhoto」の日本語用Localizable.stringsを調べてみることにします。このファイルには恐ろしく大量の文字列が列記されていますが、最初の数行を見てみると...

AppName = "iPhoto";
VersionFormat = "%1$@ (%2$@)"; // for example, "4.0d8 (150)"
AboutFormat = "バージョン %2$@"; // AppName VersionFormat
MediaBrowser = "Aperture ライブラリを表示...";

となっています。最初の1行は、CFCopyLocalizedString()の最初の引数にキーワードとしてAppNameを渡せば、"iPhoto"というユニコード文字列がCFStringRefとして返ってくることを意味しています。ちなみに、2番目の引数は翻訳用コメントを記載しておく場所であり処理自体には何も意味を持ちません。キーワード側もCFStringRefである必要がありますので、以下のように記載すれば目的は達成されます。

CFStringRef cfstr;
HFSUniStr255 ustr;

cfstr=CFCopyLocalizedString( CFSTR( "AppName" ),"" );
FSGetHFSUniStrFromString( cfstr,&ustr );

同様に、4行目のキーワードのMediaBrowserを渡せば、日本語ユニコード文字列として"Aperture ライブラリを表示..."が返ってくるわけです。

cfstr=CFCopyLocalizedString( CFSTR( "MediaBrowser" ),"" );

今回取り上げたLocalizable.stringsサンプルの2行目には、返す文字列の中に「%1$@」といった表記があります。これは、どんな意味を持つのでしょうか?次回は、さらに詳しくLocalizable.stringsの表記の仕組みを解説したいと思います。


copyright 2007 Ottimo, Inc. All rights reserved
無断転載・引用禁止