2 * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
\r
4 * This library is free software; you can redistribute it and/or modify it under
\r
5 * the terms of the GNU Lesser General Public License as published by the Free
\r
6 * Software Foundation; either version 2.1 of the License, or (at your option)
\r
9 * This library is distributed in the hope that it will be useful, but WITHOUT
\r
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
\r
11 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
\r
15 package com.liferay.portal.language;
\r
17 import com.liferay.portal.kernel.exception.SystemException;
\r
18 import com.liferay.portal.kernel.language.Language;
\r
19 import com.liferay.portal.kernel.language.LanguageWrapper;
\r
20 import com.liferay.portal.kernel.log.Log;
\r
21 import com.liferay.portal.kernel.log.LogFactoryUtil;
\r
22 import com.liferay.portal.kernel.util.CharPool;
\r
23 import com.liferay.portal.kernel.util.JavaConstants;
\r
24 import com.liferay.portal.kernel.util.LocaleUtil;
\r
25 import com.liferay.portal.kernel.util.ParamUtil;
\r
26 import com.liferay.portal.kernel.util.PropsKeys;
\r
27 import com.liferay.portal.kernel.util.ResourceBundleUtil;
\r
28 import com.liferay.portal.kernel.util.StringPool;
\r
29 import com.liferay.portal.kernel.util.StringUtil;
\r
30 import com.liferay.portal.kernel.util.Time;
\r
31 import com.liferay.portal.kernel.util.Validator;
\r
32 import com.liferay.portal.model.CompanyConstants;
\r
33 import com.liferay.portal.model.Portlet;
\r
34 import com.liferay.portal.security.auth.CompanyThreadLocal;
\r
35 import com.liferay.portal.service.PortletLocalServiceUtil;
\r
36 import com.liferay.portal.theme.ThemeDisplay;
\r
37 import com.liferay.portal.util.CookieKeys;
\r
38 import com.liferay.portal.util.PortalUtil;
\r
39 import com.liferay.portal.util.PortletKeys;
\r
40 import com.liferay.portal.util.PrefsPropsUtil;
\r
41 import com.liferay.portal.util.PropsValues;
\r
42 import com.liferay.portal.util.WebKeys;
\r
43 import com.liferay.portlet.PortletConfigFactoryUtil;
\r
45 import java.text.MessageFormat;
\r
47 import java.util.ArrayList;
\r
48 import java.util.HashMap;
\r
49 import java.util.HashSet;
\r
50 import java.util.List;
\r
51 import java.util.Locale;
\r
52 import java.util.Map;
\r
53 import java.util.ResourceBundle;
\r
54 import java.util.Set;
\r
55 import java.util.concurrent.ConcurrentHashMap;
\r
57 import javax.portlet.PortletConfig;
\r
58 import javax.portlet.PortletRequest;
\r
60 import javax.servlet.http.Cookie;
\r
61 import javax.servlet.http.HttpServletRequest;
\r
62 import javax.servlet.http.HttpServletResponse;
\r
63 import javax.servlet.jsp.PageContext;
\r
66 * @author Brian Wing Shun Chan
\r
67 * @author Andrius Vitkauskas
\r
69 public class LanguageImpl implements Language {
\r
71 public String format(Locale locale, String pattern, Object argument) {
\r
72 return format(locale, pattern, new Object[] {argument}, true);
\r
75 public String format(
\r
76 Locale locale, String pattern, Object argument,
\r
77 boolean translateArguments) {
\r
80 locale, pattern, new Object[] {argument}, translateArguments);
\r
83 public String format(Locale locale, String pattern, Object[] arguments) {
\r
84 return format(locale, pattern, arguments, true);
\r
87 public String format(
\r
88 Locale locale, String pattern, Object[] arguments,
\r
89 boolean translateArguments) {
\r
91 if (PropsValues.TRANSLATIONS_DISABLED) {
\r
95 String value = null;
\r
98 pattern = get(locale, pattern);
\r
100 if ((arguments != null) && (arguments.length > 0)) {
\r
101 pattern = _escapePattern(pattern);
\r
103 Object[] formattedArguments = new Object[arguments.length];
\r
105 for (int i = 0; i < arguments.length; i++) {
\r
106 if (translateArguments) {
\r
107 formattedArguments[i] = get(
\r
108 locale, arguments[i].toString());
\r
111 formattedArguments[i] = arguments[i];
\r
115 value = MessageFormat.format(pattern, formattedArguments);
\r
121 catch (Exception e) {
\r
122 if (_log.isWarnEnabled()) {
\r
130 public String format(
\r
131 PageContext pageContext, String pattern, LanguageWrapper argument) {
\r
134 pageContext, pattern, new LanguageWrapper[] {argument}, true);
\r
137 public String format(
\r
138 PageContext pageContext, String pattern, LanguageWrapper argument,
\r
139 boolean translateArguments) {
\r
142 pageContext, pattern, new LanguageWrapper[] {argument},
\r
143 translateArguments);
\r
146 public String format(
\r
147 PageContext pageContext, String pattern, LanguageWrapper[] arguments) {
\r
149 return format(pageContext, pattern, arguments, true);
\r
152 public String format(
\r
153 PageContext pageContext, String pattern, LanguageWrapper[] arguments,
\r
154 boolean translateArguments) {
\r
156 if (PropsValues.TRANSLATIONS_DISABLED) {
\r
160 String value = null;
\r
163 pattern = get(pageContext, pattern);
\r
165 if ((arguments != null) && (arguments.length > 0)) {
\r
166 pattern = _escapePattern(pattern);
\r
168 Object[] formattedArguments = new Object[arguments.length];
\r
170 for (int i = 0; i < arguments.length; i++) {
\r
171 if (translateArguments) {
\r
172 formattedArguments[i] =
\r
173 arguments[i].getBefore() +
\r
174 get(pageContext, arguments[i].getText()) +
\r
175 arguments[i].getAfter();
\r
178 formattedArguments[i] =
\r
179 arguments[i].getBefore() +
\r
180 arguments[i].getText() +
\r
181 arguments[i].getAfter();
\r
185 value = MessageFormat.format(pattern, formattedArguments);
\r
191 catch (Exception e) {
\r
192 if (_log.isWarnEnabled()) {
\r
200 public String format(
\r
201 PageContext pageContext, String pattern, Object argument) {
\r
203 return format(pageContext, pattern, new Object[] {argument}, true);
\r
206 public String format(
\r
207 PageContext pageContext, String pattern, Object argument,
\r
208 boolean translateArguments) {
\r
211 pageContext, pattern, new Object[] {argument}, translateArguments);
\r
214 public String format(
\r
215 PageContext pageContext, String pattern, Object[] arguments) {
\r
217 return format(pageContext, pattern, arguments, true);
\r
220 public String format(
\r
221 PageContext pageContext, String pattern, Object[] arguments,
\r
222 boolean translateArguments) {
\r
224 if (PropsValues.TRANSLATIONS_DISABLED) {
\r
228 String value = null;
\r
231 pattern = get(pageContext, pattern);
\r
233 if ((arguments != null) && (arguments.length > 0)) {
\r
234 pattern = _escapePattern(pattern);
\r
236 Object[] formattedArguments = new Object[arguments.length];
\r
238 for (int i = 0; i < arguments.length; i++) {
\r
239 if (translateArguments) {
\r
240 formattedArguments[i] = get(
\r
241 pageContext, arguments[i].toString());
\r
244 formattedArguments[i] = arguments[i];
\r
248 value = MessageFormat.format(pattern, formattedArguments);
\r
254 catch (Exception e) {
\r
255 if (_log.isWarnEnabled()) {
\r
263 public String format(
\r
264 PortletConfig portletConfig, Locale locale, String pattern,
\r
268 portletConfig, locale, pattern, new Object[] {argument}, true);
\r
271 public String format(
\r
272 PortletConfig portletConfig, Locale locale, String pattern,
\r
273 Object argument, boolean translateArguments) {
\r
276 portletConfig, locale, pattern, new Object[] {argument},
\r
277 translateArguments);
\r
280 public String format(
\r
281 PortletConfig portletConfig, Locale locale, String pattern,
\r
282 Object[] arguments) {
\r
284 return format(portletConfig, locale, pattern, arguments, true);
\r
287 public String format(
\r
288 PortletConfig portletConfig, Locale locale, String pattern,
\r
289 Object[] arguments, boolean translateArguments) {
\r
291 if (PropsValues.TRANSLATIONS_DISABLED) {
\r
295 String value = null;
\r
298 pattern = get(portletConfig, locale, pattern);
\r
300 if ((arguments != null) && (arguments.length > 0)) {
\r
301 pattern = _escapePattern(pattern);
\r
303 Object[] formattedArguments = new Object[arguments.length];
\r
305 for (int i = 0; i < arguments.length; i++) {
\r
306 if (translateArguments) {
\r
307 formattedArguments[i] = get(
\r
308 locale, arguments[i].toString());
\r
311 formattedArguments[i] = arguments[i];
\r
315 value = MessageFormat.format(pattern, formattedArguments);
\r
321 catch (Exception e) {
\r
322 if (_log.isWarnEnabled()) {
\r
330 public String get(Locale locale, String key) {
\r
331 return get(locale, key, key);
\r
334 public String get(Locale locale, String key, String defaultValue) {
\r
335 if (PropsValues.TRANSLATIONS_DISABLED) {
\r
343 String value = LanguageResources.getMessage(locale, key);
\r
345 while ((value == null) || value.equals(defaultValue)) {
\r
346 if ((key.length() > 0) &&
\r
347 (key.charAt(key.length() - 1) == CharPool.CLOSE_BRACKET)) {
\r
349 int pos = key.lastIndexOf(CharPool.OPEN_BRACKET);
\r
352 key = key.substring(0, pos);
\r
354 value = LanguageResources.getMessage(locale, key);
\r
363 if (value == null) {
\r
364 value = defaultValue;
\r
370 public String get(PageContext pageContext, String key) {
\r
371 return get(pageContext, key, key);
\r
375 PageContext pageContext, String key, String defaultValue) {
\r
378 return _get(pageContext, null, null, key, defaultValue);
\r
380 catch (Exception e) {
\r
381 if (_log.isWarnEnabled()) {
\r
385 return defaultValue;
\r
389 public String get(PortletConfig portletConfig, Locale locale, String key) {
\r
390 return get(portletConfig, locale, key, key);
\r
394 PortletConfig portletConfig, Locale locale, String key,
\r
395 String defaultValue) {
\r
398 return _get(null, portletConfig, locale, key, defaultValue);
\r
400 catch (Exception e) {
\r
401 if (_log.isWarnEnabled()) {
\r
405 return defaultValue;
\r
409 public Locale[] getAvailableLocales() {
\r
410 return _getInstance()._locales;
\r
413 public String getCharset(Locale locale) {
\r
414 return _getInstance()._getCharset(locale);
\r
417 public String getLanguageId(HttpServletRequest request) {
\r
418 String languageId = ParamUtil.getString(request, "languageId");
\r
420 if (Validator.isNotNull(languageId)) {
\r
421 if (_localesMap.containsKey(languageId) ||
\r
422 _charEncodings.containsKey(languageId)) {
\r
428 Locale locale = PortalUtil.getLocale(request);
\r
430 return getLanguageId(locale);
\r
433 public String getLanguageId(Locale locale) {
\r
434 return LocaleUtil.toLanguageId(locale);
\r
437 public String getLanguageId(PortletRequest portletRequest) {
\r
438 HttpServletRequest request = PortalUtil.getHttpServletRequest(
\r
441 return getLanguageId(request);
\r
444 public Locale getLocale(String languageCode) {
\r
445 return _getInstance()._getLocale(languageCode);
\r
448 public Locale[] getSupportedLocales() {
\r
449 List<Locale> supportedLocales = new ArrayList<Locale>();
\r
451 Locale[] locales = getAvailableLocales();
\r
453 for (Locale locale : locales) {
\r
454 if (!isBetaLocale(locale)) {
\r
455 supportedLocales.add(locale);
\r
459 return supportedLocales.toArray(new Locale[supportedLocales.size()]);
\r
462 public String getTimeDescription(Locale locale, long milliseconds) {
\r
463 return getTimeDescription(locale, milliseconds, false);
\r
466 public String getTimeDescription(
\r
467 Locale locale, long milliseconds, boolean approximate) {
\r
469 String description = Time.getDescription(milliseconds, approximate);
\r
471 String value = null;
\r
474 int pos = description.indexOf(CharPool.SPACE);
\r
476 String x = description.substring(0, pos);
\r
478 value = x.concat(StringPool.SPACE).concat(
\r
481 description.substring(
\r
482 pos + 1, description.length()).toLowerCase()));
\r
484 catch (Exception e) {
\r
485 if (_log.isWarnEnabled()) {
\r
493 public String getTimeDescription(Locale locale, Long milliseconds) {
\r
494 return getTimeDescription(locale, milliseconds.longValue());
\r
497 public String getTimeDescription(
\r
498 PageContext pageContext, long milliseconds) {
\r
500 return getTimeDescription(pageContext, milliseconds, false);
\r
503 public String getTimeDescription(
\r
504 PageContext pageContext, long milliseconds, boolean approximate) {
\r
506 String description = Time.getDescription(milliseconds, approximate);
\r
508 String value = null;
\r
511 int pos = description.indexOf(CharPool.SPACE);
\r
513 String x = description.substring(0, pos);
\r
515 value = x.concat(StringPool.SPACE).concat(
\r
518 description.substring(
\r
519 pos + 1, description.length()).toLowerCase()));
\r
521 catch (Exception e) {
\r
522 if (_log.isWarnEnabled()) {
\r
530 public String getTimeDescription(
\r
531 PageContext pageContext, Long milliseconds) {
\r
533 return getTimeDescription(pageContext, milliseconds.longValue());
\r
536 public void init() {
\r
537 _instances.clear();
\r
540 public boolean isAvailableLocale(Locale locale) {
\r
541 return _getInstance()._localesSet.contains(locale);
\r
544 public boolean isBetaLocale(Locale locale) {
\r
545 return _getInstance()._localesBetaSet.contains(locale);
\r
548 public boolean isDuplicateLanguageCode(String languageCode) {
\r
549 return _getInstance()._duplicateLanguageCodes.contains(languageCode);
\r
552 public void resetAvailableLocales(long companyId) {
\r
553 _resetAvailableLocales(companyId);
\r
556 public void updateCookie(
\r
557 HttpServletRequest request, HttpServletResponse response,
\r
560 String languageId = LocaleUtil.toLanguageId(locale);
\r
562 Cookie languageIdCookie = new Cookie(
\r
563 CookieKeys.GUEST_LANGUAGE_ID, languageId);
\r
565 languageIdCookie.setPath(StringPool.SLASH);
\r
566 languageIdCookie.setMaxAge(CookieKeys.MAX_AGE);
\r
568 CookieKeys.addCookie(request, response, languageIdCookie);
\r
571 private static LanguageImpl _getInstance() {
\r
572 Long companyId = CompanyThreadLocal.getCompanyId();
\r
574 LanguageImpl instance = _instances.get(companyId);
\r
576 if (instance == null) {
\r
577 instance = new LanguageImpl(companyId);
\r
579 _instances.put(companyId, instance);
\r
585 private LanguageImpl() {
\r
586 this(CompanyConstants.SYSTEM);
\r
589 private LanguageImpl(long companyId) {
\r
590 String[] localesArray = PropsValues.LOCALES;
\r
592 if (companyId != CompanyConstants.SYSTEM) {
\r
594 localesArray = PrefsPropsUtil.getStringArray(
\r
595 companyId, PropsKeys.LOCALES, StringPool.COMMA,
\r
596 PropsValues.LOCALES);
\r
598 catch (SystemException se) {
\r
599 localesArray = PropsValues.LOCALES;
\r
603 _charEncodings = new HashMap<String, String>();
\r
604 _duplicateLanguageCodes = new HashSet<String>();
\r
605 _locales = new Locale[localesArray.length];
\r
606 _localesMap = new HashMap<String, Locale>(localesArray.length);
\r
607 _localesSet = new HashSet<Locale>(localesArray.length);
\r
609 for (int i = 0; i < localesArray.length; i++) {
\r
610 String languageId = localesArray[i];
\r
612 Locale locale = LocaleUtil.fromLanguageId(languageId);
\r
614 _charEncodings.put(locale.toString(), StringPool.UTF8);
\r
616 String language = languageId;
\r
618 int pos = languageId.indexOf(CharPool.UNDERLINE);
\r
621 language = languageId.substring(0, pos);
\r
624 if (_localesMap.containsKey(language)) {
\r
625 _duplicateLanguageCodes.add(language);
\r
628 _locales[i] = locale;
\r
630 if (!_localesMap.containsKey(language)) {
\r
631 _localesMap.put(language, locale);
\r
634 _localesSet.add(locale);
\r
637 String[] localesBetaArray = PropsValues.LOCALES_BETA;
\r
639 _localesBetaSet = new HashSet<Locale>(localesBetaArray.length);
\r
641 for (String languageId : localesBetaArray) {
\r
642 Locale locale = LocaleUtil.fromLanguageId(languageId);
\r
644 _localesBetaSet.add(locale);
\r
648 private String _escapePattern(String pattern) {
\r
649 return StringUtil.replace(
\r
650 pattern, StringPool.APOSTROPHE, StringPool.DOUBLE_APOSTROPHE);
\r
653 private String _get(
\r
654 PageContext pageContext, PortletConfig portletConfig, Locale locale,
\r
655 String key, String defaultValue)
\r
658 if (PropsValues.TRANSLATIONS_DISABLED) {
\r
666 String value = null;
\r
668 if (pageContext != null) {
\r
669 HttpServletRequest request =
\r
670 (HttpServletRequest)pageContext.getRequest();
\r
672 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
\r
673 WebKeys.THEME_DISPLAY);
\r
675 locale = themeDisplay.getLocale();
\r
677 portletConfig = (PortletConfig)request.getAttribute(
\r
678 JavaConstants.JAVAX_PORTLET_CONFIG);
\r
681 if (portletConfig != null) {
\r
682 ResourceBundle resourceBundle = portletConfig.getResourceBundle(
\r
685 value = ResourceBundleUtil.getString(resourceBundle, key);
\r
689 String portletName = portletConfig.getPortletName();
\r
691 if (((value == null) || value.equals(defaultValue)) &&
\r
692 portletName.equals(PortletKeys.PORTLET_CONFIGURATION)) {
\r
694 value = _getPortletConfigurationValue(pageContext, locale, key);
\r
697 if (value != null) {
\r
698 value = LanguageResources.fixValue(value);
\r
702 if ((value == null) || value.equals(defaultValue)) {
\r
703 value = LanguageResources.getMessage(locale, key);
\r
706 if ((value == null) || value.equals(defaultValue)) {
\r
707 if ((key.length() > 0) &&
\r
708 (key.charAt(key.length() - 1) == CharPool.CLOSE_BRACKET)) {
\r
710 int pos = key.lastIndexOf(CharPool.OPEN_BRACKET);
\r
713 key = key.substring(0, pos);
\r
716 pageContext, portletConfig, locale, key, defaultValue);
\r
721 if ((value == null) || value.equals(key)) {
\r
722 value = defaultValue;
\r
728 private String _getCharset(Locale locale) {
\r
729 return StringPool.UTF8;
\r
732 private Locale _getLocale(String languageCode) {
\r
733 return _localesMap.get(languageCode);
\r
736 private String _getPortletConfigurationValue(
\r
737 PageContext pageContext, Locale locale, String key)
\r
740 if (PropsValues.TRANSLATIONS_DISABLED) {
\r
744 HttpServletRequest request =
\r
745 (HttpServletRequest)pageContext.getRequest();
\r
747 String portletResource = ParamUtil.getString(
\r
748 request, "portletResource");
\r
750 long companyId = PortalUtil.getCompanyId(request);
\r
752 Portlet portlet = PortletLocalServiceUtil.getPortletById(
\r
753 companyId, portletResource);
\r
755 PortletConfig portletConfig = PortletConfigFactoryUtil.create(
\r
756 portlet, pageContext.getServletContext());
\r
758 ResourceBundle resourceBundle = portletConfig.getResourceBundle(locale);
\r
760 return ResourceBundleUtil.getString(resourceBundle, key);
\r
763 private void _resetAvailableLocales(long companyId) {
\r
764 _instances.remove(companyId);
\r
767 private static Log _log = LogFactoryUtil.getLog(LanguageImpl.class);
\r
769 private static Map<Long, LanguageImpl> _instances =
\r
770 new ConcurrentHashMap<Long, LanguageImpl>();
\r
772 private Map<String, String> _charEncodings;
\r
773 private Set<String> _duplicateLanguageCodes;
\r
774 private Locale[] _locales;
\r
775 private Set<Locale> _localesBetaSet;
\r
776 private Map<String, Locale> _localesMap;
\r
777 private Set<Locale> _localesSet;
\r