Click here to Skip to main content
15,867,330 members
Articles / Programming Languages / C++
Article

Multiple language support for MFC applications with extension DLL

Rate me:
Please Sign up or sign in to vote.
4.70/5 (35 votes)
19 Jul 200517 min read 450.2K   8.9K   193   53
This document discusses: how to build a resource only language DLL, how to detect OS language setting, how to load language DLL from extension DLL, and an MFC application.

Sample image

Introduction

I have read a lot of good articles on CodeProject. Now it's time for me to provide one. Please leave any comment or suggestion you may have. All are welcome and greatly appreciated. I do want to get your feedback on this implementation of multiple language support. Following requirements have been made for this implementation of multiple language support for MFC applications with MFC extension DLL:

  • Supporting one more language should not require changing the code any more unless there is some kind of hard-code in the previous code. You should remove all hard coding. E.g. all message strings should come from resources, not hardcoded in CPP / H files.
  • Supporting one more language only needs to be dealt with resource files - *.rc and res/*.* files only. This means you can provide the resource file to anyone, and they can build resource-only DLLs for a new language without access to your code. Their new language DLL files should work with your application.
  • Each existing MFC EXE / DLL file has one resource-only language DLL file for each language. Resource-only language DLL file is named after its application; appended iwth three-letter language abbreviation codes. It uses DLL as suffix.
  • Existing EXE / DLLs have the choice to store resources or not. If no other language DLL exists, it searches the system default fake language “LOC”. If that fails, it uses the resource stored in EXE / DLL file, if any.
  • Resource-only language DLL files stay with MFC application in the same folder.
  • Use Control Panel settings in user’s OS to determine which language DLL to load to memory.
  • Easily change to existing VC6 code to make it support the above features for multiple languages. Change a few codes in InitInstance()/ExitInstance() and DllMain() and that should be enough.

This document is for Visual Studio 6, may be version 5, but not for version 7, 7.1, 8.0. MFC version 7 has some built-in support for multiple languages. This article includes the following:

  • How to build resource-only language DLLs.
  • How to detect OS language settings, how to load resource-only language DLLs when application starts.
  • Three-letter language table.

Why another Article on Multiple Language Applications

I have read some articles here at CodeProject and Microsoft:

From VC7 and up, you shouldn't worry that much on multiple language support.

I wrapped some language related functions to a class. I made some changes for VC6, and put a demo project using it. You need to exit and launch your application again for a new language selected in the Control Panel.

Make a Sample MFC Application and its Extension DLL

  • Using MFC AppWizard, make a MFC application. I chose "single document", "German [German] (APPWZDEU.DLL)", "Header files only" for database support, etc. and named it as Main. Press F7 to build it and run it.
  • In FileView, right click workspace and add a MFC AppWizard (DLL) project. Name it as SubDLL. Choose "MFC Extension DLL (Using shared MFC DLL)".
  • To avoid resource ID conflict, using main's resource.h, delete SubDLL's resource.h and replace it in ResourceView. Backup Main's resource.h before it be overwritten in this process, since there is no resource in SubDLL now. You are safe to restore it back after it is saved. Now Main.Exe and SubDLL.DLL share one resource.h. To make life easier, you can change the output SubDLL.dll to the same folder as Main.exe, and make Main dependent on SubDll.dll in Project Dependencies.
  • Now add a dialog to SubDLL and call it from Main. Export this new dialog class by adding AFX_EXT_CLASS in the class definition header file. In Main, add a new menu item to run this test dialog. Sure, you need to include main.h or resource.h in TestDlg.cpp, and include TestDlg.h in MainFrame.cpp.
  • Build them, run Main.exe, and test this TestDlg. Yes, we got our sample MFC application and MFC extension DLL working now.
  • Optional, add Unicode configuration to this project. Add new configuration from Build / Configurations menu, get new configuration by copying it from the existing release and debug versions, change _MBCS to _UNICODE at C/C++ tab in project settings dialog, change Entry-point symbol at output category of Link tab to wWinMainCRTStartup. You need do this for Main and SubDLL, Release and Debug.
  • Notes on MFC AppWizard Language Support for East Asian Languages:

    Visual C++ allows you to choose different languages when you create an MFC AppWizard program. The East Asian language support DLLs (Japanese, Korean, and simplified Chinese) for the MFC AppWizard, which require double-byte enabled operating systems, are not installed by default. Thus you will not see them in the language drop-down list on the first page of the MFC AppWizard. However, you can find them in the Microsoft Visual Studio\Common\msdev98\bin\ide directory on the Visual C++ CD as follows:

    LanguageAppWizard DLL
    JapaneseAPPWZJPN.DLL
    KoreanAPPWZKOR.DLL
    Chinese (simplified)APPWZCHS.DLL

    To take advantage of East Asian language support:

    1. Copy the appropriate MFC AppWizard DLL to your Microsoft Visual Studio\Common\msdev98\bin\ide directory. This DLL can be found in the corresponding directory on the Visual C++ CD.
    2. Install the appropriate code page on your system.

    If your application is dynamically linked to MFC, you must have the corresponding localized version of the MFC resource DLL, MFC##LOC.DLL, in your Windows system directory. To do this, copy the corresponding DLL in the MFC\include\L.XXX\MFC##XXX.DLL on the Visual C++ CD into the Windows system directory, and rename it to MFC##LOC.DLL. For more information on using the localized resources that Visual C++ provides, see Tech Note 56 and Tech Note 57.

    – or–

    If your application is statically linked to MFC, you must have the appropriate localized MFC resource files in your MFC\[src|include]\L.XXX\*.rc directory. You can find these files in the corresponding directories of Visual Studio CD1. For more information on using the localized resources that Visual C++ provides, see Tech Note 56 and Tech Note 57.

    Static linking to MFC is supported only in Visual C++ Professional and Enterprise Editions. For more information, see Visual C++ Editions.

Build Resource-only Language DLL

Now build English resource only DLL files for Main.exe and subdll.dll. A resource-only DLL is a DLL that contains nothing but resources, such as icons, bitmaps, strings, and dialog boxes. It is also a good way to provide an application with resources localized for multiple languages. See “Creating a Resource-Only DLL” (1.) in MSDN. Here are the steps to build a resource-only language DLL. It's named after its EXE or DLL, appending the three-letter language code. E.g. Main.exe has its English resource DLL as MainENU.DLL. Following are the steps to build English (ENU) resource-only language DLL from the previous German (DEU) code.

  • Copy Main.rc to MainENU.rc.
  • Copy resENU\*.* to resENU\*.*.
  • Use a text editor to edit MainENU.rc and replace the following:
    • All word "AFX_TARG_DEU" to "AFX_TARG_ENU".
    • All word "LANG_GERMAN, SUBLANG_GERMAN" to "LANG_ENGLISH, SUBLANG_ENGLISH_US".
    • The same as above "LANGUAGE 7, 1" to "LANGUAGE 9, 1". (LANG_ENGLISH is 9, LANG_GERMAN is 7; both sublanguages are 1.)
    • Take out "l.deu\\" or "l.deu\" for English. For language other than English, use “l.xxx” subfolder to locate the MFC resource for that language. xxx is the three-letter language code. See tables below.
    • Change "res\" to "resENU\".
    • VERSIONINFO block from "040704B0" to "040904B0" - "7" for German and "9" for English.
    • The same "407" to "409".
    • "German (Germany)" to "English (U.S.)".
    • "code_page(1252)" to "code_page(1252)". No need to change code page for this case. (Otherwise, you may need to update codepage based on “Code-Page Identifiers” (2.)) Keep in mind only some code pages are supported by Windows. See “Code Pages Supported by Windows” (7.).
  • Translate all resources in MainENU.rc to English.
  • Translate all resources in resENU\*.* to English.
  • In FileView, right click workspace, add a “Win32 Dynamic-Link Library” project, name it as MainENU, and put it to the same location as Main. Select "An empty DLL project" in the wizard.
  • Add the resource file MainENU.rc to this project's source files.
  • Change the setting for the project MainENU, select Link tab in Project Settings dialog. Highlight this project, add "/NOENTRY" for both release and debug configurations.
  • Optionally update intermediate and output files folder as the same as Main project. This can be done under General tab and Link tab.
  • Under Resources tab change Language to English (United States).
  • Build this project, you should get MainENU.DLL.

Detect OS UI Language settings

For MUI (Multiple User Interface) OS, a user can update his OS user language in Control Panel, Region and language options, Language. Following code is partially copied from VC7.1 appcore.cpp. It detects UI language, and stores a language list for loading later.

LANGID CMultiLanguage::DetectUILanguage()
{
    LANGID langid = 0;
    int nPrimaryLang = 0;
    int nSubLang = 0;
    LCID lcid = 0;
    PFNGETUSERDEFAULTUILANGUAGE pfnGetUserDefaultUILanguage;
    PFNGETSYSTEMDEFAULTUILANGUAGE pfnGetSystemDefaultUILanguage;
    HINSTANCE hKernel32;

    hKernel32 = ::GetModuleHandle(_T("kernel32.dll"));
    ASSERT(hKernel32 != NULL);
    pfnGetUserDefaultUILanguage = 
       (PFNGETUSERDEFAULTUILANGUAGE)::GetProcAddress(hKernel32, 
       "GetUserDefaultUILanguage");
    if(pfnGetUserDefaultUILanguage != NULL)
    {
        // First, try the user's UI language
        langid = pfnGetUserDefaultUILanguage();
        AddLangId( langid );
        TRACE(_T("CMultiLanguage::DetectUILanguage()" 
          _T" 1st/2nd = %04X\n"), langid );

        // Then, try the system's default UI language
        pfnGetSystemDefaultUILanguage = 
          (PFNGETSYSTEMDEFAULTUILANGUAGE)::GetProcAddress(hKernel32, 
          "GetSystemDefaultUILanguage");
        ASSERT( pfnGetSystemDefaultUILanguage != NULL );

        langid = pfnGetSystemDefaultUILanguage();
        AddLangId( langid );
        TRACE(_T("CMultiLanguage::DetectUILanguage()" 
           _T" 3rd/4th = %04X\n"), langid );
    }
    else
    {
        // We're not on an MUI-capable system.
        if (::GetVersion()&0x80000000)
        {
            // We're on Windows 9x, so look
            // in the registry for the UI language
            HKEY hKey = NULL;
            LONG nResult = ::RegOpenKeyEx(HKEY_CURRENT_USER, 
                _T( "Control Panel\\Desktop\\ResourceLocale" ), 
                0, KEY_READ, &hKey);
            if (nResult == ERROR_SUCCESS)
            {
                DWORD dwType;
                TCHAR szValue[16];
                ULONG nBytes = sizeof( szValue );
                nResult = ::RegQueryValueEx(hKey, NULL, NULL, &dwType,
                    LPBYTE( szValue ), &nBytes );
                if ((nResult == ERROR_SUCCESS) && (dwType == REG_SZ))
                {
                  DWORD dwLangID;
                  int nFields = _stscanf( szValue, _T( "%x" ), &dwLangID );
                  if( nFields == 1 )
                  {
                    langid = LANGID( dwLangID );
                    AddLangId( langid );
                    TRACE(_T("CMultiLanguage::DetectUILanguage()" 
                      _T" 9X1st/2nd = %04X\n"), langid );
                  }
                }
                ::RegCloseKey(hKey);
            }
        }
        else
        {
            // We're on NT 4. The UI language
            // is the same as the language of the
            // version resource in ntdll.dll
            HMODULE hNTDLL = ::GetModuleHandle( _T( "ntdll.dll" ) );
            if (hNTDLL != NULL)
            {
                langid = 0;
                ::EnumResourceLanguages( hNTDLL, RT_VERSION, MAKEINTRESOURCE( 1 ),
                    _AfxEnumResLangProc, 
                    reinterpret_cast< LONG_PTR >( &langid ) );
                if (langid != 0)
                {
                    AddLangId( langid );
                    TRACE(_T("CMultiLanguage::DetectUILanguage()" 
                      _T" NT1st/2nd = %04X\n"), langid );
                }
            }
        }
    }

    if ( m_nLocales < MAX_NUM_LCID )
    {
        m_alcidSearch[m_nLocales] = LOCALE_SYSTEM_DEFAULT;
        m_nLocales++;
    } else {
        m_alcidSearch[MAX_NUM_LCID-1] = LOCALE_SYSTEM_DEFAULT;
        m_nLocales = MAX_NUM_LCID;
    }

    return LANGIDFROMLCID(m_alcidSearch[0]);
}

While the above code works for MUI OS, a user may change the default locale, not the UI language. The following code detects the user default language, not the UI language.

LANGID CMultiLanguage::DetectLangID()
{
    LANGID langid = 0;
    int nPrimaryLang = 0;
    int nSubLang = 0;
    LCID lcid = 0;
    int nLocales = 0;

    langid = GetUserDefaultLangID();    // WinNT3.1/95 and later
    AddLangId( langid );
    TRACE(_T("CMultiLanguage::GetUserDefaultLangID() 1st/2nd = %0X\n"),
        langid );

    LANGID langSysid = GetSystemDefaultLangID();// WinNT3.1/95 and later
    AddLangId( langSysid );
    TRACE(_T("CMultiLanguage::GetSystemDefaultLangID() 3rd/4th = %0X\n"),
        langid );

    return langid;
}

We can get user selected languages in the OS now. I tested these only on Win200 Pro and WinXP Pro. If you can test this on 9X or NT, let me know if this failed or succeeded.

Load Language Resource DLL

Like that in MFC version 7, we attempt to load the resource DLL for each of the following languages in order, stopping when it finds one:

  • The current user's default language, as returned from the GetUserDefaultLangID() Win32 API.
  • The current user's default language, without any specific sublanguage (that is, ENC [Canadian English] becomes ENU [U.S. English]).
  • The system's default language, as returned from the GetSystemDefaultLangID() Win32 API.
  • The system's default language, without any specific sublanguage.
  • (Windows 2000 or later only) The current user's default UI language, as returned from the GetUserDefaultUILanguage() Win32 API.
  • (Windows 2000 or later only) The current user's default UI language, without any specific sublanguage.
  • The system's default UI language. On Windows 2000 or higher, this is returned from the GetSystemDefaultUILanguage() API. On other platforms, this is the language of the OS itself.
  • The system's default UI language, without any specific sublanguage.
  • A "fake" language with the 3-letter code LOC.

To detect the user’s default language and system default language, we should make a call to DetectLangID(). For user and system’s UI language, calling DetectUILanguage() will be OK. After these two calls, a list of languages requested is stored in the CMultiLanguage::m_alcidSearch[] array. To load it, use the following:

HINSTANCE CMultiLanguage::LoadLangResourceDLL(LPCTSTR szModuleName, 
                                               LANGID langUpdateId)
{
    TCHAR        szResDLLName[_MAX_PATH+14];
    HINSTANCE    hLangDLL = NULL;
    LCID        alcid[MAX_NUM_LCID+1];
    TCHAR        szLangCode[4];
    //LPTSTR    pszExtension;
    int            nNoExtension;
    LCID        lcid;
    int            nLocales = 0;

    //pszExtension = ::PathFindExtension(szModuleName);
    //nNoExtension = pszExtension - szModuleName;    temp. for ".exe"
    nNoExtension = lstrlen(szModuleName) - 3 ;
    // Quick and kind of dirty way to take ".exe"/".dll" away.

    if ( langUpdateId != MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL) )
    {
        alcid[nLocales] = MAKELCID(langUpdateId, SORT_DEFAULT);
        nLocales++;
    }
    for ( int iLocale = 0; iLocale < m_nLocales; iLocale++ )
    {
        if ( m_alcidSearch[iLocale] != 0 )
        {
            alcid[nLocales] = m_alcidSearch[iLocale];
            nLocales++;
        }
    }
    for ( iLocale = 0; iLocale < nLocales; iLocale++ )
    {
        lcid = alcid[iLocale];
        if (lcid == LOCALE_SYSTEM_DEFAULT)
            lstrcpy(szLangCode, _T("LOC"));
        else {
            int nResult = ::GetLocaleInfo(lcid, 
                LOCALE_SABBREVLANGNAME, szLangCode, 4);
            ASSERT( nResult == 4 );
            if ( nResult == 0 )
                return NULL;
        }

        if ( nNoExtension + 3 + 4 + 1 < _MAX_PATH+14 )
        {    // append "ENU.DLL" to moduleName
            lstrcpyn(szResDLLName, szModuleName, nNoExtension);
            lstrcat(szResDLLName, szLangCode);
            lstrcat(szResDLLName, _T(".DLL"));
        } else {
            ASSERT(FALSE);
            // No enough space to hold language resource dll name path.

            return NULL;
        }
        hLangDLL = ::LoadLibrary(szResDLLName);
        if(hLangDLL != NULL)
            return hLangDLL;// Successful return
    }

    return hLangDLL;
}

We can call LoadLangResourceDLL(…) to load the first available language DLL in the list. You can change the language ID detected from above. For example, you only include the resource DLL for Chinese PRC, and you want to use it for Chinese Taiwan and Chinese Singapore too. You can do this hard-coding here. If you don't want to hard code here, you can make a duplicated copy of the resource-only DLL file with another three-letter language name. (Copy XXXXCHS.DLL to XXXXCHT.DLL for this case.)

If your EXE or DLL files don't include resource, you need to have one system default language "LOC" in your resource-only language DLL file list. This is the last chance the system will try to find the language resource.

Application Code Changes

For Main.exe to load a language related resource-only DLL, add the following code to main.cpp in the very beginning of CMain::InitInstance():

// Begin of Multiple Language support
if ( CMultiLanguage::m_nLocales <= 0 )    // Not detected yet
{
    CMultiLanguage::DetectLangID(); // Detect language as user locale
    CMultiLanguage::DetectUILanguage();    // Detect language in MUI OS
}
TCHAR szModuleFileName[MAX_PATH];        // Get Module File Name and path
int ret = ::GetModuleFileName(theApp.m_hInstance, szModuleFileName, MAX_PATH);
if ( ret == 0 || ret == MAX_PATH )
    ASSERT(FALSE);
// Load resource-only language DLL. It will use the languages
// detected above, take first available language,
// or you can specify another language as second parameter to
// LoadLangResourceDLL. And try that first.
ghLangInst = CMultiLanguage::LoadLangResourceDLL( szModuleFileName );
if (ghLangInst)
    AfxSetResourceHandle( ghLangInst );
// End of Multiple Language support

You may want to free the library in ExitInstance().

DLL Code Changes

For the MFC extension DLL SubDLL.DLL to load language related resource-only DLL, add the following code to SubDLL.cpp in DllMain(...) just before calling CDynLinkLibrary(...):

// Begin of Multiple Language support
if ( CMultiLanguage::m_nLocales <= 0 )
// Not detected yet
{
    CMultiLanguage::DetectLangID(); // Detect language as user locale
    CMultiLanguage::DetectUILanguage(); // Detect language in MUI OS
}
TCHAR szModuleFileName[MAX_PATH]; // Get Module File Name and path
int ret = ::GetModuleFileName(hInstance, szModuleFileName, MAX_PATH);
if ( ret == 0 || ret == MAX_PATH )
    ASSERT(FALSE);
// Load resource-only language DLL. It will use the languages
// detected above, take first available language,
// or you can specify another language as second parameter to
// LoadLangResourceDLL. And try that first.
shLangInst = CMultiLanguage::LoadLangResourceDLL( szModuleFileName );
if (shLangInst)
    SubDLLDLL.hResource = shLangInst;
// End of Multiple Language support

You may want to free the library when system detaches the process.

Using the Software

  • Include MultiLanguage.cpp and MultiLanguage.h in your project. With dependence, put this to the most independent DLL project.
  • Use *.rc, res\*.* to build your resource-only DLL file for each EXE / DLL and each language. See "Build resource-only language DLL" above.
  • Load language resource-only DLL in your MFC application as "Application Code Changes" above.
  • Load language resource-only DLL in your MFC extension DLL as described in "DLL Code Changes" above for each extension DLL project.
  • If you have only one EXE file, you can forget all extension related issues here.
  • It’s better to detect language once and use it everywhere, so I put this as static. FYI: DetectUILanguage() function in DLLMain(...) will be called earlier than that in InitInstance().
  • Bugs are expected. This is only demo level code. You can report any bugs here or send an email to me with [codeproject] in the Subject line.

Three-letter Language Identifier Table

Column one is LANGID; the lower 10 bits are for the language, the higher 6 bits are for the sub-language. Column two is the three-letter language code. Column three is the three-letter language code without sub-language. It looks for this language if the language in column two does not exist. Column one and column four are got from “Language Identifier”(3.); column two and column three are got from the GetLocaleInfo() function on my XP Pro PC. See CMultiLanguage::PrintThreeLetterLanguageCodeList() function in MultiLanguage.cpp for details.

IdentifierColumn 2Column 3Description and notes
0x0436AFKAFKAfrikaans
0x041cSQISQIAlbanian
0x0401ARAARAArabic (Saudi Arabia)
0x0801ARIARAArabic (Iraq)
0x0c01AREARAArabic (Egypt)
0x1001ARLARAArabic (Libya)
0x1401ARGARAArabic (Algeria)
0x1801ARMARAArabic (Morocco)
0x1c01ARTARAArabic (Tunisia)
0x2001AROARAArabic (Oman)
0x2401ARYARAArabic (Yemen)
0x2801ARSARAArabic (Syria)
0x2c01ARJARAArabic (Jordan)
0x3001ARBARAArabic (Lebanon)
0x3401ARKARAArabic (Kuwait)
0x3801ARUARAArabic (U.A.E.)
0x3c01ARHARAArabic (Bahrain)
0x4001ARQARAArabic (Qatar)
0x042bHYEHYEWindows 2000/XP: Armenian. This is Unicode only.
0x042cAZEAZEAzeri (Latin)
0x082cAZEAZEAzeri (Cyrillic)
0x042dEUQEUQBasque
0x0423BELBELBelarusian
0x0445BNGBNGBengali (India)
0x141aBSBHRVBosnian (Bosnia and Herzego vina)
0x0402BGRBGRBulgarian
0x0455======Burmese
0x0403CATCATCatalan
0x0404CHTCHTChinese (Taiwan)
0x0804CHSCHTChinese (PRC)
0x0c04ZHHCHTChinese (Hong Kong SAR, PRC )
0x1004ZHICHTChinese (Singapore)
0x1404ZHMCHTWindows 98/ME, Windows 2000 /XP: Chinese (Macao SAR)
0x041aHRVHRVCroatian
0x101aHRBHRVCroatian (Bosnia and Herzeg ovina)
0x0405CSYCSYCzech
0x0406DANDANDanish
0x0465DIVDIVWindows XP: Divehi. This is Unicode only.
0x0413NLDNLDDutch (Netherlands)
0x0813NLBNLDDutch (Belgium)
0x0409ENUENUEnglish (United States)
0x0809ENGENUEnglish (United Kingdom)
0x0c09ENAENUEnglish (Australian)
0x1009ENCENUEnglish (Canadian)
0x1409ENZENUEnglish (New Zealand)
0x1809ENIENUEnglish (Ireland)
0x1c09ENSENUEnglish (South Africa)
0x2009ENJENUEnglish (Jamaica)
0x2409ENBENUEnglish (Caribbean)
0x2809ENLENUEnglish (Belize)
0x2c09ENTENUEnglish (Trinidad)
0x3009ENWENUWindows 98/ME, Windows 2000 /XP: English (Zimbabwe)
0x3409ENPENUWindows 98/ME, Windows 2000 /XP: English (Philippines)
0x0425ETIETIEstonian
0x0438FOSFOSFaeroese
0x0429FARFARFarsi
0x040bFINFINFinnish
0x040cFRAFRAFrench (Standard)
0x080cFRBFRAFrench (Belgian)
0x0c0cFRCFRAFrench (Canadian)
0x100cFRSFRAFrench (Switzerland)
0x140cFRLFRAFrench (Luxembourg)
0x180cFRMFRAWindows 98/ME, Windows 2000 /XP: French (Monaco)
0x0456GLCGLCWindows XP: Galician
0x0437KATKATWindows 2000/XP: Georgian. This is Unicode only.
0x0407DEUDEUGerman (Standard)
0x0807DESDEUGerman (Switzerland)
0x0c07DEADEUGerman (Austria)
0x1007DELDEUGerman (Luxembourg)
0x1407DECDEUGerman (Liechtenstein)
0x0408ELLELLGreek
0x0447GUJGUJWindows XP: Gujarati. This is Unicode only.
0x040dHEBHEBHebrew
0x0439HINHINWindows 2000/XP: Hindi. This is Unicode only.
0x040eHUNHUNHungarian
0x040fISLISLIcelandic
0x0421INDINDIndonesian
0x0434XHOXHOisiXhosa/Xhosa (South Africa)
0x0435ZULZULisiZulu/Zulu (South Africa)
0x0410ITAITAItalian (Standard)
0x0810ITSITAItalian (Switzerland)
0x0411JPNJPNJapanese
0x044bKANKANWindows XP: Kannada. This is Unicode only.
0x0457KNKKNKWindows 2000/XP: Konkani. This is Unicode only.
0x0412KORKORKorean
0x0812===KORWindows 95, Windows NT 4.0 only: Korean (Johab)
0x0440KYRKYRWindows XP: Kyrgyz.
0x0426LVILVILatvian
0x0427LTHLTHLithuanian
0x0827===LTHWindows 98 only: Lithuanian (Classic)
0x042fMKIMKIMacedonian (FYROM)
0x043eMSLMSLMalay (Malaysian)
0x083eMSBMSLMalay (Brunei Darussalam)
0x044cMYMMYMMalayalam (India)
0x0481MRIMRIMaori (New Zealand)
0x043aMLTMLTMaltese (Malta)
0x044eMARMARWindows 2000/XP: Marathi. This is Unicode only.
0x0450MONMONWindows XP: Mongolian
0x0414NORNORNorwegian (Bokmal)
0x0814NONNORNorwegian (Nynorsk)
0x0415PLKPLKPolish
0x0416PTBPTBPortuguese (Brazil)
0x0816PTGPTBPortuguese (Portugal)
0x0446PANPANWindows XP: Punjabi. This is Unicode only.
0x046bQUBQUBQuechua (Bolivia)
0x086bQUEQUBQuechua (Ecuador)
0x0c6bQUPQUBQuechua (Peru)
0x0418ROMROMRomanian
0x0419RUSRUSRussian
0x044fSANSANWindows 2000/XP: Sanskrit. This is Unicode only.
0x043bSMESMESami, Northern (Norway)
0x083bSMFSMESami, Northern (Sweden)
0x0c3bSMGSMESami, Northern (Finland)
0x103bSMJSMESami, Lule (Norway)
0x143bSMKSMESami, Lule (Sweden)
0x183bSMASMESami, Southern (Norway)
0x1c3bSMBSMESami, Southern (Sweden)
0x203bSMSSMESami, Skolt (Finland)
0x243bSMNSMESami, Inari (Finland)
0x0c1aSRBHRVSerbian (Cyrillic)
0x1c1aSRNHRVSerbian (Cyrillic, Bosnia, and Herzegovina)
0x081aSRLHRVSerbian (Latin)
0x181aSRSHRVSerbian (Latin, Bosnia, and Herzegovina)
0x046cNSONSOSesotho sa Leboa/Northern Sotho (South Africa)
0x0432TSNTSNSetswana/Tswana (South Africa)
0x041bSKYSKYSlovak
0x0424SLVSLVSlovenian
0x040aESPESPSpanish (Spain, Traditional Sort)
0x080aESMESPSpanish (Mexican)
0x0c0aESNESPSpanish (Spain, Modern Sort )
0x100aESGESPSpanish (Guatemala)
0x140aESCESPSpanish (Costa Rica)
0x180aESAESPSpanish (Panama)
0x1c0aESDESPSpanish (Dominican Republic)
0x200aESVESPSpanish (Venezuela)
0x240aESOESPSpanish (Colombia)
0x280aESRESPSpanish (Peru)
0x2c0aESSESPSpanish (Argentina)
0x300aESFESPSpanish (Ecuador)
0x340aESLESPSpanish (Chile)
0x380aESYESPSpanish (Uruguay)
0x3c0aESZESPSpanish (Paraguay)
0x400aESBESPSpanish (Bolivia)
0x440aESEESPSpanish (El Salvador)
0x480aESHESPSpanish (Honduras)
0x4c0aESIESPSpanish (Nicaragua)
0x500aESUESPSpanish (Puerto Rico)
0x0430======Sutu
0x0441SWKSWKSwahili (Kenya)
0x041dSVESVESwedish
0x081dSVFSVESwedish (Finland)
0x045aSYRSYRWindows XP: Syriac. This is Unicode only.
0x0449TAMTAMWindows 2000/XP: Tamil. This is Unicode only.
0x0444TTTTTTTatar (Tatarstan)
0x044aTELTELWindows XP: Telugu. This is Unicode only.
0x041eTHATHAThai
0x041fTRKTRKTurkish
0x0422UKRUKRUkrainian
0x0420URDURDWindows 98/ME, Windows 2000 /XP: Urdu (Pakistan)
0x0820===URDUrdu (India)
0x0443UZBUZBUzbek (Latin)
0x0843UZBUZBUzbek (Cyrillic)
0x042aVITVITWindows 98/ME, Windows NT 4 .0 and later: Vietnamese
0x0452CYMCYMWelsh (United Kingdom)

Reference

  1. Creating a Resource-Only DLL.
  2. Code-Page Identifiers.
  3. Language Identifier.
  4. How to test your programs with Unicode characters in multiple languages on Windows 2000.
  5. Localized Resources in MFC Applications: Satellite DLLs.
  6. Localization of MFC Components.
  7. Code Pages Supported by Windows.

History

  • 2005.07.19 - First released.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior)
United States United States
This man is too lazy to post anything here.

Comments and Discussions

 
QuestionWhy I cann't open the dialog? Pin
Gorilly10-Jul-08 0:03
Gorilly10-Jul-08 0:03 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.