C ++:すでに作成されたプログラムをローカライズする方法
-
07-07-2019 - |
質問
すでに書いたプログラムをローカライズしたい..それはかなり大きく(ほぼ5万行)、理想的には(プログラマー)が可能な限り最小限の作業を行うことができ、システムに大きな変更を加えないシステムが欲しいプログラム-可能な場合はまったくありません。
gettext()を見て、とても気に入ったのですが、次のような文字列をどのように翻訳するかはわかりません:
const char *Colors[] = {
{ "Red" },
{ "Blue" },
{ "Yellow" },
....
};
これは私のプログラムでは非常に一般的です。ここで、「赤」を置き換えます。 gettext(" Red")では明らかに動作しません。
だから、OutputFunction(gettext(Colors [Id]))のようなことをすると思ったのですが、ローカライズする文字列のリストを取得するにはどうすればよいですか?どのプログラムも、「赤」、「青」、「黄」を取得できるほどスマートではないのではないかと思います。 to-localizeリストの静的なものから。
基本的にサーバーであるため、再コンパイルせずに言語を変更する必要はありません(サポートされているすべての言語で大きな問題や迷惑なしにコンパイルできます)。C++ 0xのconstexprについて考えました。完璧!配列などで機能し、コンパイル時にローカライズする文字列のリストを簡単に取得できます。コンパイラがまだ実装していないのは残念です。
すべての文字列をIDに変更することは、私の側で大量の作業を必要とし、特にすべての新しい文字列に新しいIDを作成するのは面倒なことなので、オプションではありません。上記のようなすべての配列を別の配列に変換する場合も同様です。
では、アイデアはありますか? :/
解決 2
gettext()とxgettextを何度も試してみたところ、自分で方法を見つけたと思います(1つは申し訳ありませんが、あなたのアプローチは好きではありませんでした。それらのmain()で、それは多くのexternと多くの余分な作業です:/)。
とにかく、これは理論的にはできると思う方法です(実際にはまだ翻訳を試みていませんが、なぜ機能しないのかはわかりません)
2つの#define:
#define _ gettext
#define __(x) x
その後、_を使用して実際に翻訳し、__を使用して文字列を単に「翻訳対象」としてマークします:
const char *Colors[] = {
{ __("Red") },
{ __("Blue") },
{ __("Yellow") },
....
};
void PrintColor(int id) {
cout << _("The color is: ") << _(Colors[id]);
}
次に実行します:
xgettext -k_ -k__ *.cpp
そして、次の.poファイルを取得します:
#: test.cpp:2
msgid "Red"
msgstr ""
#: test.cpp:3
msgid "Blue"
msgstr ""
#: test.cpp:4
msgid "Yellow"
msgstr ""
#: test.cpp:9
msgid "The color is: "
msgstr ""
したがって、__(または他の名前、実際には問題ではない)を&quot;ダミー関数&quot;として使用します。文字列を翻訳する必要があることを xgettext に通知し、_で実際にgettext()を呼び出します。
文字列で_を呼び出すと、文字列も翻訳対象としてマークされ、変数、配列などで呼び出すと、xgettextによって単に無視されるように見えます。
すばらしい! 5兆個のファイルを調べて、アンダースコアを追加するだけで、まるで猿のようになります:/
他のヒント
具体的な例として、次のようなものを試してみます:
// presumably globals
const char *Colors_en[] = {
{ "Red" },
{ "Blue" },
{ "Yellow" },
....
};
const char *Colors[] = {0};
// in main()
gettextarray(Colors_en, Colors, sizeof(Colors_en) / sizeof(char*));
gettextarrayは、各入力でgettextを呼び出し、出力を書き込みます。 std :: transformの呼び出しとして実装できると思います。そして、ちょっとしたテンプレートのトリックで、sizeパラメーターを回避できます。
別のオプションは、色文字列のいずれかが使用される(表示される、または表示用の文字列に追加される)時点でgettextを呼び出すことです。それはより多くのコードを変更することを意味しますが、main()がそれらを使用するかもしれない何かをする前にプログラム内のすべての文字列のセットを翻訳することを必要としません。
mainで作業を行いたくない場合は、次のような文字列を使用するコードで実行できます。
if (Colors[0] == 0)
gettextarray(Colors_en, Colors, sizeof(Colors_en) / sizeof(char*));
またはアプリがマルチスレッドの場合、 pthread_once
または使用するスレッドAPIの同等のものを検討してください。