Is it possible to create a global list of marked lines at compile time / runtime?

So, I am working on translating my C ++ application into several languages. I am currently using something like:

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

Translation is carried out from a CSV file that maps the English string to the translated string.

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

This is simplified, but the main idea.

My question is about creating a list of English phrases to translate. I just need a CSV with all English phrases and empty translated phrases. I was hoping that it might be possible to generate this list at compile time or at runtime. In compiletime, I thought something like this:

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

and then maybe analyze the compilation log or something else. It doesn't seem so good.

Runtime will also be great. I only thought about starting the application and had a hidden command that would reset the CSV. I have 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 two problems with the above code. I doubt that it compiles, but more importantly, to create a list of all English phrases, I would have to hit every path of the code before accessing sEnglishPhrases.

It looks like I'll write a small parser to read all my code and look for TR lines, which is actually not that difficult. I was just hoping to learn a little more about C ++, and if there is a better way to do this.

+2
source share
3 answers

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 need to run the code on each TR() statement, but you can configure the unit test framework for this.

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

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

Now you just need to bind an alternative main() to print TrString :: sEnglishPhrases

+1
source

You can simply create a quick script to parse the file and delete everything you need.

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

If you need something a little more complicated then perl is your friend.

+2
source

What you are looking for seems to be similar to what GNU gettext does. In particular, check out the xgettext tool.

0
source

Source: https://habr.com/ru/post/1343089/


All Articles