diff --git a/common/supplemental/units.xml b/common/supplemental/units.xml
index 33d6d68d466..ebaa8e9d08f 100644
--- a/common/supplemental/units.xml
+++ b/common/supplemental/units.xml
@@ -255,7 +255,7 @@ For terms of use, see http://www.unicode.org/copyright.html
-
+
diff --git a/tools/cldr-code/src/main/java/org/unicode/cldr/util/UnitConverter.java b/tools/cldr-code/src/main/java/org/unicode/cldr/util/UnitConverter.java
index 6fb6961f6c6..694dee2e677 100644
--- a/tools/cldr-code/src/main/java/org/unicode/cldr/util/UnitConverter.java
+++ b/tools/cldr-code/src/main/java/org/unicode/cldr/util/UnitConverter.java
@@ -15,6 +15,7 @@
import com.google.common.collect.TreeMultimap;
import com.ibm.icu.impl.Row.R2;
import com.ibm.icu.lang.UCharacter;
+import com.ibm.icu.number.UnlocalizedNumberFormatter;
import com.ibm.icu.text.PluralRules;
import com.ibm.icu.util.Freezable;
import com.ibm.icu.util.Output;
@@ -2236,4 +2237,30 @@ public String resolve(String unit) {
String resolved = unitId.resolve().toString();
return getStandardUnit(resolved.isBlank() ? unit : resolved);
}
+
+ public String format(
+ final String languageTag,
+ Rational outputAmount,
+ final String unit,
+ UnlocalizedNumberFormatter nf3) {
+ final CLDRConfig config = CLDRConfig.getInstance();
+ Factory factory = config.getCldrFactory();
+ int pos = languageTag.indexOf("-u");
+ String localeBase =
+ (pos < 0 ? languageTag : languageTag.substring(0, pos)).replace('-', '_');
+ CLDRFile localeFile = factory.make(localeBase, true);
+ PluralRules pluralRules =
+ config.getSupplementalDataInfo()
+ .getPluralRules(
+ localeBase, com.ibm.icu.text.PluralRules.PluralType.CARDINAL);
+ String pluralCategory = pluralRules.select(outputAmount.doubleValue());
+ String path =
+ UnitPathType.unit.getTranslationPath(
+ localeFile, "long", unit, pluralCategory, "nominative", "neuter");
+ String pattern = localeFile.getStringValue(path);
+ final ULocale uLocale = ULocale.forLanguageTag(languageTag);
+ String cldrFormattedNumber =
+ nf3.locale(uLocale).format(outputAmount.doubleValue()).toString();
+ return com.ibm.icu.text.MessageFormat.format(pattern, cldrFormattedNumber);
+ }
}
diff --git a/tools/cldr-code/src/main/java/org/unicode/cldr/util/UnitPreferences.java b/tools/cldr-code/src/main/java/org/unicode/cldr/util/UnitPreferences.java
index 7eac1dd6270..79ccb40a39c 100644
--- a/tools/cldr-code/src/main/java/org/unicode/cldr/util/UnitPreferences.java
+++ b/tools/cldr-code/src/main/java/org/unicode/cldr/util/UnitPreferences.java
@@ -2,19 +2,25 @@
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
-import com.ibm.icu.impl.locale.XCldrStub.ImmutableMap;
import com.ibm.icu.util.Freezable;
+import com.ibm.icu.util.Output;
+import com.ibm.icu.util.ULocale;
import java.util.Collection;
import java.util.LinkedHashMap;
+import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
+import org.unicode.cldr.tool.LikelySubtags;
+import org.unicode.cldr.util.UnitConverter.ConversionInfo;
public class UnitPreferences implements Freezable {
Map, UnitPreference>>> quantityToUsageToRegionsToInfo =
@@ -93,8 +99,9 @@ public void add(
Rational newGeq = geq == null || geq.isEmpty() ? Rational.ONE : Rational.of(geq);
final UnitPreference newUnitPref = new UnitPreference(newGeq, unit, skeleton);
- regionsToInfo.put(
- ImmutableSet.copyOf(new TreeSet<>(SPLIT_SPACE.splitToList(regions))), newUnitPref);
+ final ImmutableSet regionSet =
+ ImmutableSet.copyOf(new TreeSet<>(SPLIT_SPACE.splitToList(regions)));
+ boolean old = regionsToInfo.put(regionSet, newUnitPref);
}
boolean frozen;
@@ -195,33 +202,41 @@ public String getPath(
*
* @return
*/
- public Map>> getFastMap(
- UnitConverter converter) {
- Map>> result = new LinkedHashMap<>();
+ private Map>> getRawFastMap() {
+ UnitConverter converter = SupplementalDataInfo.getInstance().getUnitConverter();
+ Map>> result = new LinkedHashMap<>();
for (Entry, UnitPreference>>> entry1 :
quantityToUsageToRegionsToInfo.entrySet()) {
String quantity = entry1.getKey();
- Map> result2 = new LinkedHashMap<>();
+ Map> result2 = new LinkedHashMap<>();
result.put(quantity, result2);
for (Entry, UnitPreference>> entry2 :
entry1.getValue().entrySet()) {
String usage = entry2.getKey();
- Map result3 = new LinkedHashMap<>();
+ Multimap result3 = LinkedHashMultimap.create();
result2.put(usage, result3);
+
+ // split the regions
for (Entry, Collection> entry :
entry2.getValue().asMap().entrySet()) {
Set regions = entry.getKey();
+ int len = entry.getValue().size();
for (UnitPreference up : entry.getValue()) {
String unit = SPLIT_AND.split(up.unit).iterator().next(); // first unit
quantity = converter.getQuantityFromUnit(unit, false);
String baseUnit = converter.getBaseUnitFromQuantity(quantity);
- Rational geq = converter.parseRational(String.valueOf(up.geq));
- Rational value = converter.convert(geq, unit, baseUnit, false);
- if (value.equals(Rational.NaN)) {
- converter.convert(geq, unit, baseUnit, true); // debug
+ Rational baseGeq;
+ if (--len == 0) { // set last value to least possible
+ baseGeq = Rational.NEGATIVE_INFINITY;
+ } else {
+ Rational geq = converter.parseRational(String.valueOf(up.geq));
+ baseGeq = converter.convert(geq, unit, baseUnit, false);
+ if (baseGeq.equals(Rational.NaN)) {
+ converter.convert(geq, unit, baseUnit, true); // debug
+ }
}
- UnitPreference up2 = new UnitPreference(value, up.unit, up.skeleton);
+ UnitPreference up2 = new UnitPreference(baseGeq, up.unit, up.skeleton);
for (String region : regions) {
result3.put(region, up2);
}
@@ -229,10 +244,116 @@ public Map>> getFastMap(
}
}
}
- return ImmutableMap.copyOf(result);
+ return CldrUtility.protectCollection(result);
+ }
+
+ Supplier