Search code examples
c++windowswinapilocalizationlocale

Can I get a code page from a language preference?


Windows seems to keep track of at least four dimensions of "current locale": http://www.siao2.com/2005/02/01/364707.aspx

  • DEFAULT USER LOCALE
  • DEFAULT SYSTEM LOCALE
  • DEFAULT USER INTERFACE LANGUAGE
  • DEFAULT INPUT LOCALE

My brain hurts just trying to keep track of what the hell four separate locale's are useful for...

However, I don't grok the relationship between code page and locale (or LCID, or Language ID), all of which appear to be different (e.g. Japanese (Japan) is LANGID = 0x411 location code 1, but the code page for Japan is 932).

How can I configure our application to use the user's desired language as the default MBCS target when converting between Unicode and narrow strings?

That is to say, we used to be an MBCS application. Then we switched to Unicode. Things work well in English, but fail in Asian languages, apparently because Windows conversion functions WideCharToMultiByte and MultiByteToWideChar take an explicit code page (not a locale ID or language ID), which can be set to CP_ACP (default to ANSI code page), but don't appear to have a value for "default to user's default interface language's code page".

I mean, this is some seriously convoluted twaddle. Four separate dimensions of "current language", three different identifier types, as well as (different) string-identifiers for C library and C++ standard library.

In our previous MBCS builds, disk I/O and user I/O worked correctly: everything remained in the DEFAULT SYSTEM LOCALE (Windows XP term: "Language for non-Unicode Programs"). But now, in our UNICODE builds, everything tries to use "C" as the locale, and file I/O fails to properly transcode UNICODE to user's locale, and vice verse.

We want to have text files written out (when narrow) using the current user's language's code page. And when read in, the current user's language's code page should be converted back to UNICODE.

Help!!!

Clarification: I would ideally like to use the MUI language code page rather than the OS default code page. GetACP() returns the system default code page, but I am unaware of a function that returns the user's chosen MUI language (which auto-reverts to system default if no MUI specified / installed).


Solution

  • FWIW, this is what I ended up doing:

    1. #define _CONVERSION_DONT_USE_THREAD_LOCALE // force CP_ACP *not* CP_THREAD_ACP for MFC CString auto-conveters!!!
    2. In application startup, construct the desired locale: m_locale(FStringA(".%u", GetACP()).GetString(), LC_CTYPE)
    3. force it to agree with GetACP(): // force C++ and C libraries based on setlocale() to use system locale for narrow strings
      m_locale = ::std::locale::global(m_locale); // we store the previous global so we can restore before termination to avoid memory loss

    This gives me relatively ideal use of MFC's built-in narrow<->wide conversions in CString to automatically use the user's default language when converting to or from MBCS strings for the current locale.

    Note: m_locale is type ::std::locale