ICU-8474 Updated the plural rules factory to match CLDR; took a first pass at modifying NumberFormat to get the right information out for plural select with fractions.

X-SVN-Rev: 33649
This commit is contained in:
Mark Davis 2013-05-14 12:32:16 +00:00
parent c43fdd0dce
commit 9469a6c1be
7 changed files with 147 additions and 15 deletions

View File

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 2009-2011, International Business Machines Corporation and *
* Copyright (C) 2009-2013, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@ -233,11 +233,23 @@ public class CurrencyPluralInfo implements Cloneable, Serializable {
/**
* Given a number, returns the keyword of the first rule that applies
* to the number.
* @internal
* @deprecated This API is ICU internal only.
*/
String select(double number) {
return pluralRules.select(number);
}
/**
* Given a number, returns the keyword of the first rule that applies
* to the number.
* @internal
* @deprecated This API is ICU internal only.
*/
String select(PluralRules.NumberInfo numberInfo) {
return pluralRules.select(numberInfo);
}
/**
* Currency plural pattern iterator.
*

View File

@ -1330,6 +1330,9 @@ public class DecimalFormat extends NumberFormat {
} else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
fieldPosition.setBeginIndex(result.length());
}
long fractionalDigits = 0;
int fractionalDigitsCount = 0;
boolean recordFractionDigits = false;
int sigCount = 0;
int minSigDig = getMinimumSignificantDigits();
@ -1429,6 +1432,7 @@ public class DecimalFormat extends NumberFormat {
// [Spark/CDL] Record the begin index of fraction part.
int fracBegin = result.length();
recordFractionDigits = fieldPosition instanceof UFieldPosition;
count = useSigDig ? Integer.MAX_VALUE : getMaximumFractionDigits();
if (useSigDig && (sigCount == maxSigDig ||
@ -1451,15 +1455,29 @@ public class DecimalFormat extends NumberFormat {
// abs(number being formatted) < 1.0.
if (-1 - i > (digitList.decimalAt - 1)) {
result.append(digits[0]);
if (recordFractionDigits) {
++fractionalDigitsCount;
fractionalDigits *= 10;
}
continue;
}
// Output a digit, if we have any precision left, or a zero if we
// don't. We don't want to output noise digits.
if (!isInteger && digitIndex < digitList.count) {
result.append(digits[digitList.getDigitValue(digitIndex++)]);
byte digit = digitList.getDigitValue(digitIndex++);
result.append(digits[digit]);
if (recordFractionDigits) {
++fractionalDigitsCount;
fractionalDigits *= 10;
fractionalDigits += digit;
}
} else {
result.append(digits[0]);
if (recordFractionDigits) {
++fractionalDigitsCount;
fractionalDigits *= 10;
}
}
// If we reach the maximum number of significant digits, or if we output
@ -1477,6 +1495,9 @@ public class DecimalFormat extends NumberFormat {
} else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
fieldPosition.setEndIndex(result.length());
}
if (recordFractionDigits) {
((UFieldPosition) fieldPosition).setFractionDigits(fractionalDigitsCount, fractionalDigits);
}
// [Spark/CDL] Add attribute information if necessary.
if (parseAttr && (decimalSeparatorAlwaysShown || fractionPresent)) {
@ -1507,6 +1528,7 @@ public class DecimalFormat extends NumberFormat {
fieldPosition.setBeginIndex(-1);
}
// [Spark/CDL]
// the begin index of integer part
// the end index of integer part
@ -1530,6 +1552,9 @@ public class DecimalFormat extends NumberFormat {
minIntDig = 1;
}
}
long fractionalDigits = 0;
int fractionalDigitsCount = 0;
boolean recordFractionDigits = false;
// Minimum integer digits are handled in exponential format by adjusting the
// exponent. For example, 0.01234 with 3 minimum integer digits is "123.4E-4".
@ -1594,10 +1619,16 @@ public class DecimalFormat extends NumberFormat {
} else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
fieldPosition.setBeginIndex(result.length());
}
recordFractionDigits = fieldPosition instanceof UFieldPosition;
}
byte digit = (i < digitList.count) ? digitList.getDigitValue(i) : (byte)0;
result.append(digits[digit]);
if (recordFractionDigits) {
++fractionalDigitsCount;
fractionalDigits *= 10;
fractionalDigits += digit;
}
result.append((i < digitList.count)
? digits[digitList.getDigitValue(i)]
: digits[0]);
}
// For ICU compatibility and format 0 to 0E0 with pattern "#E0" [Richard/GCL]
@ -1625,6 +1656,9 @@ public class DecimalFormat extends NumberFormat {
}
fieldPosition.setEndIndex(result.length());
}
if (recordFractionDigits) {
((UFieldPosition) fieldPosition).setFractionDigits(fractionalDigitsCount, fractionalDigits);
}
// [Spark/CDL] Calcuate the end index of integer part and fractional
// part if they are not properly processed yet.

View File

@ -384,7 +384,7 @@ public class PluralRules implements Serializable {
public final boolean hasIntegerValue;
public final boolean isNegative;
public NumberInfo(double n, int v, int f) {
public NumberInfo(double n, int v, long f) {
isNegative = n < 0;
source = isNegative ? -n : n;
visibleFractionDigitCount = v;
@ -1357,10 +1357,11 @@ public class PluralRules implements Serializable {
* @internal
* @deprecated This API is ICU internal only.
*/
public String select(double number, int countVisibleFractionDigits, int fractionaldigits) {
public String select(double number, int countVisibleFractionDigits, long fractionaldigits) {
return rules.select(new NumberInfo(number, countVisibleFractionDigits, fractionaldigits));
}
/**
* Given a number, returns the keyword of the first rule that applies to
* the number.

View File

@ -0,0 +1,41 @@
/*
*******************************************************************************
* Copyright (C) 2013, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
package com.ibm.icu.text;
import java.text.FieldPosition;
import java.text.Format.Field;
/**
* Adds the ability to get the decimal digits
*/
public class UFieldPosition extends FieldPosition {
private int countVisibleFractionDigits = -1;
private long fractionDigits = 0;
public UFieldPosition() {
super(-1);
}
public UFieldPosition(int field) {
super(field);
}
public UFieldPosition(Field attribute, int fieldID) {
super(attribute, fieldID);
}
public UFieldPosition(Field attribute) {
super(attribute);
}
public void setFractionDigits(int countVisibleFractionDigits, long fractionDigits ) {
this.countVisibleFractionDigits = countVisibleFractionDigits;
this.fractionDigits = fractionDigits;
}
public int getCountVisibleFractionDigits() {
return countVisibleFractionDigits;
}
public long getFractionDigits() {
return fractionDigits;
}
}

View File

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 2007-2012, International Business Machines Corporation and
* Copyright (C) 2007-2013, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
*/
@ -19,6 +19,7 @@ import com.ibm.icu.text.MessageFormat;
import com.ibm.icu.text.NumberFormat;
import com.ibm.icu.text.PluralFormat;
import com.ibm.icu.text.PluralRules;
import com.ibm.icu.text.UFieldPosition;
import com.ibm.icu.text.PluralRules.PluralType;
import com.ibm.icu.util.ULocale;
@ -339,4 +340,43 @@ public class PluralFormatUnitTest extends TestFmwk {
assertEquals("PluralFormat.format(456)", "456th file", pf.format(456));
assertEquals("PluralFormat.format(111)", "111th file", pf.format(111));
}
public void TestBasicFraction() {
String[][] tests = {
{"en", "one: j is 1"},
{"1", "0", "1", "one"},
{"1", "2", "1.00", "other"},
};
ULocale locale = null;
NumberFormat nf = null;
PluralRules pr = null;
for (String[] row : tests) {
switch(row.length) {
case 2:
locale = ULocale.forLanguageTag(row[0]);
nf = NumberFormat.getInstance(locale);
pr = PluralRules.createRules(row[1]);
break;
case 4:
double n = Double.parseDouble(row[0]);
int minFracDigits = Integer.parseInt(row[1]);
nf.setMinimumFractionDigits(minFracDigits);
String expectedFormat = row[2];
String expectedKeyword = row[3];
UFieldPosition pos = new UFieldPosition();
String formatted = nf.format(1.0, new StringBuffer(), pos).toString();
int countVisibleFractionDigits = pos.getCountVisibleFractionDigits();
long fractionDigits = pos.getFractionDigits();
String keyword = pr.select(n, countVisibleFractionDigits, fractionDigits);
assertEquals("Formatted " + n + "\t" + minFracDigits, expectedFormat, formatted);
assertEquals("Keyword " + n + "\t" + minFracDigits, expectedKeyword, keyword);
break;
default:
throw new RuntimeException();
}
}
}
}

View File

@ -344,10 +344,10 @@ public abstract class PluralRulesFactory {
{"gl", "other", "{0} días"},
{"gu", "one", "{0} કિલોગ્રામ"},
{"gu", "other", "{0} કિલોગ્રામ્સ"},
{"he", "many", "{0} ימים"},
{"he", "one", " יום {0}"},
{"he", "other", "{0} ימים"},
{"he", "two", "יומיים"},
{"he", "many", "{0} שנה"},
{"he", "one", "שנה"},
{"he", "other", "{0} שנים"},
{"he", "two", "שנתיים"},
{"hi", "one", "{0} घंटा"},
{"hi", "other", "{0} घंटे"},
{"hr", "few", "za {0} mjeseca"},
@ -404,7 +404,8 @@ public abstract class PluralRulesFactory {
{"ru", "many", "{0} лет"},
{"ru", "one", "{0} год"},
{"ru", "other", "{0} года"},
{"si", "other", "දින {0}ක්"},
{"si", "one", "මට පොත් {0}ක් තිබේ. මම එය කියවීමි.්"},
{"si", "other", "මට පොත් {0}ක් තිබේ. මම ඒවා කියවීමි."},
{"sk", "few", "{0} dni"},
{"sk", "one", "{0} deň"},
{"sk", "other", "{0} dní"},
@ -451,14 +452,16 @@ public abstract class PluralRulesFactory {
{"gu,mr,kn,am,fa", "one: n within 0..1"},
{"ta,te", "one: n is 1"},
{"bn", "one: n within 0..1"},
{"en,ca,de,et,fi,gl,it,nl,sv,sw,ur", "one: j is 1"},
{"en,ca,de,et,fi,gl,it,nl,sw,ur", "one: j is 1"},
{"sv", "one: j is 1 or f is 1"},
{"pt", "one: n is 1 or f is 1"},
{"si", "one: n in 0,1 or i is 0 and f is 1"},
{"cs,sk", "one: j is 1; few: j in 2..4; many: v is not 0"},
//{"cy", "one: n is 1; two: n is 2; few: n is 3; many: n is 6"},
//{"el", "one: j is 1 or i is 0 and f is 1"},
{"da,is", "one: j is 1 or f is 1"},
{"fil,tl", "one: j in 0..1"},
{"he,iw", "one: j is 1; two: j is 2; many: j is not 0 and j mod 10 is 0", "10,20"},
{"he,iw", "one: j is 1; two: j is 2; many: j not in 0..10 and j mod 10 is 0", "10,20"},
{"hi", "one: n within 0..1"},
{"hy", "one: n within 0..2 and n is not 2"},
// {"hr", "one: j mod 10 is 1 and j mod 100 is not 11; few: j mod 10 in 2..4 and j mod 100 not in 12..14; many: j mod 10 is 0 or j mod 10 in 5..9 or j mod 100 in 11..14"},

View File

@ -550,6 +550,7 @@ public class WritePluralRulesData {
if (result.size() == 0) {
return newRules.getFractionSamples(keyword);
}
result.addAll(newRules.getFractionSamples(keyword));
return result;
}