ICU-2439 fix display name lookups to not fallback through the default locale

X-SVN-Rev: 11712
This commit is contained in:
Markus Scherer 2003-04-25 22:56:51 +00:00
parent 50f7e65914
commit bbf546a40e
5 changed files with 253 additions and 448 deletions

View file

@ -1,6 +1,6 @@
/*
**********************************************************************
* Copyright (C) 1997-2001, International Business Machines
* Copyright (C) 1997-2003, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
*
@ -842,25 +842,17 @@ _startsWith(const char *s, const char *possiblePrefix) {
}
/*
* TODO check fallback semantics - fall back through default??
* Needs discussion!
* Lookup a resource bundle table item with fallback on the table level.
* Regular resource bundle lookups perform fallback to parent locale bundles
* and eventually the root bundle, but only for top-level items.
* This function takes the name of a top-level table and of an item in that table
* and performs a lookup of both, falling back until a bundle contains a table
* with this item.
*
* Regular resource bundle lookup falls back through default only when a bundle
* is opened. Once open, the lookup for an item in that bundle follows only
* the bundle's chain, without going through default.
*
* This lookup for the display strings does go through the default locale
* for the sub-item.
* It seems to be inconsistent with how the resource bundle mechanism is documented.
*
* Note also that using this mechanism (with itemKey=NULL) for the variant's
* display string, which is a top-level item and should always be available
* at least in root, is effectively the same as opening the displayLocale's
* bundle and getting the string directly from there - the fallback is the same
* (right?!).
* So, for variant's strings, one could either do that, or if the above elaborate
* mechanism is desired, one could move variant display strings into their
* own table "Variants" like the Languages and Countries tables.
* Note: Only the opening of entire bundles falls back through the default locale
* before root. Once a bundle is open, item lookups do not go through the
* default locale because that would result in a mix of languages that is
* unpredictable to the programmer and most likely useless.
*/
static const UChar *
_res_getTableStringWithFallback(const char *path, const char *locale,
@ -868,148 +860,111 @@ _res_getTableStringWithFallback(const char *path, const char *locale,
int32_t *pLength,
UErrorCode *pErrorCode)
{
char localeBuffer[200];
char localeBuffer[80];
UResourceBundle *rb, table;
const UChar *item;
const char *defaultLocale;
UBool lookedAtDefault;
lookedAtDefault=FALSE;
defaultLocale=uloc_getDefault();
/* normalize the input locale name */
if(locale==NULL) {
locale=defaultLocale;
lookedAtDefault=TRUE;
} else {
uloc_getName(locale, localeBuffer, sizeof(localeBuffer), pErrorCode);
if(U_FAILURE(*pErrorCode) || *pErrorCode==U_STRING_NOT_TERMINATED_WARNING) {
*pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
return NULL;
}
locale=localeBuffer;
/* is the requested locale the root locale, or part of the default locale? */
if(*locale==0 || 0==uprv_strcmp(locale, "root") || _startsWith(defaultLocale, locale)) {
lookedAtDefault=TRUE;
}
}
UErrorCode errorCode;
for(;;) {
/*
* open the bundle for the current locale
* this falls back through the locale's chain to the default locale's chain to root
* this falls back through the locale's chain to root
*/
*pErrorCode=U_ZERO_ERROR;
rb=ures_open(path, locale, pErrorCode);
if(U_FAILURE(*pErrorCode)) {
errorCode=U_ZERO_ERROR;
rb=ures_open(path, locale, &errorCode);
if(U_FAILURE(errorCode)) {
/* total failure, not even root could be opened */
*pErrorCode=errorCode;
return NULL;
} else if(*pErrorCode==U_USING_DEFAULT_WARNING) {
lookedAtDefault=TRUE;
}
/* get the real locale ID for this bundle in case of aliases & fallbacks */
locale=ures_getLocale(rb, pErrorCode);
if(U_FAILURE(*pErrorCode)) {
/* error getting the locale ID for an open RB - should never happen */
*pErrorCode=U_INTERNAL_PROGRAM_ERROR;
ures_close(rb);
return NULL;
}
if(!lookedAtDefault && _startsWith(defaultLocale, locale)) {
lookedAtDefault=TRUE;
} else if(errorCode==U_USING_DEFAULT_WARNING ||
(errorCode==U_USING_FALLBACK_WARNING && *pErrorCode!=U_USING_DEFAULT_WARNING)
) {
/* set the "strongest" error code (success->fallback->default->failure) */
*pErrorCode=errorCode;
}
/*
* try to open the requested table
* this falls back through the locale's chain to root, but not through the default locale
*/
*pErrorCode=U_ZERO_ERROR;
errorCode=U_ZERO_ERROR;
ures_initStackObject(&table);
ures_getByKey(rb, tableKey, &table, pErrorCode);
if(U_FAILURE(*pErrorCode)) {
ures_getByKey(rb, tableKey, &table, &errorCode);
if(U_FAILURE(errorCode)) {
/* no such table anywhere in this fallback chain */
ures_close(rb);
if(lookedAtDefault) {
return NULL;
}
/* try fallback through the default locale */
locale=defaultLocale;
lookedAtDefault=TRUE;
continue;
*pErrorCode=errorCode;
return NULL;
} else if(errorCode==U_USING_DEFAULT_WARNING ||
(errorCode==U_USING_FALLBACK_WARNING && *pErrorCode!=U_USING_DEFAULT_WARNING)
) {
/* set the "strongest" error code (success->fallback->default->failure) */
*pErrorCode=errorCode;
}
/*
* Disable (#if 0) the following check:
* Assume that only the language that is the same as the root language does not
* have its own override of this item.
* Therefore, we _do_ want to use the item even if it is from root before default,
* because for the languages where this happens, it is exactly what we need.
* Markus Scherer 2001-oct-02
*/
#if 0
/* do not use the root bundle if we did not look at the default locale yet */
if(*pErrorCode==U_USING_DEFAULT_WARNING && !lookedAtDefault) {
ures_close(table);
ures_close(rb);
/* try fallback through the default locale */
locale=defaultLocale;
lookedAtDefault=TRUE;
continue;
}
#endif
/* get the real locale ID for this table in case of aliases & fallbacks */
locale=ures_getLocale(&table, pErrorCode);
if(U_FAILURE(*pErrorCode)) {
/* error getting the locale ID for an open RB - should never happen */
*pErrorCode=U_INTERNAL_PROGRAM_ERROR;
/* try to open the requested item in the table */
errorCode=U_ZERO_ERROR;
item=ures_getStringByKey(&table, itemKey, pLength, &errorCode);
if(U_SUCCESS(errorCode)) {
/* we got the requested item! */
ures_close(&table);
ures_close(rb);
return NULL;
}
if(itemKey!=NULL) {
/* try to open the requested item in the table */
item=ures_getStringByKey(&table, itemKey, pLength, pErrorCode);
if(U_SUCCESS(*pErrorCode)) {
/* we got the requested item! */
ures_close(&table);
ures_close(rb);
return item;
if(errorCode==U_USING_DEFAULT_WARNING ||
(errorCode==U_USING_FALLBACK_WARNING && *pErrorCode!=U_USING_DEFAULT_WARNING)
) {
/* set the "strongest" error code (success->fallback->default->failure) */
*pErrorCode=errorCode;
}
} else {
/* return the "table" resource itself, not an item from it */
item=ures_getString(&table, pLength, pErrorCode);
ures_close(&table); /* we will not need the table any more */
ures_close(rb);
/*
* It is safe to close the bundle and still return the
* string pointer because resource bundles are
* cached until u_cleanup().
*/
return item;
}
ures_close(&table);
ures_close(rb);
if(lookedAtDefault && (*locale==0 || 0==uprv_strcmp(locale, "root"))) {
/* end of fallback, default and root do not have the requested item either */
/*
* We get here if the item was not found.
* We will follow the chain to the parent locale bundle and look in
* the table there.
*/
/* get the real locale ID for this table */
errorCode=U_ZERO_ERROR;
locale=ures_getLocale(&table, &errorCode);
/* keep table and rb open until we are done using the locale string owned by the table bundle */
if(U_FAILURE(errorCode)) {
/* error getting the locale ID for an open RB - should never happen */
ures_close(&table);
ures_close(rb);
*pErrorCode=U_INTERNAL_PROGRAM_ERROR;
return NULL;
}
if(*locale==0 || 0==uprv_strcmp(locale, "root")) {
/* end of fallback; even root does not have the requested item either */
ures_close(&table);
ures_close(rb);
*pErrorCode=U_MISSING_RESOURCE_ERROR;
return NULL;
}
/* could not find the table, or its item, try to fall back to a different RB and table */
*pErrorCode=U_ZERO_ERROR;
uloc_getParent(locale, localeBuffer, sizeof(localeBuffer), pErrorCode);
if(U_FAILURE(*pErrorCode) || *pErrorCode==U_STRING_NOT_TERMINATED_WARNING) {
errorCode=U_ZERO_ERROR;
uloc_getParent(locale, localeBuffer, sizeof(localeBuffer), &errorCode);
/* done with the locale string - ready to close table and rb */
ures_close(&table);
ures_close(rb);
if(U_FAILURE(errorCode) || errorCode==U_STRING_NOT_TERMINATED_WARNING) {
/* error getting the parent locale ID - should never happen */
*pErrorCode=U_INTERNAL_PROGRAM_ERROR;
return NULL;
}
locale=localeBuffer;
/* parent==root? try the default locale if not done so already */
if(!lookedAtDefault && (*locale==0 || 0==uprv_strcmp(locale, "root"))) {
/* try fallback through the default locale */
locale=defaultLocale;
lookedAtDefault=TRUE;
}
/* continue the fallback lookup with the parent locale ID */
locale=localeBuffer;
}
}
@ -1022,25 +977,33 @@ _getStringOrCopyKey(const char *path, const char *locale,
const UChar *s;
int32_t length;
length=-1;
s=_res_getTableStringWithFallback(path, locale,
tableKey, itemKey,
&length,
pErrorCode);
if(U_SUCCESS(*pErrorCode) && s) {
if(itemKey==NULL) {
/* top-level item: normal resource bundle access */
UResourceBundle *rb;
rb=ures_open(path, locale, pErrorCode);
if(U_SUCCESS(*pErrorCode)) {
s=ures_getStringByKey(rb, tableKey, &length, pErrorCode);
/* see comment about closing rb near "return item;" in _res_getTableStringWithFallback() */
ures_close(rb);
}
} else {
/* second-level item, use special fallback */
s=_res_getTableStringWithFallback(path, locale,
tableKey, itemKey,
&length,
pErrorCode);
}
if(U_SUCCESS(*pErrorCode)) {
int32_t copyLength=uprv_min(length, destCapacity);
if(copyLength>0) {
u_memcpy(dest, s, copyLength);
}
} else {
length=-1;
}
/* no string from a resource bundle: convert the substitute */
if(length==-1) {
/* no string from a resource bundle: convert the substitute */
length=(int32_t)uprv_strlen(substitute);
u_charsToUChars(substitute, dest, uprv_min(length, destCapacity));
*pErrorCode=U_ZERO_ERROR;
*pErrorCode=U_USING_DEFAULT_WARNING;
}
return u_terminateUChars(dest, destCapacity, length, pErrorCode);

View file

@ -26,6 +26,8 @@
#include "cintltst.h"
#include "cstring.h"
#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
#include "unicode/ures.h"
#ifdef WIN32
/* Get the private functions. This is a hack! [grhoten] */
@ -58,7 +60,7 @@ static const char* rawData2[LOCALE_INFO_SIZE][LOCALE_SIZE] = {
/* LCID (not currently public) */
{ "409", "40c", "41a", "408", "814" },
/* display langage (English) */
/* display language (English) */
{ "English", "French", "Croatian", "Greek", "Norwegian" },
/* display country (English) */
{ "United States", "France", "Croatia", "Greece", "Norway" },
@ -67,7 +69,7 @@ static const char* rawData2[LOCALE_INFO_SIZE][LOCALE_SIZE] = {
/* display name (English) */
{ "English (United States)", "French (France)", "Croatian (Croatia)", "Greek (Greece)", "Norwegian (Norway, Nynorsk)" },
/* display langage (French) */
/* display language (French) */
{ "anglais", "fran\\u00E7ais", "croate", "grec", "norv\\u00E9gien" },
/* display country (French) */
{ "\\u00C9tats-Unis", "France", "Croatie", "Gr\\u00E8ce", "Norv\\u00E8ge" },
@ -76,23 +78,41 @@ static const char* rawData2[LOCALE_INFO_SIZE][LOCALE_SIZE] = {
/* display name (French) */
{ "anglais (\\u00C9tats-Unis)", "fran\\u00E7ais (France)", "croate (Croatie)", "grec (Gr\\u00E8ce)", "norv\\u00E9gien (Norv\\u00E8ge, Nynorsk)" },
/* display langage (Croatian) */
/* display language (Croatian) */
{ "", "", "hrvatski", "", "" },
/* display country (Croatian) */
{ "", "", "Hrvatska", "", "" },
/* display variant (Croatian) */
{ "", "", "", "", "" },
{ "", "", "", "", "Nynorsk" },
/* display name (Croatian) */
{ "", "", "hrvatski (Hrvatska)", "", "" },
/* display langage (Greek) */
{ "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac", "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac", "\\u039a\\u03c1\\u03bf\\u03b1\\u03c4\\u03b9\\u03ba\\u03ac", "\\u03b5\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac", "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac" },
/* display language (Greek) */
{
"\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac",
"\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac",
"\\u039a\\u03c1\\u03bf\\u03b1\\u03c4\\u03b9\\u03ba\\u03ac",
"\\u03b5\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac",
"\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac"
},
/* display country (Greek) */
{ "\\u0397\\u03bd\\u03c9\\u03bc\\u03ad\\u03bd\\u03b5\\u03c2 \\u03a0\\u03bf\\u03bb\\u03b9\\u03c4\\u03b5\\u03af\\u03b5\\u03c2 \\u0391\\u03bc\\u03b5\\u03c1\\u03b9\\u03ba\\u03ae\\u03c2", "\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1", "\\u039a\\u03c1\\u03bf\\u03b1\\u03c4\\u03af\\u03b1", "\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1", "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1" },
{
"\\u0397\\u03bd\\u03c9\\u03bc\\u03ad\\u03bd\\u03b5\\u03c2 \\u03a0\\u03bf\\u03bb\\u03b9\\u03c4\\u03b5\\u03af\\u03b5\\u03c2 \\u0391\\u03bc\\u03b5\\u03c1\\u03b9\\u03ba\\u03ae\\u03c2",
"\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1",
"\\u039a\\u03c1\\u03bf\\u03b1\\u03c4\\u03af\\u03b1",
"\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1",
"\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1"
},
/* display variant (Greek) */
{ "", "", "", "", "" },
{ "", "", "", "", "Nynorsk" },
/* display name (Greek) */
{ "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac (\\u0397\\u03bd\\u03c9\\u03bc\\u03ad\\u03bd\\u03b5\\u03c2 \\u03a0\\u03bf\\u03bb\\u03b9\\u03c4\\u03b5\\u03af\\u03b5\\u03c2 \\u0391\\u03bc\\u03b5\\u03c1\\u03b9\\u03ba\\u03ae\\u03c2)", "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac (\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1)", "\\u039a\\u03c1\\u03bf\\u03b1\\u03c4\\u03b9\\u03ba\\u03ac (\\u039a\\u03c1\\u03bf\\u03b1\\u03c4\\u03af\\u03b1)", "\\u03b5\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac (\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1)", "" }
{
"\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac (\\u0397\\u03bd\\u03c9\\u03bc\\u03ad\\u03bd\\u03b5\\u03c2 \\u03a0\\u03bf\\u03bb\\u03b9\\u03c4\\u03b5\\u03af\\u03b5\\u03c2 \\u0391\\u03bc\\u03b5\\u03c1\\u03b9\\u03ba\\u03ae\\u03c2)",
"\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac (\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1)",
"\\u039a\\u03c1\\u03bf\\u03b1\\u03c4\\u03b9\\u03ba\\u03ac (\\u039a\\u03c1\\u03bf\\u03b1\\u03c4\\u03af\\u03b1)",
"\\u03b5\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac (\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1)",
"\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac (\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1, Nynorsk)"
}
};
static UChar*** dataTable=0;
@ -100,9 +120,8 @@ enum {
ENGLISH = 0,
FRENCH = 1,
CROATIAN = 2,
GREEKS = 3,
NORWEGIAN = 4,
MAX_LOCALES = 4
GREEK = 3,
NORWEGIAN = 4
};
enum {
@ -162,7 +181,7 @@ static void TestBasicGetters() {
char *testLocale = 0;
char *temp = 0, *name = 0;
log_verbose("Testing Basic Getters\n");
for (i = 0; i <= MAX_LOCALES; i++) {
for (i = 0; i < LOCALE_SIZE; i++) {
testLocale=(char*)malloc(sizeof(char) * (strlen(rawData2[NAME][i])+1));
strcpy(testLocale,rawData2[NAME][i]);
@ -364,7 +383,7 @@ static void TestSimpleResourceInfo() {
setUpDataTable();
log_verbose("Testing getISO3Language and getISO3Country\n");
for (i = 0; i <= MAX_LOCALES; i++) {
for (i = 0; i < LOCALE_SIZE; i++) {
testLocale=(char*)realloc(testLocale, sizeof(char) * (u_strlen(dataTable[NAME][i])+1));
u_austrcpy(testLocale, dataTable[NAME][i]);
@ -398,75 +417,43 @@ setUpDataTable();
cleanUpDataTable();
}
/*
* Jitterbug 2439 -- markus 20030425
*
* The lookup of display names must not fall back through the default
* locale because that yields useless results.
*/
static void TestDisplayNames()
{
/* sfb 990721
Can't just save a pointer to the default locale.
Although the pointer won't change, the contents will, so the
restore at the end doesn't actually restore the original.
*/
const char *saveDefault;
char *defaultLocale;
UErrorCode err = U_ZERO_ERROR;
saveDefault = uloc_getDefault();
defaultLocale = (char*) malloc(strlen(saveDefault) + 1);
if(defaultLocale == 0) {
log_err("out of memory");
return;
}
strcpy(defaultLocale, saveDefault);
uloc_setDefault("en_US", &err);
if (U_FAILURE(err)) {
log_err("uloc_setDefault returned error code ");
return;
}
UChar buffer[100];
UErrorCode errorCode;
int32_t length;
log_verbose("Testing getDisplayName for different locales\n");
log_verbose("With default = en_US...\n");
log_verbose(" In default locale...\n");
doTestDisplayNames(" ", DLANG_EN, FALSE);
log_verbose(" In locale = en_US...\n");
doTestDisplayNames("en_US", DLANG_EN, FALSE);
doTestDisplayNames("en_US", DLANG_EN);
log_verbose(" In locale = fr_FR....\n");
doTestDisplayNames("fr_FR", DLANG_FR, FALSE);
doTestDisplayNames("fr_FR", DLANG_FR);
log_verbose(" In locale = hr_HR...\n");
doTestDisplayNames("hr_HR", DLANG_HR, FALSE);
doTestDisplayNames("hr_HR", DLANG_HR);
log_verbose(" In locale = gr_EL..\n");
doTestDisplayNames("el_GR", DLANG_EL, FALSE);
doTestDisplayNames("el_GR", DLANG_EL);
uloc_setDefault("fr_FR", &err);
if (U_FAILURE(err)) {
log_err("Locale::setDefault returned error code %s\n", myErrorName(err));
return;
/* test that the default locale has a display name for its own language */
errorCode=U_ZERO_ERROR;
length=uloc_getDisplayLanguage(NULL, NULL, buffer, LENGTHOF(buffer), &errorCode);
if(U_FAILURE(errorCode) || length<=3) {
/* check <=3 to reject getting the language code as a display name */
log_err("unable to get a display string for the language of the default locale - %s\n", u_errorName(errorCode));
}
log_verbose("With default = fr_FR...\n");
log_verbose(" In default locale...\n");
doTestDisplayNames(" ", DLANG_FR, TRUE);
log_verbose(" In locale = en_US...\n");
doTestDisplayNames("en_US", DLANG_EN, TRUE);
log_verbose(" In locale = fr_FR....\n");
doTestDisplayNames("fr_FR", DLANG_FR, TRUE);
log_verbose(" In locale = hr_HR...\n");
doTestDisplayNames("hr_HR", DLANG_HR, TRUE);
log_verbose(" In locale = el_GR...\n");
doTestDisplayNames("el_GR", DLANG_EL, TRUE);
uloc_setDefault(defaultLocale, &err);
if (U_FAILURE(err)) {
log_err("Locale::setDefault returned error code %s\n", myErrorName(err));
return;
/* test that we get the language code itself for an unknown language, and a default warning */
errorCode=U_ZERO_ERROR;
length=uloc_getDisplayLanguage("qq", "rr", buffer, LENGTHOF(buffer), &errorCode);
if(errorCode!=U_USING_DEFAULT_WARNING || length!=2 || buffer[0]!=0x71 || buffer[1]!=0x71) {
log_err("error getting the display string for an unknown language - %s\n", u_errorName(errorCode));
}
free(defaultLocale);
}
@ -541,15 +528,13 @@ static void TestDataDirectory()
static UChar _NUL=0;
static void doTestDisplayNames(const char* inLocale,
int32_t compareIndex,
int32_t defaultIsFrench)
static void doTestDisplayNames(const char* displayLocale, int32_t compareIndex)
{
UErrorCode status = U_ZERO_ERROR;
int32_t i;
int32_t maxresultsize;
char* testLocale;
const char *testLocale;
UChar *testLang = 0;
@ -562,207 +547,110 @@ static void doTestDisplayNames(const char* inLocale,
UChar* expectedCtry = 0;
UChar* expectedVar = 0;
UChar* expectedName = 0;
char temp[5];
const char* defaultDefaultLocale=" ";
setUpDataTable();
uloc_getLanguage(uloc_getDefault(), temp, 5, &status);
if(U_FAILURE(status)){
log_err("ERROR: in getDefault %s \n", myErrorName(status));
}
if (defaultIsFrench && 0 != strcmp(temp, "fr")) {
log_err("Default locale should be French, but it's really %s\n", temp);
}
else if (!defaultIsFrench && 0 != strcmp(temp, "en")){
log_err("Default locale should be English, but it's really %s\n", temp);
}
testLocale = (char*)malloc(sizeof(char) * 1);
for(i=0;i<MAX_LOCALES; ++i)
for(i=0;i<LOCALE_SIZE; ++i)
{
testLocale=(char*)realloc(testLocale, sizeof(char) * (u_strlen(dataTable[NAME][i])+1));
u_austrcpy(testLocale,dataTable[NAME][i]);
testLocale=rawData2[NAME][i];
log_verbose("Testing..... %s\n", testLocale);
if (strcmp(inLocale, defaultDefaultLocale)==0) {
maxresultsize=0;
maxresultsize=uloc_getDisplayLanguage(testLocale, NULL, NULL, maxresultsize, &status);
if(status==U_BUFFER_OVERFLOW_ERROR)
{
status=U_ZERO_ERROR;
testLang=(UChar*)malloc(sizeof(UChar) * (maxresultsize + 1));
uloc_getDisplayLanguage(testLocale, NULL, testLang, maxresultsize + 1, &status);
}
else
{
testLang=&_NUL;
}
if(U_FAILURE(status)){
log_err("Error in getDisplayLanguage() %s\n", myErrorName(status));
}
maxresultsize=0;
maxresultsize=uloc_getDisplayCountry(testLocale, NULL, NULL, maxresultsize, &status);
if(status==U_BUFFER_OVERFLOW_ERROR)
{
status=U_ZERO_ERROR;
testCtry=(UChar*)malloc(sizeof(UChar) * (maxresultsize + 1));
uloc_getDisplayCountry(testLocale, NULL, testCtry, maxresultsize + 1, &status);
}
else
{
testCtry=&_NUL;
}
if(U_FAILURE(status)){
log_err("Error in getDisplayCountry() %s\n", myErrorName(status));
}
maxresultsize=0;
maxresultsize=uloc_getDisplayVariant(testLocale, NULL, NULL, maxresultsize, &status);
if(status==U_BUFFER_OVERFLOW_ERROR)
{
status=U_ZERO_ERROR;
testVar=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
uloc_getDisplayVariant(testLocale, NULL, testVar, maxresultsize + 1, &status);
}
else
{
testVar=&_NUL;
}
if(U_FAILURE(status)){
log_err("Error in getDisplayVariant() %s\n", myErrorName(status));
}
maxresultsize=0;
maxresultsize=uloc_getDisplayName(testLocale, NULL, NULL, maxresultsize, &status);
if(status==U_BUFFER_OVERFLOW_ERROR)
{
status=U_ZERO_ERROR;
testName=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
uloc_getDisplayName(testLocale, NULL, testName, maxresultsize + 1, &status);
}
else
{
testName=&_NUL;
}
if(U_FAILURE(status)){
log_err("Error in getDisplayName() %s\n", myErrorName(status));
}
maxresultsize=0;
maxresultsize=uloc_getDisplayLanguage(testLocale, displayLocale, NULL, maxresultsize, &status);
if(status==U_BUFFER_OVERFLOW_ERROR)
{
status=U_ZERO_ERROR;
testLang=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
uloc_getDisplayLanguage(testLocale, displayLocale, testLang, maxresultsize + 1, &status);
}
else
{
testLang=&_NUL;
}
if(U_FAILURE(status)){
log_err("Error in getDisplayLanguage() %s\n", myErrorName(status));
}
else {
maxresultsize=0;
maxresultsize=uloc_getDisplayLanguage(testLocale, inLocale, NULL, maxresultsize, &status);
if(status==U_BUFFER_OVERFLOW_ERROR)
{
status=U_ZERO_ERROR;
testLang=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
uloc_getDisplayLanguage(testLocale, inLocale, testLang, maxresultsize + 1, &status);
}
else
{
testLang=&_NUL;
}
if(U_FAILURE(status)){
log_err("Error in getDisplayLanguage() %s\n", myErrorName(status));
}
maxresultsize=0;
maxresultsize=uloc_getDisplayCountry(testLocale, inLocale, NULL, maxresultsize, &status);
if(status==U_BUFFER_OVERFLOW_ERROR)
{
status=U_ZERO_ERROR;
testCtry=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
uloc_getDisplayCountry(testLocale, inLocale, testCtry, maxresultsize + 1, &status);
}
else
{
testCtry=&_NUL;
}
if(U_FAILURE(status)){
log_err("Error in getDisplayCountry() %s\n", myErrorName(status));
}
maxresultsize=0;
maxresultsize=uloc_getDisplayCountry(testLocale, displayLocale, NULL, maxresultsize, &status);
if(status==U_BUFFER_OVERFLOW_ERROR)
{
status=U_ZERO_ERROR;
testCtry=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
uloc_getDisplayCountry(testLocale, displayLocale, testCtry, maxresultsize + 1, &status);
}
else
{
testCtry=&_NUL;
}
if(U_FAILURE(status)){
log_err("Error in getDisplayCountry() %s\n", myErrorName(status));
}
maxresultsize=0;
maxresultsize=uloc_getDisplayVariant(testLocale, inLocale, NULL, maxresultsize, &status);
if(status==U_BUFFER_OVERFLOW_ERROR)
{
status=U_ZERO_ERROR;
testVar=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
uloc_getDisplayVariant(testLocale, inLocale, testVar, maxresultsize + 1, &status);
}
else
{
testVar=&_NUL;
}
if(U_FAILURE(status)){
log_err("Error in getDisplayVariant() %s\n", myErrorName(status));
}
maxresultsize=0;
maxresultsize=uloc_getDisplayName(testLocale, inLocale, NULL, maxresultsize, &status);
if(status==U_BUFFER_OVERFLOW_ERROR)
{
status=U_ZERO_ERROR;
testName=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
uloc_getDisplayName(testLocale, inLocale, testName, maxresultsize + 1, &status);
}
else
{
testName=&_NUL;
}
if(U_FAILURE(status)){
log_err("Error in getDisplayName() %s\n", myErrorName(status));
}
maxresultsize=0;
maxresultsize=uloc_getDisplayVariant(testLocale, displayLocale, NULL, maxresultsize, &status);
if(status==U_BUFFER_OVERFLOW_ERROR)
{
status=U_ZERO_ERROR;
testVar=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
uloc_getDisplayVariant(testLocale, displayLocale, testVar, maxresultsize + 1, &status);
}
else
{
testVar=&_NUL;
}
if(U_FAILURE(status)){
log_err("Error in getDisplayVariant() %s\n", myErrorName(status));
}
maxresultsize=0;
maxresultsize=uloc_getDisplayName(testLocale, displayLocale, NULL, maxresultsize, &status);
if(status==U_BUFFER_OVERFLOW_ERROR)
{
status=U_ZERO_ERROR;
testName=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
uloc_getDisplayName(testLocale, displayLocale, testName, maxresultsize + 1, &status);
}
else
{
testName=&_NUL;
}
if(U_FAILURE(status)){
log_err("Error in getDisplayName() %s\n", myErrorName(status));
}
expectedLang=dataTable[compareIndex][i];
if(u_strlen(expectedLang) == 0 && defaultIsFrench)
expectedLang=dataTable[DLANG_FR][i];
if(u_strlen(expectedLang)== 0)
expectedLang=dataTable[DLANG_EN][i];
expectedCtry=dataTable[compareIndex + 1][i];
if(u_strlen(expectedCtry) == 0 && defaultIsFrench)
expectedCtry=dataTable[DCTRY_FR][i];
if(u_strlen(expectedCtry)== 0)
expectedCtry=dataTable[DCTRY_EN][i];
expectedVar=dataTable[compareIndex + 2][i];
if(u_strlen(expectedVar) == 0 && defaultIsFrench)
expectedVar=dataTable[DVAR_FR][i];
if(u_strlen(expectedCtry)== 0)
expectedVar=dataTable[DVAR_EN][i];
expectedName=dataTable[compareIndex + 3][i];
if(u_strlen(expectedName) ==0 && defaultIsFrench)
expectedName=dataTable[DNAME_FR][i];
if(u_strlen(expectedName) == 0)
expectedName=dataTable[DNAME_EN][i];
if (0 !=u_strcmp(testLang,expectedLang)) {
log_data_err(" Display Language mismatch: %s versus %s inLocale=%s\n", austrdup(testLang), austrdup(expectedLang), inLocale);
log_data_err(" Display Language mismatch: got %s expected %s displayLocale=%s\n", austrdup(testLang), austrdup(expectedLang), displayLocale);
}
if (0 != u_strcmp(testCtry,expectedCtry)) {
log_data_err(" Display Country mismatch: %s versus %s inLocale=%s\n", austrdup(testCtry), austrdup(expectedCtry), inLocale);
log_data_err(" Display Country mismatch: got %s expected %s displayLocale=%s\n", austrdup(testCtry), austrdup(expectedCtry), displayLocale);
}
if (0 != u_strcmp(testVar,expectedVar)) {
log_data_err(" Display Variant mismatch: %s versus %s inLocale=%s\n", austrdup(testVar), austrdup(expectedVar), inLocale);
log_data_err(" Display Variant mismatch: got %s expected %s displayLocale=%s\n", austrdup(testVar), austrdup(expectedVar), displayLocale);
}
if(0 != u_strcmp(testName, expectedName)) {
log_data_err(" Display Name mismatch: %s versus %s inLocale=%s\n", austrdup(testName), austrdup(expectedName), inLocale);
log_data_err(" Display Name mismatch: got %s expected %s displayLocale=%s\n", austrdup(testName), austrdup(expectedName), displayLocale);
}
if(testName!=&_NUL) {
@ -778,7 +666,6 @@ setUpDataTable();
free(testVar);
}
}
free(testLocale);
cleanUpDataTable();
}

View file

@ -1,6 +1,6 @@
/********************************************************************
* COPYRIGHT:
* Copyright (c) 1997-2001, International Business Machines Corporation and
* Copyright (c) 1997-2003, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
/********************************************************************************
@ -70,7 +70,7 @@ static void TestDisplayNames(void);
/**
* routine to perform subtests, used by TestDisplayNames
*/
static void doTestDisplayNames(const char* inLocale, int32_t compareIndex, int32_t defaultIsFrench);
static void doTestDisplayNames(const char* inLocale, int32_t compareIndex);
/**
* additional intialization for datatables storing expected values

View file

@ -371,57 +371,35 @@ void LocaleTest::TestSimpleResourceInfo() {
}
/*
* Jitterbug 2439 -- markus 20030425
*
* The lookup of display names must not fall back through the default
* locale because that yields useless results.
*/
void
LocaleTest::TestDisplayNames()
{
Locale saveDefault = Locale::getDefault();
Locale empty("", "");
Locale english("en", "US");
Locale french("fr", "FR");
Locale croatian("hr", "HR");
Locale greek("el", "GR");
UErrorCode err = U_ZERO_ERROR;
Locale::setDefault(english, err);
if (U_FAILURE(err)) {
errln("Locale::setDefault returned error code " + (int)err);
return;
}
logln("With default = en_US...");
logln(" In default locale...");
doTestDisplayNames(empty, DLANG_EN, FALSE);
logln(" In locale = en_US...");
doTestDisplayNames(english, DLANG_EN, FALSE);
doTestDisplayNames(english, DLANG_EN);
logln(" In locale = fr_FR...");
doTestDisplayNames(french, DLANG_FR, FALSE);
doTestDisplayNames(french, DLANG_FR);
logln(" In locale = hr_HR...");
doTestDisplayNames(croatian, DLANG_HR, FALSE);
doTestDisplayNames(croatian, DLANG_HR);
logln(" In locale = el_GR...");
doTestDisplayNames(greek, DLANG_EL, FALSE);
doTestDisplayNames(greek, DLANG_EL);
Locale::setDefault(french, err);
if (U_FAILURE(err)) {
errln("Locale::setDefault returned error code " + (int)err);
return;
}
logln("With default = fr_FR...");
logln(" In default locale...");
doTestDisplayNames(empty, DLANG_FR, TRUE);
logln(" In locale = en_US...");
doTestDisplayNames(english, DLANG_EN, TRUE);
logln(" In locale = fr_FR...");
doTestDisplayNames(french, DLANG_FR, TRUE);
logln(" In locale = hr_HR...");
doTestDisplayNames(croatian, DLANG_HR, TRUE);
logln(" In locale = el_GR...");
doTestDisplayNames(greek, DLANG_EL, TRUE);
Locale::setDefault(saveDefault, err);
if (U_FAILURE(err)) {
errln("Locale::setDefault returned error code " + (int)err);
return;
/* test that the default locale has a display name for its own language */
UnicodeString s;
Locale().getDisplayName(Locale(), s);
if(s.length()<=3) {
/* check <=3 to reject getting the language code as a display name */
errln("unable to get a display string for the language of the default locale\n");
}
}
@ -655,16 +633,9 @@ void LocaleTest::TestDataDirectory()
//===========================================================
void LocaleTest::doTestDisplayNames(Locale& inLocale,
int32_t compareIndex,
UBool defaultIsFrench) {
void LocaleTest::doTestDisplayNames(Locale& displayLocale, int32_t compareIndex) {
UnicodeString temp;
if (defaultIsFrench && (temp=Locale::getDefault().getLanguage()) != "fr")
errln("Default locale should be French, but it's really " + temp);
else if (!defaultIsFrench && (temp=Locale::getDefault().getLanguage()) != "en")
errln("Default locale should be English, but it's really " + temp);
for (int32_t i = 0; i <= MAX_LOCALES; i++) {
Locale testLocale(rawData[LANG][i], rawData[CTRY][i], rawData[VAR][i]);
logln(" Testing " + (temp=testLocale.getName()) + "...");
@ -674,18 +645,10 @@ void LocaleTest::doTestDisplayNames(Locale& inLocale,
UnicodeString testVar;
UnicodeString testName;
if (inLocale == Locale("", "", "")) {
testLocale.getDisplayLanguage(testLang);
testLocale.getDisplayCountry(testCtry);
testLocale.getDisplayVariant(testVar);
testLocale.getDisplayName(testName);
}
else {
testLocale.getDisplayLanguage(inLocale, testLang);
testLocale.getDisplayCountry(inLocale, testCtry);
testLocale.getDisplayVariant(inLocale, testVar);
testLocale.getDisplayName(inLocale, testName);
}
testLocale.getDisplayLanguage(displayLocale, testLang);
testLocale.getDisplayCountry(displayLocale, testCtry);
testLocale.getDisplayVariant(displayLocale, testVar);
testLocale.getDisplayName(displayLocale, testName);
UnicodeString expectedLang;
UnicodeString expectedCtry;
@ -693,37 +656,29 @@ void LocaleTest::doTestDisplayNames(Locale& inLocale,
UnicodeString expectedName;
expectedLang = dataTable[compareIndex][i];
if (expectedLang.length() == 0 && defaultIsFrench)
expectedLang = dataTable[DLANG_FR][i];
if (expectedLang.length() == 0)
expectedLang = dataTable[DLANG_EN][i];
expectedCtry = dataTable[compareIndex + 1][i];
if ((expectedCtry.length() == 0) && defaultIsFrench)
expectedCtry = dataTable[DCTRY_FR][i];
if (expectedCtry.length() == 0)
expectedCtry = dataTable[DCTRY_EN][i];
expectedVar = dataTable[compareIndex + 2][i];
if (expectedVar.length() == 0 && defaultIsFrench)
expectedVar = dataTable[DVAR_FR][i];
if (expectedVar.length() == 0)
expectedVar = dataTable[DVAR_EN][i];
expectedName = dataTable[compareIndex + 3][i];
if (expectedName.length() == 0 && defaultIsFrench)
expectedName = dataTable[DNAME_FR][i];
if (expectedName.length() == 0)
expectedName = dataTable[DNAME_EN][i];
if (testLang != expectedLang)
errln("Display language (" + UnicodeString(inLocale.getName()) + ") mismatch: " + testLang + " versus " + expectedLang);
errln("Display language (" + UnicodeString(displayLocale.getName()) + ") got " + testLang + " expected " + expectedLang);
if (testCtry != expectedCtry)
errln("Display country (" + UnicodeString(inLocale.getName()) + ") mismatch: " + testCtry + " versus " + expectedCtry + (defaultIsFrench?UnicodeString("French"):UnicodeString("_")) );
errln("Display country (" + UnicodeString(displayLocale.getName()) + ") got " + testCtry + " expected " + expectedCtry);
if (testVar != expectedVar)
errln("Display variant (" + UnicodeString(inLocale.getName()) + ") mismatch: " + testVar + " versus " + expectedVar);
errln("Display variant (" + UnicodeString(displayLocale.getName()) + ") got " + testVar + " expected " + expectedVar);
if (testName != expectedName)
errln("Display name (" + UnicodeString(inLocale.getName()) + ") mismatch: " + testName + " versus " + expectedName);
errln("Display name (" + UnicodeString(displayLocale.getName()) + ") got " + testName + " expected " + expectedName);
}
}

View file

@ -84,7 +84,7 @@ private:
/**
* routine to perform subtests, used by TestDisplayNames
**/
void doTestDisplayNames(Locale& inLocale, int32_t compareIndex, UBool defaultIsFrench);
void doTestDisplayNames(Locale& inLocale, int32_t compareIndex);
/**
* additional intialization for datatables storing expected values
**/