Java tutorial
/* * 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.providers.contacts; import java.util.Locale; import android.os.Build; import android.support.v4.text.ICUCompat; import android.text.TextUtils; public class LocaleSet { private static final String CHINESE_LANGUAGE = Locale.CHINESE.getLanguage().toLowerCase(); private static class LocaleWrapper { private final Locale mLocale; private final String mLanguage; public LocaleWrapper(Locale locale) { mLocale = locale; if (mLocale != null) { mLanguage = mLocale.getLanguage().toLowerCase(); } else { mLanguage = null; } } 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 isLanguage(String language) { return mLanguage == null ? (language == null) : mLanguage.equalsIgnoreCase(language); } public String toString() { return mLocale != null ? toBcp47Language(mLocale) : "(null)"; } } public static LocaleSet getDefault() { return new LocaleSet(Locale.getDefault()); } public LocaleSet(Locale locale) { this(locale, null); } 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 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"; 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(ICUCompat.maximizeAndGetScript(locale))) { return ICUCompat.maximizeAndGetScript(locale).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()); } public boolean isPrimaryLanguage(String language) { return mPrimaryLocale.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(); } /** * Modified from: * https://github.com/apache/cordova-plugin-globalization/blob/master/src/android/Globalization.java * * Returns a well-formed ITEF BCP 47 language tag representing this locale string * identifier for the client's current locale * * @return String: The BCP 47 language tag for the current locale */ private static String toBcp47Language(Locale loc) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { return loc.toLanguageTag(); } // we will use a dash as per BCP 47 final char SEP = '-'; String language = loc.getLanguage(); String region = loc.getCountry(); String variant = loc.getVariant(); // special case for Norwegian Nynorsk since "NY" cannot be a variant as per BCP 47 // this goes before the string matching since "NY" wont pass the variant checks if (language.equals("no") && region.equals("NO") && variant.equals("NY")) { language = "nn"; region = "NO"; variant = ""; } if (language.isEmpty() || !language.matches("\\p{Alpha}{2,8}")) { language = "und"; // Follow the Locale#toLanguageTag() implementation // which says to return "und" for Undetermined } else if (language.equals("iw")) { language = "he"; // correct deprecated "Hebrew" } else if (language.equals("in")) { language = "id"; // correct deprecated "Indonesian" } else if (language.equals("ji")) { language = "yi"; // correct deprecated "Yiddish" } // ensure valid country code, if not well formed, it's omitted if (!region.matches("\\p{Alpha}{2}|\\p{Digit}{3}")) { region = ""; } // variant subtags that begin with a letter must be at least 5 characters long if (!variant.matches("\\p{Alnum}{5,8}|\\p{Digit}\\p{Alnum}{3}")) { variant = ""; } StringBuilder bcp47Tag = new StringBuilder(language); if (!region.isEmpty()) { bcp47Tag.append(SEP).append(region); } if (!variant.isEmpty()) { bcp47Tag.append(SEP).append(variant); } return bcp47Tag.toString(); } }