1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.textservices; 18 19 import android.annotation.Nullable; 20 import android.text.TextUtils; 21 22 import java.util.ArrayList; 23 import java.util.Locale; 24 25 /** 26 * Provides {@code Locale} related utility methods for {@link TextServicesManagerService}. 27 * <p>This class is intentionally package-private. Utility methods here are tightly coupled with 28 * implementation details in {@link TextServicesManagerService}. Hence this class is not suitable 29 * for other components to directly use.</p> 30 */ 31 final class LocaleUtils { 32 /** 33 * Returns a list of {@link Locale} in the order of appropriateness for the default spell 34 * checker service. 35 * 36 * <p>If the system language is English, and the region is also explicitly specified in the 37 * system locale, the following fallback order will be applied.</p> 38 * <ul> 39 * <li>(system-locale-language, system-locale-region, system-locale-variant) (if exists)</li> 40 * <li>(system-locale-language, system-locale-region)</li> 41 * <li>("en", "US")</li> 42 * <li>("en", "GB")</li> 43 * <li>("en")</li> 44 * </ul> 45 * 46 * <p>If the system language is English, but no region is specified in the system locale, 47 * the following fallback order will be applied.</p> 48 * <ul> 49 * <li>("en")</li> 50 * <li>("en", "US")</li> 51 * <li>("en", "GB")</li> 52 * </ul> 53 * 54 * <p>If the system language is not English, the following fallback order will be applied.</p> 55 * <ul> 56 * <li>(system-locale-language, system-locale-region, system-locale-variant) (if exists)</li> 57 * <li>(system-locale-language, system-locale-region) (if exists)</li> 58 * <li>(system-locale-language) (if exists)</li> 59 * <li>("en", "US")</li> 60 * <li>("en", "GB")</li> 61 * <li>("en")</li> 62 * </ul> 63 * 64 * @param systemLocale the current system locale to be taken into consideration. 65 * @return a list of {@link Locale}. The first one is considered to be most appropriate. 66 */ getSuitableLocalesForSpellChecker( @ullable final Locale systemLocale)67 public static ArrayList<Locale> getSuitableLocalesForSpellChecker( 68 @Nullable final Locale systemLocale) { 69 final Locale systemLocaleLanguageCountryVariant; 70 final Locale systemLocaleLanguageCountry; 71 final Locale systemLocaleLanguage; 72 if (systemLocale != null) { 73 final String language = systemLocale.getLanguage(); 74 final boolean hasLanguage = !TextUtils.isEmpty(language); 75 final String country = systemLocale.getCountry(); 76 final boolean hasCountry = !TextUtils.isEmpty(country); 77 final String variant = systemLocale.getVariant(); 78 final boolean hasVariant = !TextUtils.isEmpty(variant); 79 if (hasLanguage && hasCountry && hasVariant) { 80 systemLocaleLanguageCountryVariant = new Locale(language, country, variant); 81 } else { 82 systemLocaleLanguageCountryVariant = null; 83 } 84 if (hasLanguage && hasCountry) { 85 systemLocaleLanguageCountry = new Locale(language, country); 86 } else { 87 systemLocaleLanguageCountry = null; 88 } 89 if (hasLanguage) { 90 systemLocaleLanguage = new Locale(language); 91 } else { 92 systemLocaleLanguage = null; 93 } 94 } else { 95 systemLocaleLanguageCountryVariant = null; 96 systemLocaleLanguageCountry = null; 97 systemLocaleLanguage = null; 98 } 99 100 final ArrayList<Locale> locales = new ArrayList<>(); 101 if (systemLocaleLanguageCountryVariant != null) { 102 locales.add(systemLocaleLanguageCountryVariant); 103 } 104 105 if (Locale.ENGLISH.equals(systemLocaleLanguage)) { 106 if (systemLocaleLanguageCountry != null) { 107 // If the system language is English, and the region is also explicitly specified, 108 // following fallback order will be applied. 109 // - systemLocaleLanguageCountry [if systemLocaleLanguageCountry is non-null] 110 // - en_US [if systemLocaleLanguageCountry is non-null and not en_US] 111 // - en_GB [if systemLocaleLanguageCountry is non-null and not en_GB] 112 // - en 113 if (systemLocaleLanguageCountry != null) { 114 locales.add(systemLocaleLanguageCountry); 115 } 116 if (!Locale.US.equals(systemLocaleLanguageCountry)) { 117 locales.add(Locale.US); 118 } 119 if (!Locale.UK.equals(systemLocaleLanguageCountry)) { 120 locales.add(Locale.UK); 121 } 122 locales.add(Locale.ENGLISH); 123 } else { 124 // If the system language is English, but no region is specified, following 125 // fallback order will be applied. 126 // - en 127 // - en_US 128 // - en_GB 129 locales.add(Locale.ENGLISH); 130 locales.add(Locale.US); 131 locales.add(Locale.UK); 132 } 133 } else { 134 // If the system language is not English, the fallback order will be 135 // - systemLocaleLanguageCountry [if non-null] 136 // - systemLocaleLanguage [if non-null] 137 // - en_US 138 // - en_GB 139 // - en 140 if (systemLocaleLanguageCountry != null) { 141 locales.add(systemLocaleLanguageCountry); 142 } 143 if (systemLocaleLanguage != null) { 144 locales.add(systemLocaleLanguage); 145 } 146 locales.add(Locale.US); 147 locales.add(Locale.UK); 148 locales.add(Locale.ENGLISH); 149 } 150 return locales; 151 } 152 } 153