!!!SXULによるリソース管理 多言語対応のアプリケーションの場合、表示するテキストは 言語によって切り替える必要があります。 プログラムにダイレクトに埋め込むと、別の言語対応を行う場合に 苦労してしまいます。 この場合は、文字列やウィンドウなどを「リソース」としてプログラムから 分離します。 XOOPS(PHPプログラム)や最近のJavaプログラムでも一般的に使われるようになっている方法です。 Shadeでも同じで、現在はShadeの日本語版・英語版・中国語版などが あります。 ユーザ視点から見ると、一言語だけしか使わないのが普通でしょうから問題ないですが プラグインやShade本体を作る側から見ると、この管理をしっかりしないと 大変なことになりそうなのが分かるかと思います。 それで、Shade8で追加されたのが「'''SXUL'''」という仕組みです。 残念ながらSDKドキュメントでは詳しいことが書いておりません。 そこで、このサイトで補間してみることにします。 !!SXUL なんの略なんでしょうね、「Shade Exなんとか Universal Language」でしょうか・・・(^_^;;。これはドキュメントにも無いので適当に想像してください。 何をするものかというと、ウィンドウ(window_interface)やダイアログ(dialog_interface)の定義・デザインを言語ごとにXML形式で記述して、 Shadeにてリソース管理をする仕組みです。 で、Shadeの開発の方にお聞きしたところ 文字列自身も扱えるよ、とのことでした。 てっきりウィンドウ管理用のリソースと思って触ってなかったのですが、 文字列だけのリソースもSXULで管理できるようです。 極端に言うと、プログラムロジック部では言語依存部分(日本語表示・英語への切り替えなど)は分離してしまいSXULに分けてしまうことができます。 あくまでもプログラム・プラグイン内部の仕組みでありますので、 Shadeを使う側からみると、過去のShadeと何が変わったのかは分かりにくいかと 思います。 しかし、プラグインを作る側から見ると非常に大きな変更ともいえるかもしれません。 !!SXULで扱える言語(ロケール)について 現在のShadeで言うと、日本語と英語ですね。 ただ、OSXのプラグインSDKのディレクトリ名から判断すると、以下のものを 作成することができそうです。 ,識別名,言語名 ,de,ドイツ語 ,en,英語 ,es,スペイン語 ,fr,フランス語 ,ja,日本語 ,zh_CN,中国語 (簡体字) このようなロケールは、Javaでも同等のものが定義されています。 Javaというか、UTF-8で扱うことができる言語が指定できます。 WindowsとOSXでは、SXULのファイル名やディレクトリ構成が 異なりますので注意してください。 !!プラグインソースからのSXUL文字列の参照 「文字列としてのリソース」をSXULを使って実現する方法を説明します。 SXULを扱う場合は、文字コードとしてはすべて「UTF-8」で処理します。 ただし、ソース自身は(コメント以外)言語・コード依存するものではありませんので これは不問です。 !ShadeプラグインをUTF-8で管理する グローバル関数の「get_text_encoding」にて、日本語の場合は「plugin_interface::japanese_encoding」を返す(この場合は、文字列はSHIFT_JISで処理しないといけない)、それ以外はUTF-8で、という指定をしてました。 extern "C" int STDCALL get_text_encoding (shade_interface *shade, void *) { return shade->is_japanese_mode() ? plugin_interface::japanese_encoding : 0; } これは不要になります。記述しないとすべて0(つまりUTF-8)を返すことになりますので、この部分をコメントアウトします。 //extern "C" int STDCALL get_text_encoding (shade_interface *shade, void *) { // return shade->is_japanese_mode() ? plugin_interface::japanese_encoding : 0; //} !SXULの文字列取り出し ヘッダ部分でstringinterface.hをインクルードします。 SXULで文字列を扱うには、strings_interfaceを使用します。 #include "stringsinterface.h" たとえば、「HelloWorldStrings」というリソース識別名(後述)から 2番目に指定された文字列を取得する場合は、以下のように「strings_interface」 を作成して「get_string(2)」で文字列を取得してきます。 元のSXULファイルはUTF-8で保存していますので、そのままUTF-8形式の 文字列を取得することができます。 compointer strings(shade->create_strings_interface("HelloWorldStrings")); // SXULのXMLファイルより2番目の文字列を取得 shade->message(strings->get_string(2)); 日本語・英語などはSXULファイルごとに分離されていますので、 どの言語でShadeが動いているか、は意識する必要がありません。 「shade->create_strings_interface("HelloWorldStrings"));」の部分での "HelloWorldStrings"はりソースとして割り当てられている識別名です。 Windowsでは大文字と小文字の区別はないようです。Windowsでは プロジェクトのリソース(script2.rc)として、 "HelloWorldStrings"の名称がSXULのファイルに結び付けられています。 プラグインのソース部からはこれだけです。シンプルですね。 ただし、「では、どのSXULファイルをリソースとして参照するのか」というのを プロジェクトに結びつけるのがやっかいです。 これはOSごとに違いますので、Windowsの場合、OSXの場合、のそれぞれを 見ていくことにします。 !!プロジェクトにSXULファイルを割り当てる(Windowsの場合) Windowsの「Visual C++ .NET 2003」では、開発環境のGUIにて リソースを割り当てることができるのですが、これではうまいこと SXULを割り当てることができません。 リソースファイルである「script2.rc」を直接いじっていきます。 プラグインSDKの「win\plugins\script2.rc」をテキストエディタで開きます。 !script2.rcの編集 ///////////////////////////////////////////////////////////////////////////// // 日本語 resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN) #ifdef _WIN32 LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT #pragma code_page(932) #endif //_WIN32 ///////////////////////////////////////////////////////////////////////////// // // SXUL // SIMPLE_WINDOW SXUL "..\\..\\sample\\resources\\sxuls\\simple_window.ja.sxul" SIMPLE_STRINGS_ID SXUL "..\\..\\sample\\resources\\sxuls\\simple_strings_id.ja.sxul" SIMPLE_DIALOG_ID SXUL "..\\..\\sample\\resources\\sxuls\\simple_dialog_id.ja.sxul" TEXT SXUL "..\\..\\sample\\resources\\sxuls\\text.ja.sxul" のように書かれているものが2箇所あります。 「// 日本語 resources」のところの「SIMPLE_WINDOW」「SIMPLE_STRINGS_ID」 「SIMPLE_DIALOG_ID」が、サンプルプラグインで利用しているリソースです。 順番に、window_interfaceの定義/dialog_interfaceの定義/文字列リソースの定義、 となります。 どの識別名がどのSXULファイルに対応しているのか、というのが分かるかと 思います。実際のリソースの編集は「xxxx.ja.sxul」ファイルをいじるとよいです。 .NETでのリソースでは、あくまでもリソース識別名とファイルを結び付けているだけです。 ちょっと下を見ると、今度は英語リソースの記述があります。 ///////////////////////////////////////////////////////////////////////////// // 英語 (米国) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) #ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) #endif //_WIN32 ///////////////////////////////////////////////////////////////////////////// // // SXUL // SIMPLE_WINDOW SXUL "..\\..\\sample\\resources\\sxuls\\simple_window.en.sxul" SIMPLE_STRINGS_ID SXUL "..\\..\\sample\\resources\\sxuls\\simple_strings_id.en.sxul" SIMPLE_DIALOG_ID SXUL "..\\..\\sample\\resources\\sxuls\\simple_dialog_id.en.sxul" TEXT SXUL "..\\..\\sample\\resources\\sxuls\\text.en.sxul" 識別名は日本語の場合とまったく同じですが、 「xxxxx.en.sxul」とjaがenになってます。このSXULファイルでは 英語の文字列を指定しています。 新たに「HELLOWORLDSTRINGS」という識別名を加えて、日本語を「HelloWorldStrings.ja.sxul」、英語を「HelloWorldStrings.en.sxul」とします。 // 日本語 resources ... HELLOWORLDSTRINGS SXUL "..\\..\\sample\\resources\\sxuls\\HelloWorldStrings.ja.sxul" ... // 英語 (米国) resources ... HELLOWORLDSTRINGS SXUL "..\\..\\sample\\resources\\sxuls\\HelloWorldStrings.en.sxul" 後は、プラグインソースで compointer strings(shade->create_strings_interface("HelloWorldStrings")); にて、「HELLOWORLDSTRINGS」のリソースを読み込み、 // SXULのXMLファイルより2番目の文字列を取得 shade->message(strings->get_string(2)); でUTF-8の文字列を取得しています。 !!プロジェクトにSXULファイルを割り当てる(OSXの場合) Windowsとは構成が違います。 リソースであるSXULファイルは、 macos/plugins/ja.lproj/sxutils/simple_strings_id.sxul macos/plugins/en.lproj/sxutils/simple_strings_id.sxul のように分かれています。 Windowsのようにファイル名が「xxxx.ja.sxul」となるのではなく、 ディレクトリ名が「ja.lproj/sxutils/xxxx.sxul」となっています。 プラグインSDKではディレクトリはあらかじめ用意されていますので、 言語が異なる場合は「ファイル名は同じで中身を変えて」言語別ディレクトリに SXULファイルを放り込んでいきます。 ここに、日本語の「HelloWorldStrings.sxul」を入れている例です。 {{ref_image img03.png}} ファイル名がそのままリソース識別名になりますので、間違えないようにしてください。 Xcodeでは、そのままではSXULがどのファイルなのか、というのが分かりません。 ですので、明示的に割り当ててあげる必要があります。 左端にある「Groups & Files」より、[xplugins] - [Resources] - [sxuls]の ツリーノードを選択します。 その後、右に出る「sxul(de)」〜「sxul(zh_CN)」までをすべて選択してください。 {{ref_image img01.png}} ターゲットとなるプロジェクト(ここではHelloShade)を開き、 [HelloShade] - [Copy Bundle Resources]内に、 上記で選択した状態の「sxul(de)」などをドラッグ&ドロップします。 すると、プロジェクト内に「sxuls(de)」〜「sxuls(zh_CN)」が追加されます。 これで、プロジェクトがSXULファイルを参照することができるようになります。 {{ref_image img02.png}} 後は、Windowsの場合と同様に、プラグインソースで compointer strings(shade->create_strings_interface("HelloWorldStrings")); shade->message(strings->get_string(2)); のようにすることで文字列リソース類を参照することができるようになります。 !!SXULファイルの中身 最後に、SXULファイルの中身についてです。 「HelloWorldStrings.ja.sxul」(OSXでは「macos/plugins/ja.lproj/sxutils/HelloWorldStrings.sxul」) 普通のXMLファイル形式です。1行目はUTF-8であることを明示する部分で そのまま記述します。 タブ内にで文字列を記述します。 文字コードは「UTF-8」で保存するようにしてください。 文字列リソースは、列挙する順番がプラグインソース部で「strings->get_string(index);」 としたときの第一引数のindexに対応します。 上記だと、0番目が"はろ〜Shade"、1番目が"SXULを使った簡単なプラグイン"と続きます。 英語リソースは構成が同じでvalueだけ英語になってます。 「HelloWorldStrings.en.sxul」(OSXでは「macos/plugins/en.lproj/sxutils/HelloWorldStrings.sxul」) 以下のようにプラグインソースから文字列を取得してメッセージウィンドウに 結果を表示する場合、 compointer strings(shade->create_strings_interface("HelloWorldStrings")); shade->message(strings->get_string(2)); Shadeが英語モードの場合は「The display that uses SXUL is done.」、 日本語モードの場合は「SXULを使った表示を行います。」が表示されることになります。 !!グローバル関数「get_name」ではSXULは使えない? メニューの項目名を日本語・英語切り替えしたい場合に、 extern "C" const char * STDCALL get_name (const IID &iid, int i, shade_interface *shade, void *) { if (iid == plugin_iid) { compointer strings(shade->create_strings_interface("HelloWorldStrings")); return strings->get_string(0); } return 0; } として利用しようとすると、プラグイン自身が認識できなくなってしまいました。 対応してないのかなぁ、SXULを使わずに英語で表示したほうが無難かも。 !!終わりに このように、SXULを使用することで言語依存する部分は分離してしまうことが できるようになっています。 その他、文字列だけではなくて バージョン情報はtext.ja.sxul(OSXではmacos/plugins/ja.lproj/sxutils/text.sxul)に表記、 window_interfaceでのウィンドウデザインの定義もSXULで実装できます。 まだ使いやすいものではないですが、リソースを有効利用することで 開発が効率アップするための仕組みが強化されるといいですね。 個人的には、Windows/OSXによって SXULのファイル構成が異なる・ファイル名が異なるのは あまりよろしくないと思います。 できれば、WindowsのソースやSXULファイルをポンとOSXのXcodeに放り込むと、 同じような動作をするOSX版のプラグインがビルドできる、などの可搬性が ほしいところです。といっても、プログラムのリソースの仕組み(実行ファイルまたは動的ライブラリにマージされる)の都合上、一筋縄では行かない部分ではありますが・・・。 SXULを使ったプラグインインターフェース「HelloShade」のソースコードを 以下においておきました。 Shadeのプラグインメニューから「HelloShade」を選択すると、 メッセージウィンドウにSXULより取得した文字列が表示されます。 [HelloShade_sxul_src_20051202.zip|http://ft-lab.ne.jp/files/shade/shade8_sdk/HelloShade_sxul_src_20051202.zip](3KB) :HelloShadeのプラグインソース:HelloShade.cpp :英語のSXULリソース:resources/sxuls/HelloWorldStrings.en.sxul :日本語のSXULリソース:resources/sxuls/HelloWorldStrings.ja.sxul OSXでは、SXULリソースを「HelloWorldStrings.sxul」にリネームして 「macos/plugins/en.lproj/sxutils/」「macos/plugins/ja.lproj/sxutils/」 に入れるようにしてください。