Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5833518
  • 博文数量: 671
  • 博客积分: 10010
  • 博客等级: 上将
  • 技术积分: 7310
  • 用 户 组: 普通用户
  • 注册时间: 2006-07-14 09:56
文章分类

全部博文(671)

文章存档

2011年(1)

2010年(2)

2009年(24)

2008年(271)

2007年(319)

2006年(54)

我的朋友

分类: C/C++

2008-08-23 22:26:48

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:

  • - I don't need to switch languages on the fly. But I need to handle resources in many DLL files and one EXE file. That's the problem with MFC extension DLL application.
  • - With about 100 M, I can never call LoadString() etc. but the comment area of this article is pretty good.
  • - My code has to be language neutral. Other developers in other countries should be able to add another language without accessing C++ code here. Provide only RC files and files under RES folders, they can add any language to this application.
  • - This is for VC7. This is very good for you to know satellite DLLs.
  • - How to create a resource-only DLL.
  • MS Global Development and Computing Portal - Developers going for multiple languages can start here. Know your OS support for Multilingual User Interface (MUI).

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:

    Language AppWizard DLL
    Japanese APPWZJPN.DLL
    Korean APPWZKOR.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.

Collapse
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:

Collapse
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.

Identifier Column 2 Column 3 Description and notes
0x0436 AFK AFK Afrikaans
0x041c SQI SQI Albanian
0x0401 ARA ARA Arabic (Saudi Arabia)
0x0801 ARI ARA Arabic (Iraq)
0x0c01 ARE ARA Arabic (Egypt)
0x1001 ARL ARA Arabic (Libya)
0x1401 ARG ARA Arabic (Algeria)
0x1801 ARM ARA Arabic (Morocco)
0x1c01 ART ARA Arabic (Tunisia)
0x2001 ARO ARA Arabic (Oman)
0x2401 ARY ARA Arabic (Yemen)
0x2801 ARS ARA Arabic (Syria)
0x2c01 ARJ ARA Arabic (Jordan)
0x3001 ARB ARA Arabic (Lebanon)
0x3401 ARK ARA Arabic (Kuwait)
0x3801 ARU ARA Arabic (U.A.E.)
0x3c01 ARH ARA Arabic (Bahrain)
0x4001 ARQ ARA Arabic (Qatar)
0x042b HYE HYE Windows 2000/XP: Armenian. This is Unicode only.
0x042c AZE AZE Azeri (Latin)
0x082c AZE AZE Azeri (Cyrillic)
0x042d EUQ EUQ Basque
0x0423 BEL BEL Belarusian
0x0445 BNG BNG Bengali (India)
0x141a BSB HRV Bosnian (Bosnia and Herzego vina)
0x0402 BGR BGR Bulgarian
0x0455 === === Burmese
0x0403 CAT CAT Catalan
0x0404 CHT CHT Chinese (Taiwan)
0x0804 CHS CHT Chinese (PRC)
0x0c04 ZHH CHT Chinese (Hong Kong SAR, PRC )
0x1004 ZHI CHT Chinese (Singapore)
0x1404 ZHM CHT Windows 98/ME, Windows 2000 /XP: Chinese (Macao SAR)
0x041a HRV HRV Croatian
0x101a HRB HRV Croatian (Bosnia and Herzeg ovina)
0x0405 CSY CSY Czech
0x0406 DAN DAN Danish
0x0465 DIV DIV Windows XP: Divehi. This is Unicode only.
0x0413 NLD NLD Dutch (Netherlands)
0x0813 NLB NLD Dutch (Belgium)
0x0409 ENU ENU English (United States)
0x0809 ENG ENU English (United Kingdom)
0x0c09 ENA ENU English (Australian)
0x1009 ENC ENU English (Canadian)
0x1409 ENZ ENU English (New Zealand)
0x1809 ENI ENU English (Ireland)
0x1c09 ENS ENU English (South Africa)
0x2009 ENJ ENU English (Jamaica)
0x2409 ENB ENU English (Caribbean)
0x2809 ENL ENU English (Belize)
0x2c09 ENT ENU English (Trinidad)
0x3009 ENW ENU Windows 98/ME, Windows 2000 /XP: English (Zimbabwe)
0x3409 ENP ENU Windows 98/ME, Windows 2000 /XP: English (Philippines)
0x0425 ETI ETI Estonian
0x0438 FOS FOS Faeroese
0x0429 FAR FAR Farsi
0x040b FIN FIN Finnish
0x040c FRA FRA French (Standard)
0x080c FRB FRA French (Belgian)
0x0c0c FRC FRA French (Canadian)
0x100c FRS FRA French (Switzerland)
0x140c FRL FRA French (Luxembourg)
0x180c FRM FRA Windows 98/ME, Windows 2000 /XP: French (Monaco)
0x0456 GLC GLC Windows XP: Galician
0x0437 KAT KAT Windows 2000/XP: Georgian. This is Unicode only.
0x0407 DEU DEU German (Standard)
0x0807 DES DEU German (Switzerland)
0x0c07 DEA DEU German (Austria)
0x1007 DEL DEU German (Luxembourg)
0x1407 DEC DEU German (Liechtenstein)
0x0408 ELL ELL Greek
0x0447 GUJ GUJ Windows XP: Gujarati. This is Unicode only.
0x040d HEB HEB Hebrew
0x0439 HIN HIN Windows 2000/XP: Hindi. This is Unicode only.
0x040e HUN HUN Hungarian
0x040f ISL ISL Icelandic
0x0421 IND IND Indonesian
0x0434 XHO XHO isiXhosa/Xhosa (South Africa)
0x0435 ZUL ZUL isiZulu/Zulu (South Africa)
0x0410 ITA ITA Italian (Standard)
0x0810 ITS ITA Italian (Switzerland)
0x0411 JPN JPN Japanese
0x044b KAN KAN Windows XP: Kannada. This is Unicode only.
0x0457 KNK KNK Windows 2000/XP: Konkani. This is Unicode only.
0x0412 KOR KOR Korean
0x0812 === KOR Windows 95, Windows NT 4.0 only: Korean (Johab)
0x0440 KYR KYR Windows XP: Kyrgyz.
0x0426 LVI LVI Latvian
0x0427 LTH LTH Lithuanian
0x0827 === LTH Windows 98 only: Lithuanian (Classic)
0x042f MKI MKI Macedonian (FYROM)
0x043e MSL MSL Malay (Malaysian)
0x083e MSB MSL Malay (Brunei Darussalam)
0x044c MYM MYM Malayalam (India)
0x0481 MRI MRI Maori (New Zealand)
0x043a MLT MLT Maltese (Malta)
0x044e MAR MAR Windows 2000/XP: Marathi. This is Unicode only.
0x0450 MON MON Windows XP: Mongolian
0x0414 NOR NOR Norwegian (Bokmal)
0x0814 NON NOR Norwegian (Nynorsk)
0x0415 PLK PLK Polish
0x0416 PTB PTB Portuguese (Brazil)
0x0816 PTG PTB Portuguese (Portugal)
0x0446 PAN PAN Windows XP: Punjabi. This is Unicode only.
0x046b QUB QUB Quechua (Bolivia)
0x086b QUE QUB Quechua (Ecuador)
0x0c6b QUP QUB Quechua (Peru)
0x0418 ROM ROM Romanian
0x0419 RUS RUS Russian
0x044f SAN SAN Windows 2000/XP: Sanskrit. This is Unicode only.
0x043b SME SME Sami, Northern (Norway)
0x083b SMF SME Sami, Northern (Sweden)
0x0c3b SMG SME Sami, Northern (Finland)
0x103b SMJ SME Sami, Lule (Norway)
0x143b SMK SME Sami, Lule (Sweden)
0x183b SMA SME Sami, Southern (Norway)
0x1c3b SMB SME Sami, Southern (Sweden)
0x203b SMS SME Sami, Skolt (Finland)
0x243b SMN SME Sami, Inari (Finland)
0x0c1a SRB HRV Serbian (Cyrillic)
0x1c1a SRN HRV Serbian (Cyrillic, Bosnia, and Herzegovina)
0x081a SRL HRV Serbian (Latin)
0x181a SRS HRV Serbian (Latin, Bosnia, and Herzegovina)
0x046c NSO NSO Sesotho sa Leboa/Northern Sotho (South Africa)
0x0432 TSN TSN Setswana/Tswana (South Africa)
0x041b SKY SKY Slovak
0x0424 SLV SLV Slovenian
0x040a ESP ESP Spanish (Spain, Traditional Sort)
0x080a ESM ESP Spanish (Mexican)
0x0c0a ESN ESP Spanish (Spain, Modern Sort )
0x100a ESG ESP Spanish (Guatemala)
0x140a ESC ESP Spanish (Costa Rica)
0x180a ESA ESP Spanish (Panama)
0x1c0a ESD ESP Spanish (Dominican Republic)
0x200a ESV ESP Spanish (Venezuela)
0x240a ESO ESP Spanish (Colombia)
0x280a ESR ESP Spanish (Peru)
0x2c0a ESS ESP Spanish (Argentina)
0x300a ESF ESP Spanish (Ecuador)
0x340a ESL ESP Spanish (Chile)
0x380a ESY ESP Spanish (Uruguay)
0x3c0a ESZ ESP Spanish (Paraguay)
0x400a ESB ESP Spanish (Bolivia)
0x440a ESE ESP Spanish (El Salvador)
0x480a ESH ESP Spanish (Honduras)
0x4c0a ESI ESP Spanish (Nicaragua)
0x500a ESU ESP Spanish (Puerto Rico)
0x0430 === === Sutu
0x0441 SWK SWK Swahili (Kenya)
0x041d SVE SVE Swedish
0x081d SVF SVE Swedish (Finland)
0x045a SYR SYR Windows XP: Syriac. This is Unicode only.
0x0449 TAM TAM Windows 2000/XP: Tamil. This is Unicode only.
0x0444 TTT TTT Tatar (Tatarstan)
0x044a TEL TEL Windows XP: Telugu. This is Unicode only.
0x041e THA THA Thai
0x041f TRK TRK Turkish
0x0422 UKR UKR Ukrainian
0x0420 URD URD Windows 98/ME, Windows 2000 /XP: Urdu (Pakistan)
0x0820 === URD Urdu (India)
0x0443 UZB UZB Uzbek (Latin)
0x0843 UZB UZB Uzbek (Cyrillic)
0x042a VIT VIT Windows 98/ME, Windows NT 4 .0 and later: Vietnamese
0x0452 CYM CYM Welsh (United Kingdom)

Reference

  1. .
  2. .
  3. .
  4. .
  5. .
  6. .
  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

阅读(23498) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~