Haiku OS アプリケーションのローカライズ
Haiku OS アプリケーションを C++ で実装したときにローカライズを提供する方法について説明します。
公式で提供する方法以外にも po ファイルを使った方法などがあります。ここでは、標準 API による方法について述べます。
シグネチャ
プログラムなどにシグネチャを割り当てます。他のプログラムと衝突しないように選んでください。
BApplication クラスのインスタンス化時に渡すものと同じです。以下に例を示します。
#include <Application.h> #define APP_SIGNATURE "application/x-vnd.AquaSKK-Preference" class SKKPreferenceApp : public BApplication { public: SKKPreferenceApp(); virtual ~SKKPreferenceApp() {}; }; SKKPreferenceApp::SKKPreferenceApp() : BApplication(APP_SIGNATURE) { }
この例でのシグネチャは x-vnd.AquaSKK-Preference です。application/ の部分はシグネチャには含めません。
このシグネチャを使用してプログラムとローカライズリソースを結びつけます。
ファイルの種類
以下のような種類のファイルを取り扱います。
種類 | 説明 |
---|---|
C++ | ローカライズする文字列を含むソースコード |
pre | ソースコードをまとめたファイル |
catkeys | 候補とチェックサムを含むタブ区切りテキストファイル |
catalog | ローカライズ用変換済みバイナリ |
rdef | リソース定義テキストファイル |
rsrc | 変換済みバイナリリソースファイル |
プログラム
以下のようなプログラムでローカライズ用リソースを作成します。
プログラム | 説明 |
---|---|
collectcatkeys | pre ファイルから候補を抽出して catkeys ファイル出力 |
linkcatkeys | catkeys ファイルから catalog ファイルを生成 |
rc | rdef を rsrc ファイルへ変換 |
xres | rsrc を実行フィルなどに結合 |
ソースコードでの候補マーキング
C++ ソースコード中でローカライズする文字列を指定します。
// 必要なヘッダのインクルード #include <Catalog.h> // コンテキストの定義 #undef B_TRANSLATION_CONTEXT #define B_TRANSLATION_CONTEXT "App-Preference" printf(B_TRANSLATE("Hello"));
Catalog.h をインクルードしてコンテキストなどを定義しておきます。その後、B_TRANSLATE などのマクロでローカライズ候補を指定します。
B_TRANSLATE などのマクロは B_COLLECTING_CATKEYS が定義されていると定義内容が変更され、pre ファイルを生成するときのマーキングが有効になります。普通にコンパイルするときには B_COLLECTING_CATKEYS を定義してはいけません。
マーキングの種類
以下のようなマクロが定義されています。用途に応じて使い分けてください。
マクロ | 説明 |
---|---|
B_TRANSLATE(string) | 翻訳させる。現在のコンテキスト |
B_TRANSLATE_CONTEXT(string, context) | 指定のコンテキストで翻訳 |
B_TRANSLATE_COMMENT | コメント付き |
B_TRANSLATE_ALL(string, context, comment) | コンテキストとコメントの両方を指定 |
B_TRANSLATE_ID(id) | リソース ID 参照? |
B_TRANSLATE_SYSTEM_NAME(string) | システムリソースから翻訳 |
B_TRANSLATE_MARK(string) | 翻訳マーキングのみ |
その他 | Catalog.h参照 |
B_TRANSLATE_MARK は Catalog.h に説明のあるとおり、翻訳候補としてマークされますが、実行時には翻訳されません。B_TRANSLATE などに渡して自分で翻訳後の文字列を取得してください。静的文字列配列の要素を翻訳用の catkeys に含めたいときに利用します。
候補の抽出用ファイル生成
候補抽出用にまとめた pre ファイルを生成します。これはヘッダファイルの内容もまとめて一つのファイルにしたものです。
ファイルを一つにまとめるには以下のようにコンパイラのプリプロセッサを利用します。
gcc -E -x c++ -DB_COLLECTING_CATKEYS -I./ app.cpp
-E オプションでプリプロセッサのみ実行します。-x c++ で C++ を指定しています。 -DB_COLLECTING_CATKEYS を指定して候補抽出ようマクロに切り替えます。
処理時にエラーが出た場合、大抵はインクルードパスが不足しています。
これで生成されたファイルに含まれる # から始まる行が悪さをすることがあるため、以下のようなスクリプトでそのような行を削除してしまうとよいでしょう。
# gen_pre.py import sys import argparse import subprocess def gen_pre(parser, includes, outpath, input_paths): inc = ["-I" + i for i in includes] data = [] args = [parser, '-E', '-x', 'c++', '-DB_COLLECTING_CATKEYS', '-DOS_LINUX', '-DOS_HAIKU'] args.extend(inc) args.extend(input_paths) p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if p.poll() is None: out = p.stdout.read() data.extend([line for line in out.split("\n") if not line.startswith("#")]) else: print(p.stderr.read()) return -1 with open(outpath, "w") as f: f.write("\n".join(data)) return 0 def main(): parser = argparse.ArgumentParser( description='Generates pre file from B_TRANSLATE.') parser.add_argument('--parser', help='C compiler') parser.add_argument('--outpath', help='pre file') parser.add_argument('--includes', nargs='+', help='Include dirs') parser.add_argument('--inputpath', nargs='+', help='C++ files to be extracted') args = parser.parse_args() return gen_pre(args.parser, args.includes, args.outpath, args.inputpath) if __name__ == '__main__': sys.exit(main())
python gen_pre.py --parser gcc --outpath out.pre --includes ../ --inputpath foo.cpp
catkeys ファイル生成
pre ファイルから候補を抜き出した catkeys ファイルを生成します。
collectcatkeys -s SIGNATURE -o en.catkeys out.pre
catkeys ファイルには元の文字列から生成されたチェックサムが含まれているため、元の文字列を変更するとファイルが壊れてしまいます。ソースコードでローカライズする文字列を変更したときは、pre ファイルを経由して catkeys ファイルを生成しなおしてください。
翻訳
en.catkeys ファイルを ja.catkeys としてコピーします。このファイルを翻訳します。
catkeys ファイルは以下のような構造をしています。
バージョン 言語 シグネチャ チェックサム 1 English x-vnd.AquaSKK-Preference 948131552 Select location... Preference Select location... Enable Preference Enable 元文字列 コンテキスト コメント 翻訳後文字列
各項目はタブで区切られています。言語名は変更しなくても問題ありません。
タブ区切りテキストのため、テキストエディタで編集できます。日本語が表示できてタブが可視化できるエディタをおすすめします。
CatKeysEditor で翻訳できますが、保存されないバグなどがあるようです。
catalog ファイル生成
catkeys ファイルを翻訳した後、catalog ファイルへ変換します。
linkcatkeys -o ja.catalog -s SIGNATURE -l ja ja.catkeys
-l オプションで言語名を指定します。ファイル名は言語名.catalog としておきます。
catalog ファイル配置
catalog ファイルは指定の場所に配置してシステムが読み込めるようにします。
システムまたは非パッケージ用の配置場所があります。
# システム /boot/system/data/locale/catalogs/SIGNATURE/ja.catalog # 非パッケージ /boot/home/config/non-packaged/data/locale/catalogs/SIGNATURE/ja.catalog
テストやパッケージ化セずに配布するアプリケーションでは非パッケージ用の場所に配置すると良いでしょう。
rdef ファイル定義
アプリケーションの実行ファイルにリソースに関する情報を追加しますが、その内容を定義するのが rdef ファイルです。
resource app_signature "application/x-vnd.App-Preference"; resource app_name_catalog_entry "x-vnd.App-Preference:System name:apppref";
ここで必要となるのはシグネチャです。アプリケーション、ローカライズ用 catkeys ファイルとシグネチャを合わせてください。
app.rdef などとして保存しておきます。
rdef ファイルではファイルアイコンなども指定できますが、ここでは説明を割愛します。
rdef ファイルを rsrc に変換
rdef ファイルをバイナリの rsrc ファイルに変換します。
rc -o app.rsrc app.rdef
rsrc を埋め込み
rsrc ファイルをアプリケーションの実行ファイルに埋め込みます。
xres -o app app.rsrc
ここでは、すでに存在する実行ファイル app に app.rsrc ファイルを埋め込んでいます。app ファイルが上書きされるので注意してください。リソースを埋め込んだ後のファイルを別ファイルにしたい場合、事前に実行ファイルをコピーしてください。