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:
parent
c43fdd0dce
commit
9469a6c1be
@ -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.
|
||||
*
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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"},
|
||||
|
@ -550,6 +550,7 @@ public class WritePluralRulesData {
|
||||
if (result.size() == 0) {
|
||||
return newRules.getFractionSamples(keyword);
|
||||
}
|
||||
result.addAll(newRules.getFractionSamples(keyword));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user