1 /* 2 * Copyright (C) 2014 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.providers.contacts; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.icu.util.ULocale; 22 import android.os.LocaleList; 23 import android.text.TextUtils; 24 25 import com.google.common.annotations.VisibleForTesting; 26 import java.util.Locale; 27 import java.util.Objects; 28 29 public class LocaleSet { 30 private static final String SCRIPT_SIMPLIFIED_CHINESE = "Hans"; 31 private static final String SCRIPT_TRADITIONAL_CHINESE = "Hant"; 32 33 private final Locale mDefaultLocaleOverrideForTest; 34 private final LocaleList mLocaleList; 35 LocaleSet(LocaleList localeList, Locale defaultLocaleOverrideForTest)36 private LocaleSet(LocaleList localeList, Locale defaultLocaleOverrideForTest) { 37 mLocaleList = localeList; 38 mDefaultLocaleOverrideForTest = defaultLocaleOverrideForTest; 39 } 40 newDefault()41 public static LocaleSet newDefault() { 42 return new LocaleSet(LocaleList.getDefault(), 43 /*defaultLocaleOverrideForTest= */ null); 44 } 45 46 @VisibleForTesting newForTest(Locale... locales)47 public static LocaleSet newForTest(Locale... locales) { 48 return new LocaleSet(new LocaleList(locales), locales[0]); 49 } 50 51 @VisibleForTesting isLanguageChinese(@ullable Locale locale)52 static boolean isLanguageChinese(@Nullable Locale locale) { 53 return locale != null && "zh".equals(locale.getLanguage()); 54 } 55 56 @VisibleForTesting isLanguageJapanese(@ullable Locale locale)57 static boolean isLanguageJapanese(@Nullable Locale locale) { 58 return locale != null && "ja".equals(locale.getLanguage()); 59 } 60 61 @VisibleForTesting isLanguageKorean(@ullable Locale locale)62 static boolean isLanguageKorean(@Nullable Locale locale) { 63 return locale != null && "ko".equals(locale.getLanguage()); 64 } 65 66 @VisibleForTesting isLocaleCJK(@ullable Locale locale)67 static boolean isLocaleCJK(@Nullable Locale locale) { 68 return isLanguageChinese(locale) || 69 isLanguageJapanese(locale) || 70 isLanguageKorean(locale); 71 } 72 getLikelyScript(Locale locale)73 private static String getLikelyScript(Locale locale) { 74 final String script = locale.getScript(); 75 if (!script.isEmpty()) { 76 return script; 77 } else { 78 return ULocale.addLikelySubtags(ULocale.forLocale(locale)).getScript(); 79 } 80 } 81 82 /** 83 * @return the script if the language is Chinese, and otherwise null. 84 */ 85 @VisibleForTesting getScriptIfChinese(@ullable Locale locale)86 static String getScriptIfChinese(@Nullable Locale locale) { 87 return isLanguageChinese(locale) ? getLikelyScript(locale) : null; 88 } 89 isLocaleSimplifiedChinese(@ullable Locale locale)90 static boolean isLocaleSimplifiedChinese(@Nullable Locale locale) { 91 return SCRIPT_SIMPLIFIED_CHINESE.equals(getScriptIfChinese(locale)); 92 } 93 94 @VisibleForTesting isLocaleTraditionalChinese(@ullable Locale locale)95 static boolean isLocaleTraditionalChinese(@Nullable Locale locale) { 96 return SCRIPT_TRADITIONAL_CHINESE.equals(getScriptIfChinese(locale)); 97 } 98 99 /** 100 * Returns the primary locale, which may not be the first item of {@link #getAllLocales}. 101 * (See {@link LocaleList}) 102 */ getPrimaryLocale()103 public @NonNull Locale getPrimaryLocale() { 104 if (mDefaultLocaleOverrideForTest != null) { 105 return mDefaultLocaleOverrideForTest; 106 } 107 return Locale.getDefault(); 108 } 109 getAllLocales()110 public @NonNull LocaleList getAllLocales() { 111 return mLocaleList; 112 } 113 isPrimaryLocaleCJK()114 public boolean isPrimaryLocaleCJK() { 115 return isLocaleCJK(getPrimaryLocale()); 116 } 117 118 /** 119 * @return true if Japanese is found in the list before simplified Chinese. 120 */ shouldPreferJapanese()121 public boolean shouldPreferJapanese() { 122 if (isLanguageJapanese(getPrimaryLocale())) { 123 return true; 124 } 125 for (int i = 0; i < mLocaleList.size(); i++) { 126 final Locale l = mLocaleList.get(i); 127 if (isLanguageJapanese(l)) { 128 return true; 129 } 130 if (isLanguageChinese(l)) { 131 return false; 132 } 133 } 134 return false; 135 } 136 137 /** 138 * @return true if simplified Chinese is found before Japanese or traditional Chinese. 139 */ shouldPreferSimplifiedChinese()140 public boolean shouldPreferSimplifiedChinese() { 141 if (isLocaleSimplifiedChinese(getPrimaryLocale())) { 142 return true; 143 } 144 for (int i = 0; i < mLocaleList.size(); i++) { 145 final Locale l = mLocaleList.get(i); 146 if (isLocaleSimplifiedChinese(l)) { 147 return true; 148 } 149 if (isLanguageJapanese(l)) { 150 return false; 151 } 152 if (isLocaleTraditionalChinese(l)) { // Traditional chinese wins here. 153 return false; 154 } 155 } 156 return false; 157 } 158 159 /** 160 * @return true if the instance contains the current system locales. 161 */ isCurrent()162 public boolean isCurrent() { 163 return Objects.equals(mLocaleList, LocaleList.getDefault()); 164 } 165 166 @Override equals(Object object)167 public boolean equals(Object object) { 168 if (object == this) { 169 return true; 170 } 171 if (object instanceof LocaleSet) { 172 final LocaleSet other = (LocaleSet) object; 173 return mLocaleList.equals(other.mLocaleList); 174 } 175 return false; 176 } 177 178 @Override toString()179 public final String toString() { 180 return mLocaleList.toString(); 181 } 182 } 183