Microsoft provides a redistributable library that adds this functionality for XP, but it's 2MB and yet another module to install. Since my entire installation is 4MB, this isn't an option for me. You can read about that library in the article Mapping Locale Data on Downlevel Systems. In that article, they discuss the function DownlevelLocaleNameToLCID().
For handy reference, Microsoft provides a list of Language Identifier Constants and Strings on MSDN.
If you then need to convert the LCID to a CODEPAGEID, you can use this call to retrieve the code page for a particular LCID:
GetLocaleInfo(lcid, LOCALE_IDEFAULTCODEPAGE, ...)
Additional information on this topic can be found on The Old New Thing blog, including a discussion of using the MLang library.
// This is a version of LocaleNameToLCID() that works on Windows XP.
// On Windows Vista or later, it automatically delegates to the
// built-in version of LocaleNameToLCID().
// This function is not case-sensitive.
// Tested with Unicode builds only, not tested under ANSI builds, but should be pretty close.
// Example value for szLocale is "en-US"
LCID CompatibleLocaleNameToLCID(LPCSTR szLocale)
{
CString strValue(szLocale);
CStringW wstrValue(strValue);
static bool bDone;
LCID (WINAPI * pfnLocaleNameToLCID)(LPCWSTR, DWORD);
if (!bDone)
{
bDone = true ;
*(FARPROC*)&pfnLocaleNameToLCID = ::GetProcAddress(GetModuleHandleA("Kernel32" ), "LocaleNameToLCID" );
}
if (pfnLocaleNameToLCID)
return LocaleNameToLCID(wstrValue, 0);
CComPtr<IMultiLanguage> iLang;
HRESULT hr = iLang.CoCreateInstance(CLSID_CMultiLanguage);
LCID lcid;
if (SUCCEEDED(hr) && SUCCEEDED(iLang->GetLcidFromRfc1766(&lcid, (BSTR)wstrValue.GetString()))) {
return lcid;
}
return LOCALE_USER_DEFAULT;
}