2 *******************************************************************************
\r
3 * Copyright (C) 2008-2010, International Business Machines Corporation and *
\r
4 * others. All Rights Reserved. *
\r
5 *******************************************************************************
\r
7 package com.ibm.icu.impl.javaspi;
\r
9 import java.io.IOException;
\r
10 import java.io.InputStream;
\r
11 import java.util.Arrays;
\r
12 import java.util.HashSet;
\r
13 import java.util.Locale;
\r
14 import java.util.Properties;
\r
15 import java.util.Set;
\r
17 import com.ibm.icu.impl.ICUResourceBundle;
\r
18 import com.ibm.icu.text.DecimalFormatSymbols;
\r
19 import com.ibm.icu.util.ULocale;
\r
21 public class ICULocaleServiceProvider {
\r
22 private static final String SPI_PROP_FILE = "com/ibm/icu/impl/javaspi/ICULocaleServiceProviderConfig.properties";
\r
24 private static final String SUFFIX_KEY = "com.ibm.icu.impl.javaspi.ICULocaleServiceProvider.icuVariantSuffix";
\r
25 private static final String ENABLE_VARIANTS_KEY = "com.ibm.icu.impl.javaspi.ICULocaleServiceProvider.enableIcuVariants";
\r
26 private static final String ENABLE_ISO3_LANG_KEY = "com.ibm.icu.impl.javaspi.ICULocaleServiceProvider.enableIso3Languages";
\r
27 private static final String USE_DECIMALFORMAT_KEY = "com.ibm.icu.impl.javaspi.ICULocaleServiceProvider.useDecimalFormat";
\r
29 private static boolean configLoaded = false;
\r
31 private static String suffix = "ICU";
\r
32 private static boolean enableVariants = true;
\r
33 private static boolean enableIso3Lang = true;
\r
34 private static boolean useDecimalFormat = false;
\r
36 private static final Locale[] SPECIAL_LOCALES = {
\r
37 new Locale("ja", "JP", "JP"),
\r
39 new Locale("no", "NO"),
\r
40 new Locale("no", "NO", "NY"),
\r
41 new Locale("sr", "CS"),
\r
42 new Locale("th", "TH", "TH"),
\r
45 private static Locale[] LOCALES = null;
\r
47 public static Locale[] getAvailableLocales() {
\r
48 Locale[] all = getLocales();
\r
49 return Arrays.copyOf(all, all.length);
\r
52 public static Locale canonicalize(Locale locale) {
\r
53 Locale result = locale;
\r
54 String variant = locale.getVariant();
\r
55 String suffix = getIcuSuffix();
\r
56 if (variant.equals(suffix)) {
\r
57 result = new Locale(locale.getLanguage(), locale.getCountry());
\r
58 } else if (variant.endsWith(suffix)
\r
59 && variant.charAt(variant.length() - suffix.length() - 1) == '_') {
\r
60 variant = variant.substring(0, variant.length() - suffix.length() - 1);
\r
61 result = new Locale(locale.getLanguage(), locale.getCountry(), variant);
\r
66 public static boolean useDecimalFormat() {
\r
67 loadConfiguration();
\r
68 return useDecimalFormat;
\r
71 private static final Locale THAI_NATIVE_DIGIT_LOCALE = new Locale("th", "TH", "TH");
\r
72 private static final char THAI_NATIVE_ZERO = '\u0E50';
\r
73 private static DecimalFormatSymbols THAI_NATIVE_DECIMAL_SYMBOLS = null;
\r
76 * Returns a DecimalFormatSymbols if the given locale requires
\r
77 * non-standard symbols, more specifically, native digits used
\r
78 * by JDK Locale th_TH_TH. If the locale does not requre a special
\r
79 * symbols, null is returned.
\r
81 public static synchronized DecimalFormatSymbols getDecimalFormatSymbolsForLocale(Locale loc) {
\r
82 if (loc.equals(THAI_NATIVE_DIGIT_LOCALE)) {
\r
83 if (THAI_NATIVE_DECIMAL_SYMBOLS == null) {
\r
84 THAI_NATIVE_DECIMAL_SYMBOLS = new DecimalFormatSymbols(new ULocale("th_TH"));
\r
85 THAI_NATIVE_DECIMAL_SYMBOLS.setDigit(THAI_NATIVE_ZERO);
\r
87 return (DecimalFormatSymbols)THAI_NATIVE_DECIMAL_SYMBOLS.clone();
\r
92 private static synchronized Locale[] getLocales() {
\r
93 if (LOCALES != null) {
\r
97 Set<Locale> localeSet = new HashSet<Locale>();
\r
98 ULocale[] icuLocales = ICUResourceBundle.getAvailableULocales();
\r
100 for (ULocale uloc : icuLocales) {
\r
101 String language = uloc.getLanguage();
\r
102 String country = uloc.getCountry();
\r
103 String variant = uloc.getVariant();
\r
104 if (language.length() >= 3 && !enableIso3Languages()) {
\r
107 addLocale(new Locale(language, country, variant), localeSet);
\r
110 for (Locale l : SPECIAL_LOCALES) {
\r
111 addLocale(l, localeSet);
\r
114 LOCALES = localeSet.toArray(new Locale[0]);
\r
118 private static void addLocale(Locale loc, Set<Locale> locales) {
\r
121 if (enableIcuVariants()) {
\r
123 String language = loc.getLanguage();
\r
124 String country = loc.getCountry();
\r
125 String variant = loc.getVariant();
\r
127 StringBuilder var = new StringBuilder(variant);
\r
128 if (var.length() != 0) {
\r
131 var.append(getIcuSuffix());
\r
132 locales.add(new Locale(language, country, var.toString()));
\r
136 private static boolean enableIso3Languages() {
\r
137 return enableIso3Lang;
\r
140 private static boolean enableIcuVariants() {
\r
141 loadConfiguration();
\r
142 return enableVariants;
\r
145 private static String getIcuSuffix() {
\r
146 loadConfiguration();
\r
150 private static synchronized void loadConfiguration() {
\r
151 if (configLoaded) {
\r
154 Properties spiConfigProps = new Properties();
\r
156 InputStream is = ClassLoader.getSystemResourceAsStream(SPI_PROP_FILE);
\r
157 spiConfigProps.load(is);
\r
159 String val = (String)spiConfigProps.get(SUFFIX_KEY);
\r
160 if (val != null && val.length() > 0) {
\r
163 enableVariants = parseBooleanString((String)spiConfigProps.get(ENABLE_VARIANTS_KEY), enableVariants);
\r
164 enableIso3Lang = parseBooleanString((String)spiConfigProps.get(ENABLE_ISO3_LANG_KEY), enableIso3Lang);
\r
165 useDecimalFormat = parseBooleanString((String)spiConfigProps.get(USE_DECIMALFORMAT_KEY), useDecimalFormat);
\r
166 } catch (IOException ioe) {
\r
167 // Any IO errors, ignore
\r
169 configLoaded = true;
\r
172 private static boolean parseBooleanString(String str, boolean defaultVal) {
\r
176 if (str.equalsIgnoreCase("true")) {
\r
178 } else if (str.equalsIgnoreCase("false")) {
\r