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