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 isAvailableLanguageCode(String languageCode) {
541 return _getInstance()._localesMap.containsKey(languageCode);
542 }
543
544 public boolean isAvailableLocale(Locale locale) {
545 return _getInstance()._localesSet.contains(locale);
546 }
547
548 public boolean isBetaLocale(Locale locale) {
549 return _getInstance()._localesBetaSet.contains(locale);
550 }
551
552 public boolean isDuplicateLanguageCode(String languageCode) {
553 return _getInstance()._duplicateLanguageCodes.contains(languageCode);
554 }
555
556 public void resetAvailableLocales(long companyId) {
557 _resetAvailableLocales(companyId);
558 }
559
560 public void updateCookie(
561 HttpServletRequest request, HttpServletResponse response,
562 Locale locale) {
563
564 String languageId = LocaleUtil.toLanguageId(locale);
565
566 Cookie languageIdCookie = new Cookie(
567 CookieKeys.GUEST_LANGUAGE_ID, languageId);
568
569 languageIdCookie.setPath(StringPool.SLASH);
570 languageIdCookie.setMaxAge(CookieKeys.MAX_AGE);
571
572 CookieKeys.addCookie(request, response, languageIdCookie);
573 }
574
575 private static LanguageImpl _getInstance() {
576 Long companyId = CompanyThreadLocal.getCompanyId();
577
578 LanguageImpl instance = _instances.get(companyId);
579
580 if (instance == null) {
581 instance = new LanguageImpl(companyId);
582
583 _instances.put(companyId, instance);
584 }
585
586 return instance;
587 }
588
589 private LanguageImpl() {
590 this(CompanyConstants.SYSTEM);
591 }
592
593 private LanguageImpl(long companyId) {
594 String[] localesArray = PropsValues.LOCALES;
595
596 if (companyId != CompanyConstants.SYSTEM) {
597 try {
598 localesArray = PrefsPropsUtil.getStringArray(
599 companyId, PropsKeys.LOCALES, StringPool.COMMA,
600 PropsValues.LOCALES);
601 }
602 catch (SystemException se) {
603 localesArray = PropsValues.LOCALES;
604 }
605 }
606
607 _charEncodings = new HashMap<String, String>();
608 _duplicateLanguageCodes = new HashSet<String>();
609 _locales = new Locale[localesArray.length];
610 _localesMap = new HashMap<String, Locale>(localesArray.length);
611 _localesSet = new HashSet<Locale>(localesArray.length);
612
613 for (int i = 0; i < localesArray.length; i++) {
614 String languageId = localesArray[i];
615
616 Locale locale = LocaleUtil.fromLanguageId(languageId, false);
617
618 _charEncodings.put(locale.toString(), StringPool.UTF8);
619
620 String language = languageId;
621
622 int pos = languageId.indexOf(CharPool.UNDERLINE);
623
624 if (pos > 0) {
625 language = languageId.substring(0, pos);
626 }
627
628 if (_localesMap.containsKey(language)) {
629 _duplicateLanguageCodes.add(language);
630 }
631
632 _locales[i] = locale;
633
634 if (!_localesMap.containsKey(language)) {
635 _localesMap.put(language, locale);
636 }
637
638 _localesSet.add(locale);
639 }
640
641 String[] localesBetaArray = PropsValues.LOCALES_BETA;
642
643 _localesBetaSet = new HashSet<Locale>(localesBetaArray.length);
644
645 for (String languageId : localesBetaArray) {
646 Locale locale = LocaleUtil.fromLanguageId(languageId, false);
647
648 _localesBetaSet.add(locale);
649 }
650 }
651
652 private String _escapePattern(String pattern) {
653 return StringUtil.replace(
654 pattern, StringPool.APOSTROPHE, StringPool.DOUBLE_APOSTROPHE);
655 }
656
657 private String _get(
658 PageContext pageContext, PortletConfig portletConfig, Locale locale,
659 String key, String defaultValue)
660 throws Exception {
661
662 if (PropsValues.TRANSLATIONS_DISABLED) {
663 return key;
664 }
665
666 if (key == null) {
667 return null;
668 }
669
670 String value = null;
671
672 if (pageContext != null) {
673 HttpServletRequest request =
674 (HttpServletRequest)pageContext.getRequest();
675
676 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
677 WebKeys.THEME_DISPLAY);
678
679 locale = themeDisplay.getLocale();
680
681 portletConfig = (PortletConfig)request.getAttribute(
682 JavaConstants.JAVAX_PORTLET_CONFIG);
683 }
684
685 if (portletConfig != null) {
686 ResourceBundle resourceBundle = portletConfig.getResourceBundle(
687 locale);
688
689 value = ResourceBundleUtil.getString(resourceBundle, key);
690
691
692
693 String portletName = portletConfig.getPortletName();
694
695 if (((value == null) || value.equals(defaultValue)) &&
696 portletName.equals(PortletKeys.PORTLET_CONFIGURATION)) {
697
698 value = _getPortletConfigurationValue(pageContext, locale, key);
699 }
700
701 if (value != null) {
702 value = LanguageResources.fixValue(value);
703 }
704 }
705
706 if ((value == null) || value.equals(defaultValue)) {
707 value = LanguageResources.getMessage(locale, key);
708 }
709
710 if ((value == null) || value.equals(defaultValue)) {
711 if ((key.length() > 0) &&
712 (key.charAt(key.length() - 1) == CharPool.CLOSE_BRACKET)) {
713
714 int pos = key.lastIndexOf(CharPool.OPEN_BRACKET);
715
716 if (pos != -1) {
717 key = key.substring(0, pos);
718
719 return _get(
720 pageContext, portletConfig, locale, key, defaultValue);
721 }
722 }
723 }
724
725 if ((value == null) || value.equals(key)) {
726 value = defaultValue;
727 }
728
729 return value;
730 }
731
732 private String _getCharset(Locale locale) {
733 return StringPool.UTF8;
734 }
735
736 private Locale _getLocale(String languageCode) {
737 return _localesMap.get(languageCode);
738 }
739
740 private String _getPortletConfigurationValue(
741 PageContext pageContext, Locale locale, String key)
742 throws Exception {
743
744 if (PropsValues.TRANSLATIONS_DISABLED) {
745 return key;
746 }
747
748 HttpServletRequest request =
749 (HttpServletRequest)pageContext.getRequest();
750
751 String portletResource = ParamUtil.getString(
752 request, "portletResource");
753
754 long companyId = PortalUtil.getCompanyId(request);
755
756 Portlet portlet = PortletLocalServiceUtil.getPortletById(
757 companyId, portletResource);
758
759 PortletConfig portletConfig = PortletConfigFactoryUtil.create(
760 portlet, pageContext.getServletContext());
761
762 ResourceBundle resourceBundle = portletConfig.getResourceBundle(locale);
763
764 return ResourceBundleUtil.getString(resourceBundle, key);
765 }
766
767 private void _resetAvailableLocales(long companyId) {
768 _instances.remove(companyId);
769 }
770
771 private static Log _log = LogFactoryUtil.getLog(LanguageImpl.class);
772
773 private static Map<Long, LanguageImpl> _instances =
774 new ConcurrentHashMap<Long, LanguageImpl>();
775
776 private Map<String, String> _charEncodings;
777 private Set<String> _duplicateLanguageCodes;
778 private Locale[] _locales;
779 private Set<Locale> _localesBetaSet;
780 private Map<String, Locale> _localesMap;
781 private Set<Locale> _localesSet;
782
783 }