diff --git a/icu4c/source/i18n/nfrule.cpp b/icu4c/source/i18n/nfrule.cpp index a2eb9d01cc8..f8ed0b6c35f 100644 --- a/icu4c/source/i18n/nfrule.cpp +++ b/icu4c/source/i18n/nfrule.cpp @@ -54,7 +54,6 @@ NFRule::~NFRule() static const UChar gLeftBracket = 0x005b; static const UChar gRightBracket = 0x005d; -static const UChar gClosedParenthesis = 0x0029; static const UChar gColon = 0x003a; static const UChar gZero = 0x0030; static const UChar gNine = 0x0039; @@ -74,6 +73,7 @@ static const UChar gXDotZero[] = {0x78, 0x2E, 0x30, 0}; /* "x.0" static const UChar gZeroDotX[] = {0x30, 0x2E, 0x78, 0}; /* "0.x" */ static const UChar gDollarOpenParenthesis[] = {0x24, 0x28, 0}; /* "$(" */ +static const UChar gClosedParenthesisDollar[] = {0x29, 0x24, 0}; /* ")$" */ static const UChar gLessLess[] = {0x3C, 0x3C, 0}; /* "<<" */ static const UChar gLessPercent[] = {0x3C, 0x25, 0}; /* "<%" */ @@ -394,7 +394,7 @@ NFRule::extractSubstitutions(const NFRuleSet* ruleSet, sub2 = extractSubstitution(ruleSet, predecessor, status); } int32_t pluralRuleStart = this->ruleText.indexOf(gDollarOpenParenthesis, -1, 0); - int32_t pluralRuleEnd = (pluralRuleStart >= 0 ? this->ruleText.indexOf(gClosedParenthesis, pluralRuleStart) : -1); + int32_t pluralRuleEnd = (pluralRuleStart >= 0 ? this->ruleText.indexOf(gClosedParenthesisDollar, -1, pluralRuleStart) : -1); if (pluralRuleEnd >= 0) { int32_t endType = this->ruleText.indexOf(gComma, pluralRuleStart); if (endType < 0) { @@ -696,10 +696,10 @@ NFRule::doFormat(int64_t number, UnicodeString& toInsertInto, int32_t pos, UErro } else { pluralRuleStart = ruleText.indexOf(gDollarOpenParenthesis, -1, 0); - int pluralRuleEnd = ruleText.indexOf(gClosedParenthesis, pluralRuleStart); + int pluralRuleEnd = ruleText.indexOf(gClosedParenthesisDollar, -1, pluralRuleStart); int initialLength = toInsertInto.length(); if (pluralRuleEnd < ruleText.length() - 1) { - toInsertInto.insert(pos, ruleText.tempSubString(pluralRuleEnd + 1)); + toInsertInto.insert(pos, ruleText.tempSubString(pluralRuleEnd + 2)); } toInsertInto.insert(pos, rulePatternFormat->format((int32_t)(number/uprv_pow(radix, exponent)), status)); @@ -742,10 +742,10 @@ NFRule::doFormat(double number, UnicodeString& toInsertInto, int32_t pos, UError } else { pluralRuleStart = ruleText.indexOf(gDollarOpenParenthesis, -1, 0); - int pluralRuleEnd = ruleText.indexOf(gClosedParenthesis, pluralRuleStart); + int pluralRuleEnd = ruleText.indexOf(gClosedParenthesisDollar, -1, pluralRuleStart); int initialLength = toInsertInto.length(); if (pluralRuleEnd < ruleText.length() - 1) { - toInsertInto.insert(pos, ruleText.tempSubString(pluralRuleEnd + 1)); + toInsertInto.insert(pos, ruleText.tempSubString(pluralRuleEnd + 2)); } toInsertInto.insert(pos, rulePatternFormat->format((int32_t)(number/uprv_pow(radix, exponent)), status)); @@ -1400,7 +1400,7 @@ NFRule::findText(const UnicodeString& str, int start = position.getBeginIndex(); if (start >= 0) { int32_t pluralRuleStart = ruleText.indexOf(gDollarOpenParenthesis, -1, 0); - int32_t pluralRuleSuffix = ruleText.indexOf(gClosedParenthesis, pluralRuleStart) + 1; + int32_t pluralRuleSuffix = ruleText.indexOf(gClosedParenthesisDollar, -1, pluralRuleStart) + 2; int32_t matchLen = position.getEndIndex() - start; UnicodeString prefix(ruleText.tempSubString(0, pluralRuleStart)); UnicodeString suffix(ruleText.tempSubString(pluralRuleSuffix)); diff --git a/icu4c/source/i18n/unicode/rbnf.h b/icu4c/source/i18n/unicode/rbnf.h index f3b4ff103b1..398454b2877 100644 --- a/icu4c/source/i18n/unicode/rbnf.h +++ b/icu4c/source/i18n/unicode/rbnf.h @@ -431,7 +431,7 @@ enum URBNFRuleSetTag { * Omit the optional text if multiplying the number by the rule's base value yields 1. * * - * $(cardinal,plural syntax) + * $(cardinal,plural syntax)$ * * in all rule sets * This provides the ability to choose a word based on the number divided by the radix to the power of the @@ -440,7 +440,7 @@ enum URBNFRuleSetTag { * as the same base value for parsing. * * - * $(ordinal,plural syntax) + * $(ordinal,plural syntax)$ * * in all rule sets * This provides the ability to choose a word based on the number divided by the radix to the power of the diff --git a/icu4c/source/test/intltest/itrbnf.cpp b/icu4c/source/test/intltest/itrbnf.cpp index 8830258a61f..64b94b76971 100644 --- a/icu4c/source/test/intltest/itrbnf.cpp +++ b/icu4c/source/test/intltest/itrbnf.cpp @@ -1961,7 +1961,7 @@ IntlTestRBNF::TestSetDecimalFormatSymbols() { void IntlTestRBNF::TestPluralRules() { UErrorCode status = U_ZERO_ERROR; - UnicodeString enRules("%digits-ordinal:-x: −>>;0: =#,##0=$(ordinal,one{st}two{nd}few{rd}other{th});"); + UnicodeString enRules("%digits-ordinal:-x: −>>;0: =#,##0=$(ordinal,one{st}two{nd}few{rd}other{th})$;"); UParseError parseError; RuleBasedNumberFormat enFormatter(enRules, Locale::getEnglish(), parseError, status); if (U_FAILURE(status)) { @@ -2023,8 +2023,8 @@ void IntlTestRBNF::TestPluralRules() { "200: << hundred[ >>];" "300: << hundreds[ >>];" "500: << hundredss[ >>];" - "1000: << $(cardinal,one{thousand}few{thousands}other{thousandss})[ >>];" - "1000000: << $(cardinal,one{million}few{millions}other{millionss})[ >>];"); + "1000: << $(cardinal,one{thousand}few{thousands}other{thousandss})$[ >>];" + "1000000: << $(cardinal,one{million}few{millions}other{millionss})$[ >>];"); RuleBasedNumberFormat ruFormatter(ruRules, Locale("ru"), parseError, status); const char* const ruTestData[][2] = { { "1", "one" }, @@ -2041,6 +2041,7 @@ void IntlTestRBNF::TestPluralRules() { { "11,000", "eleven thousandss" }, { "21,000", "twenty-one thousand" }, { "22,000", "twenty-two thousands" }, + { "25,001", "twenty-five thousandss one" }, { NULL, NULL } };