Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/macosx/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java
38918 views
/*1* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.util.locale.provider;2627import java.lang.ref.SoftReference;28import java.text.*;29import java.text.spi.DateFormatProvider;30import java.text.spi.DateFormatSymbolsProvider;31import java.text.spi.DecimalFormatSymbolsProvider;32import java.text.spi.NumberFormatProvider;33import java.util.Collections;34import java.util.Calendar;35import java.util.HashSet;36import java.util.Locale;37import java.util.Map;38import java.util.ResourceBundle.Control;39import java.util.Set;40import java.util.TimeZone;41import java.util.concurrent.ConcurrentHashMap;42import java.util.concurrent.ConcurrentMap;43import java.util.concurrent.atomic.AtomicReferenceArray;44import java.util.spi.CalendarDataProvider;45import java.util.spi.CalendarNameProvider;46import java.util.spi.CurrencyNameProvider;47import java.util.spi.LocaleNameProvider;48import java.util.spi.TimeZoneNameProvider;49import sun.util.spi.CalendarProvider;5051/**52* LocaleProviderAdapter implementation for the Mac OS X locale data53*54* @author Naoto Sato55*/56public class HostLocaleProviderAdapterImpl {5758// per supported locale instances59private static ConcurrentMap<Locale, SoftReference<AtomicReferenceArray<String>>> dateFormatPatternsMap =60new ConcurrentHashMap<>(2);61private static ConcurrentMap<Locale, SoftReference<AtomicReferenceArray<String>>> numberFormatPatternsMap =62new ConcurrentHashMap<>(2);63private static ConcurrentMap<Locale, SoftReference<DateFormatSymbols>> dateFormatSymbolsMap =64new ConcurrentHashMap<>(2);65private static ConcurrentMap<Locale, SoftReference<DecimalFormatSymbols>> decimalFormatSymbolsMap =66new ConcurrentHashMap<>(2);6768// locale categories69private static final int CAT_DISPLAY = 0;70private static final int CAT_FORMAT = 1;7172// NumberFormat styles73private static final int NF_NUMBER = 0;74private static final int NF_CURRENCY = 1;75private static final int NF_PERCENT = 2;76private static final int NF_INTEGER = 3;77private static final int NF_MAX = NF_INTEGER;7879// CalendarData value types80private static final int CD_FIRSTDAYOFWEEK = 0;81private static final int CD_MINIMALDAYSINFIRSTWEEK = 1;8283// Locale/Currency display name types84private static final int DN_LOCALE_LANGUAGE = 0;85private static final int DN_LOCALE_SCRIPT = 1;86private static final int DN_LOCALE_REGION = 2;87private static final int DN_LOCALE_VARIANT = 3;88private static final int DN_CURRENCY_CODE = 4;89private static final int DN_CURRENCY_SYMBOL = 5;9091// TimeZone display name types92private static final int DN_TZ_SHORT_STANDARD = 0;93private static final int DN_TZ_SHORT_DST = 1;94private static final int DN_TZ_LONG_STANDARD = 2;95private static final int DN_TZ_LONG_DST = 3;9697private static final Set<Locale> supportedLocaleSet;98static {99Set<Locale> tmpSet = new HashSet<>();100// Assuming the default locales do not include any extensions, so101// no stripping is needed here.102Locale l = convertMacOSXLocaleToJavaLocale(getDefaultLocale(CAT_FORMAT));103tmpSet.addAll(Control.getNoFallbackControl(Control.FORMAT_DEFAULT).getCandidateLocales("", l));104l = convertMacOSXLocaleToJavaLocale(getDefaultLocale(CAT_DISPLAY));105tmpSet.addAll(Control.getNoFallbackControl(Control.FORMAT_DEFAULT).getCandidateLocales("", l));106supportedLocaleSet = Collections.unmodifiableSet(tmpSet);107}108private final static Locale[] supportedLocale = supportedLocaleSet.toArray(new Locale[0]);109110@SuppressWarnings("fallthrough")111private static Locale convertMacOSXLocaleToJavaLocale(String macosxloc) {112// MacOSX may return ICU notation, here is the quote from CFLocale doc:113// "The corresponding value is a CFString containing the POSIX locale114// identifier as used by ICU, such as "ja_JP". If you have a variant115// locale or a different currency or calendar, it can be as complex as116// "en_US_POSIX@calendar=japanese;currency=EUR" or117// "az_Cyrl_AZ@calendar=buddhist;currency=JPY".118String[] tmp = macosxloc.split("@");119String langTag = tmp[0].replace('_', '-');120if (tmp.length > 1) {121String[] ext = tmp[1].split(";");122for (String keyval : ext) {123// We are only interested in "calendar" value for now.124if (keyval.startsWith("calendar=")) {125String calid = keyval.substring(keyval.indexOf('=')+1);126switch (calid) {127case "gregorian":128langTag += "-u-ca-gregory";129break;130case "japanese":131// Tweak for ja_JP_JP132if (tmp[0].equals("ja_JP")) {133return JRELocaleConstants.JA_JP_JP;134}135136// fall through137138default:139langTag += "-u-ca-" + calid;140break;141}142}143}144}145146return Locale.forLanguageTag(langTag);147}148149public static DateFormatProvider getDateFormatProvider() {150return new DateFormatProvider() {151152@Override153public Locale[] getAvailableLocales() {154return getSupportedCalendarLocales();155}156157@Override158public boolean isSupportedLocale(Locale locale) {159return isSupportedCalendarLocale(locale);160}161162@Override163public DateFormat getDateInstance(int style, Locale locale) {164return new SimpleDateFormat(getDateTimePattern(style, -1, locale),165getCalendarLocale(locale));166}167168@Override169public DateFormat getTimeInstance(int style, Locale locale) {170return new SimpleDateFormat(getDateTimePattern(-1, style, locale),171getCalendarLocale(locale));172}173174@Override175public DateFormat getDateTimeInstance(int dateStyle,176int timeStyle, Locale locale) {177return new SimpleDateFormat(getDateTimePattern(dateStyle, timeStyle, locale),178getCalendarLocale(locale));179}180181private String getDateTimePattern(int dateStyle, int timeStyle, Locale locale) {182AtomicReferenceArray<String> dateFormatPatterns;183SoftReference<AtomicReferenceArray<String>> ref = dateFormatPatternsMap.get(locale);184185if (ref == null || (dateFormatPatterns = ref.get()) == null) {186dateFormatPatterns = new AtomicReferenceArray<>(5 * 5);187ref = new SoftReference<>(dateFormatPatterns);188dateFormatPatternsMap.put(locale, ref);189}190191int index = (dateStyle + 1) * 5 + timeStyle + 1;192String pattern = dateFormatPatterns.get(index);193if (pattern == null) {194String langTag = locale.toLanguageTag();195pattern = translateDateFormatLetters(getCalendarID(langTag),196getDateTimePatternNative(dateStyle, timeStyle, langTag));197if (!dateFormatPatterns.compareAndSet(index, null, pattern)) {198pattern = dateFormatPatterns.get(index);199}200}201202return pattern;203}204};205}206207public static DateFormatSymbolsProvider getDateFormatSymbolsProvider() {208return new DateFormatSymbolsProvider() {209@Override210public Locale[] getAvailableLocales() {211if (isSupportedLocale(Locale.getDefault(Locale.Category.FORMAT))) {212return supportedLocale;213}214return new Locale[0];215}216217@Override218public boolean isSupportedLocale(Locale locale) {219// Only supports the locale with Gregorian calendar220Locale base = locale.stripExtensions();221if (supportedLocaleSet.contains(base)) {222return getCalendarID(locale.toLanguageTag()).equals("gregorian");223}224return false;225}226227@Override228public DateFormatSymbols getInstance(Locale locale) {229DateFormatSymbols dateFormatSymbols;230SoftReference<DateFormatSymbols> ref = dateFormatSymbolsMap.get(locale);231232if (ref == null || (dateFormatSymbols = ref.get()) == null) {233dateFormatSymbols = new DateFormatSymbols(locale);234String langTag = locale.toLanguageTag();235dateFormatSymbols.setAmPmStrings(getAmPmStrings(langTag, dateFormatSymbols.getAmPmStrings()));236dateFormatSymbols.setEras(getEras(langTag, dateFormatSymbols.getEras()));237dateFormatSymbols.setMonths(getMonths(langTag, dateFormatSymbols.getMonths()));238dateFormatSymbols.setShortMonths(getShortMonths(langTag, dateFormatSymbols.getShortMonths()));239dateFormatSymbols.setWeekdays(getWeekdays(langTag, dateFormatSymbols.getWeekdays()));240dateFormatSymbols.setShortWeekdays(getShortWeekdays(langTag, dateFormatSymbols.getShortWeekdays()));241ref = new SoftReference<>(dateFormatSymbols);242dateFormatSymbolsMap.put(locale, ref);243}244return (DateFormatSymbols)dateFormatSymbols.clone();245}246};247}248249public static NumberFormatProvider getNumberFormatProvider() {250return new NumberFormatProvider() {251@Override252public Locale[] getAvailableLocales() {253return supportedLocale;254}255256@Override257public boolean isSupportedLocale(Locale locale) {258// Ignore the extensions for now259return supportedLocaleSet.contains(locale.stripExtensions());260}261262@Override263public NumberFormat getCurrencyInstance(Locale locale) {264return new DecimalFormat(getNumberPattern(NF_CURRENCY, locale),265DecimalFormatSymbols.getInstance(locale));266}267268@Override269public NumberFormat getIntegerInstance(Locale locale) {270return new DecimalFormat(getNumberPattern(NF_INTEGER, locale),271DecimalFormatSymbols.getInstance(locale));272}273274@Override275public NumberFormat getNumberInstance(Locale locale) {276return new DecimalFormat(getNumberPattern(NF_NUMBER, locale),277DecimalFormatSymbols.getInstance(locale));278}279280@Override281public NumberFormat getPercentInstance(Locale locale) {282return new DecimalFormat(getNumberPattern(NF_PERCENT, locale),283DecimalFormatSymbols.getInstance(locale));284}285286private String getNumberPattern(int style, Locale locale) {287AtomicReferenceArray<String> numberFormatPatterns;288SoftReference<AtomicReferenceArray<String>> ref = numberFormatPatternsMap.get(locale);289290if (ref == null || (numberFormatPatterns = ref.get()) == null) {291numberFormatPatterns = new AtomicReferenceArray<>(4);292ref = new SoftReference<>(numberFormatPatterns);293numberFormatPatternsMap.put(locale, ref);294}295296String pattern = numberFormatPatterns.get(style);297if (pattern == null) {298pattern = getNumberPatternNative(style, locale.toLanguageTag());299if (!numberFormatPatterns.compareAndSet(style, null, pattern)) {300pattern = numberFormatPatterns.get(style);301}302}303304return pattern;305}306};307}308309public static DecimalFormatSymbolsProvider getDecimalFormatSymbolsProvider() {310return new DecimalFormatSymbolsProvider() {311312@Override313public Locale[] getAvailableLocales() {314return supportedLocale;315}316317@Override318public boolean isSupportedLocale(Locale locale) {319// Ignore the extensions for now320return supportedLocaleSet.contains(locale.stripExtensions());321}322323@Override324public DecimalFormatSymbols getInstance(Locale locale) {325DecimalFormatSymbols decimalFormatSymbols;326SoftReference<DecimalFormatSymbols> ref = decimalFormatSymbolsMap.get(locale);327328if (ref == null || (decimalFormatSymbols = ref.get()) == null) {329decimalFormatSymbols = new DecimalFormatSymbols(locale);330String langTag = locale.toLanguageTag();331332// DecimalFormatSymbols.setInternationalCurrencySymbol() has333// a side effect of setting the currency symbol as well. So334// the calling order is relevant here.335decimalFormatSymbols.setInternationalCurrencySymbol(getInternationalCurrencySymbol(langTag, decimalFormatSymbols.getInternationalCurrencySymbol()));336decimalFormatSymbols.setCurrencySymbol(getCurrencySymbol(langTag, decimalFormatSymbols.getCurrencySymbol()));337decimalFormatSymbols.setDecimalSeparator(getDecimalSeparator(langTag, decimalFormatSymbols.getDecimalSeparator()));338decimalFormatSymbols.setGroupingSeparator(getGroupingSeparator(langTag, decimalFormatSymbols.getGroupingSeparator()));339decimalFormatSymbols.setInfinity(getInfinity(langTag, decimalFormatSymbols.getInfinity()));340decimalFormatSymbols.setMinusSign(getMinusSign(langTag, decimalFormatSymbols.getMinusSign()));341decimalFormatSymbols.setMonetaryDecimalSeparator(getMonetaryDecimalSeparator(langTag, decimalFormatSymbols.getMonetaryDecimalSeparator()));342decimalFormatSymbols.setNaN(getNaN(langTag, decimalFormatSymbols.getNaN()));343decimalFormatSymbols.setPercent(getPercent(langTag, decimalFormatSymbols.getPercent()));344decimalFormatSymbols.setPerMill(getPerMill(langTag, decimalFormatSymbols.getPerMill()));345decimalFormatSymbols.setZeroDigit(getZeroDigit(langTag, decimalFormatSymbols.getZeroDigit()));346decimalFormatSymbols.setExponentSeparator(getExponentSeparator(langTag, decimalFormatSymbols.getExponentSeparator()));347ref = new SoftReference<>(decimalFormatSymbols);348decimalFormatSymbolsMap.put(locale, ref);349}350return (DecimalFormatSymbols)decimalFormatSymbols.clone();351}352};353}354355public static CalendarDataProvider getCalendarDataProvider() {356return new CalendarDataProvider() {357@Override358public Locale[] getAvailableLocales() {359return getSupportedCalendarLocales();360}361362@Override363public boolean isSupportedLocale(Locale locale) {364return isSupportedCalendarLocale(locale);365}366367@Override368public int getFirstDayOfWeek(Locale locale) {369return getCalendarInt(locale.toLanguageTag(), CD_FIRSTDAYOFWEEK);370}371372@Override373public int getMinimalDaysInFirstWeek(Locale locale) {374return getCalendarInt(locale.toLanguageTag(), CD_MINIMALDAYSINFIRSTWEEK);375}376};377}378379public static CalendarNameProvider getCalendarNameProvider() {380return new CalendarNameProvider() {381@Override382public Locale[] getAvailableLocales() {383return getSupportedCalendarLocales();384}385386@Override387public boolean isSupportedLocale(Locale locale) {388return isSupportedCalendarLocale(locale);389}390391@Override392public String getDisplayName(String calType, int field, int value,393int style, Locale locale) {394return null;395}396397@Override398public Map<String, Integer> getDisplayNames(String calType,399int field, int style, Locale locale) {400return null;401}402};403}404405public static CalendarProvider getCalendarProvider() {406return new CalendarProvider() {407@Override408public Locale[] getAvailableLocales() {409return getSupportedCalendarLocales();410}411412@Override413public boolean isSupportedLocale(Locale locale) {414return isSupportedCalendarLocale(locale);415}416417@Override418public Calendar getInstance(TimeZone zone, Locale locale) {419return new Calendar.Builder()420.setLocale(locale)421.setCalendarType(getCalendarID(locale.toLanguageTag()))422.setTimeZone(zone)423.setInstant(System.currentTimeMillis())424.build();425}426};427}428429public static CurrencyNameProvider getCurrencyNameProvider() {430return new CurrencyNameProvider() {431@Override432public Locale[] getAvailableLocales() {433return supportedLocale;434}435436@Override437public boolean isSupportedLocale(Locale locale) {438// Ignore the extensions for now439return supportedLocaleSet.contains(locale.stripExtensions());440}441442@Override443public String getDisplayName(String code, Locale locale) {444return getDisplayString(locale.toLanguageTag(), DN_CURRENCY_CODE, code);445}446447@Override448public String getSymbol(String code, Locale locale) {449return getDisplayString(locale.toLanguageTag(), DN_CURRENCY_SYMBOL, code);450}451};452}453454public static LocaleNameProvider getLocaleNameProvider() {455return new LocaleNameProvider() {456@Override457public Locale[] getAvailableLocales() {458return supportedLocale;459}460461@Override462public boolean isSupportedLocale(Locale locale) {463// Ignore the extensions for now464return supportedLocaleSet.contains(locale.stripExtensions());465}466467@Override468public String getDisplayLanguage(String languageCode, Locale locale) {469return getDisplayString(locale.toLanguageTag(), DN_LOCALE_LANGUAGE, languageCode);470}471472@Override473public String getDisplayCountry(String countryCode, Locale locale) {474return getDisplayString(locale.toLanguageTag(), DN_LOCALE_REGION, countryCode);475}476477@Override478public String getDisplayScript(String scriptCode, Locale locale) {479return getDisplayString(locale.toLanguageTag(), DN_LOCALE_SCRIPT, scriptCode);480}481482@Override483public String getDisplayVariant(String variantCode, Locale locale) {484return getDisplayString(locale.toLanguageTag(), DN_LOCALE_VARIANT, variantCode);485}486};487}488489public static TimeZoneNameProvider getTimeZoneNameProvider() {490return new TimeZoneNameProvider() {491@Override492public Locale[] getAvailableLocales() {493return supportedLocale;494}495496@Override497public boolean isSupportedLocale(Locale locale) {498// Ignore the extensions for now499return supportedLocaleSet.contains(locale.stripExtensions());500}501502@Override503public String getDisplayName(String ID, boolean daylight, int style, Locale locale) {504return getTimeZoneDisplayString(locale.toLanguageTag(), style * 2 + (daylight ? 1 : 0), ID);505}506};507}508509private static Locale[] getSupportedCalendarLocales() {510if (supportedLocale.length != 0 &&511supportedLocaleSet.contains(Locale.JAPAN) &&512isJapaneseCalendar()) {513Locale[] sup = new Locale[supportedLocale.length+1];514sup[0] = JRELocaleConstants.JA_JP_JP;515System.arraycopy(supportedLocale, 0, sup, 1, supportedLocale.length);516return sup;517}518return supportedLocale;519}520521private static boolean isSupportedCalendarLocale(Locale locale) {522Locale base = locale;523524if (base.hasExtensions() || base.getVariant() != "") {525base = new Locale.Builder()526.setLocale(locale)527.clearExtensions()528.build();529}530531if (!supportedLocaleSet.contains(base)) {532return false;533}534535String requestedCalType = locale.getUnicodeLocaleType("ca");536String nativeCalType =537getCalendarID(base.toLanguageTag()).replaceFirst("gregorian", "gregory");538539if (requestedCalType == null) {540return Calendar.getAvailableCalendarTypes().contains(nativeCalType);541} else {542return requestedCalType.equals(nativeCalType);543}544}545546private static boolean isJapaneseCalendar() {547return getCalendarID("ja-JP").equals("japanese");548}549550private static Locale getCalendarLocale(Locale locale) {551String nativeCalType = getCalendarID(locale.toLanguageTag())552.replaceFirst("gregorian", "gregory");553if (Calendar.getAvailableCalendarTypes().contains(nativeCalType)) {554return new Locale.Builder()555.setLocale(locale)556.setUnicodeLocaleKeyword("ca", nativeCalType)557.build();558} else {559return locale;560}561}562563// The following methods are copied from CLDRConverter build tool.564private static String translateDateFormatLetters(String calendarType, String cldrFormat) {565String pattern = cldrFormat;566int length = pattern.length();567boolean inQuote = false;568StringBuilder jrePattern = new StringBuilder(length);569int count = 0;570char lastLetter = 0;571572for (int i = 0; i < length; i++) {573char c = pattern.charAt(i);574575if (c == '\'') {576// '' is treated as a single quote regardless of being577// in a quoted section.578if ((i + 1) < length) {579char nextc = pattern.charAt(i + 1);580if (nextc == '\'') {581i++;582if (count != 0) {583convert(calendarType, lastLetter, count, jrePattern);584lastLetter = 0;585count = 0;586}587jrePattern.append("''");588continue;589}590}591if (!inQuote) {592if (count != 0) {593convert(calendarType, lastLetter, count, jrePattern);594lastLetter = 0;595count = 0;596}597inQuote = true;598} else {599inQuote = false;600}601jrePattern.append(c);602continue;603}604if (inQuote) {605jrePattern.append(c);606continue;607}608if (!(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')) {609if (count != 0) {610convert(calendarType, lastLetter, count, jrePattern);611lastLetter = 0;612count = 0;613}614jrePattern.append(c);615continue;616}617618if (lastLetter == 0 || lastLetter == c) {619lastLetter = c;620count++;621continue;622}623convert(calendarType, lastLetter, count, jrePattern);624lastLetter = c;625count = 1;626}627628if (count != 0) {629convert(calendarType, lastLetter, count, jrePattern);630}631if (cldrFormat.contentEquals(jrePattern)) {632return cldrFormat;633}634return jrePattern.toString();635}636637private static void convert(String calendarType, char cldrLetter, int count, StringBuilder sb) {638switch (cldrLetter) {639case 'G':640if (!calendarType.equals("gregorian")) {641// Adjust the number of 'G's for JRE SimpleDateFormat642if (count == 5) {643// CLDR narrow -> JRE short644count = 1;645} else if (count == 1) {646// CLDR abbr -> JRE long647count = 4;648}649}650appendN(cldrLetter, count, sb);651break;652653// TODO: support 'c' and 'e' in JRE SimpleDateFormat654// Use 'u' and 'E' for now.655case 'c':656case 'e':657switch (count) {658case 1:659sb.append('u');660break;661case 3:662case 4:663appendN('E', count, sb);664break;665case 5:666appendN('E', 3, sb);667break;668}669break;670671case 'v':672case 'V':673appendN('z', count, sb);674break;675676case 'Z':677if (count == 4 || count == 5) {678sb.append("XXX");679}680break;681682case 'u':683case 'U':684case 'q':685case 'Q':686case 'l':687case 'g':688case 'j':689case 'A':690// Unsupported letter. Just append it within quotes691sb.append('\'');692sb.append(cldrLetter);693sb.append('\'');694break;695696default:697appendN(cldrLetter, count, sb);698break;699}700}701702private static void appendN(char c, int n, StringBuilder sb) {703for (int i = 0; i < n; i++) {704sb.append(c);705}706}707708// initialize709private static native String getDefaultLocale(int cat);710711// For DateFormatProvider712private static native String getDateTimePatternNative(int dateStyle, int timeStyle, String langtag);713private static native String getCalendarID(String langTag);714715// For NumberFormatProvider716private static native String getNumberPatternNative(int style, String langtag);717718// For DateFormatSymbolsProvider719private static native String[] getAmPmStrings(String langTag, String[] ampm);720private static native String[] getEras(String langTag, String[] eras);721private static native String[] getMonths(String langTag, String[] months);722private static native String[] getShortMonths(String langTag, String[] smonths);723private static native String[] getWeekdays(String langTag, String[] wdays);724private static native String[] getShortWeekdays(String langTag, String[] swdays);725726// For DecimalFormatSymbolsProvider727private static native String getCurrencySymbol(String langTag, String currencySymbol);728private static native char getDecimalSeparator(String langTag, char decimalSeparator);729private static native char getGroupingSeparator(String langTag, char groupingSeparator);730private static native String getInfinity(String langTag, String infinity);731private static native String getInternationalCurrencySymbol(String langTag, String internationalCurrencySymbol);732private static native char getMinusSign(String langTag, char minusSign);733private static native char getMonetaryDecimalSeparator(String langTag, char monetaryDecimalSeparator);734private static native String getNaN(String langTag, String nan);735private static native char getPercent(String langTag, char percent);736private static native char getPerMill(String langTag, char perMill);737private static native char getZeroDigit(String langTag, char zeroDigit);738private static native String getExponentSeparator(String langTag, String exponent);739740// For CalendarDataProvider741private static native int getCalendarInt(String langTag, int type);742743// For Locale/CurrencyNameProvider744private static native String getDisplayString(String langTag, int key, String value);745746// For TimeZoneNameProvider747private static native String getTimeZoneDisplayString(String langTag, int style, String value);748}749750751