是否可以在编译时/运行时生成标记字符串的全局列表?

发布于 2024-08-03 20:46:36 字数 1143 浏览 3 评论 0原文

因此,我正在努力将我的 C++ 应用程序翻译成多种语言。我目前使用的是这样的:

#define TR(x) (lookupTranslatedString( currentLocale(), x ))
wcout << TR(L"This phrase is in English") << endl;

翻译来自 CSV 文件,它将英语字符串映射到翻译后的字符串。

"This phrase is in English","Nasa Tagalog itong pagsabi"

这是简化的,但这是基本思想。

我的问题是关于生成需要翻译的英语短语列表。我只需要包含所有英语短语和空白翻译短语的 CSV。我希望可以在编译时或运行时生成此列表。在编译时我在想这样的事情:

#define TR(x) \
    #warning x \
    (lookupTranslatedString( currentLocale(), x ))

然后可能解析编译日志,或者其他什么。这似乎不太管用。

在运行时也很棒。我正在考虑启动应用程序并使用一个隐藏命令来转储英文 CSV。我见过类似的方法,用于使用全局变量向中央列表注册命令。它可能看起来像这样:

class TrString
{
public:
    static std::set< std::wstring > sEnglishPhrases;
    TrString( std::wstring english_phrase ) { sEnglishPhrases.insert( english_phrase ); }
};

#define TR(x) do {static TrString trstr(x);} while( false ); (lookupTranslatedString( currentLocale(), x ));

我知道上面的代码有两个问题。我怀疑它是否可以编译,但更重要的是,为了生成所有英语短语的列表,我需要在访问 sEnglishPhrases 之前点击每个代码路径。

看起来我最终会编写一个小型解析器来读取所有代码并查找 TR 字符串,这并不是那么困难。我只是希望更多地了解 C++,以及是否有更好的方法来做到这一点。

So, I'm working on translating my C++ app into multiple languages. What I'm currently using is something like:

#define TR(x) (lookupTranslatedString( currentLocale(), x ))
wcout << TR(L"This phrase is in English") << endl;

The translations are from a CSV file which maps the english string to the translated string.

"This phrase is in English","Nasa Tagalog itong pagsabi"

This is simplified, but that's the basic idea.

My question is about generating the list of English phrases that need to be translated. I just need the CSV with all the english phrases, and blank translated phrases. I was hoping that it might be possible to either generate this list at compile time or at runtime. At compiletime I was thinking something like this:

#define TR(x) \
    #warning x \
    (lookupTranslatedString( currentLocale(), x ))

and then maybe parse the compile log, or something. This seems not to work so well.

At runtime would also be great. I was thinking of just starting the app and having a hidden command that would dump the english CSV. I've seen similar methods used to register commands with a central list, using global variables. It might look something like this:

class TrString
{
public:
    static std::set< std::wstring > sEnglishPhrases;
    TrString( std::wstring english_phrase ) { sEnglishPhrases.insert( english_phrase ); }
};

#define TR(x) do {static TrString trstr(x);} while( false ); (lookupTranslatedString( currentLocale(), x ));

I know there's two problems with the above code. I doubt it compiles, but more importantly, in order to generate a list of all english phrases, I'd need to hit every single code path before accessing sEnglishPhrases.

It looks like I'll end up writing a small parser to read through all my code and look for TR strings, which isn't really that tough. I was just hoping to learn a little more about C++, and if there's a better way to do this.

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

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

发布评论

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

评论(3

无敌元气妹 2024-08-10 20:46:36

您可以构建一个快速脚本来解析文件并删除您需要的内容。

awk '/TR\(L"[^"]*")/ {print}' plop.c

如果您需要稍微复杂一些的东西,那么 Perl 是您的朋友。

You could just build a quick script to parse the file and strip what you need.

awk '/TR\(L"[^"]*")/ {print}' plop.c

If you need somthing slightly more complex then perl is your friend.

自在安然 2024-08-10 20:46:36

我想你已经快到了。采用最后一个想法:

class TrString
{
public:
    static std::set< std::string > sEnglishPhrases;
    std::string phrase;
    TrString(const std::string& english_phrase ):phrase(english_phrase)
    { sEnglishPhrases.insert( english_phrase ); }
    friend ostream &operator<<(ostream &stream, const TrString& o);
};

ostream &operator<<(ostream &stream, const TrString& o)
{
    stream << lookupTranslatedString( currentLocale(), o.phrase);
    return stream;
}

#define TR(x) ( TrString(x) )
// ...
std::cout << TR("This phrase is in English") << std::endl;

正如您所说,您确实需要在每个 TR() 语句上运行代码,但您可以配置一个单元测试框架来执行此操作。

我的替代方案是使用上面的 TrString 类为每个模块创建静态变量:

// unnamed namespace gives static instances
namespace
{
   TrString InEnglish("This phrase is in English");
   // ...
}

现在您只需链接到替代 main() 即可打印出 TrString:: sEnglishPhrases

I think you're almost there. Taking the last idea:

class TrString
{
public:
    static std::set< std::string > sEnglishPhrases;
    std::string phrase;
    TrString(const std::string& english_phrase ):phrase(english_phrase)
    { sEnglishPhrases.insert( english_phrase ); }
    friend ostream &operator<<(ostream &stream, const TrString& o);
};

ostream &operator<<(ostream &stream, const TrString& o)
{
    stream << lookupTranslatedString( currentLocale(), o.phrase);
    return stream;
}

#define TR(x) ( TrString(x) )
// ...
std::cout << TR("This phrase is in English") << std::endl;

And as you say, you do need to run the code over every TR() statement, but you could configure a unit test framework to do this.

My alternative would be to use the above TrString class to make static variables for each module:

// unnamed namespace gives static instances
namespace
{
   TrString InEnglish("This phrase is in English");
   // ...
}

Now you just need to link in an alternative main() to print out TrString:: sEnglishPhrases

逆光下的微笑 2024-08-10 20:46:36

您正在寻找的内容似乎与 GNU gettext 的内容非常相似。特别是,请查看 xgettext 工具。

What you're looking for seems very similar to what GNU gettext does. In particular, look at the xgettext tool.

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