As a follow-up of this question (Message compiler replacement in Linux gcc), I have the following problem:
When using MC.exe on Windows for compiling and generating messages, within the C++ code I call FormatMessage, which retrieves the message and uses the va_list *Arguments parameter to send the varied message arguments.
For example:
messages.mc file:
MessageId=1
Severity=Error
SymbolicName=MULTIPLE_MESSAGE_OCCURED
Language=English
message %1 occured %2 times.
.
C++ code:
void GetMsg(unsigned int errCode, wstring& message,unsigned int paramNumber, ...)
{
HLOCAL msg;
DWORD ret;
LANGID lang = GetUserDefaultLangID();
try
{
va_list argList;
va_start( argList, paramNumber );
const TCHAR* dll = L"MyDll.dll";
_hModule = GetModuleHandle(dll);
ret =::FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE|FORMAT_MESSAGE_IGNORE_INSERTS,
_hModule,
errCode,
lang,
(LPTSTR) &msg,
0,
&argList );
if ( 0 != ret )
{
unsigned int count = 0 ;
message = msg;
if (paramNumber>0)
{
wstring::const_iterator iter;
for (iter = message.begin();iter!=message.end();iter++)
{
wchar_t xx = *iter;
if (xx ==L'%')
count++;
}
}
if ((count == paramNumber) && (count >0))
{
::LocalFree( msg );
ret =::FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_HMODULE,
_hModule,
errCode,
GetUserDefaultLangID(),
(LPTSTR) &msg,
0,
&argList );
}
else if (count != paramNumber)
{
wstringstream tmp;
wstring messNumber;
tmp << (errCode & 0xFFFF);
tmp >> messNumber;
message = message +L"("+ messNumber + L"). Bad Format String. ";
}
}
::LocalFree( msg );
}
catch (...)
{
message << L"last error: " << GetLastError();
}
va_end( argList );
}
Caller code:
wstring message;
GetMsg(MULTIPLE_MESSAGE_OCCURED, message,2, "Error message", 5);
Now, I wrote a simple script to generate a .msg file from the .mc file, and then I use gencat to generate a catalog from it.
But is there a way to use the formatted strings as they contain %1, %2, etc. and NOT the general (%d, %s…) format?
Please note, that the solution has to be generic enough for each possible message with each posible types\ arguments order…
Is it possible at all?
Thank you.
First of all functions like printf support positioned format:
For C++, beside the C solution there is a
boost::formatlibrary:Also if you are moving software to Linux I would suggest use “different” approach for localization: use either gettext or boost.locale library.
And instead of this:
Use :
C/gettext:
C++/gettext:
C++ using boost.locale: