UMeasureFormatWidth widthFallback[WIDTH_INDEX_COUNT];
/** Measure unit -> format width -> array of patterns ("{0} meters") (plurals + PER_UNIT_INDEX) */
SimpleFormatter *patterns[MEAS_UNIT_COUNT][WIDTH_INDEX_COUNT][PATTERN_COUNT];
+ const UChar* dnams[MEAS_UNIT_COUNT][WIDTH_INDEX_COUNT];
SimpleFormatter perFormatters[WIDTH_INDEX_COUNT];
MeasureFormatCacheData();
currencyFormats[i] = NULL;
}
uprv_memset(patterns, 0, sizeof(patterns));
+ uprv_memset(dnams, 0, sizeof(dnams));
integerFormat = NULL;
numericDateFormatters = NULL;
}
}
}
}
+ // Note: the contents of 'dnams' are pointers into the resource bundle
delete integerFormat;
delete numericDateFormatters;
}
void setFormatterIfAbsent(int32_t index, const ResourceValue &value,
int32_t minPlaceholders, UErrorCode &errorCode) {
- SimpleFormatter **patterns =
- &cacheData.patterns[unitIndex][width][0];
+ SimpleFormatter **patterns = &cacheData.patterns[unitIndex][width][0];
if (U_SUCCESS(errorCode) && patterns[index] == NULL) {
- patterns[index] = new SimpleFormatter(
- value.getUnicodeString(errorCode), minPlaceholders, 1, errorCode);
+ if (minPlaceholders >= 0) {
+ patterns[index] = new SimpleFormatter(
+ value.getUnicodeString(errorCode), minPlaceholders, 1, errorCode);
+ }
if (U_SUCCESS(errorCode) && patterns[index] == NULL) {
errorCode = U_MEMORY_ALLOCATION_ERROR;
}
}
}
+ void setDnamIfAbsent(const ResourceValue &value, UErrorCode& errorCode) {
+ if (cacheData.dnams[unitIndex][width] == NULL) {
+ int32_t length;
+ cacheData.dnams[unitIndex][width] = value.getString(length, errorCode);
+ }
+ }
+
/**
* Consume a display pattern. For example,
* unitsShort/duration/hour contains other{"{0} hrs"}.
void consumePattern(const char *key, const ResourceValue &value, UErrorCode &errorCode) {
if (U_FAILURE(errorCode)) { return; }
if (uprv_strcmp(key, "dnam") == 0) {
- // Skip the unit display name for now.
+ // The display name for the unit in the current width.
+ setDnamIfAbsent(value, errorCode);
} else if (uprv_strcmp(key, "per") == 0) {
// For example, "{0}/h".
setFormatterIfAbsent(MeasureFormatCacheData::PER_UNIT_INDEX, value, 1, errorCode);
return appendTo;
}
+UnicodeString MeasureFormat::getUnitDisplayName(const MeasureUnit& unit, UErrorCode& /*status*/) const {
+ UMeasureFormatWidth width = getRegularWidth(this->width);
+ const UChar* const* styleToDnam = cache->dnams[unit.getIndex()];
+ const UChar* dnam = styleToDnam[width];
+ if (dnam == NULL) {
+ int32_t fallbackWidth = cache->widthFallback[width];
+ dnam = styleToDnam[fallbackWidth];
+ }
+
+ UnicodeString result;
+ if (dnam == NULL) {
+ result.setToBogus();
+ } else {
+ result.setTo(dnam, -1);
+ }
+ return result;
+}
+
void MeasureFormat::initMeasureFormat(
const Locale &locale,
UMeasureFormatWidth w,
#include "unicode/tmunit.h"
#include "unicode/plurrule.h"
#include "charstr.h"
+#include "cstr.h"
#include "unicode/reldatefmt.h"
struct ExpectedResult {
void TestManyLocaleDurations();
void TestGram();
void TestCurrencies();
+ void TestDisplayNames();
void TestFieldPosition();
void TestFieldPositionMultiple();
void TestBadArg();
const Measure *measures,
int32_t measureCount,
const char *expected);
+ void helperTestDisplayName(
+ const MeasureUnit *unit,
+ const char *localeID,
+ UMeasureFormatWidth width,
+ const char *expected);
void verifyFieldPosition(
const char *description,
const MeasureFormat &fmt,
TESTCASE_AUTO(TestManyLocaleDurations);
TESTCASE_AUTO(TestGram);
TESTCASE_AUTO(TestCurrencies);
+ TESTCASE_AUTO(TestDisplayNames);
TESTCASE_AUTO(TestFieldPosition);
TESTCASE_AUTO(TestFieldPositionMultiple);
TESTCASE_AUTO(TestBadArg);
verifyFormat("TestCurrenciesNumeric", fmt, &USD_2, 1, "$2.00");
}
+void MeasureFormatTest::TestDisplayNames() {
+ UErrorCode status = U_ZERO_ERROR;
+ helperTestDisplayName( MeasureUnit::createYear(status), "en", UMEASFMT_WIDTH_WIDE, "years" );
+ helperTestDisplayName( MeasureUnit::createYear(status), "ja", UMEASFMT_WIDTH_WIDE, "\\u5E74" );
+ helperTestDisplayName( MeasureUnit::createYear(status), "es", UMEASFMT_WIDTH_WIDE, "a\\u00F1os" );
+ helperTestDisplayName( MeasureUnit::createYear(status), "pt", UMEASFMT_WIDTH_WIDE, "anos" );
+ helperTestDisplayName( MeasureUnit::createYear(status), "pt-PT", UMEASFMT_WIDTH_WIDE, "anos" );
+ helperTestDisplayName( MeasureUnit::createAmpere(status), "en", UMEASFMT_WIDTH_WIDE, "amperes" );
+ helperTestDisplayName( MeasureUnit::createAmpere(status), "ja", UMEASFMT_WIDTH_WIDE, "\\u30A2\\u30F3\\u30DA\\u30A2" );
+ helperTestDisplayName( MeasureUnit::createAmpere(status), "es", UMEASFMT_WIDTH_WIDE, "amperios" );
+ helperTestDisplayName( MeasureUnit::createAmpere(status), "pt", UMEASFMT_WIDTH_WIDE, "amperes" );
+ helperTestDisplayName( MeasureUnit::createAmpere(status), "pt-PT", UMEASFMT_WIDTH_WIDE, "amperes" );
+ helperTestDisplayName( MeasureUnit::createMeterPerSecondSquared(status), "pt", UMEASFMT_WIDTH_WIDE, "metros por segundo ao quadrado" );
+ helperTestDisplayName( MeasureUnit::createMeterPerSecondSquared(status), "pt-PT", UMEASFMT_WIDTH_WIDE, "metros por segundo quadrado" );
+ helperTestDisplayName( MeasureUnit::createSquareKilometer(status), "pt", UMEASFMT_WIDTH_NARROW, "km\\u00B2" );
+ helperTestDisplayName( MeasureUnit::createSquareKilometer(status), "pt", UMEASFMT_WIDTH_SHORT, "km\\u00B2" );
+ helperTestDisplayName( MeasureUnit::createSquareKilometer(status), "pt", UMEASFMT_WIDTH_WIDE, "quil\\u00F4metros quadrados" );
+ helperTestDisplayName( MeasureUnit::createSecond(status), "pt-PT", UMEASFMT_WIDTH_NARROW, "s" );
+ helperTestDisplayName( MeasureUnit::createSecond(status), "pt-PT", UMEASFMT_WIDTH_SHORT, "s" );
+ helperTestDisplayName( MeasureUnit::createSecond(status), "pt-PT", UMEASFMT_WIDTH_WIDE, "segundos" );
+ helperTestDisplayName( MeasureUnit::createSecond(status), "pt", UMEASFMT_WIDTH_NARROW, "seg" );
+ helperTestDisplayName( MeasureUnit::createSecond(status), "pt", UMEASFMT_WIDTH_SHORT, "segs" );
+ helperTestDisplayName( MeasureUnit::createSecond(status), "pt", UMEASFMT_WIDTH_WIDE, "segundos" );
+ assertSuccess("Error creating measure units", status);
+}
+
+void MeasureFormatTest::helperTestDisplayName(const MeasureUnit *unit,
+ const char *localeID,
+ UMeasureFormatWidth width,
+ const char *expected) {
+ UErrorCode status = U_ZERO_ERROR;
+ MeasureFormat fmt(Locale(localeID), width, status);
+ if (U_FAILURE(status)) {
+ errln("Could not create MeasureFormat for locale %s, width %d, status: %s",
+ localeID, (int)width, u_errorName(status));
+ return;
+ }
+
+ UnicodeString dnam = fmt.getUnitDisplayName(*unit, status);
+ if (U_FAILURE(status)) {
+ errln("MeasureFormat::getUnitDisplayName failed for unit %s-%s, locale %s, width %d, status: %s",
+ unit->getType(), unit->getSubtype(), localeID, (int)width, u_errorName(status));
+ return;
+ }
+
+ UnicodeString expStr(UnicodeString(expected).unescape());
+ if (dnam != expStr) {
+ errln("MeasureFormat::getUnitDisplayName for unit %s-%s, locale %s, width %d: expected \"%s\", got \"%s\"",
+ unit->getType(), unit->getSubtype(), localeID, (int)width, CStr(expStr)(), CStr(dnam)());
+ }
+
+ // Delete the measure unit
+ delete unit;
+}
+
void MeasureFormatTest::TestFieldPosition() {
UErrorCode status = U_ZERO_ERROR;
MeasureFormat fmt("en", UMEASFMT_WIDTH_SHORT, status);