ICU-11986 MeasureFormat unit display patterns need to fall back to the parent locales per plural form, not as a set; add MeasureFormatTest::TestIndividualPluralFallback(); fix RelativeDateTimeFormatterTest::TestSerbianFallback() test data

X-SVN-Rev: 38103
This commit is contained in:
Markus Scherer 2015-12-02 22:54:54 +00:00
parent 8b03bbc037
commit 5a7ff3049b
8 changed files with 85 additions and 45 deletions

View file

@ -241,10 +241,8 @@ struct UnitDataSink : public ResourceTableSink {
// The key must be one of the plural form strings. For example:
// one{"{0} hr"}
// other{"{0} hrs"}
if (!outer.hasPatterns) {
outer.cacheData.formatters[outer.unitIndex][outer.width].add(
key, value.getUnicodeString(errorCode), errorCode);
}
outer.cacheData.formatters[outer.unitIndex][outer.width].
addIfAbsent(key, value, errorCode);
}
}
UnitDataSink &outer;
@ -262,8 +260,6 @@ struct UnitDataSink : public ResourceTableSink {
if (U_FAILURE(errorCode)) { return NULL; }
outer.unitIndex = MeasureUnit::internalGetIndexForTypeAndSubtype(outer.type, key);
if (outer.unitIndex >= 0) {
outer.hasPatterns =
outer.cacheData.formatters[outer.unitIndex][outer.width].isValid();
return &outer.patternSink;
}
return NULL;
@ -316,7 +312,7 @@ struct UnitDataSink : public ResourceTableSink {
UnitDataSink(MeasureFormatCacheData &outputData)
: patternSink(*this), subtypeSink(*this), compoundSink(*this), typeSink(*this),
cacheData(outputData),
width(UMEASFMT_WIDTH_COUNT), type(NULL), unitIndex(0), hasPatterns(FALSE) {}
width(UMEASFMT_WIDTH_COUNT), type(NULL), unitIndex(0) {}
~UnitDataSink();
virtual void put(const char *key, const ResourceValue &value, UErrorCode &errorCode) {
// Handle aliases like
@ -388,9 +384,6 @@ struct UnitDataSink : public ResourceTableSink {
UMeasureFormatWidth width;
const char *type;
int32_t unitIndex;
/** True if we already have plural-form display patterns for width/type/unitIndex. */
UBool hasPatterns;
};
// Virtual destructors must be defined out of line.

View file

@ -5,6 +5,11 @@
******************************************************************************
* quantityformatter.cpp
*/
#include "unicode/utypes.h"
#if !UCONFIG_NO_FORMATTING
#include "quantityformatter.h"
#include "simplepatternformatter.h"
#include "uassert.h"
@ -15,9 +20,9 @@
#include "charstr.h"
#include "unicode/fmtable.h"
#include "unicode/fieldpos.h"
#include "resource.h"
#include "visibledigits.h"
#if !UCONFIG_NO_FORMATTING
#include "uassert.h"
U_NAMESPACE_BEGIN
@ -101,20 +106,25 @@ void QuantityFormatter::reset() {
}
}
UBool QuantityFormatter::add(
UBool QuantityFormatter::addIfAbsent(
const char *variant,
const UnicodeString &rawPattern,
const UnicodeString *rawPattern,
const ResourceValue *patternValue,
UErrorCode &status) {
if (U_FAILURE(status)) {
return FALSE;
}
int32_t pluralIndex = getPluralIndex(variant);
if (pluralIndex == -1) {
if (pluralIndex < 0) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return FALSE;
}
SimplePatternFormatter *newFmt =
new SimplePatternFormatter(rawPattern);
if (formatters[pluralIndex] != NULL) {
return TRUE;
}
const UnicodeString &pattern =
rawPattern != NULL ? *rawPattern : patternValue->getUnicodeString(status);
SimplePatternFormatter *newFmt = new SimplePatternFormatter(pattern);
if (newFmt == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return FALSE;
@ -124,7 +134,6 @@ UBool QuantityFormatter::add(
status = U_ILLEGAL_ARGUMENT_ERROR;
return FALSE;
}
delete formatters[pluralIndex];
formatters[pluralIndex] = newFmt;
return TRUE;
}
@ -135,6 +144,7 @@ UBool QuantityFormatter::isValid() const {
const SimplePatternFormatter *QuantityFormatter::getByVariant(
const char *variant) const {
U_ASSERT(isValid());
int32_t pluralIndex = getPluralIndex(variant);
if (pluralIndex == -1) {
pluralIndex = 0;

View file

@ -1,6 +1,6 @@
/*
******************************************************************************
* Copyright (C) 2014, International Business Machines
* Copyright (C) 2014-2015, International Business Machines
* Corporation and others. All Rights Reserved.
******************************************************************************
* quantityformatter.h
@ -14,6 +14,8 @@
#if !UCONFIG_NO_FORMATTING
#include "resource.h"
U_NAMESPACE_BEGIN
class SimplePatternFormatter;
@ -64,17 +66,30 @@ public:
void reset();
/**
* Adds a plural variant.
*
* @param variant "zero", "one", "two", "few", "many", "other"
* @param rawPattern the pattern for the variant e.g "{0} meters"
* @param status any error returned here.
* @return TRUE on success; FALSE if status was set to a non zero error.
*/
UBool add(
const char *variant,
const UnicodeString &rawPattern,
UErrorCode &status);
* Adds a plural variant if there is none yet for the plural form.
*
* @param variant "zero", "one", "two", "few", "many", "other"
* @param rawPattern the pattern for the variant e.g "{0} meters"
* @param status any error returned here.
* @return TRUE on success; FALSE if status was set to a non zero error.
*/
UBool addIfAbsent(const char *variant, const UnicodeString &rawPattern, UErrorCode &status) {
return addIfAbsent(variant, &rawPattern, NULL, status);
}
/**
* Adds a plural variant if there is none yet for the plural form.
* This version only calls ResourceValue::getString()
* if there is no template yet for the plural form.
*
* @param variant "zero", "one", "two", "few", "many", "other"
* @param rawPattern the pattern for the variant e.g "{0} meters"
* @param status any error returned here.
* @return TRUE on success; FALSE if status was set to a non zero error.
*/
UBool addIfAbsent(const char *variant, const ResourceValue &rawPattern, UErrorCode &status) {
return addIfAbsent(variant, NULL, &rawPattern, status);
}
/**
* returns TRUE if this object has at least the "other" variant.
@ -109,6 +124,12 @@ public:
UErrorCode &status) const;
private:
UBool addIfAbsent(
const char *variant,
const UnicodeString *rawPattern,
const ResourceValue *patternValue,
UErrorCode &status);
SimplePatternFormatter *formatters[6];
};

View file

@ -1,10 +1,10 @@
/*
******************************************************************************
* Copyright (C) 2014, International Business Machines Corporation and
* others. All Rights Reserved.
* Copyright (C) 2014-2015, International Business Machines Corporation and
* others. All Rights Reserved.
******************************************************************************
*
* File RELDATEFMT.CPP
*
* File reldatefmt.cpp
******************************************************************************
*/
@ -186,7 +186,7 @@ static void initQuantityFormatter(
if (!getString(pluralBundle.getAlias(), rawPattern, status)) {
return;
}
if (!formatter.add(
if (!formatter.addIfAbsent(
ures_getKey(pluralBundle.getAlias()),
rawPattern,
status)) {

View file

@ -124,6 +124,7 @@ void IntlTestUtilities::runIndexedTest( int32_t index, UBool exec, const char* &
LocalPointer<IntlTest> test(createQuantityFormatterTest());
callTest(*test, par);
}
break;
case 23:
name = "PluralMapTest";
if (exec) {

View file

@ -61,6 +61,7 @@ private:
void TestGroupingSeparator();
void TestDoubleZero();
void TestUnitPerUnitResolution();
void TestIndividualPluralFallback();
void verifyFormat(
const char *description,
const MeasureFormat &fmt,
@ -141,6 +142,7 @@ void MeasureFormatTest::runIndexedTest(
TESTCASE_AUTO(TestGroupingSeparator);
TESTCASE_AUTO(TestDoubleZero);
TESTCASE_AUTO(TestUnitPerUnitResolution);
TESTCASE_AUTO(TestIndividualPluralFallback);
TESTCASE_AUTO_END;
}
@ -1588,6 +1590,19 @@ void MeasureFormatTest::TestUnitPerUnitResolution() {
assertEquals("", "50 psi", actual);
}
void MeasureFormatTest::TestIndividualPluralFallback() {
// See ticket #11986 "incomplete fallback in MeasureFormat".
// In CLDR 28, fr_CA temperature-generic/short has only the "one" form,
// and falls back to fr for the "other" form.
IcuTestErrorCode errorCode(*this, "TestIndividualPluralFallback");
MeasureFormat mf("fr_CA", UMEASFMT_WIDTH_SHORT, errorCode);
LocalPointer<Measure> twoDeg(
new Measure(2, MeasureUnit::createGenericTemperature(errorCode), errorCode), errorCode);
UnicodeString expected = UNICODE_STRING_SIMPLE("2\\u00B0").unescape();
UnicodeString actual;
assertEquals("2 deg temp in fr_CA", expected, mf.format(twoDeg.orphan(), actual, errorCode));
}
void MeasureFormatTest::verifyFieldPosition(
const char *description,
const MeasureFormat &fmt,

View file

@ -1,7 +1,7 @@
/*
*******************************************************************************
* Copyright (C) 2014, International Business Machines Corporation and *
* others. All Rights Reserved. *
* Copyright (C) 2014-2015, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
*
* File QUANTITYFORMATTERTEST.CPP
@ -37,25 +37,25 @@ void QuantityFormatterTest::TestBasic() {
QuantityFormatter fmt;
assertFalse(
"adding bad variant",
fmt.add("a bad variant", "{0} pounds", status));
fmt.addIfAbsent("a bad variant", "{0} pounds", status));
assertEquals("adding bad variant status", U_ILLEGAL_ARGUMENT_ERROR, status);
status = U_ZERO_ERROR;
assertFalse(
"Adding bad pattern",
fmt.add("other", "{0} {1} too many placeholders", status));
fmt.addIfAbsent("other", "{0} {1} too many placeholders", status));
assertEquals("adding bad pattern status", U_ILLEGAL_ARGUMENT_ERROR, status);
status = U_ZERO_ERROR;
assertFalse("isValid with no patterns", fmt.isValid());
assertTrue(
"Adding good pattern with no placeholders",
fmt.add("other", "no placeholder", status));
fmt.addIfAbsent("zero", "no placeholder", status));
assertTrue(
"Adding good pattern",
fmt.add("other", "{0} pounds", status));
fmt.addIfAbsent("other", "{0} pounds", status));
assertTrue("isValid with other", fmt.isValid());
assertTrue(
"Adding good pattern",
fmt.add("one", "{0} pound", status));
fmt.addIfAbsent("one", "{0} pound", status));
assertEquals(
"getByVariant",

View file

@ -231,9 +231,9 @@ static WithQuantityExpected kSerbian[] = {
};
static WithQuantityExpected kSerbianNarrow[] = {
{0.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MONTHS, "\\u0437\\u0430 0 \\u043c\\u0435\\u0441."},
{1.2, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MONTHS, "\\u0437\\u0430 1,2 \\u043c\\u0435\\u0441."},
{21.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MONTHS, "\\u0437\\u0430 21 \\u043c\\u0435\\u0441."}
{0.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MONTHS, "\\u0437\\u0430 0 \\u043c."},
{1.2, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MONTHS, "\\u0437\\u0430 1,2 \\u043c."},
{21.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MONTHS, "\\u0437\\u0430 21 \\u043c."}
};
static WithoutQuantityExpected kEnglishNoQuantity[] = {