001
014
015 package com.liferay.portal.language;
016
017 import com.liferay.portal.kernel.exception.SystemException;
018 import com.liferay.portal.kernel.language.Language;
019 import com.liferay.portal.kernel.language.LanguageWrapper;
020 import com.liferay.portal.kernel.log.Log;
021 import com.liferay.portal.kernel.log.LogFactoryUtil;
022 import com.liferay.portal.kernel.util.CharPool;
023 import com.liferay.portal.kernel.util.CookieKeys;
024 import com.liferay.portal.kernel.util.JavaConstants;
025 import com.liferay.portal.kernel.util.LocaleUtil;
026 import com.liferay.portal.kernel.util.ParamUtil;
027 import com.liferay.portal.kernel.util.PropsKeys;
028 import com.liferay.portal.kernel.util.ResourceBundleUtil;
029 import com.liferay.portal.kernel.util.StringPool;
030 import com.liferay.portal.kernel.util.StringUtil;
031 import com.liferay.portal.kernel.util.Time;
032 import com.liferay.portal.kernel.util.Validator;
033 import com.liferay.portal.model.CompanyConstants;
034 import com.liferay.portal.model.Portlet;
035 import com.liferay.portal.security.auth.CompanyThreadLocal;
036 import com.liferay.portal.service.PortletLocalServiceUtil;
037 import com.liferay.portal.theme.ThemeDisplay;
038 import com.liferay.portal.util.PortalUtil;
039 import com.liferay.portal.util.PortletKeys;
040 import com.liferay.portal.util.PrefsPropsUtil;
041 import com.liferay.portal.util.PropsValues;
042 import com.liferay.portal.util.WebKeys;
043 import com.liferay.portlet.PortletConfigFactoryUtil;
044
045 import java.text.MessageFormat;
046
047 import java.util.ArrayList;
048 import java.util.HashMap;
049 import java.util.HashSet;
050 import java.util.List;
051 import java.util.Locale;
052 import java.util.Map;
053 import java.util.ResourceBundle;
054 import java.util.Set;
055 import java.util.concurrent.ConcurrentHashMap;
056
057 import javax.portlet.PortletConfig;
058 import javax.portlet.PortletRequest;
059
060 import javax.servlet.http.Cookie;
061 import javax.servlet.http.HttpServletRequest;
062 import javax.servlet.http.HttpServletResponse;
063 import javax.servlet.jsp.PageContext;
064
065
069 public class LanguageImpl implements Language {
070
071 public String format(Locale locale, String pattern, Object argument) {
072 return format(locale, pattern, new Object[] {argument}, true);
073 }
074
075 public String format(
076 Locale locale, String pattern, Object argument,
077 boolean translateArguments) {
078
079 return format(
080 locale, pattern, new Object[] {argument}, translateArguments);
081 }
082
083 public String format(Locale locale, String pattern, Object[] arguments) {
084 return format(locale, pattern, arguments, true);
085 }
086
087 public String format(
088 Locale locale, String pattern, Object[] arguments,
089 boolean translateArguments) {
090
091 if (PropsValues.TRANSLATIONS_DISABLED) {
092 return pattern;
093 }
094
095 String value = null;
096
097 try {
098 pattern = get(locale, pattern);
099
100 if ((arguments != null) && (arguments.length > 0)) {
101 pattern = _escapePattern(pattern);
102
103 Object[] formattedArguments = new Object[arguments.length];
104
105 for (int i = 0; i < arguments.length; i++) {
106 if (translateArguments) {
107 formattedArguments[i] = get(
108 locale, arguments[i].toString());
109 }
110 else {
111 formattedArguments[i] = arguments[i];
112 }
113 }
114
115 value = MessageFormat.format(pattern, formattedArguments);
116 }
117 else {
118 value = pattern;
119 }
120 }
121 catch (Exception e) {
122 if (_log.isWarnEnabled()) {
123 _log.warn(e, e);
124 }
125 }
126
127 return value;
128 }
129
130 public String format(
131 PageContext pageContext, String pattern, LanguageWrapper argument) {
132
133 return format(
134 pageContext, pattern, new LanguageWrapper[] {argument}, true);
135 }
136
137 public String format(
138 PageContext pageContext, String pattern, LanguageWrapper argument,
139 boolean translateArguments) {
140
141 return format(
142 pageContext, pattern, new LanguageWrapper[] {argument},
143 translateArguments);
144 }
145
146 public String format(
147 PageContext pageContext, String pattern, LanguageWrapper[] arguments) {
148
149 return format(pageContext, pattern, arguments, true);
150 }
151
152 public String format(
153 PageContext pageContext, String pattern, LanguageWrapper[] arguments,
154 boolean translateArguments) {
155
156 if (PropsValues.TRANSLATIONS_DISABLED) {
157 return pattern;
158 }
159
160 String value = null;
161
162 try {
163 pattern = get(pageContext, pattern);
164
165 if ((arguments != null) && (arguments.length > 0)) {
166 pattern = _escapePattern(pattern);
167
168 Object[] formattedArguments = new Object[arguments.length];
169
170 for (int i = 0; i < arguments.length; i++) {
171 if (translateArguments) {
172 formattedArguments[i] =
173 arguments[i].getBefore() +
174 get(pageContext, arguments[i].getText()) +
175 arguments[i].getAfter();
176 }
177 else {
178 formattedArguments[i] =
179 arguments[i].getBefore() +
180 arguments[i].getText() +
181 arguments[i].getAfter();
182 }
183 }
184
185 value = MessageFormat.format(pattern, formattedArguments);
186 }
187 else {
188 value = pattern;
189 }
190 }
191 catch (Exception e) {
192 if (_log.isWarnEnabled()) {
193 _log.warn(e, e);
194 }
195 }
196
197 return value;
198 }
199
200 public String format(
201 PageContext pageContext, String pattern, Object argument) {
202
203 return format(pageContext, pattern, new Object[] {argument}, true);
204 }
205
206 public String format(
207 PageContext pageContext, String pattern, Object argument,
208 boolean translateArguments) {
209
210 return format(
211 pageContext, pattern, new Object[] {argument}, translateArguments);
212 }
213
214 public String format(
215 PageContext pageContext, String pattern, Object[] arguments) {
216
217 return format(pageContext, pattern, arguments, true);
218 }
219
220 public String format(
221 PageContext pageContext, String pattern, Object[] arguments,
222 boolean translateArguments) {
223
224 if (PropsValues.TRANSLATIONS_DISABLED) {
225 return pattern;
226 }
227
228 String value = null;
229
230 try {
231 pattern = get(pageContext, pattern);
232
233 if ((arguments != null) && (arguments.length > 0)) {
234 pattern = _escapePattern(pattern);
235
236 Object[] formattedArguments = new Object[arguments.length];
237
238 for (int i = 0; i < arguments.length; i++) {
239 if (translateArguments) {
240 formattedArguments[i] = get(
241 pageContext, arguments[i].toString());
242 }
243 else {
244 formattedArguments[i] = arguments[i];
245 }
246 }
247
248 value = MessageFormat.format(pattern, formattedArguments);
249 }
250 else {
251 value = pattern;
252 }
253 }
254 catch (Exception e) {
255 if (_log.isWarnEnabled()) {
256 _log.warn(e, e);
257 }
258 }
259
260 return value;
261 }
262
263 public String format(
264 PortletConfig portletConfig, Locale locale, String pattern,
265 Object argument) {
266
267 return format(
268 portletConfig, locale, pattern, new Object[] {argument}, true);
269 }
270
271 public String format(
272 PortletConfig portletConfig, Locale locale, String pattern,
273 Object argument, boolean translateArguments) {
274
275 return format(
276 portletConfig, locale, pattern, new Object[] {argument},
277 translateArguments);
278 }
279
280 public String format(
281 PortletConfig portletConfig, Locale locale, String pattern,
282 Object[] arguments) {
283
284 return format(portletConfig, locale, pattern, arguments, true);
285 }
286
287 public String format(
288 PortletConfig portletConfig, Locale locale, String pattern,
289 Object[] arguments, boolean translateArguments) {
290
291 if (PropsValues.TRANSLATIONS_DISABLED) {
292 return pattern;
293 }
294
295 String value = null;
296
297 try {
298 pattern = get(portletConfig, locale, pattern);
299
300 if ((arguments != null) && (arguments.length > 0)) {
301 pattern = _escapePattern(pattern);
302
303 Object[] formattedArguments = new Object[arguments.length];
304
305 for (int i = 0; i < arguments.length; i++) {
306 if (translateArguments) {
307 formattedArguments[i] = get(
308 locale, arguments[i].toString());
309 }
310 else {
311 formattedArguments[i] = arguments[i];
312 }
313 }
314
315 value = MessageFormat.format(pattern, formattedArguments);
316 }
317 else {
318 value = pattern;
319 }
320 }
321 catch (Exception e) {
322 if (_log.isWarnEnabled()) {
323 _log.warn(e, e);
324 }
325 }
326
327 return value;
328 }
329
330 public String get(Locale locale, String key) {
331 return get(locale, key, key);
332 }
333
334 public String get(Locale locale, String key, String defaultValue) {
335 if (PropsValues.TRANSLATIONS_DISABLED) {
336 return key;
337 }
338
339 if (key == null) {
340 return null;
341 }
342
343 String value = LanguageResources.getMessage(locale, key);
344
345 while ((value == null) || value.equals(defaultValue)) {
346 if ((key.length() > 0) &&
347 (key.charAt(key.length() - 1) == CharPool.CLOSE_BRACKET)) {
348
349 int pos = key.lastIndexOf(CharPool.OPEN_BRACKET);
350
351 if (pos != -1) {
352 key = key.substring(0, pos);
353
354 value = LanguageResources.getMessage(locale, key);
355
356 continue;
357 }
358 }
359
360 break;
361 }
362
363 if (value == null) {
364 value = defaultValue;
365 }
366
367 return value;
368 }
369
370 public String get(PageContext pageContext, String key) {
371 return get(pageContext, key, key);
372 }
373
374 public String get(
375 PageContext pageContext, String key, String defaultValue) {
376
377 try {
378 return _get(pageContext, null, null, key, defaultValue);
379 }
380 catch (Exception e) {
381 if (_log.isWarnEnabled()) {
382 _log.warn(e, e);
383 }
384
385 return defaultValue;
386 }
387 }
388
389 public String get(PortletConfig portletConfig, Locale locale, String key) {
390 return get(portletConfig, locale, key, key);
391 }
392
393 public String get(
394 PortletConfig portletConfig, Locale locale, String key,
395 String defaultValue) {
396
397 try {
398 return _get(null, portletConfig, locale, key, defaultValue);
399 }
400 catch (Exception e) {
401 if (_log.isWarnEnabled()) {
402 _log.warn(e, e);
403 }
404
405 return defaultValue;
406 }
407 }
408
409 public Locale[] getAvailableLocales() {
410 return _getInstance()._locales;
411 }
412
413 public String getCharset(Locale locale) {
414 return _getInstance()._getCharset(locale);
415 }
416
417 public String getLanguageId(HttpServletRequest request) {
418 String languageId = ParamUtil.getString(request, "languageId");
419
420 if (Validator.isNotNull(languageId)) {
421 if (_localesMap.containsKey(languageId) ||
422 _charEncodings.containsKey(languageId)) {
423
424 return languageId;
425 }
426 }
427
428 Locale locale = PortalUtil.getLocale(request);
429
430 return getLanguageId(locale);
431 }
432
433 public String getLanguageId(Locale locale) {
434 return LocaleUtil.toLanguageId(locale);
435 }
436
437 public String getLanguageId(PortletRequest portletRequest) {
438 HttpServletRequest request = PortalUtil.getHttpServletRequest(
439 portletRequest);
440
441 return getLanguageId(request);
442 }
443
444 public Locale getLocale(String languageCode) {
445 return _getInstance()._getLocale(languageCode);
446 }
447
448 public Locale[] getSupportedLocales() {
449 List<Locale> supportedLocales = new ArrayList<Locale>();
450
451 Locale[] locales = getAvailableLocales();
452
453 for (Locale locale : locales) {
454 if (!isBetaLocale(locale)) {
455 supportedLocales.add(locale);
456 }
457 }
458
459 return supportedLocales.toArray(new Locale[supportedLocales.size()]);
460 }
461
462 public String getTimeDescription(Locale locale, long milliseconds) {
463 return getTimeDescription(locale, milliseconds, false);
464 }
465
466 public String getTimeDescription(
467 Locale locale, long milliseconds, boolean approximate) {
468
469 String description = Time.getDescription(milliseconds, approximate);
470
471 String value = null;
472
473 try {
474 int pos = description.indexOf(CharPool.SPACE);
475
476 String x = description.substring(0, pos);
477
478 value = x.concat(StringPool.SPACE).concat(
479 get(
480 locale,
481 description.substring(
482 pos + 1, description.length()).toLowerCase()));
483 }
484 catch (Exception e) {
485 if (_log.isWarnEnabled()) {
486 _log.warn(e, e);
487 }
488 }
489
490 return value;
491 }
492
493 public String getTimeDescription(Locale locale, Long milliseconds) {
494 return getTimeDescription(locale, milliseconds.longValue());
495 }
496
497 public String getTimeDescription(
498 PageContext pageContext, long milliseconds) {
499
500 return getTimeDescription(pageContext, milliseconds, false);
501 }
502
503 public String getTimeDescription(
504 PageContext pageContext, long milliseconds, boolean approximate) {
505
506 String description = Time.getDescription(milliseconds, approximate);
507
508 String value = null;
509
510 try {
511 int pos = description.indexOf(CharPool.SPACE);
512
513 String x = description.substring(0, pos);
514
515 value = x.concat(StringPool.SPACE).concat(
516 get(
517 pageContext,
518 description.substring(
519 pos + 1, description.length()).toLowerCase()));
520 }
521 catch (Exception e) {
522 if (_log.isWarnEnabled()) {
523 _log.warn(e, e);
524 }
525 }
526
527 return value;
528 }
529
530 public String getTimeDescription(
531 PageContext pageContext, Long milliseconds) {
532
533 return getTimeDescription(pageContext, milliseconds.longValue());
534 }
535
536 public void init() {
537 _instances.clear();
538 }
539
540 public boolean isAvailableLocale(Locale locale) {
541 return _getInstance()._localesSet.contains(locale);
542 }
543
544 public boolean isBetaLocale(Locale locale) {
545 return _getInstance()._localesBetaSet.contains(locale);
546 }
547
548 public boolean isDuplicateLanguageCode(String languageCode) {
549 return _getInstance()._duplicateLanguageCodes.contains(languageCode);
550 }
551
552 public void resetAvailableLocales(long companyId) {
553 _resetAvailableLocales(companyId);
554 }
555
556 public void updateCookie(
557 HttpServletRequest request, HttpServletResponse response,
558 Locale locale) {
559
560 String languageId = LocaleUtil.toLanguageId(locale);
561
562 Cookie languageIdCookie = new Cookie(
563 CookieKeys.GUEST_LANGUAGE_ID, languageId);
564
565 languageIdCookie.setPath(StringPool.SLASH);
566 languageIdCookie.setMaxAge(CookieKeys.MAX_AGE);
567
568 CookieKeys.addCookie(request, response, languageIdCookie);
569 }
570
571 private static LanguageImpl _getInstance() {
572 Long companyId = CompanyThreadLocal.getCompanyId();
573
574 LanguageImpl instance = _instances.get(companyId);
575
576 if (instance == null) {
577 instance = new LanguageImpl(companyId);
578
579 _instances.put(companyId, instance);
580 }
581
582 return instance;
583 }
584
585 private LanguageImpl() {
586 this(CompanyConstants.SYSTEM);
587 }
588
589 private LanguageImpl(long companyId) {
590 String[] localesArray = PropsValues.LOCALES;
591
592 if (companyId != CompanyConstants.SYSTEM) {
593 try {
594 localesArray = PrefsPropsUtil.getStringArray(
595 companyId, PropsKeys.LOCALES, StringPool.COMMA,
596 PropsValues.LOCALES);
597 }
598 catch (SystemException se) {
599 localesArray = PropsValues.LOCALES;
600 }
601 }
602
603 _charEncodings = new HashMap<String, String>();
604 _duplicateLanguageCodes = new HashSet<String>();
605 _locales = new Locale[localesArray.length];
606 _localesMap = new HashMap<String, Locale>(localesArray.length);
607 _localesSet = new HashSet<Locale>(localesArray.length);
608
609 for (int i = 0; i < localesArray.length; i++) {
610 String languageId = localesArray[i];
611
612 Locale locale = LocaleUtil.fromLanguageId(languageId);
613
614 _charEncodings.put(locale.toString(), StringPool.UTF8);
615
616 String language = languageId;
617
618 int pos = languageId.indexOf(CharPool.UNDERLINE);
619
620 if (pos > 0) {
621 language = languageId.substring(0, pos);
622 }
623
624 if (_localesMap.containsKey(language)) {
625 _duplicateLanguageCodes.add(language);
626 }
627
628 _locales[i] = locale;
629
630 if (!_localesMap.containsKey(language)) {
631 _localesMap.put(language, locale);
632 }
633
634 _localesSet.add(locale);
635 }
636
637 String[] localesBetaArray = PropsValues.LOCALES_BETA;
638
639 _localesBetaSet = new HashSet<Locale>(localesBetaArray.length);
640
641 for (String languageId : localesBetaArray) {
642 Locale locale = LocaleUtil.fromLanguageId(languageId);
643
644 _localesBetaSet.add(locale);
645 }
646 }
647
648 private String _escapePattern(String pattern) {
649 return StringUtil.replace(
650 pattern, StringPool.APOSTROPHE, StringPool.DOUBLE_APOSTROPHE);
651 }
652
653 private String _get(
654 PageContext pageContext, PortletConfig portletConfig, Locale locale,
655 String key, String defaultValue)
656 throws Exception {
657
658 if (PropsValues.TRANSLATIONS_DISABLED) {
659 return key;
660 }
661
662 if (key == null) {
663 return null;
664 }
665
666 String value = null;
667
668 if (pageContext != null) {
669 HttpServletRequest request =
670 (HttpServletRequest)pageContext.getRequest();
671
672 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
673 WebKeys.THEME_DISPLAY);
674
675 locale = themeDisplay.getLocale();
676
677 portletConfig = (PortletConfig)request.getAttribute(
678 JavaConstants.JAVAX_PORTLET_CONFIG);
679 }
680
681 if (portletConfig != null) {
682 ResourceBundle resourceBundle = portletConfig.getResourceBundle(
683 locale);
684
685 value = ResourceBundleUtil.getString(resourceBundle, key);
686
687
688
689 String portletName = portletConfig.getPortletName();
690
691 if (((value == null) || value.equals(defaultValue)) &&
692 portletName.equals(PortletKeys.PORTLET_CONFIGURATION)) {
693
694 value = _getPortletConfigurationValue(pageContext, locale, key);
695 }
696
697 if (value != null) {
698 value = LanguageResources.fixValue(value);
699 }
700 }
701
702 if ((value == null) || value.equals(defaultValue)) {
703 value = LanguageResources.getMessage(locale, key);
704 }
705
706 if ((value == null) || value.equals(defaultValue)) {
707 if ((key.length() > 0) &&
708 (key.charAt(key.length() - 1) == CharPool.CLOSE_BRACKET)) {
709
710 int pos = key.lastIndexOf(CharPool.OPEN_BRACKET);
711
712 if (pos != -1) {
713 key = key.substring(0, pos);
714
715 return _get(
716 pageContext, portletConfig, locale, key, defaultValue);
717 }
718 }
719 }
720
721 if ((value == null) || value.equals(key)) {
722 value = defaultValue;
723 }
724
725 return value;
726 }
727
728 private String _getCharset(Locale locale) {
729 return StringPool.UTF8;
730 }
731
732 private Locale _getLocale(String languageCode) {
733 return _localesMap.get(languageCode);
734 }
735
736 private String _getPortletConfigurationValue(
737 PageContext pageContext, Locale locale, String key)
738 throws Exception {
739
740 if (PropsValues.TRANSLATIONS_DISABLED) {
741 return key;
742 }
743
744 HttpServletRequest request =
745 (HttpServletRequest)pageContext.getRequest();
746
747 String portletResource = ParamUtil.getString(
748 request, "portletResource");
749
750 long companyId = PortalUtil.getCompanyId(request);
751
752 Portlet portlet = PortletLocalServiceUtil.getPortletById(
753 companyId, portletResource);
754
755 PortletConfig portletConfig = PortletConfigFactoryUtil.create(
756 portlet, pageContext.getServletContext());
757
758 ResourceBundle resourceBundle = portletConfig.getResourceBundle(locale);
759
760 return ResourceBundleUtil.getString(resourceBundle, key);
761 }
762
763 private void _resetAvailableLocales(long companyId) {
764 _instances.remove(companyId);
765 }
766
767 private static Log _log = LogFactoryUtil.getLog(LanguageImpl.class);
768
769 private static Map<Long, LanguageImpl> _instances =
770 new ConcurrentHashMap<Long, LanguageImpl>();
771
772 private Map<String, String> _charEncodings;
773 private Set<String> _duplicateLanguageCodes;
774 private Locale[] _locales;
775 private Set<Locale> _localesBetaSet;
776 private Map<String, Locale> _localesMap;
777 private Set<Locale> _localesSet;
778
779 }