|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionSome countries and languages standardize on number and date formats that don't translate smoothly between cultures. It is important for C++/Windows developers to have strategies and techniques to handle this challenge and other challenges presented by diverging sets of localization API functions. The CtrSynch sample app illustrates how to keep the Windows API locale in synch with the C-runtime (CRT) locale so that functions like BackgroundHave you ever encountered a situation where you need to read a double/floating point value from text formatted in another locale? For example, the number 1023.54 displays in English-US as 1,023.54 and in German-Germany as 1.023,54. This problem comes up often when sharing text-based information generated in Europe (Germany, France, Spain) and consumed in the US. The reverse is also true. Say, a German company exports a Tab Separated text (TSV) file from a spreadsheet on a workstation running in the German-Germany locale. The file is emailed to an American firm, where values like 1.023,54 import as a decimal number between 1 and 2 rather than 1023. This is a very common scenario. The first step in properly transferring double values (or dates formatted by locale defaults) is to include a locale identifier in the data. This can be accomplished using a file header, an LCID field in each data row, embedded logic in the file name, and so on. In my simple example, I just wrote a method to pack an LCID onto the end of the string containing the number. Conversely, I wrote a routine to parse it back out before reading the number. The final issue is the actual conversion of the text to doubles. My first instinct was to run It doesn't work! I spent a lot of time trying to figure this out, and I hope to save you the effort! It turns out, the C-runtime routine Well, I wish it was that simple! Here is what must happen in your code to keep the thread locale in step with the CRT's locale: SetThreadLocale(1033); setlocale(LC_ALL, "English_USA.1252"); You probably see the problem -- the two functions consume very different input parameters. After struggling with this, I found the solution is actually quite simple. It just required digging in the Windows API a bit. LPCTSTR CCrtLocaleSwitch::loadLocaleId(LCID lcid, _bstr_t& bstrRetBuf)
{
TCHAR arcBuf[128];
memset(arcBuf, 0, sizeof(arcBuf));
//We should check the return code, but skipped for brevity...
//Loading the English name fo the locale
GetLocaleInfo( lcid, LOCALE_SENGLANGUAGE, arcBuf, 127);
bstrRetBuf = arcBuf;
memset(arcBuf, 0, sizeof(arcBuf));
//Loading the English name for the country/region
GetLocaleInfo( lcid, LOCALE_SENGCOUNTRY, arcBuf, 127);
if( *arcBuf )
{
bstrRetBuf += TEXT("_");
bstrRetBuf += arcBuf;
}
//Loading the code page
memset(arcBuf, 0, sizeof(arcBuf));
if( (GetLocaleInfo( lcid, LOCALE_IDEFAULTANSICODEPAGE, arcBuf, 127)
|| GetLocaleInfo( lcid, LOCALE_IDEFAULTCODEPAGE, arcBuf, 127))
&& *arcBuf )
{
bstrRetBuf += TEXT(".");
bstrRetBuf += arcBuf;
}
return bstrRetBuf;
}
The function above creates the string that is acceptable for One final note regarding the sample application -- the sample classes are designed to restore state when they go out of scope. Regardless of how you exit a function, whether it's a normal Using the codeThe sample application was written in Visual C++ 7.1. The two main reusable classes, #include <comdef.h> #include <TempLocale.h> The application itself is rather useless, but it illustrates keeping the CRT in synch with the Windows thread locale. When you select a new culture on the left, the window caption changes to "Hello World" in the selected language. Since MFC's ConclusionThe Windows API provides routines to load resources in the current thread's locale. The CRT provides routines to convert numbers to text and back again. The two sets of APIs don't share a locale status; therefore, C++ developers must build a way to keep them in synch. This article demonstrated a way to handle this task. History
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||