001
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
034 public class LocaleUtil {
035
036 public static final Locale BRAZIL = new Locale("pt", "BR");
037
038 public static final Locale CANADA = Locale.CANADA;
039
040 public static final Locale CANADA_FRENCH = Locale.CANADA_FRENCH;
041
042 public static final Locale CHINA = Locale.CHINA;
043
044 public static final Locale CHINESE = Locale.CHINESE;
045
046 public static final Locale ENGLISH = Locale.ENGLISH;
047
048 public static final Locale FRANCE = Locale.FRANCE;
049
050 public static final Locale FRENCH = Locale.FRENCH;
051
052 public static final Locale GERMAN = Locale.GERMAN;
053
054 public static final Locale GERMANY = Locale.GERMANY;
055
056 public static final Locale HUNGARY = new Locale("hu", "HU");
057
058 public static final Locale ITALIAN = Locale.ITALIAN;
059
060 public static final Locale ITALY = Locale.ITALY;
061
062 public static final Locale JAPAN = Locale.JAPAN;
063
064 public static final Locale JAPANESE = Locale.JAPANESE;
065
066 public static final Locale KOREA = Locale.KOREA;
067
068 public static final Locale KOREAN = Locale.KOREAN;
069
070 public static final Locale PORTUGAL = new Locale("pt", "PT");
071
072 public static final Locale PRC = Locale.PRC;
073
074 public static final Locale ROOT = Locale.ROOT;
075
076 public static final Locale SIMPLIFIED_CHINESE = Locale.SIMPLIFIED_CHINESE;
077
078 public static final Locale SPAIN = new Locale("es", "ES");
079
080 public static final Locale TAIWAN = Locale.TAIWAN;
081
082 public static final Locale TRADITIONAL_CHINESE = Locale.TRADITIONAL_CHINESE;
083
084 public static final Locale UK = Locale.UK;
085
086 public static final Locale US = Locale.US;
087
088 public static boolean equals(Locale locale1, Locale locale2) {
089 return getInstance()._equals(locale1, locale2);
090 }
091
092 public static Locale fromLanguageId(String languageId) {
093 return getInstance()._fromLanguageId(languageId, true);
094 }
095
096 public static Locale fromLanguageId(String languageId, boolean validate) {
097 return getInstance()._fromLanguageId(languageId, validate);
098 }
099
100 public static Locale fromLanguageId(
101 String languageId, boolean validate, boolean useDefault) {
102
103 return getInstance()._fromLanguageId(languageId, validate, useDefault);
104 }
105
106 public static Locale[] fromLanguageIds(List<String> languageIds) {
107 return getInstance()._fromLanguageIds(languageIds);
108 }
109
110 public static Locale[] fromLanguageIds(String[] languageIds) {
111 return getInstance()._fromLanguageIds(languageIds);
112 }
113
114 public static Locale getDefault() {
115 return getInstance()._getDefault();
116 }
117
118 public static LocaleUtil getInstance() {
119 PortalRuntimePermission.checkGetBeanProperty(LocaleUtil.class);
120
121 return _instance;
122 }
123
124 public static Map<String, String> getISOLanguages(Locale locale) {
125 return getInstance()._getISOLanguages(locale);
126 }
127
128 public static String getLongDisplayName(
129 Locale locale, Set<String> duplicateLanguages) {
130
131 return getInstance()._getLongDisplayName(locale, duplicateLanguages);
132 }
133
134 public static Locale getMostRelevantLocale() {
135 return getInstance()._getMostRelevantLocale();
136 }
137
138 public static String getShortDisplayName(
139 Locale locale, Set<String> duplicateLanguages) {
140
141 return getInstance()._getShortDisplayName(locale, duplicateLanguages);
142 }
143
144 public static Locale getSiteDefault() {
145 return getInstance()._getSiteDefault();
146 }
147
148 public static void setDefault(
149 String userLanguage, String userCountry, String userVariant) {
150
151 getInstance()._setDefault(userLanguage, userCountry, userVariant);
152 }
153
154 public static String toBCP47LanguageId(Locale locale) {
155 return getInstance()._toBCP47LanguageId(locale);
156 }
157
158 public static String toBCP47LanguageId(String languageId) {
159 return getInstance()._toBCP47LanguageId(languageId);
160 }
161
162 public static String[] toBCP47LanguageIds(Locale[] locales) {
163 return getInstance()._toBCP47LanguageIds(locales);
164 }
165
166 public static String[] toBCP47LanguageIds(String[] languageIds) {
167 return getInstance()._toBCP47LanguageIds(languageIds);
168 }
169
170 public static String[] toDisplayNames(Locale[] locales, Locale locale) {
171 return getInstance()._toDisplayNames(locales, locale);
172 }
173
174 public static String toLanguageId(Locale locale) {
175 return getInstance()._toLanguageId(locale);
176 }
177
178 public static String[] toLanguageIds(Locale[] locales) {
179 return getInstance()._toLanguageIds(locales);
180 }
181
182 public static String toW3cLanguageId(Locale locale) {
183 return getInstance()._toW3cLanguageId(locale);
184 }
185
186 public static String toW3cLanguageId(String languageId) {
187 return getInstance()._toW3cLanguageId(languageId);
188 }
189
190 public static String[] toW3cLanguageIds(Locale[] locales) {
191 return getInstance()._toW3cLanguageIds(locales);
192 }
193
194 public static String[] toW3cLanguageIds(String[] languageIds) {
195 return getInstance()._toW3cLanguageIds(languageIds);
196 }
197
198 private LocaleUtil() {
199 _locale = new Locale("en", "US");
200 }
201
202 private boolean _equals(Locale locale1, Locale locale2) {
203 String languageId1 = _toLanguageId(locale1);
204 String languageId2 = _toLanguageId(locale2);
205
206 return languageId1.equalsIgnoreCase(languageId2);
207 }
208
209 private Locale _fromLanguageId(String languageId, boolean validate) {
210 return _fromLanguageId(languageId, validate, true);
211 }
212
213 private Locale _fromLanguageId(
214 String languageId, boolean validate, boolean useDefault) {
215
216 if (languageId == null) {
217 if (useDefault) {
218 return _locale;
219 }
220 else {
221 return null;
222 }
223 }
224
225 Locale locale = _locales.get(languageId);
226
227 if (locale != null) {
228 return locale;
229 }
230
231 try {
232 int pos = languageId.indexOf(CharPool.UNDERLINE);
233
234 if (pos == -1) {
235 locale = new Locale(languageId);
236 }
237 else {
238 String[] languageIdParts = StringUtil.split(
239 languageId, CharPool.UNDERLINE);
240
241 String languageCode = languageIdParts[0];
242 String countryCode = languageIdParts[1];
243
244 String variant = null;
245
246 if (languageIdParts.length > 2) {
247 variant = languageIdParts[2];
248 }
249
250 if (Validator.isNotNull(variant)) {
251 locale = new Locale(languageCode, countryCode, variant);
252 }
253 else {
254 locale = new Locale(languageCode, countryCode);
255 }
256 }
257
258 if (validate && !LanguageUtil.isAvailableLanguageCode(languageId)) {
259 throw new IllegalArgumentException("Invalid locale " + locale);
260 }
261
262 _locales.put(languageId, locale);
263 }
264 catch (Exception e) {
265 locale = null;
266
267 if (_log.isWarnEnabled()) {
268 _log.warn(languageId + " is not a valid language id");
269 }
270 }
271
272 if ((locale == null) && useDefault) {
273 locale = _locale;
274 }
275
276 return locale;
277 }
278
279 private Locale[] _fromLanguageIds(List<String> languageIds) {
280 Locale[] locales = new Locale[languageIds.size()];
281
282 for (int i = 0; i < languageIds.size(); i++) {
283 locales[i] = _fromLanguageId(languageIds.get(i), true);
284 }
285
286 return locales;
287 }
288
289 private Locale[] _fromLanguageIds(String[] languageIds) {
290 Locale[] locales = new Locale[languageIds.length];
291
292 for (int i = 0; i < languageIds.length; i++) {
293 locales[i] = _fromLanguageId(languageIds[i], true);
294 }
295
296 return locales;
297 }
298
299 private Locale _getDefault() {
300 Locale locale = LocaleThreadLocal.getDefaultLocale();
301
302 if (locale != null) {
303 return locale;
304 }
305
306 return _locale;
307 }
308
309 private String _getDisplayName(
310 String language, String country, Locale locale,
311 Set<String> duplicateLanguages) {
312
313 StringBundler sb = new StringBundler(6);
314
315 sb.append(language);
316
317 if (duplicateLanguages.contains(locale.getLanguage())) {
318 sb.append(StringPool.SPACE);
319 sb.append(StringPool.OPEN_PARENTHESIS);
320 sb.append(country);
321 sb.append(StringPool.CLOSE_PARENTHESIS);
322 }
323
324 if (LanguageUtil.isBetaLocale(locale)) {
325 sb.append(_BETA_SUFFIX);
326 }
327
328 return sb.toString();
329 }
330
331 private Map<String, String> _getISOLanguages(Locale locale) {
332 Map<String, String> isoLanguages = new TreeMap<String, String>(
333 String.CASE_INSENSITIVE_ORDER);
334
335 for (String isoLanguageId : Locale.getISOLanguages()) {
336 Locale isoLocale = _fromLanguageId(isoLanguageId, true);
337
338 isoLanguages.put(
339 isoLocale.getDisplayLanguage(locale), isoLanguageId);
340 }
341
342 return isoLanguages;
343 }
344
345 private String _getLongDisplayName(
346 Locale locale, Set<String> duplicateLanguages) {
347
348 return _getDisplayName(
349 locale.getDisplayLanguage(locale), locale.getDisplayCountry(locale),
350 locale, duplicateLanguages);
351 }
352
353 private Locale _getMostRelevantLocale() {
354 Locale locale = LocaleThreadLocal.getThemeDisplayLocale();
355
356 if (locale == null) {
357 locale = _getDefault();
358 }
359
360 return locale;
361 }
362
363 private String _getShortDisplayName(
364 Locale locale, Set<String> duplicateLanguages) {
365
366 String language = locale.getDisplayLanguage(locale);
367
368 if (language.length() > 3) {
369 language = locale.getLanguage();
370 language = language.toUpperCase();
371 }
372
373 String country = locale.getCountry();
374
375 return _getDisplayName(
376 language, country.toUpperCase(), locale, duplicateLanguages);
377 }
378
379 private Locale _getSiteDefault() {
380 Locale locale = LocaleThreadLocal.getSiteDefaultLocale();
381
382 if (locale != null) {
383 return locale;
384 }
385
386 return _getDefault();
387 }
388
389 private void _setDefault(
390 String userLanguage, String userCountry, String userVariant) {
391
392 PortalRuntimePermission.checkSetBeanProperty(getClass());
393
394 if (Validator.isNotNull(userLanguage) &&
395 Validator.isNull(userCountry) && Validator.isNull(userVariant)) {
396
397 _locale = new Locale(userLanguage);
398 }
399 else if (Validator.isNotNull(userLanguage) &&
400 Validator.isNotNull(userCountry) &&
401 Validator.isNull(userVariant)) {
402
403 _locale = new Locale(userLanguage, userCountry);
404 }
405 else if (Validator.isNotNull(userLanguage) &&
406 Validator.isNotNull(userCountry) &&
407 Validator.isNotNull(userVariant)) {
408
409 _locale = new Locale(userLanguage, userCountry, userVariant);
410 }
411 }
412
413 private String _toBCP47LanguageId(Locale locale) {
414 return _toBCP47LanguageId(_toLanguageId(locale));
415 }
416
417 private String _toBCP47LanguageId(String languageId) {
418 if (languageId.equals("zh_CN")) {
419 return "zh-Hans-CN";
420 }
421 else if (languageId.equals("zh_TW")) {
422 return "zh-Hant-TW";
423 }
424 else {
425 return StringUtil.replace(
426 languageId, CharPool.UNDERLINE, CharPool.MINUS);
427 }
428 }
429
430 private String[] _toBCP47LanguageIds(Locale[] locales) {
431 return _toBCP47LanguageIds(_toLanguageIds(locales));
432 }
433
434 private String[] _toBCP47LanguageIds(String[] languageIds) {
435 String[] bcp47LanguageIds = new String[languageIds.length];
436
437 for (int i = 0; i < languageIds.length; i++) {
438 bcp47LanguageIds[i] = _toBCP47LanguageId(languageIds[i]);
439 }
440
441 return bcp47LanguageIds;
442 }
443
444 private String[] _toDisplayNames(Locale[] locales, Locale locale) {
445 String[] displayNames = new String[locales.length];
446
447 for (int i = 0; i < locales.length; i++) {
448 displayNames[i] = locales[i].getDisplayName(locale);
449 }
450
451 return displayNames;
452 }
453
454 private String _toLanguageId(Locale locale) {
455 if (locale == null) {
456 locale = _locale;
457 }
458
459 String country = locale.getCountry();
460
461 boolean hasCountry = false;
462
463 if (country.length() != 0) {
464 hasCountry = true;
465 }
466
467 String variant = locale.getVariant();
468
469 boolean hasVariant = false;
470
471 if (variant.length() != 0) {
472 hasVariant = true;
473 }
474
475 if (!hasCountry && !hasVariant) {
476 return locale.getLanguage();
477 }
478
479 int length = 3;
480
481 if (hasCountry && hasVariant) {
482 length = 5;
483 }
484
485 StringBundler sb = new StringBundler(length);
486
487 sb.append(locale.getLanguage());
488
489 if (hasCountry) {
490 sb.append(StringPool.UNDERLINE);
491 sb.append(country);
492 }
493
494 if (hasVariant) {
495 sb.append(StringPool.UNDERLINE);
496 sb.append(variant);
497 }
498
499 return sb.toString();
500 }
501
502 private String[] _toLanguageIds(Locale[] locales) {
503 String[] languageIds = new String[locales.length];
504
505 for (int i = 0; i < locales.length; i++) {
506 languageIds[i] = _toLanguageId(locales[i]);
507 }
508
509 return languageIds;
510 }
511
512 private String _toW3cLanguageId(Locale locale) {
513 return _toW3cLanguageId(_toLanguageId(locale));
514 }
515
516 private String _toW3cLanguageId(String languageId) {
517 return StringUtil.replace(
518 languageId, CharPool.UNDERLINE, CharPool.MINUS);
519 }
520
521 private String[] _toW3cLanguageIds(Locale[] locales) {
522 return _toW3cLanguageIds(_toLanguageIds(locales));
523 }
524
525 private String[] _toW3cLanguageIds(String[] languageIds) {
526 String[] w3cLanguageIds = new String[languageIds.length];
527
528 for (int i = 0; i < languageIds.length; i++) {
529 w3cLanguageIds[i] = _toW3cLanguageId(languageIds[i]);
530 }
531
532 return w3cLanguageIds;
533 }
534
535 private static final String _BETA_SUFFIX = " [Beta]";
536
537 private static Log _log = LogFactoryUtil.getLog(LocaleUtil.class);
538
539 private static LocaleUtil _instance = new LocaleUtil();
540
541 private Locale _locale;
542 private Map<String, Locale> _locales = new HashMap<String, Locale>();
543
544 }