001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.util;
016    
017    import com.liferay.portal.kernel.language.LanguageUtil;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.kernel.security.pacl.permission.PortalRuntimePermission;
021    
022    import java.util.HashMap;
023    import java.util.List;
024    import java.util.Locale;
025    import java.util.Map;
026    import java.util.Set;
027    import java.util.TreeMap;
028    
029    /**
030     * @author Brian Wing Shun Chan
031     * @author Raymond Aug??
032     */
033    public class LocaleUtil {
034    
035            public static final Locale BRAZIL = new Locale("pt", "BR");
036    
037            public static final Locale CANADA = Locale.CANADA;
038    
039            public static final Locale CANADA_FRENCH = Locale.CANADA_FRENCH;
040    
041            public static final Locale CHINA = Locale.CHINA;
042    
043            public static final Locale CHINESE = Locale.CHINESE;
044    
045            public static final Locale ENGLISH = Locale.ENGLISH;
046    
047            public static final Locale FRANCE = Locale.FRANCE;
048    
049            public static final Locale FRENCH = Locale.FRENCH;
050    
051            public static final Locale GERMAN = Locale.GERMAN;
052    
053            public static final Locale GERMANY = Locale.GERMANY;
054    
055            public static final Locale HUNGARY = new Locale("hu", "HU");
056    
057            public static final Locale ITALIAN = Locale.ITALIAN;
058    
059            public static final Locale ITALY = Locale.ITALY;
060    
061            public static final Locale JAPAN = Locale.JAPAN;
062    
063            public static final Locale JAPANESE = Locale.JAPANESE;
064    
065            public static final Locale KOREA = Locale.KOREA;
066    
067            public static final Locale KOREAN = Locale.KOREAN;
068    
069            public static final Locale PORTUGAL = new Locale("pt", "PT");
070    
071            public static final Locale PRC = Locale.PRC;
072    
073            public static final Locale ROOT = Locale.ROOT;
074    
075            public static final Locale SIMPLIFIED_CHINESE = Locale.SIMPLIFIED_CHINESE;
076    
077            public static final Locale SPAIN = new Locale("es", "ES");
078    
079            public static final Locale TAIWAN = Locale.TAIWAN;
080    
081            public static final Locale TRADITIONAL_CHINESE = Locale.TRADITIONAL_CHINESE;
082    
083            public static final Locale UK = Locale.UK;
084    
085            public static final Locale US = Locale.US;
086    
087            public static boolean equals(Locale locale1, Locale locale2) {
088                    return getInstance()._equals(locale1, locale2);
089            }
090    
091            public static Locale fromLanguageId(String languageId) {
092                    return getInstance()._fromLanguageId(languageId, true);
093            }
094    
095            public static Locale fromLanguageId(String languageId, boolean validate) {
096                    return getInstance()._fromLanguageId(languageId, validate);
097            }
098    
099            public static Locale fromLanguageId(
100                    String languageId, boolean validate, boolean useDefault) {
101    
102                    return getInstance()._fromLanguageId(languageId, validate, useDefault);
103            }
104    
105            public static Locale[] fromLanguageIds(List<String> languageIds) {
106                    return getInstance()._fromLanguageIds(languageIds);
107            }
108    
109            public static Locale[] fromLanguageIds(String[] languageIds) {
110                    return getInstance()._fromLanguageIds(languageIds);
111            }
112    
113            public static Locale getDefault() {
114                    return getInstance()._getDefault();
115            }
116    
117            public static LocaleUtil getInstance() {
118                    PortalRuntimePermission.checkGetBeanProperty(LocaleUtil.class);
119    
120                    return _instance;
121            }
122    
123            public static Map<String, String> getISOLanguages(Locale locale) {
124                    return getInstance()._getISOLanguages(locale);
125            }
126    
127            public static String getLongDisplayName(
128                    Locale locale, Set<String> duplicateLanguages) {
129    
130                    return getInstance()._getLongDisplayName(locale, duplicateLanguages);
131            }
132    
133            public static Locale getMostRelevantLocale() {
134                    return getInstance()._getMostRelevantLocale();
135            }
136    
137            public static String getShortDisplayName(
138                    Locale locale, Set<String> duplicateLanguages) {
139    
140                    return getInstance()._getShortDisplayName(locale, duplicateLanguages);
141            }
142    
143            public static Locale getSiteDefault() {
144                    return getInstance()._getSiteDefault();
145            }
146    
147            public static void setDefault(
148                    String userLanguage, String userCountry, String userVariant) {
149    
150                    getInstance()._setDefault(userLanguage, userCountry, userVariant);
151            }
152    
153            public static String[] toDisplayNames(Locale[] locales, Locale locale) {
154                    return getInstance()._toDisplayNames(locales, locale);
155            }
156    
157            public static String toLanguageId(Locale locale) {
158                    return getInstance()._toLanguageId(locale);
159            }
160    
161            public static String[] toLanguageIds(Locale[] locales) {
162                    return getInstance()._toLanguageIds(locales);
163            }
164    
165            public static String toW3cLanguageId(Locale locale) {
166                    return getInstance()._toW3cLanguageId(locale);
167            }
168    
169            public static String toW3cLanguageId(String languageId) {
170                    return getInstance()._toW3cLanguageId(languageId);
171            }
172    
173            public static String[] toW3cLanguageIds(Locale[] locales) {
174                    return getInstance()._toW3cLanguageIds(locales);
175            }
176    
177            public static String[] toW3cLanguageIds(String[] languageIds) {
178                    return getInstance()._toW3cLanguageIds(languageIds);
179            }
180    
181            private LocaleUtil() {
182                    _locale = new Locale("en", "US");
183            }
184    
185            private boolean _equals(Locale locale1, Locale locale2) {
186                    String languageId1 = _toLanguageId(locale1);
187                    String languageId2 = _toLanguageId(locale2);
188    
189                    return languageId1.equalsIgnoreCase(languageId2);
190            }
191    
192            private Locale _fromLanguageId(String languageId, boolean validate) {
193                    return _fromLanguageId(languageId, validate, true);
194            }
195    
196            private Locale _fromLanguageId(
197                    String languageId, boolean validate, boolean useDefault) {
198    
199                    if (languageId == null) {
200                            if (useDefault) {
201                                    return _locale;
202                            }
203                            else {
204                                    return null;
205                            }
206                    }
207    
208                    Locale locale = _locales.get(languageId);
209    
210                    if (locale != null) {
211                            return locale;
212                    }
213    
214                    try {
215                            int pos = languageId.indexOf(CharPool.UNDERLINE);
216    
217                            if (pos == -1) {
218                                    locale = new Locale(languageId);
219                            }
220                            else {
221                                    String[] languageIdParts = StringUtil.split(
222                                            languageId, CharPool.UNDERLINE);
223    
224                                    String languageCode = languageIdParts[0];
225                                    String countryCode = languageIdParts[1];
226    
227                                    String variant = null;
228    
229                                    if (languageIdParts.length > 2) {
230                                            variant = languageIdParts[2];
231                                    }
232    
233                                    if (Validator.isNotNull(variant)) {
234                                            locale = new Locale(languageCode, countryCode, variant);
235                                    }
236                                    else {
237                                            locale = new Locale(languageCode, countryCode);
238                                    }
239                            }
240    
241                            if (validate && !LanguageUtil.isAvailableLanguageCode(languageId)) {
242                                    throw new IllegalArgumentException("Invalid locale " + locale);
243                            }
244    
245                            _locales.put(languageId, locale);
246                    }
247                    catch (Exception e) {
248                            locale = null;
249    
250                            if (_log.isWarnEnabled()) {
251                                    _log.warn(languageId + " is not a valid language id");
252                            }
253                    }
254    
255                    if ((locale == null) && useDefault) {
256                            locale = _locale;
257                    }
258    
259                    return locale;
260            }
261    
262            private Locale[] _fromLanguageIds(List<String> languageIds) {
263                    Locale[] locales = new Locale[languageIds.size()];
264    
265                    for (int i = 0; i < languageIds.size(); i++) {
266                            locales[i] = _fromLanguageId(languageIds.get(i), true);
267                    }
268    
269                    return locales;
270            }
271    
272            private Locale[] _fromLanguageIds(String[] languageIds) {
273                    Locale[] locales = new Locale[languageIds.length];
274    
275                    for (int i = 0; i < languageIds.length; i++) {
276                            locales[i] = _fromLanguageId(languageIds[i], true);
277                    }
278    
279                    return locales;
280            }
281    
282            private Locale _getDefault() {
283                    Locale locale = LocaleThreadLocal.getDefaultLocale();
284    
285                    if (locale != null) {
286                            return locale;
287                    }
288    
289                    return _locale;
290            }
291    
292            private String _getDisplayName(
293                    String language, String country, Locale locale,
294                    Set<String> duplicateLanguages) {
295    
296                    StringBundler sb = new StringBundler(6);
297    
298                    sb.append(language);
299    
300                    if (duplicateLanguages.contains(locale.getLanguage())) {
301                            sb.append(StringPool.SPACE);
302                            sb.append(StringPool.OPEN_PARENTHESIS);
303                            sb.append(country);
304                            sb.append(StringPool.CLOSE_PARENTHESIS);
305                    }
306    
307                    if (LanguageUtil.isBetaLocale(locale)) {
308                            sb.append(_BETA_SUFFIX);
309                    }
310    
311                    return sb.toString();
312            }
313    
314            private Map<String, String> _getISOLanguages(Locale locale) {
315                    Map<String, String> isoLanguages = new TreeMap<String, String>(
316                            String.CASE_INSENSITIVE_ORDER);
317    
318                    for (String isoLanguageId : Locale.getISOLanguages()) {
319                            Locale isoLocale = _fromLanguageId(isoLanguageId, true);
320    
321                            isoLanguages.put(
322                                    isoLocale.getDisplayLanguage(locale), isoLanguageId);
323                    }
324    
325                    return isoLanguages;
326            }
327    
328            private String _getLongDisplayName(
329                    Locale locale, Set<String> duplicateLanguages) {
330    
331                    return _getDisplayName(
332                            locale.getDisplayLanguage(locale), locale.getDisplayCountry(locale),
333                            locale, duplicateLanguages);
334            }
335    
336            private Locale _getMostRelevantLocale() {
337                    Locale locale = LocaleThreadLocal.getThemeDisplayLocale();
338    
339                    if (locale == null) {
340                            locale = _getDefault();
341                    }
342    
343                    return locale;
344            }
345    
346            private String _getShortDisplayName(
347                    Locale locale, Set<String> duplicateLanguages) {
348    
349                    String language = locale.getDisplayLanguage(locale);
350    
351                    if (language.length() > 3) {
352                            language = locale.getLanguage();
353                            language = language.toUpperCase();
354                    }
355    
356                    String country = locale.getCountry();
357    
358                    return _getDisplayName(
359                            language, country.toUpperCase(), locale, duplicateLanguages);
360            }
361    
362            private Locale _getSiteDefault() {
363                    Locale locale = LocaleThreadLocal.getSiteDefaultLocale();
364    
365                    if (locale != null) {
366                            return locale;
367                    }
368    
369                    return _getDefault();
370            }
371    
372            private void _setDefault(
373                    String userLanguage, String userCountry, String userVariant) {
374    
375                    PortalRuntimePermission.checkSetBeanProperty(getClass());
376    
377                    if (Validator.isNotNull(userLanguage) &&
378                            Validator.isNull(userCountry) && Validator.isNull(userVariant)) {
379    
380                            _locale = new Locale(userLanguage);
381                    }
382                    else if (Validator.isNotNull(userLanguage) &&
383                                     Validator.isNotNull(userCountry) &&
384                                     Validator.isNull(userVariant)) {
385    
386                            _locale = new Locale(userLanguage, userCountry);
387                    }
388                    else if (Validator.isNotNull(userLanguage) &&
389                                     Validator.isNotNull(userCountry) &&
390                                     Validator.isNotNull(userVariant)) {
391    
392                            _locale = new Locale(userLanguage, userCountry, userVariant);
393                    }
394            }
395    
396            private String[] _toDisplayNames(Locale[] locales, Locale locale) {
397                    String[] displayNames = new String[locales.length];
398    
399                    for (int i = 0; i < locales.length; i++) {
400                            displayNames[i] = locales[i].getDisplayName(locale);
401                    }
402    
403                    return displayNames;
404            }
405    
406            private String _toLanguageId(Locale locale) {
407                    if (locale == null) {
408                            locale = _locale;
409                    }
410    
411                    String country = locale.getCountry();
412    
413                    boolean hasCountry = false;
414    
415                    if (country.length() != 0) {
416                            hasCountry = true;
417                    }
418    
419                    String variant = locale.getVariant();
420    
421                    boolean hasVariant = false;
422    
423                    if (variant.length() != 0) {
424                            hasVariant = true;
425                    }
426    
427                    if (!hasCountry && !hasVariant) {
428                            return locale.getLanguage();
429                    }
430    
431                    int length = 3;
432    
433                    if (hasCountry && hasVariant) {
434                            length = 5;
435                    }
436    
437                    StringBundler sb = new StringBundler(length);
438    
439                    sb.append(locale.getLanguage());
440    
441                    if (hasCountry) {
442                            sb.append(StringPool.UNDERLINE);
443                            sb.append(country);
444                    }
445    
446                    if (hasVariant) {
447                            sb.append(StringPool.UNDERLINE);
448                            sb.append(variant);
449                    }
450    
451                    return sb.toString();
452            }
453    
454            private String[] _toLanguageIds(Locale[] locales) {
455                    String[] languageIds = new String[locales.length];
456    
457                    for (int i = 0; i < locales.length; i++) {
458                            languageIds[i] = _toLanguageId(locales[i]);
459                    }
460    
461                    return languageIds;
462            }
463    
464            private String _toW3cLanguageId(Locale locale) {
465                    return _toW3cLanguageId(_toLanguageId(locale));
466            }
467    
468            private String _toW3cLanguageId(String languageId) {
469                    return StringUtil.replace(
470                            languageId, CharPool.UNDERLINE, CharPool.MINUS);
471            }
472    
473            private String[] _toW3cLanguageIds(Locale[] locales) {
474                    return _toW3cLanguageIds(_toLanguageIds(locales));
475            }
476    
477            private String[] _toW3cLanguageIds(String[] languageIds) {
478                    String[] w3cLanguageIds = new String[languageIds.length];
479    
480                    for (int i = 0; i < languageIds.length; i++) {
481                            w3cLanguageIds[i] = _toW3cLanguageId(languageIds[i]);
482                    }
483    
484                    return w3cLanguageIds;
485            }
486    
487            private static final String _BETA_SUFFIX = " [Beta]";
488    
489            private static Log _log = LogFactoryUtil.getLog(LocaleUtil.class);
490    
491            private static LocaleUtil _instance = new LocaleUtil();
492    
493            private Locale _locale;
494            private Map<String, Locale> _locales = new HashMap<String, Locale>();
495    
496    }