ICU-700 Windows locale mapping works better now with variants
X-SVN-Rev: 2828
This commit is contained in:
parent
87ef71b49b
commit
fa4d7c34d9
@ -4,7 +4,7 @@
|
||||
* Corporation and others. All Rights Reserved.
|
||||
**********************************************************************
|
||||
*/
|
||||
// $Revision: 1.16 $
|
||||
// $Revision: 1.17 $
|
||||
//
|
||||
// Provides functionality for mapping between
|
||||
// LCID and Posix IDs.
|
||||
@ -55,16 +55,28 @@ struct ILcidPosixElement
|
||||
|
||||
struct ILcidPosixMap
|
||||
{
|
||||
uint32_t hostID(const char* fromPosixID) const;
|
||||
const char* posixID(uint32_t fromHostID) const;
|
||||
|
||||
// static const char* fgWildCard;
|
||||
/**
|
||||
* Searches for a Windows LCID
|
||||
*
|
||||
* @param posixid the Posix style locale id.
|
||||
* @param status gets set to U_ILLEGAL_ARGUMENT_ERROR when the Posix ID has
|
||||
* no equivalent Windows LCID.
|
||||
* @return the LCID
|
||||
*/
|
||||
uint32_t hostID(const char* fromPosixID) const;
|
||||
|
||||
// uint16_t hostLangID;
|
||||
// const char *posixLangID;
|
||||
/**
|
||||
* Do not call this function. It is called by hostID.
|
||||
* The function is not private because this struct must stay as a C struct,
|
||||
* and this is an internal class.
|
||||
*/
|
||||
uint32_t searchPosixIDmap(const char* posixID, UErrorCode* status) const;
|
||||
|
||||
uint32_t numRegions;
|
||||
const ILcidPosixElement* regionMaps;
|
||||
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
@ -299,9 +311,9 @@ static const ILcidPosixElement sv[] = {
|
||||
{0x041d, "sv_SE"}
|
||||
};
|
||||
|
||||
ILCID_POSIX_ELEMENT_ARRAY(0x0441, sw, sw_KE) // The MSJDK documentation says the default country is Kenya.
|
||||
ILCID_POSIX_ELEMENT_ARRAY(0x0441, sw, sw_KE)// The MSJDK documentation says the default country is Kenya.
|
||||
ILCID_POSIX_ELEMENT_ARRAY(0x0449, ta, ta_IN)
|
||||
ILCID_POSIX_ELEMENT_ARRAY(0x044a, te, te_IN) //Todo: Data does not exist
|
||||
ILCID_POSIX_ELEMENT_ARRAY(0x044a, te, te_IN)
|
||||
ILCID_POSIX_ELEMENT_ARRAY(0x041e, th, th_TH)
|
||||
ILCID_POSIX_ELEMENT_ARRAY(0x041f, tr, tr_TR)
|
||||
ILCID_POSIX_ELEMENT_ARRAY(0x0444, tt, tt_RU) //Todo: Data does not exist
|
||||
@ -663,7 +675,7 @@ IGlobalLocales::convertToLCID(const char* posixID, UErrorCode* status)
|
||||
uint32_t mid;
|
||||
uint32_t high = LocaleCount - 1;
|
||||
int32_t compVal;
|
||||
char langID[256];
|
||||
char langID[ULOC_FULLNAME_CAPACITY];
|
||||
|
||||
// Check for incomplete id.
|
||||
if (!posixID || uprv_strlen(posixID) < 2)
|
||||
@ -694,7 +706,7 @@ IGlobalLocales::convertToLCID(const char* posixID, UErrorCode* status)
|
||||
|
||||
// no match found
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
return 0; // return international (root)
|
||||
}
|
||||
|
||||
|
||||
@ -703,17 +715,87 @@ IGlobalLocales::convertToLCID(const char* posixID, UErrorCode* status)
|
||||
uint32_t
|
||||
ILcidPosixMap::hostID(const char* posixID) const
|
||||
{
|
||||
uint32_t low = 1;
|
||||
uint32_t mid;
|
||||
uint32_t high = numRegions;
|
||||
int32_t compVal;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
char hostID[ULOC_FULLNAME_CAPACITY];
|
||||
char *hostPtr = hostID;
|
||||
uint32_t value;
|
||||
uint32_t hostLen = strlen(posixID);
|
||||
int32_t size, hostSize;
|
||||
|
||||
// Check for incomplete id. All LCIDs have a default country,
|
||||
// and a 0x0400 in 0xFC00 indicates a default country.
|
||||
// So Windows may not like hostLangID without a default
|
||||
// country.
|
||||
if (!numRegions || strlen(posixID) < 5)
|
||||
if (!numRegions || hostLen < 5)
|
||||
return regionMaps->hostID;
|
||||
if (hostLen >= ULOC_FULLNAME_CAPACITY)
|
||||
hostLen = ULOC_FULLNAME_CAPACITY - 1;
|
||||
|
||||
// We do this because the posixID may have a '-' separator and
|
||||
// incorrect string case
|
||||
hostSize = uloc_getLanguage(posixID,
|
||||
hostID,
|
||||
ULOC_LANG_CAPACITY + 1,
|
||||
&status);
|
||||
if (U_SUCCESS(status))
|
||||
{
|
||||
hostPtr += hostSize;
|
||||
hostPtr[-1] = '_';
|
||||
size = uloc_getCountry(posixID,
|
||||
hostPtr,
|
||||
ULOC_COUNTRY_CAPACITY + 1,
|
||||
&status);
|
||||
hostSize += size - 1;
|
||||
if (U_SUCCESS(status) && hostSize < hostLen)
|
||||
{
|
||||
hostPtr += size;
|
||||
hostPtr[-1] = '_';
|
||||
uloc_getVariant(posixID, hostPtr, hostLen - size, &status);
|
||||
}
|
||||
}
|
||||
|
||||
// Try to find it the first time.
|
||||
value = searchPosixIDmap(hostID, &status);
|
||||
if (U_SUCCESS(status)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// Couldn't find it. Cut off the last part of the locale
|
||||
while (hostPtr > hostID && *hostPtr != '_')
|
||||
{
|
||||
hostPtr--;
|
||||
}
|
||||
if (*hostPtr == '_')
|
||||
{
|
||||
*hostPtr = 0;
|
||||
}
|
||||
|
||||
// Try it again without the last part of the locale
|
||||
status = U_ZERO_ERROR;
|
||||
value = searchPosixIDmap(hostID, &status);
|
||||
if (U_SUCCESS(status)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// No match found. Return the language
|
||||
return regionMaps->hostID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for a Windows LCID
|
||||
*
|
||||
* @param posixid the Posix style locale id.
|
||||
* @param status gets set to U_ILLEGAL_ARGUMENT_ERROR when the Posix ID has
|
||||
* no equivalent Windows LCID.
|
||||
* @return the LCID
|
||||
*/
|
||||
uint32_t
|
||||
ILcidPosixMap::searchPosixIDmap(const char* posixID, UErrorCode* status) const
|
||||
{
|
||||
uint32_t low = 1;
|
||||
uint32_t mid;
|
||||
uint32_t high = numRegions;
|
||||
int32_t compVal;
|
||||
|
||||
// Binary search for the map entry
|
||||
// The element at index 0 is always the POSIX wild card,
|
||||
@ -733,9 +815,11 @@ ILcidPosixMap::hostID(const char* posixID) const
|
||||
}
|
||||
|
||||
//no match found
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return regionMaps->hostID;
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
ILcidPosixMap::posixID(uint32_t hostID) const
|
||||
{
|
||||
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
*****************************************************************************************
|
||||
*/
|
||||
// $Revision: 1.10 $
|
||||
// $Revision: 1.11 $
|
||||
//===============================================================================
|
||||
//
|
||||
// File locmap.hpp : Locale Mapping Classes
|
||||
@ -46,6 +46,7 @@ public:
|
||||
* @param hostid the Windows LCID number.
|
||||
* @param status gets set to U_ILLEGAL_ARGUMENT_ERROR when the LCID has no
|
||||
* equivalent ICU locale.
|
||||
* @return ICU locale
|
||||
*/
|
||||
static const char* convertToPosix(uint32_t hostid, UErrorCode* status);
|
||||
|
||||
@ -56,6 +57,7 @@ public:
|
||||
* @param posixid the Posix style locale id.
|
||||
* @param status gets set to U_ILLEGAL_ARGUMENT_ERROR when the Posix ID has
|
||||
* no equivalent Windows LCID.
|
||||
* @return the LCID
|
||||
*/
|
||||
static uint32_t convertToLCID(const char* posixID, UErrorCode* status);
|
||||
|
||||
@ -66,6 +68,7 @@ public:
|
||||
* ID.
|
||||
*
|
||||
* @param hostid the Windows LCID number.
|
||||
* @return the language part of the LCID
|
||||
*/
|
||||
static inline uint16_t languageLCID(uint32_t hostID) {return LANGUAGE_LCID(hostID);}
|
||||
|
||||
@ -78,7 +81,7 @@ protected:
|
||||
|
||||
static void initializeMapRegions(void);
|
||||
private:
|
||||
|
||||
|
||||
static uint32_t LocaleCount;
|
||||
static ILcidPosixMap* PosixIDmap;
|
||||
|
||||
|
@ -14,10 +14,90 @@
|
||||
#include "cstring.h"
|
||||
#include "unicode/resbund.h"
|
||||
|
||||
static void
|
||||
testLCID(const char *localeName);
|
||||
|
||||
static void
|
||||
testLCID(const char *localeName,
|
||||
const UnicodeString &posixName,
|
||||
uint32_t *errors,
|
||||
uint32_t *warnings)
|
||||
{
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
uint32_t lcid;
|
||||
uint32_t expectedLCID;
|
||||
char lcidStringC[1024];
|
||||
ResourceBundle posixLocale((char *)0, Locale(posixName), status);
|
||||
|
||||
if(status != U_ZERO_ERROR) {
|
||||
if(U_SUCCESS(status)) {
|
||||
printf("ERROR: Locale %-5s not installed, and it should be!\n", localeName);
|
||||
} else {
|
||||
printf("%%%%%%% Unexpected error %d %%%%%%%", u_errorName(status));
|
||||
}
|
||||
(*errors)++;
|
||||
return;
|
||||
}
|
||||
|
||||
UnicodeString lcidString(posixLocale.getStringEx("LocaleID", status));
|
||||
|
||||
if (U_FAILURE(status)) {
|
||||
printf("ERROR: %s does not have a LocaleID (%s)\n", localeName, u_errorName(status));
|
||||
(*errors)++;
|
||||
return;
|
||||
}
|
||||
|
||||
lcidString.extract(0, lcidString.length(), lcidStringC, "");
|
||||
lcidStringC[lcidString.length()] = '\0';
|
||||
expectedLCID = uprv_strtoul(lcidStringC, NULL, 16);
|
||||
|
||||
lcid = IGlobalLocales::convertToLCID(localeName, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
printf("WARNING: %-5s does not have an LCID mapping\n", localeName);
|
||||
(*warnings)++;
|
||||
return;
|
||||
}
|
||||
|
||||
status = U_ZERO_ERROR;
|
||||
uprv_strcpy(lcidStringC, IGlobalLocales::convertToPosix(expectedLCID, &status));
|
||||
if (U_FAILURE(status)) {
|
||||
printf("ERROR: %.4x does not have a POSIX mapping due to %s\n", expectedLCID, u_errorName(status));
|
||||
(*errors)++;
|
||||
}
|
||||
|
||||
if(lcid != expectedLCID) {
|
||||
printf("ERROR: Locale %-5s wrongfully has 0x%.4x instead of 0x%.4x for LCID\n", localeName, expectedLCID, lcid);
|
||||
(*errors)++;
|
||||
}
|
||||
if(strcmp(localeName, lcidStringC) != 0) {
|
||||
char langName[1024];
|
||||
char langLCID[1024];
|
||||
uloc_getLanguage(localeName, langName, sizeof(langName), &status);
|
||||
uloc_getLanguage(lcidStringC, langLCID, sizeof(langLCID), &status);
|
||||
|
||||
if (expectedLCID == lcid && strcmp(langName, langLCID) == 0) {
|
||||
printf("WARNING: %-5s resolves to %s (0x%.4x)\n", localeName, lcidStringC, lcid);
|
||||
(*warnings)++;
|
||||
}
|
||||
else if (expectedLCID == lcid) {
|
||||
printf("ERROR: 0x%.4x is from %-5s and the number resolves wrongfully to %s\n", expectedLCID, localeName, lcidStringC);
|
||||
(*errors)++;
|
||||
}
|
||||
else {
|
||||
printf("ERROR: 0x%.4x is from %-5s and the number resolves wrongfully to %s. It should be 0x%x.\n", expectedLCID, localeName, lcidStringC, lcid);
|
||||
(*errors)++;
|
||||
}
|
||||
} else {
|
||||
//printf("0x%x is from %s and it resolves correctly to %s(0x%x)\n", expectedLCID, localeName, lcidStringC, lcid);
|
||||
//printf("%s: %x->%x\n", localeName, expectedLCID, lcid);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
ResourceBundle index((char *)0, Locale("index"), status);
|
||||
uint32_t errors = 0;
|
||||
uint32_t warnings = 0;
|
||||
|
||||
if(U_SUCCESS(status)) {
|
||||
ResourceBundle installedLocales = index.get("InstalledLocales", status);
|
||||
@ -25,51 +105,11 @@ int main() {
|
||||
installedLocales.resetIterator();
|
||||
while(installedLocales.hasNext()) {
|
||||
char localeName[1024];
|
||||
uint32_t lcid;
|
||||
UnicodeString posixName = installedLocales.getNextString(status);
|
||||
|
||||
posixName.extract(0, posixName.length(), localeName, "");
|
||||
localeName[posixName.length()] = '\0';
|
||||
ResourceBundle posixLocale((char *)0, Locale(posixName), status);
|
||||
if(status == U_ZERO_ERROR) {
|
||||
UnicodeString lcidString = posixLocale.getStringEx("LocaleID", status);
|
||||
char lcidStringC[1024];
|
||||
lcidString.extract(0, lcidString.length(), lcidStringC, "");
|
||||
lcidStringC[lcidString.length()] = '\0';
|
||||
uint32_t expectedLCID = uprv_strtoul(lcidStringC, NULL, 16);
|
||||
|
||||
status = U_ZERO_ERROR;
|
||||
lcid = IGlobalLocales::convertToLCID(localeName, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
printf("WARNING: %s does not have an LCID mapping (%s)\n", localeName, u_errorName(status));
|
||||
status = U_ZERO_ERROR;
|
||||
}
|
||||
else {
|
||||
status = U_ZERO_ERROR;
|
||||
uprv_strcpy(lcidStringC, IGlobalLocales::convertToPosix(expectedLCID, &status));
|
||||
if (U_FAILURE(status)) {
|
||||
printf("ERROR: %x does not have an POSIX mapping due to error %s\n", expectedLCID, u_errorName(status));
|
||||
}
|
||||
if(strcmp(localeName, lcidStringC) == 0) {
|
||||
//printf("0x%x is from %s and it resolves correctly to %s(0x%x)\n", expectedLCID, localeName, lcidStringC, lcid);
|
||||
//printf("%s: %x->%x\n", localeName, expectedLCID, lcid);
|
||||
} else {
|
||||
printf("ERROR: 0x%x is from %s and it resolves wrongfully to %s, it should have (0x%x)\n", expectedLCID, localeName, lcidStringC, lcid);
|
||||
//printf("Name mismatch: %s vs. %s: %x->%x\n", localeName, lcidStringC, expectedLCID, lcid);
|
||||
errors++;
|
||||
}
|
||||
if(lcid != expectedLCID) {
|
||||
printf("ERROR: Locale %s wrongfully has 0x%x instead of 0x%x for LCID\n", localeName, expectedLCID, lcid);
|
||||
//printf("LCID mismatch: %s: %x->%x\n", localeName, expectedLCID, lcid);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
} else if(U_SUCCESS(status)) {
|
||||
printf("ERROR: Locale %s not installed, and it should be!\n", localeName);
|
||||
errors++;
|
||||
} else {
|
||||
printf("%%%%%%% Unexpected error %d %%%%%%%", status);
|
||||
}
|
||||
|
||||
testLCID(localeName, posixName, &errors, &warnings);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -79,6 +119,10 @@ int main() {
|
||||
printf("There were no errors\n");
|
||||
}
|
||||
|
||||
if(warnings > 0) {
|
||||
printf("There were %d warning(s)\n", warnings);
|
||||
}
|
||||
|
||||
char temp;
|
||||
scanf("%c", &temp);
|
||||
|
||||
|
@ -39,9 +39,10 @@ RSC=rc.exe
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /I "../../common" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
@ -49,7 +50,7 @@ BSC32=bscmake.exe
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 icuuc17.lib /nologo /subsystem:console /machine:I386 /libpath:"../../../lib" /libpath:"../../common/Release"
|
||||
|
||||
!ELSEIF "$(CFG)" == "lcid - Win32 Debug"
|
||||
|
||||
@ -73,7 +74,7 @@ BSC32=bscmake.exe
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 icuuc.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"../../../lib/debug" /libpath:"../../common/debug"
|
||||
# ADD LINK32 icuuc17d.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"../../../lib" /libpath:"../../common/debug"
|
||||
# SUBTRACT LINK32 /incremental:no
|
||||
|
||||
!ENDIF
|
||||
|
Loading…
Reference in New Issue
Block a user