ICU-12760 support UDISPCTX_TYPE_SUBSTITUTE_HANDLING

add tests

remove printf

fix localeDisplayName and add tests

fix fallback

remove get
This commit is contained in:
Frank Tang 2019-05-10 18:38:35 -07:00 committed by Frank Yung-Fong Tang
parent 14649a41f4
commit 53dd621e3a
3 changed files with 238 additions and 20 deletions

View file

@ -291,6 +291,7 @@ class LocaleDisplayNamesImpl : public LocaleDisplayNames {
UnicodeString formatCloseParen;
UnicodeString formatReplaceCloseParen;
UDisplayContext nameLength;
UDisplayContext substitute;
// Constants for capitalization context usage types.
enum CapContextUsage {
@ -337,7 +338,7 @@ public:
UnicodeString& result) const;
private:
UnicodeString& localeIdName(const char* localeId,
UnicodeString& result) const;
UnicodeString& result, bool substitute) const;
UnicodeString& appendWithSep(UnicodeString& buffer, const UnicodeString& src) const;
UnicodeString& adjustForUsageAndContext(CapContextUsage usage, UnicodeString& result) const;
UnicodeString& scriptDisplayName(const char* script, UnicodeString& result, UBool skipAdjust) const;
@ -359,6 +360,7 @@ LocaleDisplayNamesImpl::LocaleDisplayNamesImpl(const Locale& locale,
, capitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
, capitalizationBrkIter(NULL)
, nameLength(UDISPCTX_LENGTH_FULL)
, substitute(UDISPCTX_SUBSTITUTE)
{
initialize();
}
@ -371,6 +373,7 @@ LocaleDisplayNamesImpl::LocaleDisplayNamesImpl(const Locale& locale,
, capitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
, capitalizationBrkIter(NULL)
, nameLength(UDISPCTX_LENGTH_FULL)
, substitute(UDISPCTX_SUBSTITUTE)
{
while (length-- > 0) {
UDisplayContext value = *contexts++;
@ -385,6 +388,9 @@ LocaleDisplayNamesImpl::LocaleDisplayNamesImpl(const Locale& locale,
case UDISPCTX_TYPE_DISPLAY_LENGTH:
nameLength = value;
break;
case UDISPCTX_TYPE_SUBSTITUTE_HANDLING:
substitute = value;
break;
default:
break;
}
@ -535,6 +541,8 @@ LocaleDisplayNamesImpl::getContext(UDisplayContextType type) const {
return capitalizationContext;
case UDISPCTX_TYPE_DISPLAY_LENGTH:
return nameLength;
case UDISPCTX_TYPE_SUBSTITUTE_HANDLING:
return substitute;
default:
break;
}
@ -583,7 +591,7 @@ LocaleDisplayNamesImpl::localeDisplayName(const Locale& loc,
do { // loop construct is so we can break early out of search
if (hasScript && hasCountry) {
ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", script, "_", country, (char *)0);
localeIdName(buffer, resultName);
localeIdName(buffer, resultName, false);
if (!resultName.isBogus()) {
hasScript = FALSE;
hasCountry = FALSE;
@ -592,7 +600,7 @@ LocaleDisplayNamesImpl::localeDisplayName(const Locale& loc,
}
if (hasScript) {
ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", script, (char *)0);
localeIdName(buffer, resultName);
localeIdName(buffer, resultName, false);
if (!resultName.isBogus()) {
hasScript = FALSE;
break;
@ -600,7 +608,7 @@ LocaleDisplayNamesImpl::localeDisplayName(const Locale& loc,
}
if (hasCountry) {
ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", country, (char*)0);
localeIdName(buffer, resultName);
localeIdName(buffer, resultName, false);
if (!resultName.isBogus()) {
hasCountry = FALSE;
break;
@ -609,7 +617,11 @@ LocaleDisplayNamesImpl::localeDisplayName(const Locale& loc,
} while (FALSE);
}
if (resultName.isBogus() || resultName.isEmpty()) {
localeIdName(lang, resultName);
localeIdName(lang, resultName, substitute == UDISPCTX_SUBSTITUTE);
if (resultName.isBogus()) {
result.setToBogus();
return result;
}
}
UnicodeString resultRemainder;
@ -617,13 +629,28 @@ LocaleDisplayNamesImpl::localeDisplayName(const Locale& loc,
UErrorCode status = U_ZERO_ERROR;
if (hasScript) {
resultRemainder.append(scriptDisplayName(script, temp, TRUE));
UnicodeString script_str = scriptDisplayName(script, temp, TRUE);
if (script_str.isBogus()) {
result.setToBogus();
return result;
}
resultRemainder.append(script_str);
}
if (hasCountry) {
appendWithSep(resultRemainder, regionDisplayName(country, temp, TRUE));
UnicodeString region_str = regionDisplayName(country, temp, TRUE);
if (region_str.isBogus()) {
result.setToBogus();
return result;
}
appendWithSep(resultRemainder, region_str);
}
if (hasVariant) {
appendWithSep(resultRemainder, variantDisplayName(variant, temp, TRUE));
UnicodeString variant_str = variantDisplayName(variant, temp, TRUE);
if (variant_str.isBogus()) {
result.setToBogus();
return result;
}
appendWithSep(resultRemainder, variant_str);
}
resultRemainder.findAndReplace(formatOpenParen, formatReplaceOpenParen);
resultRemainder.findAndReplace(formatCloseParen, formatReplaceCloseParen);
@ -689,14 +716,18 @@ LocaleDisplayNamesImpl::localeDisplayName(const char* localeId,
// private
UnicodeString&
LocaleDisplayNamesImpl::localeIdName(const char* localeId,
UnicodeString& result) const {
UnicodeString& result, bool substitute) const {
if (nameLength == UDISPCTX_LENGTH_SHORT) {
langData.getNoFallback("Languages%short", localeId, result);
if (!result.isBogus()) {
return result;
}
}
return langData.getNoFallback("Languages", localeId, result);
if (substitute) {
return langData.get("Languages", localeId, result);
} else {
return langData.getNoFallback("Languages", localeId, result);
}
}
UnicodeString&
@ -706,12 +737,16 @@ LocaleDisplayNamesImpl::languageDisplayName(const char* lang,
return result = UnicodeString(lang, -1, US_INV);
}
if (nameLength == UDISPCTX_LENGTH_SHORT) {
langData.get("Languages%short", lang, result);
langData.getNoFallback("Languages%short", lang, result);
if (!result.isBogus()) {
return adjustForUsageAndContext(kCapContextUsageLanguage, result);
}
}
langData.get("Languages", lang, result);
if (substitute == UDISPCTX_SUBSTITUTE) {
langData.get("Languages", lang, result);
} else {
langData.getNoFallback("Languages", lang, result);
}
return adjustForUsageAndContext(kCapContextUsageLanguage, result);
}
@ -720,12 +755,16 @@ LocaleDisplayNamesImpl::scriptDisplayName(const char* script,
UnicodeString& result,
UBool skipAdjust) const {
if (nameLength == UDISPCTX_LENGTH_SHORT) {
langData.get("Scripts%short", script, result);
langData.getNoFallback("Scripts%short", script, result);
if (!result.isBogus()) {
return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageScript, result);
}
}
langData.get("Scripts", script, result);
if (substitute == UDISPCTX_SUBSTITUTE) {
langData.get("Scripts", script, result);
} else {
langData.getNoFallback("Scripts", script, result);
}
return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageScript, result);
}
@ -746,12 +785,16 @@ LocaleDisplayNamesImpl::regionDisplayName(const char* region,
UnicodeString& result,
UBool skipAdjust) const {
if (nameLength == UDISPCTX_LENGTH_SHORT) {
regionData.get("Countries%short", region, result);
regionData.getNoFallback("Countries%short", region, result);
if (!result.isBogus()) {
return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageTerritory, result);
}
}
regionData.get("Countries", region, result);
if (substitute == UDISPCTX_SUBSTITUTE) {
regionData.get("Countries", region, result);
} else {
regionData.getNoFallback("Countries", region, result);
}
return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageTerritory, result);
}
@ -767,7 +810,11 @@ LocaleDisplayNamesImpl::variantDisplayName(const char* variant,
UnicodeString& result,
UBool skipAdjust) const {
// don't have a resource for short variant names
langData.get("Variants", variant, result);
if (substitute == UDISPCTX_SUBSTITUTE) {
langData.get("Variants", variant, result);
} else {
langData.getNoFallback("Variants", variant, result);
}
return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageVariant, result);
}
@ -782,7 +829,11 @@ LocaleDisplayNamesImpl::keyDisplayName(const char* key,
UnicodeString& result,
UBool skipAdjust) const {
// don't have a resource for short key names
langData.get("Keys", key, result);
if (substitute == UDISPCTX_SUBSTITUTE) {
langData.get("Keys", key, result);
} else {
langData.getNoFallback("Keys", key, result);
}
return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageKey, result);
}
@ -815,12 +866,16 @@ LocaleDisplayNamesImpl::keyValueDisplayName(const char* key,
}
if (nameLength == UDISPCTX_LENGTH_SHORT) {
langData.get("Types%short", key, value, result);
langData.getNoFallback("Types%short", key, value, result);
if (!result.isBogus()) {
return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageKeyValue, result);
}
}
langData.get("Types", key, value, result);
if (substitute == UDISPCTX_SUBSTITUTE) {
langData.get("Types", key, value, result);
} else {
langData.getNoFallback("Types", key, value, result);
}
return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageKeyValue, result);
}

View file

@ -82,6 +82,7 @@ void LocaleDisplayNamesTest::runIndexedTest(int32_t index, UBool exec, const cha
TESTCASE(11, TestPrivateUse);
TESTCASE(12, TestUldnDisplayContext);
TESTCASE(13, TestUldnWithGarbage);
TESTCASE(14, TestSubstituteHandling);
#endif
default:
name = "";
@ -422,4 +423,161 @@ void LocaleDisplayNamesTest::TestRootEtc() {
delete ldn;
}
static const char unknown_region[] = "wx";
static const char unknown_lang[] = "xy";
static const char unknown_script[] = "wxyz";
static const char unknown_variant[] = "abc";
static const char unknown_key[] = "efg";
static const char unknown_ca_value[] = "ijk";
static const char known_lang_unknown_script[] = "en-wxyz";
static const char unknown_lang_unknown_script[] = "xy-wxyz";
static const char unknown_lang_known_script[] = "xy-Latn";
static const char unknown_lang_unknown_region[] = "xy-wx";
static const char known_lang_unknown_region[] = "en-wx";
static const char unknown_lang_known_region[] = "xy-US";
static const char unknown_lang_unknown_script_unknown_region[] = "xy-wxyz-wx";
static const char known_lang_unknown_script_unknown_region[] = "en-wxyz-wx";
static const char unknown_lang_known_script_unknown_region[] = "xy-Latn-wx";
static const char unknown_lang_known_script_known_region[] = "xy-wxyz-US";
static const char known_lang[] = "en";
static const char known_lang_known_script[] = "en-Latn";
static const char known_lang_known_region[] = "en-US";
static const char known_lang_known_script_known_region[] = "en-Latn-US";
void LocaleDisplayNamesTest::VerifySubstitute(LocaleDisplayNames* ldn) {
UnicodeString temp;
// Ensure the default is UDISPCTX_SUBSTITUTE
UDisplayContext context = ldn->getContext(UDISPCTX_TYPE_SUBSTITUTE_HANDLING);
test_assert(UDISPCTX_SUBSTITUTE == context);
ldn->regionDisplayName(unknown_region, temp);
test_assert_equal(unknown_region, temp);
ldn->languageDisplayName(unknown_lang, temp);
test_assert_equal(unknown_lang, temp);
ldn->scriptDisplayName(unknown_script, temp);
test_assert_equal(unknown_script, temp);
ldn->variantDisplayName(unknown_variant, temp);
test_assert_equal(unknown_variant, temp);
ldn->keyDisplayName(unknown_key, temp);
test_assert_equal(unknown_key, temp);
ldn->keyValueDisplayName("ca", unknown_ca_value, temp);
test_assert_equal(unknown_ca_value, temp);
ldn->localeDisplayName(unknown_lang, temp);
test_assert_equal(unknown_lang, temp);
ldn->localeDisplayName(known_lang_unknown_script, temp);
test_assert_equal("Englisch (Wxyz)", temp);
ldn->localeDisplayName(unknown_lang_unknown_script, temp);
test_assert_equal("xy (Wxyz)", temp);
ldn->localeDisplayName(unknown_lang_known_script, temp);
test_assert_equal("xy (Lateinisch)", temp);
ldn->localeDisplayName(unknown_lang_unknown_region, temp);
test_assert_equal("xy (WX)", temp);
ldn->localeDisplayName(known_lang_unknown_region, temp);
test_assert_equal("Englisch (WX)", temp);
ldn->localeDisplayName(unknown_lang_known_region, temp);
test_assert_equal("xy (Vereinigte Staaten)", temp);
ldn->localeDisplayName(unknown_lang_unknown_script_unknown_region, temp);
test_assert_equal("xy (Wxyz, WX)", temp);
ldn->localeDisplayName(known_lang_unknown_script_unknown_region, temp);
test_assert_equal("Englisch (Wxyz, WX)", temp);
ldn->localeDisplayName(unknown_lang_known_script_unknown_region, temp);
test_assert_equal("xy (Lateinisch, WX)", temp);
ldn->localeDisplayName(unknown_lang_known_script_known_region, temp);
test_assert_equal("xy (Wxyz, Vereinigte Staaten)", temp);
ldn->localeDisplayName(known_lang, temp);
test_assert_equal("Englisch", temp);
ldn->localeDisplayName(known_lang_known_script, temp);
test_assert_equal("Englisch (Lateinisch)", temp);
ldn->localeDisplayName(known_lang_known_region, temp);
test_assert_equal("Englisch (Vereinigte Staaten)", temp);
ldn->localeDisplayName(known_lang_known_script_known_region, temp);
test_assert_equal("Englisch (Lateinisch, Vereinigte Staaten)", temp);
}
void LocaleDisplayNamesTest::VerifyNoSubstitute(LocaleDisplayNames* ldn) {
UnicodeString temp("");
std::string utf8;
// Ensure the default is UDISPCTX_SUBSTITUTE
UDisplayContext context = ldn->getContext(UDISPCTX_TYPE_SUBSTITUTE_HANDLING);
test_assert(UDISPCTX_NO_SUBSTITUTE == context);
ldn->regionDisplayName(unknown_region, temp);
test_assert(TRUE == temp.isBogus());
ldn->languageDisplayName(unknown_lang, temp);
test_assert(TRUE == temp.isBogus());
ldn->scriptDisplayName(unknown_script, temp);
test_assert(TRUE == temp.isBogus());
ldn->variantDisplayName(unknown_variant, temp);
test_assert(TRUE == temp.isBogus());
ldn->keyDisplayName(unknown_key, temp);
test_assert(TRUE == temp.isBogus());
ldn->keyValueDisplayName("ca", unknown_ca_value, temp);
test_assert(TRUE == temp.isBogus());
ldn->localeDisplayName(unknown_lang, temp);
test_assert(TRUE == temp.isBogus());
ldn->localeDisplayName(known_lang_unknown_script, temp);
test_assert(TRUE == temp.isBogus());
ldn->localeDisplayName(unknown_lang_unknown_script, temp);
test_assert(TRUE == temp.isBogus());
ldn->localeDisplayName(unknown_lang_known_script, temp);
test_assert(TRUE == temp.isBogus());
ldn->localeDisplayName(unknown_lang_unknown_region, temp);
test_assert(TRUE == temp.isBogus());
ldn->localeDisplayName(known_lang_unknown_region, temp);
test_assert(TRUE == temp.isBogus());
ldn->localeDisplayName(unknown_lang_known_region, temp);
test_assert(TRUE == temp.isBogus());
ldn->localeDisplayName(unknown_lang_unknown_script_unknown_region, temp);
test_assert(TRUE == temp.isBogus());
ldn->localeDisplayName(known_lang_unknown_script_unknown_region, temp);
test_assert(TRUE == temp.isBogus());
ldn->localeDisplayName(unknown_lang_known_script_unknown_region, temp);
test_assert(TRUE == temp.isBogus());
ldn->localeDisplayName(unknown_lang_known_script_known_region, temp);
test_assert(TRUE == temp.isBogus());
ldn->localeDisplayName(known_lang, temp);
test_assert_equal("Englisch", temp);
ldn->localeDisplayName(known_lang_known_script, temp);
test_assert_equal("Englisch (Lateinisch)", temp);
ldn->localeDisplayName(known_lang_known_region, temp);
test_assert_equal("Englisch (Vereinigte Staaten)", temp);
ldn->localeDisplayName(known_lang_known_script_known_region, temp);
test_assert_equal("Englisch (Lateinisch, Vereinigte Staaten)", temp);
}
void LocaleDisplayNamesTest::TestSubstituteHandling() {
// With substitute as default
logln("Context: none\n");
std::unique_ptr<LocaleDisplayNames> ldn(LocaleDisplayNames::createInstance(Locale::getGermany()));
VerifySubstitute(ldn.get());
// With explicit set substitute, and standard names
logln("Context: UDISPCTX_SUBSTITUTE, UDISPCTX_STANDARD_NAMES\n");
UDisplayContext context_1[] = { UDISPCTX_SUBSTITUTE, UDISPCTX_STANDARD_NAMES };
ldn.reset(LocaleDisplayNames::createInstance(Locale::getGermany(), context_1, 2));
VerifySubstitute(ldn.get());
// With explicit set substitute and dialect names
logln("Context: UDISPCTX_SUBSTITUTE, UDISPCTX_DIALECT_NAMES\n");
UDisplayContext context_2[] = { UDISPCTX_SUBSTITUTE, UDISPCTX_DIALECT_NAMES };
ldn.reset(LocaleDisplayNames::createInstance(Locale::getGermany(), context_2, 2));
VerifySubstitute(ldn.get());
// With explicit set no_substitute, and standard names
logln("Context: UDISPCTX_NO_SUBSTITUTE, UDISPCTX_STANDARD_NAMES\n");
UDisplayContext context_3[] = { UDISPCTX_NO_SUBSTITUTE, UDISPCTX_STANDARD_NAMES };
ldn.reset(LocaleDisplayNames::createInstance(Locale::getGermany(), context_3, 2));
VerifyNoSubstitute(ldn.get());
// With explicit set no_substitute and dialect names
logln("Context: UDISPCTX_NO_SUBSTITUTE, UDISPCTX_DIALECT_NAMES\n");
UDisplayContext context_4[] = { UDISPCTX_NO_SUBSTITUTE, UDISPCTX_DIALECT_NAMES };
ldn.reset(LocaleDisplayNames::createInstance(Locale::getGermany(), context_4, 2));
VerifyNoSubstitute(ldn.get());
}
#endif /* UCONFIG_NO_FORMATTING */

View file

@ -37,5 +37,10 @@ public:
void TestPrivateUse(void);
void TestUldnDisplayContext(void);
void TestUldnWithGarbage(void);
void TestSubstituteHandling(void);
void VerifySubstitute(LocaleDisplayNames* ldn);
void VerifyNoSubstitute(LocaleDisplayNames* ldn);
#endif
};