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