From f1a8a63f067c82ac8225f22ab63e92050ce6fbe8 Mon Sep 17 00:00:00 2001 From: Frank Tang Date: Thu, 8 Oct 2020 00:25:34 +0000 Subject: [PATCH] ICU-21316 Fix bug under different default locales See #1399 --- icu4c/source/common/locid.cpp | 5 ++++- icu4c/source/i18n/ulocdata.cpp | 2 +- icu4c/source/test/cintltst/cloctst.c | 14 ++++++++++++-- icu4c/source/test/cintltst/crestst.c | 20 ++++++++++++++++---- icu4c/source/test/cintltst/creststn.c | 18 ++++++++++++++++++ 5 files changed, 51 insertions(+), 8 deletions(-) diff --git a/icu4c/source/common/locid.cpp b/icu4c/source/common/locid.cpp index a00a7ab50d1e..2804e36bf62c 100644 --- a/icu4c/source/common/locid.cpp +++ b/icu4c/source/common/locid.cpp @@ -1333,7 +1333,10 @@ AliasReplacer::replaceTerritory(UVector& toBeFreed, UErrorCode& status) if (firstSpace != nullptr) { // If there are are more than one region in the replacement. // We need to check which one match based on the language. - Locale l(language, nullptr, script); + // Cannot use nullptr for language because that will construct + // the default locale, in that case, use "und" to get the correct + // locale. + Locale l(language == nullptr ? "und" : language, nullptr, script); l.addLikelySubtags(status); const char* likelyRegion = l.getCountry(); CharString* item = nullptr; diff --git a/icu4c/source/i18n/ulocdata.cpp b/icu4c/source/i18n/ulocdata.cpp index 7f4e7b9b116e..68b9e0cf6344 100644 --- a/icu4c/source/i18n/ulocdata.cpp +++ b/icu4c/source/i18n/ulocdata.cpp @@ -172,7 +172,7 @@ ulocdata_getDelimiter(ULocaleData *uld, ULocaleDataDelimiterType type, return 0; } - delimiter = ures_getStringByKey(delimiterBundle, delimiterKeys[type], &len, &localStatus); + delimiter = ures_getStringByKeyWithFallback(delimiterBundle, delimiterKeys[type], &len, &localStatus); ures_close(delimiterBundle); if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) { diff --git a/icu4c/source/test/cintltst/cloctst.c b/icu4c/source/test/cintltst/cloctst.c index 63a8d1139869..373c2d5fe83e 100644 --- a/icu4c/source/test/cintltst/cloctst.c +++ b/icu4c/source/test/cintltst/cloctst.c @@ -704,9 +704,19 @@ static void TestDisplayNames() /* test that the default locale has a display name for its own language */ errorCode=U_ZERO_ERROR; length=uloc_getDisplayLanguage(NULL, NULL, buffer, UPRV_LENGTHOF(buffer), &errorCode); + /* check <=3 to reject getting the language code as a display name */ if(U_FAILURE(errorCode) || (length<=3 && buffer[0]<=0x7f)) { - /* check <=3 to reject getting the language code as a display name */ - log_data_err("unable to get a display string for the language of the default locale - %s (Are you missing data?)\n", u_errorName(errorCode)); + const char* defaultLocale = uloc_getDefault(); + for (int32_t i = 0, count = uloc_countAvailable(); i < count; i++) { + /* Only report error if the default locale is in the available list */ + if (uprv_strcmp(defaultLocale, uloc_getAvailable(i)) == 0) { + log_data_err( + "unable to get a display string for the language of the " + "default locale - %s (Are you missing data?)\n", + u_errorName(errorCode)); + break; + } + } } /* test that we get the language code itself for an unknown language, and a default warning */ diff --git a/icu4c/source/test/cintltst/crestst.c b/icu4c/source/test/cintltst/crestst.c index b7af6eacd7f0..080301090d1d 100644 --- a/icu4c/source/test/cintltst/crestst.c +++ b/icu4c/source/test/cintltst/crestst.c @@ -149,6 +149,15 @@ void TestAliasConflict(void) { void TestResourceBundles() { + // The test expectation only works if the default locale is not one of the + // locale bundle in the testdata which have those info. Therefore, we skip + // the test if the default locale is te, sh, mc, or them with subtags. + if ( uprv_strncmp(uloc_getDefault(), "te", 2) == 0 || + uprv_strncmp(uloc_getDefault(), "sh", 2) == 0 || + uprv_strncmp(uloc_getDefault(), "mc", 2) == 0) { + return; + } + UErrorCode status = U_ZERO_ERROR; loadTestData(&status); if(U_FAILURE(status)) { @@ -595,16 +604,19 @@ TestOpenDirect(void) { ures_close(casing); /* - * verify that ures_open("ne") finds the root bundle but - * ures_openDirect("ne") does not + * verify that ures_open("ne") finds the root bundle or default locale + * bundle but ures_openDirect("ne") does not. */ errorCode=U_ZERO_ERROR; ne=ures_open("testdata", "ne", &errorCode); if(U_FAILURE(errorCode)) { log_data_err("ures_open(\"ne\") failed (expected to get root): %s\n", u_errorName(errorCode)); } - if(errorCode!=U_USING_DEFAULT_WARNING || 0!=uprv_strcmp("root", ures_getLocale(ne, &errorCode))) { - log_err("ures_open(\"ne\") found something other than \"root\" - %s\n", u_errorName(errorCode)); + if( errorCode!=U_USING_DEFAULT_WARNING || + (0!=uprv_strcmp("root", ures_getLocale(ne, &errorCode)) && + 0!=uprv_strcmp(uloc_getDefault(), ures_getLocale(ne, &errorCode)))) { + log_err("ures_open(\"ne\") found something other than \"root\" " + "or default locale \"%s\" - %s\n", uloc_getDefault(), u_errorName(errorCode)); } ures_close(ne); diff --git a/icu4c/source/test/cintltst/creststn.c b/icu4c/source/test/cintltst/creststn.c index 88ea652f049a..3155172029c9 100644 --- a/icu4c/source/test/cintltst/creststn.c +++ b/icu4c/source/test/cintltst/creststn.c @@ -1509,6 +1509,15 @@ static void TestGetVersionColl(){ static void TestResourceBundles() { + // The test expectation only works if the default locale is not one of the + // locale bundle in the testdata which have those info. Therefore, we skip + // the test if the default locale is te, sh, mc, or them with subtags. + if ( uprv_strncmp(uloc_getDefault(), "te", 2) == 0 || + uprv_strncmp(uloc_getDefault(), "sh", 2) == 0 || + uprv_strncmp(uloc_getDefault(), "mc", 2) == 0) { + return; + } + UErrorCode status = U_ZERO_ERROR; loadTestData(&status); if(U_FAILURE(status)) { @@ -1532,6 +1541,15 @@ static void TestResourceBundles() static void TestConstruction1() { + // The test expectation only works if the default locale is not one of the + // locale bundle in the testdata which have those info. Therefore, we skip + // the test if the default locale is te, sh, mc, or them with subtags. + if ( uprv_strncmp(uloc_getDefault(), "te", 2) == 0 || + uprv_strncmp(uloc_getDefault(), "sh", 2) == 0 || + uprv_strncmp(uloc_getDefault(), "mc", 2) == 0) { + return; + } + UResourceBundle *test1 = 0, *test2 = 0,*empty = 0; const UChar *result1, *result2; UErrorCode status= U_ZERO_ERROR;