C++:如何本地化已编写的程序

发布于 2024-08-04 20:08:50 字数 705 浏览 7 评论 0原文

我想本地化我已经编写的程序..它相当大(几乎 50k 行),理想情况下我想要一个允许我(程序员)做尽可能少的工作的系统,并且无需对程序进行重大更改 - 如果可能根本没有。

我查看了 gettext() 并非常喜欢它,但我不清楚它如何翻译这些字符串:

const char *Colors[] = {
 { "Red" },
 { "Blue" },
 { "Yellow" },
 ....
};

这些字符串在我的程序中非常很常见。这里用 gettext( 替换“Red”) “红色”)显然行不通。

所以我想我会做类似 OutputFunction(gettext(Colors[Id])) 的事情,但是如何获取要本地化的字符串列表?我怀疑任何程序都足够聪明,能够从静态本地化列表中获取“红色”、“蓝色”、“黄色”。

因为它基本上是一个服务器,所以不需要能够在不重新编译的情况下更改语言(我可以为每种支持的语言编译它,而不会出现任何重大问题或烦恼),我想到了 C++0x 的 constexpr,这将是完美的!它可以在数组/等中工作,并且我可以轻松获得要在编译时本地化的字符串列表。遗憾的是,还没有编译器实现它。

将所有字符串更改为 ID 并不是一种选择,因为这需要我做大量的工作,尤其是为每个新字符串创建一个新 id 会非常烦人。这同样适用于将所有数组(如上面的数组)转换为其他数组。

那么,有什么想法吗? :/

I want to localize a program I already written.. It's fairly big (almost 50k lines) and ideally I want a system that allows me (the programmer) to do the least amount of work possible, and without major changes to the program - if possible none at all.

I looked at gettext() and liked it a lot, but it's unclear to me how it would translate strings such as these:

const char *Colors[] = {
 { "Red" },
 { "Blue" },
 { "Yellow" },
 ....
};

which are VERY common in my program.. Here replacing "Red" with gettext("Red") would obviously not work.

So I thought I would do something like, OutputFunction(gettext(Colors[Id])), but then how can I get a list of strings to localize? I doubt any program is smart enough to be able to get "Red", "Blue", "Yellow" from that in a to-localize list statically.

Since it's basically a server there is no need for the ability to change the language without recompiling (I can compile it for every supported language without any major problem or annoyance), I thought about C++0x's constexpr, which would be perfect! It would work in arrays/etc and I would easily get a list of strings to localize at compile time.. Too bad that no compiler implemented it yet.

Changing all the strings to an ID is not an option since it would require a massive amount of work on my part and especially creating a new id for every new string would be annoying as hell. The same applies to converting all the arrays like the one above to something else.

So, any ideas? :/

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

超可爱的懒熊 2024-08-11 20:08:50

对于您的具体示例,我可能会尝试以下操作:

// 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 一样实现。您可以通过一些模板技巧来避免使用大小参数。

另一种选择是在将要使用任何颜色字符串(显示或附加到字符串以进行显示)的位置调用 gettext。这意味着更改更多代码,但不需要 main() 在执行任何可能使用它们的操作之前翻译程序中的每组字符串。

如果您不想在 main 中执行该工作,则可以在使用字符串的代码中执行此操作,如下所示:

if (Colors[0] == 0)
  gettextarray(Colors_en, Colors, sizeof(Colors_en) / sizeof(char*));

或者,如果您的应用程序是多线程的,请考虑 pthread_once 或中的等效项您使用的线程 API。

For your specific example, I might try something like:

// 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 calls gettext on each input and writes an output. I think it could be implemented just as a call to std::transform. And you could avoid the size parameter with a bit of template trickery.

Another option is to call gettext at the point where any of the color strings is about to be used (displayed, or appended to a string for display). That means changing more code, but doesn't require that main() translates every set of strings in the program prior to doing anything that might use them.

If you don't want to do the work in main, you could do it in the code which uses the strings, something like this:

if (Colors[0] == 0)
  gettextarray(Colors_en, Colors, sizeof(Colors_en) / sizeof(char*));

Or if your app is multithreaded, consider pthread_once or the equivalent in the thread API you use.

御弟哥哥 2024-08-11 20:08:50

经过大量使用 gettext() 和 xgettext 之后,我想我自己找到了一种方法(对不起,onebyone,但我不喜欢你的方法。一定有数百个这样的数组,我必须将它们全部导入main(),这是很多 extern 和很多额外的工作:/)。

无论如何,这就是我认为理论上可以完成的方式(我还没有尝试实际翻译,但我不明白为什么它不起作用)

两个#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 ""

因此,您使用 __ (或任何其他名称,并不重要)作为“虚拟函数”来让 xgettext 知道该字符串需要翻译,并且 _ 实际调用 gettext()。

如果您使用字符串调用 _ ,那么该字符串也将被标记为待翻译,如果您使用变量、数组等调用它,那么它似乎会被 xgettext 忽略。

伟大的!现在我所要做的就是浏览 5 万亿个文件并在周围添加下划线,就好像我是一只猴子一样:/

After a lot of playing around with gettext() and xgettext I think I found a way myself (sorry onebyone but I didn't like your approach.. There must be hundreds of arrays like that and I would have to import all of them in main(), that's a lot of extern and a lot of extra work :/).

Anyways, this is how I think it can theoretically be done (I haven't tried yet to actually translate but I don't see why it wouldn't work)

Two #define's:

#define _ gettext
#define __(x) x

Then you use _ to actually translate and __ to simply mark strings as "to be translated":

const char *Colors[] = {
 { __("Red") },
 { __("Blue") },
 { __("Yellow") },
 ....
};

void PrintColor(int id) {
    cout << _("The color is: ") << _(Colors[id]);
}

Then you run:

xgettext -k_ -k__ *.cpp

And you get the following .po file:

#: 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 ""

So, you use __ (or any other name, doesn't really matter) as a "dummy function" to just let xgettext know that the string needs to be translated, and _ to actually call gettext().

If you call _ with a string then the string will be marked to-be-translated as well, if you call it with a variable, array, whatever then it appears to be simply ignored by xgettext.

Great! Now all I have to do is go through 5 trillion files and add underscores around, as if I was a monkey :/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文