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