| /* |
| * Copyright (C) 2022 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.settings.regionalpreferences; |
| import android.icu.number.LocalizedNumberFormatter; |
| import android.icu.number.NumberFormatter; |
| import android.icu.text.DateFormat; |
| import android.icu.text.DateTimePatternGenerator; |
| import android.icu.util.MeasureUnit; |
| import android.os.Build.VERSION; |
| |
| import androidx.annotation.DoNotInline; |
| import androidx.annotation.NonNull; |
| import androidx.annotation.OptIn; |
| import androidx.annotation.RestrictTo; |
| import androidx.annotation.StringDef; |
| import androidx.core.os.BuildCompat; |
| |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| import java.util.Locale; |
| import java.util.Locale.Category; |
| |
| /** |
| * TODO(b/263861083) This is a temp file and will replace it to Androidx version. |
| * Provides friendly APIs to get the user's locale preferences. The data can refer to |
| * external/cldr/common/main/en.xml. |
| */ |
| public final class LocalePreferences { |
| private static final String TAG = LocalePreferences.class.getSimpleName(); |
| |
| /** APIs to get the user's preference of the hour cycle. */ |
| public static class HourCycle { |
| private static final String U_EXTENSION_OF_HOUR_CYCLE = "hc"; |
| |
| /** 12 Hour System (0-11) */ |
| public static final String H11 = "h11"; |
| /** 12 Hour System (1-12) */ |
| public static final String H12 = "h12"; |
| /** 24 Hour System (0-23) */ |
| public static final String H23 = "h23"; |
| /** 24 Hour System (1-24) */ |
| public static final String H24 = "h24"; |
| /** Default hour cycle for the locale */ |
| public static final String DEFAULT = ""; |
| |
| /** @hide */ |
| @RestrictTo(RestrictTo.Scope.LIBRARY) |
| @StringDef({ |
| H11, |
| H12, |
| H23, |
| H24, |
| DEFAULT |
| }) |
| @Retention(RetentionPolicy.SOURCE) |
| public @interface HourCycleTypes { |
| } |
| |
| private HourCycle() { |
| } |
| } |
| |
| /** |
| * Return the user's preference of the hour cycle which is from |
| * {@link Locale#getDefault(Locale.Category)}. The returned result is resolved and |
| * bases on the {@code Locale#getDefault(Locale.Category)}. E.g. "h23" |
| */ |
| @NonNull |
| @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class) |
| @HourCycle.HourCycleTypes |
| public static String getHourCycle() { |
| return getHourCycle(true); |
| } |
| |
| /** |
| * Return the hour cycle setting of the inputted {@link Locale}. The returned result is resolved |
| * and bases on the inputted {@code Locale}. |
| * E.g. "h23" |
| */ |
| @NonNull |
| @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class) |
| @HourCycle.HourCycleTypes |
| public static String getHourCycle(@NonNull Locale locale) { |
| return getHourCycle(locale, true); |
| } |
| |
| /** |
| * Return the user's preference of the hour cycle which is from |
| * {@link Locale#getDefault(Locale.Category)}. E.g. "h23" |
| * |
| * @param resolved If the {@code Locale#getDefault(Locale.Category)} contains hour cycle subtag, |
| * this argument is ignored. If the |
| * {@code Locale#getDefault(Locale.Category)} doesn't contain hour cycle subtag |
| * and the resolved argument is true, this function tries to find the default |
| * hour cycle for the {@code Locale#getDefault(Locale.Category)}. If the |
| * {@code Locale#getDefault(Locale.Category)} doesn't contain hour cycle subtag |
| * and the resolved argument is false, this function returns empty string |
| * i.e. HourCycle.Default. |
| * @return {@link HourCycle.HourCycleTypes} If the malformed hour cycle format was specified |
| * in the hour cycle subtag, e.g. en-US-u-hc-h32, this function returns empty string |
| * i.e. HourCycle.Default. |
| */ |
| @NonNull |
| @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class) |
| @HourCycle.HourCycleTypes |
| public static String getHourCycle( |
| boolean resolved) { |
| return getHourCycle(Api33Impl.getDefaultLocale(), resolved); |
| } |
| |
| /** |
| * Return the hour cycle setting of the inputted {@link Locale}. E.g. "en-US-u-hc-h23". |
| * |
| * @param locale The {@code Locale} to get the hour cycle. |
| * @param resolved If the given {@code Locale} contains hour cycle subtag, this argument is |
| * ignored. If the given {@code Locale} doesn't contain hour cycle subtag and |
| * the resolved argument is true, this function tries to find the default |
| * hour cycle for the given {@code Locale}. If the given {@code Locale} doesn't |
| * contain hour cycle subtag and the resolved argument is false, this function |
| * return empty string i.e. HourCycle.Default. |
| * @return {@link HourCycle.HourCycleTypes} If the malformed hour cycle format was specified |
| * in the hour cycle subtag, e.g. en-US-u-hc-h32, this function returns empty string |
| * i.e. HourCycle.Default. |
| */ |
| @NonNull |
| @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class) |
| @HourCycle.HourCycleTypes |
| public static String getHourCycle(@NonNull Locale locale, boolean resolved) { |
| if (!BuildCompat.isAtLeastT()) { |
| throw new IllegalArgumentException("not a valid extension: " + VERSION.SDK_INT); |
| } |
| return Api33Impl.getHourCycle(locale, resolved); |
| } |
| |
| /** APIs to get the user's preference of Calendar. */ |
| public static class CalendarType { |
| private static final String U_EXTENSION_OF_CALENDAR = "ca"; |
| /** Chinese Calendar */ |
| public static final String CHINESE = "chinese"; |
| /** Dangi Calendar (Korea Calendar) */ |
| public static final String DANGI = "dangi"; |
| /** Gregorian Calendar */ |
| public static final String GREGORIAN = "gregorian"; |
| /** Hebrew Calendar */ |
| public static final String HEBREW = "hebrew"; |
| /** Indian National Calendar */ |
| public static final String INDIAN = "indian"; |
| /** Islamic Calendar */ |
| public static final String ISLAMIC = "islamic"; |
| /** Islamic Calendar (tabular, civil epoch) */ |
| public static final String ISLAMIC_CIVIL = "islamic-civil"; |
| /** Islamic Calendar (Saudi Arabia, sighting) */ |
| public static final String ISLAMIC_RGSA = "islamic-rgsa"; |
| /** Islamic Calendar (tabular, astronomical epoch) */ |
| public static final String ISLAMIC_TBLA = "islamic-tbla"; |
| /** Islamic Calendar (Umm al-Qura) */ |
| public static final String ISLAMIC_UMALQURA = "islamic-umalqura"; |
| /** Persian Calendar */ |
| public static final String PERSIAN = "persian"; |
| /** Default calendar for the locale */ |
| public static final String DEFAULT = ""; |
| |
| /** @hide */ |
| @RestrictTo(RestrictTo.Scope.LIBRARY) |
| @StringDef({ |
| CHINESE, |
| DANGI, |
| GREGORIAN, |
| HEBREW, |
| INDIAN, |
| ISLAMIC, |
| ISLAMIC_CIVIL, |
| ISLAMIC_RGSA, |
| ISLAMIC_TBLA, |
| ISLAMIC_UMALQURA, |
| PERSIAN, |
| DEFAULT |
| }) |
| @Retention(RetentionPolicy.SOURCE) |
| public @interface CalendarTypes { |
| } |
| |
| private CalendarType() { |
| } |
| } |
| |
| /** |
| * Return the user's preference of the calendar type which is from {@link |
| * Locale#getDefault(Locale.Category)}. The returned result is resolved and bases on |
| * the {@code Locale#getDefault(Locale.Category)} settings. E.g. "chinese" |
| */ |
| @NonNull |
| @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class) |
| @CalendarType.CalendarTypes |
| public static String getCalendarType() { |
| return getCalendarType(true); |
| } |
| |
| /** |
| * Return the calendar type of the inputted {@link Locale}. The returned result is resolved and |
| * bases on the inputted {@link Locale} settings. |
| * E.g. "chinese" |
| */ |
| @NonNull |
| @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class) |
| @CalendarType.CalendarTypes |
| public static String getCalendarType(@NonNull Locale locale) { |
| return getCalendarType(locale, true); |
| } |
| |
| /** |
| * Return the user's preference of the calendar type which is from {@link |
| * Locale#getDefault(Locale.Category)}. E.g. "chinese" |
| * |
| * @param resolved If the {@code Locale#getDefault(Locale.Category)} contains calendar type |
| * subtag, this argument is ignored. If the |
| * {@code Locale#getDefault(Locale.Category)} doesn't contain calendar type |
| * subtag and the resolved argument is true, this function tries to find |
| * the default calendar type for the |
| * {@code Locale#getDefault(Locale.Category)}. If the |
| * {@code Locale#getDefault(Locale.Category)} doesn't contain calendar type |
| * subtag and the resolved argument is false, this function returns empty string |
| * i.e. CalendarTypes.Default. |
| * @return {@link CalendarType.CalendarTypes} If the malformed calendar type format was |
| * specified in the calendar type subtag, e.g. en-US-u-ca-calendar, this function returns |
| * empty string i.e. CalendarTypes.Default. |
| */ |
| @NonNull |
| @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class) |
| @CalendarType.CalendarTypes |
| public static String getCalendarType(boolean resolved) { |
| return getCalendarType(Api33Impl.getDefaultLocale(), resolved); |
| } |
| |
| /** |
| * Return the calendar type of the inputted {@link Locale}. E.g. "chinese" |
| * |
| * @param locale The {@link Locale} to get the calendar type. |
| * @param resolved If the given {@code Locale} contains calendar type subtag, this argument is |
| * ignored. If the given {@code Locale} doesn't contain calendar type subtag and |
| * the resolved argument is true, this function tries to find the default |
| * calendar type for the given {@code Locale}. If the given {@code Locale} |
| * doesn't contain calendar type subtag and the resolved argument is false, this |
| * function return empty string i.e. CalendarTypes.Default. |
| * @return {@link CalendarType.CalendarTypes} If the malformed calendar type format was |
| * specified in the calendar type subtag, e.g. en-US-u-ca-calendar, this function returns |
| * empty string i.e. CalendarTypes.Default. |
| */ |
| @NonNull |
| @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class) |
| @CalendarType.CalendarTypes |
| public static String getCalendarType(@NonNull Locale locale, boolean resolved) { |
| if (!BuildCompat.isAtLeastT()) { |
| throw new IllegalArgumentException("not a valid extension: " + VERSION.SDK_INT); |
| } |
| return Api33Impl.getCalendarType(locale, resolved); |
| } |
| |
| /** APIs to get the user's preference of temperature unit. */ |
| public static class TemperatureUnit { |
| private static final String U_EXTENSION_OF_TEMPERATURE_UNIT = "mu"; |
| /** Celsius */ |
| public static final String CELSIUS = "celsius"; |
| /** Fahrenheit */ |
| public static final String FAHRENHEIT = "fahrenhe"; |
| /** Kelvin */ |
| public static final String KELVIN = "kelvin"; |
| /** Default Temperature for the locale */ |
| public static final String DEFAULT = ""; |
| |
| /** @hide */ |
| @RestrictTo(RestrictTo.Scope.LIBRARY) |
| @StringDef({ |
| CELSIUS, |
| FAHRENHEIT, |
| KELVIN, |
| DEFAULT |
| }) |
| @Retention(RetentionPolicy.SOURCE) |
| public @interface TemperatureUnits { |
| } |
| |
| private TemperatureUnit() { |
| } |
| } |
| |
| /** |
| * Return the user's preference of the temperature unit which is from {@link |
| * Locale#getDefault(Locale.Category)}. The returned result is resolved and bases on the |
| * {@code Locale#getDefault(Locale.Category)} settings. E.g. "fahrenhe" |
| */ |
| @NonNull |
| @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class) |
| @TemperatureUnit.TemperatureUnits |
| public static String getTemperatureUnit() { |
| return getTemperatureUnit(true); |
| } |
| |
| /** |
| * Return the temperature unit of the inputted {@link Locale}. The returned result is resolved |
| * and bases on the inputted {@code Locale} settings. E.g. "fahrenhe" |
| */ |
| @NonNull |
| @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class) |
| @TemperatureUnit.TemperatureUnits |
| public static String getTemperatureUnit( |
| @NonNull Locale locale) { |
| return getTemperatureUnit(locale, true); |
| } |
| |
| /** |
| * Return the user's preference of the temperature unit which is from {@link |
| * Locale#getDefault(Locale.Category)}. E.g. "fahrenhe" |
| * |
| * @param resolved If the {@code Locale#getDefault(Locale.Category)} contains temperature unit |
| * subtag, this argument is ignored. If the |
| * {@code Locale#getDefault(Locale.Category)} doesn't contain temperature unit |
| * subtag and the resolved argument is true, this function tries to find |
| * the default temperature unit for the |
| * {@code Locale#getDefault(Locale.Category)}. If the |
| * {@code Locale#getDefault(Locale.Category)} doesn't contain temperature unit |
| * subtag and the resolved argument is false, this function returns empty string |
| * i.e. TemperatureUnits.Default. |
| * @return {@link TemperatureUnit.TemperatureUnits} If the malformed temperature unit format was |
| * specified in the temperature unit subtag, e.g. en-US-u-mu-temperature, this function returns |
| * empty string i.e. TemperatureUnits.Default. |
| */ |
| @NonNull |
| @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class) |
| @TemperatureUnit.TemperatureUnits |
| public static String getTemperatureUnit(boolean resolved) { |
| return getTemperatureUnit(Api33Impl.getDefaultLocale(), resolved); |
| } |
| |
| /** |
| * Return the temperature unit of the inputted {@link Locale}. E.g. "fahrenheit" |
| * |
| * @param locale The {@link Locale} to get the temperature unit. |
| * @param resolved If the given {@code Locale} contains temperature unit subtag, this argument |
| * is ignored. If the given {@code Locale} doesn't contain temperature unit |
| * subtag and the resolved argument is true, this function tries to find |
| * the default temperature unit for the given {@code Locale}. If the given |
| * {@code Locale} doesn't contain temperature unit subtag and the resolved |
| * argument is false, this function return empty string |
| * i.e. TemperatureUnits.Default. |
| * @return {@link TemperatureUnit.TemperatureUnits} If the malformed temperature unit format was |
| * specified in the temperature unit subtag, e.g. en-US-u-mu-temperature, this function returns |
| * empty string i.e. TemperatureUnits.Default. |
| */ |
| @NonNull |
| @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class) |
| @TemperatureUnit.TemperatureUnits |
| public static String getTemperatureUnit(@NonNull Locale locale, boolean resolved) { |
| if (!BuildCompat.isAtLeastT()) { |
| throw new IllegalArgumentException("not a valid extension: " + VERSION.SDK_INT); |
| } |
| return Api33Impl.getTemperatureUnit(locale, resolved); |
| } |
| |
| /** APIs to get the user's preference of the first day of week. */ |
| public static class FirstDayOfWeek { |
| private static final String U_EXTENSION_OF_FIRST_DAY_OF_WEEK = "fw"; |
| /** Sunday */ |
| public static final String SUNDAY = "sun"; |
| /** Monday */ |
| public static final String MONDAY = "mon"; |
| /** Tuesday */ |
| public static final String TUESDAY = "tue"; |
| /** Wednesday */ |
| public static final String WEDNESDAY = "wed"; |
| /** Thursday */ |
| public static final String THURSDAY = "thu"; |
| /** Friday */ |
| public static final String FRIDAY = "fri"; |
| /** Saturday */ |
| public static final String SATURDAY = "sat"; |
| /** Default first day of week for the locale */ |
| public static final String DEFAULT = ""; |
| |
| /** @hide */ |
| @RestrictTo(RestrictTo.Scope.LIBRARY) |
| @StringDef({ |
| SUNDAY, |
| MONDAY, |
| TUESDAY, |
| WEDNESDAY, |
| THURSDAY, |
| FRIDAY, |
| SATURDAY, |
| DEFAULT |
| }) |
| @Retention(RetentionPolicy.SOURCE) |
| public @interface Days { |
| } |
| |
| private FirstDayOfWeek() { |
| } |
| } |
| |
| /** |
| * Return the user's preference of the first day of week which is from |
| * {@link Locale#getDefault(Locale.Category)}. The returned result is resolved and bases on the |
| * {@code Locale#getDefault(Locale.Category)} settings. E.g. "sun" |
| */ |
| @NonNull |
| @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class) |
| @FirstDayOfWeek.Days |
| public static String getFirstDayOfWeek() { |
| return getFirstDayOfWeek(true); |
| } |
| |
| /** |
| * Return the first day of week of the inputted {@link Locale}. The returned result is resolved |
| * and bases on the inputted {@code Locale} settings. |
| * E.g. "sun" |
| */ |
| @NonNull |
| @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class) |
| public static @FirstDayOfWeek.Days String getFirstDayOfWeek(@NonNull Locale locale) { |
| return getFirstDayOfWeek(locale, true); |
| } |
| |
| /** |
| * Return the user's preference of the first day of week which is from {@link |
| * Locale#getDefault(Locale.Category)}. E.g. "sun" |
| * |
| * @param resolved If the {@code Locale#getDefault(Locale.Category)} contains first day of week |
| * subtag, this argument is ignored. If the |
| * {@code Locale#getDefault(Locale.Category)} doesn't contain first day of week |
| * subtag and the resolved argument is true, this function tries to find |
| * the default first day of week for the |
| * {@code Locale#getDefault(Locale.Category)}. If the |
| * {@code Locale#getDefault(Locale.Category)} doesn't contain first day of week |
| * subtag and the resolved argument is false, this function returns empty string |
| * i.e. Days.Default. |
| * @return {@link FirstDayOfWeek.Days} If the malformed first day of week format was specified |
| * in the first day of week subtag, e.g. en-US-u-fw-days, this function returns empty string |
| * i.e. Days.Default. |
| */ |
| @NonNull |
| @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class) |
| @FirstDayOfWeek.Days |
| public static String getFirstDayOfWeek(boolean resolved) { |
| return getFirstDayOfWeek(Api33Impl.getDefaultLocale(), resolved); |
| } |
| |
| /** |
| * Return the first day of week of the inputted {@link Locale}. E.g. "sun" |
| * |
| * @param locale The {@link Locale} to get the first day of week. |
| * @param resolved If the given {@code Locale} contains first day of week subtag, this argument |
| * is ignored. If the given {@code Locale} doesn't contain first day of week |
| * subtag and the resolved argument is true, this function tries to find |
| * the default first day of week for the given {@code Locale}. If the given |
| * {@code Locale} doesn't contain first day of week subtag and the resolved |
| * argument is false, this function return empty string i.e. Days.Default. |
| * @return {@link FirstDayOfWeek.Days} If the malformed first day of week format was |
| * specified in the first day of week subtag, e.g. en-US-u-fw-days, this function returns |
| * empty string i.e. Days.Default. |
| */ |
| @NonNull |
| @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class) |
| @FirstDayOfWeek.Days |
| public static String getFirstDayOfWeek( |
| @NonNull Locale locale, boolean resolved) { |
| if (!BuildCompat.isAtLeastT()) { |
| throw new IllegalArgumentException("not a valid extension: " + VERSION.SDK_INT); |
| } |
| |
| return Api33Impl.getFirstDayOfWeek(locale, resolved); |
| } |
| |
| private static class Api33Impl { |
| @DoNotInline |
| @HourCycle.HourCycleTypes |
| static String getHourCycle(@NonNull Locale locale, |
| boolean resolved) { |
| String hc = locale.getUnicodeLocaleType(HourCycle.U_EXTENSION_OF_HOUR_CYCLE); |
| if (hc != null) { |
| return hc; |
| } |
| if (!resolved) { |
| return HourCycle.DEFAULT; |
| } |
| |
| return getHourCycleType( |
| DateTimePatternGenerator.getInstance(locale).getDefaultHourCycle()); |
| |
| } |
| |
| @DoNotInline |
| @CalendarType.CalendarTypes |
| static String getCalendarType(@NonNull Locale locale, boolean resolved) { |
| String ca = locale.getUnicodeLocaleType(CalendarType.U_EXTENSION_OF_CALENDAR); |
| if (ca != null) { |
| return ca; |
| } |
| if (!resolved) { |
| return CalendarType.DEFAULT; |
| } |
| |
| return android.icu.util.Calendar.getInstance(locale).getType(); |
| } |
| |
| @DoNotInline |
| @TemperatureUnit.TemperatureUnits |
| static String getTemperatureUnit(@NonNull Locale locale, boolean resolved) { |
| String mu = |
| locale.getUnicodeLocaleType(TemperatureUnit.U_EXTENSION_OF_TEMPERATURE_UNIT); |
| if (mu != null) { |
| return mu; |
| } |
| if (!resolved) { |
| return TemperatureUnit.DEFAULT; |
| } |
| |
| return getResolvedTemperatureUnit(locale); |
| } |
| |
| @DoNotInline |
| @FirstDayOfWeek.Days |
| static String getFirstDayOfWeek(@NonNull Locale locale, boolean resolved) { |
| String mu = |
| locale.getUnicodeLocaleType(FirstDayOfWeek.U_EXTENSION_OF_FIRST_DAY_OF_WEEK); |
| if (mu != null) { |
| return mu; |
| } |
| if (!resolved) { |
| return FirstDayOfWeek.DEFAULT; |
| } |
| // TODO(b/262294472) Use {@code android.icu.util.Calendar} instead of |
| // {@code java.util.Calendar}. |
| return getStringOfFirstDayOfWeek( |
| java.util.Calendar.getInstance(locale).getFirstDayOfWeek()); |
| } |
| |
| @DoNotInline |
| static Locale getDefaultLocale() { |
| return Locale.getDefault(Category.FORMAT); |
| } |
| |
| private static String getStringOfFirstDayOfWeek(int fw) { |
| String[] arrDays = { |
| FirstDayOfWeek.SUNDAY, |
| FirstDayOfWeek.MONDAY, |
| FirstDayOfWeek.TUESDAY, |
| FirstDayOfWeek.WEDNESDAY, |
| FirstDayOfWeek.THURSDAY, |
| FirstDayOfWeek.FRIDAY, |
| FirstDayOfWeek.SATURDAY}; |
| |
| return fw >= 1 && fw <= 7 ? arrDays[fw - 1] : FirstDayOfWeek.DEFAULT; |
| } |
| |
| @HourCycle.HourCycleTypes |
| private static String getHourCycleType( |
| DateFormat.HourCycle hourCycle) { |
| switch (hourCycle) { |
| case HOUR_CYCLE_11: |
| return HourCycle.H11; |
| case HOUR_CYCLE_12: |
| return HourCycle.H12; |
| case HOUR_CYCLE_23: |
| return HourCycle.H23; |
| case HOUR_CYCLE_24: |
| return HourCycle.H24; |
| default: |
| return HourCycle.DEFAULT; |
| } |
| } |
| |
| @TemperatureUnit.TemperatureUnits |
| private static String getResolvedTemperatureUnit(@NonNull Locale locale) { |
| LocalizedNumberFormatter nf = NumberFormatter.with() |
| .usage("temperature") |
| .unit(MeasureUnit.CELSIUS) |
| .locale(locale); |
| String unit = nf.format(1).getOutputUnit().getIdentifier(); |
| if (unit.contains(TemperatureUnit.FAHRENHEIT)) { |
| return TemperatureUnit.FAHRENHEIT; |
| } |
| return unit; |
| } |
| |
| private Api33Impl() { |
| } |
| } |
| |
| private LocalePreferences() { |
| } |
| } |