summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3/locale/LocaleSet.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/launcher3/locale/LocaleSet.java')
-rw-r--r--src/com/android/launcher3/locale/LocaleSet.java253
1 files changed, 253 insertions, 0 deletions
diff --git a/src/com/android/launcher3/locale/LocaleSet.java b/src/com/android/launcher3/locale/LocaleSet.java
new file mode 100644
index 000000000..34634ab7e
--- /dev/null
+++ b/src/com/android/launcher3/locale/LocaleSet.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2014 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.launcher3.locale;
+
+import android.text.TextUtils;
+import com.google.common.annotations.VisibleForTesting;
+import java.util.Locale;
+
+public class LocaleSet {
+ private static final String CHINESE_LANGUAGE = Locale.CHINESE.getLanguage().toLowerCase();
+ private static final String JAPANESE_LANGUAGE = Locale.JAPANESE.getLanguage().toLowerCase();
+ private static final String KOREAN_LANGUAGE = Locale.KOREAN.getLanguage().toLowerCase();
+
+ private static class LocaleWrapper {
+ private final Locale mLocale;
+ private final String mLanguage;
+ private final boolean mLocaleIsCJK;
+
+ private static boolean isLanguageCJK(String language) {
+ return CHINESE_LANGUAGE.equals(language) ||
+ JAPANESE_LANGUAGE.equals(language) ||
+ KOREAN_LANGUAGE.equals(language);
+ }
+
+ public LocaleWrapper(Locale locale) {
+ mLocale = locale;
+ if (mLocale != null) {
+ mLanguage = mLocale.getLanguage().toLowerCase();
+ mLocaleIsCJK = isLanguageCJK(mLanguage);
+ } else {
+ mLanguage = null;
+ mLocaleIsCJK = false;
+ }
+ }
+
+ public boolean hasLocale() {
+ return mLocale != null;
+ }
+
+ public Locale getLocale() {
+ return mLocale;
+ }
+
+ public boolean isLocale(Locale locale) {
+ return mLocale == null ? (locale == null) : mLocale.equals(locale);
+ }
+
+ public boolean isLocaleCJK() {
+ return mLocaleIsCJK;
+ }
+
+ public boolean isLanguage(String language) {
+ return mLanguage == null ? (language == null)
+ : mLanguage.equalsIgnoreCase(language);
+ }
+
+ public String toString() {
+ return mLocale != null ? mLocale.toLanguageTag() : "(null)";
+ }
+ }
+
+ public static LocaleSet getDefault() {
+ return new LocaleSet(Locale.getDefault());
+ }
+
+ public LocaleSet(Locale locale) {
+ this(locale, null);
+ }
+
+ /**
+ * Returns locale set for a given set of IETF BCP-47 tags separated by ';'.
+ * BCP-47 tags are what is used by ICU 52's toLanguageTag/forLanguageTag
+ * methods to represent individual Locales: "en-US" for Locale.US,
+ * "zh-CN" for Locale.CHINA, etc. So eg "en-US;zh-CN" specifies the locale
+ * set LocaleSet(Locale.US, Locale.CHINA).
+ *
+ * @param localeString One or more BCP-47 tags separated by ';'.
+ * @return LocaleSet for specified locale string, or default set if null
+ * or unable to parse.
+ */
+ public static LocaleSet getLocaleSet(String localeString) {
+ // Locale.toString() generates strings like "en_US" and "zh_CN_#Hans".
+ // Locale.toLanguageTag() generates strings like "en-US" and "zh-Hans-CN".
+ // We can only parse language tags.
+ if (localeString != null && localeString.indexOf('_') == -1) {
+ final String[] locales = localeString.split(";");
+ final Locale primaryLocale = Locale.forLanguageTag(locales[0]);
+ // ICU tags undefined/unparseable locales "und"
+ if (primaryLocale != null &&
+ !TextUtils.equals(primaryLocale.toLanguageTag(), "und")) {
+ if (locales.length > 1 && locales[1] != null) {
+ final Locale secondaryLocale = Locale.forLanguageTag(locales[1]);
+ if (secondaryLocale != null &&
+ !TextUtils.equals(secondaryLocale.toLanguageTag(), "und")) {
+ return new LocaleSet(primaryLocale, secondaryLocale);
+ }
+ }
+ return new LocaleSet(primaryLocale);
+ }
+ }
+ return getDefault();
+ }
+
+ private final LocaleWrapper mPrimaryLocale;
+ private final LocaleWrapper mSecondaryLocale;
+
+ public LocaleSet(Locale primaryLocale, Locale secondaryLocale) {
+ mPrimaryLocale = new LocaleWrapper(primaryLocale);
+ mSecondaryLocale = new LocaleWrapper(
+ mPrimaryLocale.equals(secondaryLocale) ? null : secondaryLocale);
+ }
+
+ public LocaleSet normalize() {
+ final Locale primaryLocale = getPrimaryLocale();
+ if (primaryLocale == null) {
+ return getDefault();
+ }
+ Locale secondaryLocale = getSecondaryLocale();
+ // disallow both locales with same language (redundant and/or conflicting)
+ // disallow both locales CJK (conflicting rules)
+ if (secondaryLocale == null ||
+ isPrimaryLanguage(secondaryLocale.getLanguage()) ||
+ (isPrimaryLocaleCJK() && isSecondaryLocaleCJK())) {
+ return new LocaleSet(primaryLocale);
+ }
+ // unnecessary to specify English as secondary locale (redundant)
+ if (isSecondaryLanguage(Locale.ENGLISH.getLanguage())) {
+ return new LocaleSet(primaryLocale);
+ }
+ return this;
+ }
+
+ public boolean hasSecondaryLocale() {
+ return mSecondaryLocale.hasLocale();
+ }
+
+ public Locale getPrimaryLocale() {
+ return mPrimaryLocale.getLocale();
+ }
+
+ public Locale getSecondaryLocale() {
+ return mSecondaryLocale.getLocale();
+ }
+
+ public boolean isPrimaryLocale(Locale locale) {
+ return mPrimaryLocale.isLocale(locale);
+ }
+
+ public boolean isSecondaryLocale(Locale locale) {
+ return mSecondaryLocale.isLocale(locale);
+ }
+
+ private static final String SCRIPT_SIMPLIFIED_CHINESE = "Hans";
+ private static final String SCRIPT_TRADITIONAL_CHINESE = "Hant";
+
+ @VisibleForTesting
+ public static boolean isLocaleSimplifiedChinese(Locale locale) {
+ // language must match
+ if (locale == null || !TextUtils.equals(locale.getLanguage(), CHINESE_LANGUAGE)) {
+ return false;
+ }
+ // script is optional but if present must match
+ if (!TextUtils.isEmpty(locale.getScript())) {
+ return locale.getScript().equals(SCRIPT_SIMPLIFIED_CHINESE);
+ }
+ // if no script, must match known country
+ return locale.equals(Locale.SIMPLIFIED_CHINESE);
+ }
+
+ public boolean isPrimaryLocaleSimplifiedChinese() {
+ return isLocaleSimplifiedChinese(getPrimaryLocale());
+ }
+
+ public boolean isSecondaryLocaleSimplifiedChinese() {
+ return isLocaleSimplifiedChinese(getSecondaryLocale());
+ }
+
+ @VisibleForTesting
+ public static boolean isLocaleTraditionalChinese(Locale locale) {
+ // language must match
+ if (locale == null || !TextUtils.equals(locale.getLanguage(), CHINESE_LANGUAGE)) {
+ return false;
+ }
+ // script is optional but if present must match
+ if (!TextUtils.isEmpty(locale.getScript())) {
+ return locale.getScript().equals(SCRIPT_TRADITIONAL_CHINESE);
+ }
+ // if no script, must match known country
+ return locale.equals(Locale.TRADITIONAL_CHINESE);
+ }
+
+ public boolean isPrimaryLocaleTraditionalChinese() {
+ return isLocaleTraditionalChinese(getPrimaryLocale());
+ }
+
+ public boolean isSecondaryLocaleTraditionalChinese() {
+ return isLocaleTraditionalChinese(getSecondaryLocale());
+ }
+
+ public boolean isPrimaryLocaleCJK() {
+ return mPrimaryLocale.isLocaleCJK();
+ }
+
+ public boolean isSecondaryLocaleCJK() {
+ return mSecondaryLocale.isLocaleCJK();
+ }
+
+ public boolean isPrimaryLanguage(String language) {
+ return mPrimaryLocale.isLanguage(language);
+ }
+
+ public boolean isSecondaryLanguage(String language) {
+ return mSecondaryLocale.isLanguage(language);
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (object == this) {
+ return true;
+ }
+ if (object instanceof LocaleSet) {
+ final LocaleSet other = (LocaleSet) object;
+ return other.isPrimaryLocale(mPrimaryLocale.getLocale())
+ && other.isSecondaryLocale(mSecondaryLocale.getLocale());
+ }
+ return false;
+ }
+
+ @Override
+ public final String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append(mPrimaryLocale.toString());
+ if (hasSecondaryLocale()) {
+ builder.append(";");
+ builder.append(mSecondaryLocale.toString());
+ }
+ return builder.toString();
+ }
+}