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