001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.language;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.language.Language;
020    import com.liferay.portal.kernel.language.LanguageWrapper;
021    import com.liferay.portal.kernel.log.Log;
022    import com.liferay.portal.kernel.log.LogFactoryUtil;
023    import com.liferay.portal.kernel.security.pacl.DoPrivileged;
024    import com.liferay.portal.kernel.util.ArrayUtil;
025    import com.liferay.portal.kernel.util.CharPool;
026    import com.liferay.portal.kernel.util.CookieKeys;
027    import com.liferay.portal.kernel.util.GetterUtil;
028    import com.liferay.portal.kernel.util.JavaConstants;
029    import com.liferay.portal.kernel.util.LocaleUtil;
030    import com.liferay.portal.kernel.util.ParamUtil;
031    import com.liferay.portal.kernel.util.PropsKeys;
032    import com.liferay.portal.kernel.util.ResourceBundleUtil;
033    import com.liferay.portal.kernel.util.StringPool;
034    import com.liferay.portal.kernel.util.StringUtil;
035    import com.liferay.portal.kernel.util.Time;
036    import com.liferay.portal.kernel.util.UnicodeProperties;
037    import com.liferay.portal.kernel.util.Validator;
038    import com.liferay.portal.model.CompanyConstants;
039    import com.liferay.portal.model.Group;
040    import com.liferay.portal.model.Portlet;
041    import com.liferay.portal.security.auth.CompanyThreadLocal;
042    import com.liferay.portal.service.GroupLocalServiceUtil;
043    import com.liferay.portal.service.PortletLocalServiceUtil;
044    import com.liferay.portal.theme.ThemeDisplay;
045    import com.liferay.portal.util.PortalUtil;
046    import com.liferay.portal.util.PortletKeys;
047    import com.liferay.portal.util.PrefsPropsUtil;
048    import com.liferay.portal.util.PropsValues;
049    import com.liferay.portal.util.WebKeys;
050    import com.liferay.portlet.PortletConfigFactoryUtil;
051    
052    import java.text.MessageFormat;
053    
054    import java.util.ArrayList;
055    import java.util.HashMap;
056    import java.util.HashSet;
057    import java.util.List;
058    import java.util.Locale;
059    import java.util.Map;
060    import java.util.ResourceBundle;
061    import java.util.Set;
062    import java.util.concurrent.ConcurrentHashMap;
063    
064    import javax.portlet.PortletConfig;
065    import javax.portlet.PortletRequest;
066    
067    import javax.servlet.http.Cookie;
068    import javax.servlet.http.HttpServletRequest;
069    import javax.servlet.http.HttpServletResponse;
070    import javax.servlet.jsp.PageContext;
071    
072    /**
073     * @author Brian Wing Shun Chan
074     * @author Andrius Vitkauskas
075     * @author Eduardo Lundgren
076     */
077    @DoPrivileged
078    public class LanguageImpl implements Language {
079    
080            @Override
081            public String format(
082                    Locale locale, String pattern, List<Object> arguments) {
083    
084                    return format(locale, pattern, arguments.toArray(), true);
085            }
086    
087            @Override
088            public String format(Locale locale, String pattern, Object argument) {
089                    return format(locale, pattern, new Object[] {argument}, true);
090            }
091    
092            @Override
093            public String format(
094                    Locale locale, String pattern, Object argument,
095                    boolean translateArguments) {
096    
097                    return format(
098                            locale, pattern, new Object[] {argument}, translateArguments);
099            }
100    
101            @Override
102            public String format(Locale locale, String pattern, Object[] arguments) {
103                    return format(locale, pattern, arguments, true);
104            }
105    
106            @Override
107            public String format(
108                    Locale locale, String pattern, Object[] arguments,
109                    boolean translateArguments) {
110    
111                    if (PropsValues.TRANSLATIONS_DISABLED) {
112                            return pattern;
113                    }
114    
115                    String value = null;
116    
117                    try {
118                            pattern = get(locale, pattern);
119    
120                            if (ArrayUtil.isNotEmpty(arguments)) {
121                                    pattern = _escapePattern(pattern);
122    
123                                    Object[] formattedArguments = new Object[arguments.length];
124    
125                                    for (int i = 0; i < arguments.length; i++) {
126                                            if (translateArguments) {
127                                                    formattedArguments[i] = get(
128                                                            locale, arguments[i].toString());
129                                            }
130                                            else {
131                                                    formattedArguments[i] = arguments[i];
132                                            }
133                                    }
134    
135                                    value = MessageFormat.format(pattern, formattedArguments);
136                            }
137                            else {
138                                    value = pattern;
139                            }
140                    }
141                    catch (Exception e) {
142                            if (_log.isWarnEnabled()) {
143                                    _log.warn(e, e);
144                            }
145                    }
146    
147                    return value;
148            }
149    
150            @Override
151            public String format(
152                    PageContext pageContext, String pattern, LanguageWrapper argument) {
153    
154                    return format(
155                            pageContext, pattern, new LanguageWrapper[] {argument}, true);
156            }
157    
158            @Override
159            public String format(
160                    PageContext pageContext, String pattern, LanguageWrapper argument,
161                    boolean translateArguments) {
162    
163                    return format(
164                            pageContext, pattern, new LanguageWrapper[] {argument},
165                            translateArguments);
166            }
167    
168            @Override
169            public String format(
170                    PageContext pageContext, String pattern, LanguageWrapper[] arguments) {
171    
172                    return format(pageContext, pattern, arguments, true);
173            }
174    
175            @Override
176            public String format(
177                    PageContext pageContext, String pattern, LanguageWrapper[] arguments,
178                    boolean translateArguments) {
179    
180                    if (PropsValues.TRANSLATIONS_DISABLED) {
181                            return pattern;
182                    }
183    
184                    String value = null;
185    
186                    try {
187                            pattern = get(pageContext, pattern);
188    
189                            if (ArrayUtil.isNotEmpty(arguments)) {
190                                    pattern = _escapePattern(pattern);
191    
192                                    Object[] formattedArguments = new Object[arguments.length];
193    
194                                    for (int i = 0; i < arguments.length; i++) {
195                                            if (translateArguments) {
196                                                    formattedArguments[i] =
197                                                            arguments[i].getBefore() +
198                                                            get(pageContext, arguments[i].getText()) +
199                                                            arguments[i].getAfter();
200                                            }
201                                            else {
202                                                    formattedArguments[i] =
203                                                            arguments[i].getBefore() +
204                                                            arguments[i].getText() +
205                                                            arguments[i].getAfter();
206                                            }
207                                    }
208    
209                                    value = MessageFormat.format(pattern, formattedArguments);
210                            }
211                            else {
212                                    value = pattern;
213                            }
214                    }
215                    catch (Exception e) {
216                            if (_log.isWarnEnabled()) {
217                                    _log.warn(e, e);
218                            }
219                    }
220    
221                    return value;
222            }
223    
224            @Override
225            public String format(
226                    PageContext pageContext, String pattern, Object argument) {
227    
228                    return format(pageContext, pattern, new Object[] {argument}, true);
229            }
230    
231            @Override
232            public String format(
233                    PageContext pageContext, String pattern, Object argument,
234                    boolean translateArguments) {
235    
236                    return format(
237                            pageContext, pattern, new Object[] {argument}, translateArguments);
238            }
239    
240            @Override
241            public String format(
242                    PageContext pageContext, String pattern, Object[] arguments) {
243    
244                    return format(pageContext, pattern, arguments, true);
245            }
246    
247            @Override
248            public String format(
249                    PageContext pageContext, String pattern, Object[] arguments,
250                    boolean translateArguments) {
251    
252                    if (PropsValues.TRANSLATIONS_DISABLED) {
253                            return pattern;
254                    }
255    
256                    String value = null;
257    
258                    try {
259                            pattern = get(pageContext, pattern);
260    
261                            if (ArrayUtil.isNotEmpty(arguments)) {
262                                    pattern = _escapePattern(pattern);
263    
264                                    Object[] formattedArguments = new Object[arguments.length];
265    
266                                    for (int i = 0; i < arguments.length; i++) {
267                                            if (translateArguments) {
268                                                    formattedArguments[i] = get(
269                                                            pageContext, arguments[i].toString());
270                                            }
271                                            else {
272                                                    formattedArguments[i] = arguments[i];
273                                            }
274                                    }
275    
276                                    value = MessageFormat.format(pattern, formattedArguments);
277                            }
278                            else {
279                                    value = pattern;
280                            }
281                    }
282                    catch (Exception e) {
283                            if (_log.isWarnEnabled()) {
284                                    _log.warn(e, e);
285                            }
286                    }
287    
288                    return value;
289            }
290    
291            @Override
292            public String format(
293                    PortletConfig portletConfig, Locale locale, String pattern,
294                    Object argument) {
295    
296                    return format(
297                            portletConfig, locale, pattern, new Object[] {argument}, true);
298            }
299    
300            @Override
301            public String format(
302                    PortletConfig portletConfig, Locale locale, String pattern,
303                    Object argument, boolean translateArguments) {
304    
305                    return format(
306                            portletConfig, locale, pattern, new Object[] {argument},
307                            translateArguments);
308            }
309    
310            @Override
311            public String format(
312                    PortletConfig portletConfig, Locale locale, String pattern,
313                    Object[] arguments) {
314    
315                    return format(portletConfig, locale, pattern, arguments, true);
316            }
317    
318            @Override
319            public String format(
320                    PortletConfig portletConfig, Locale locale, String pattern,
321                    Object[] arguments, boolean translateArguments) {
322    
323                    if (PropsValues.TRANSLATIONS_DISABLED) {
324                            return pattern;
325                    }
326    
327                    String value = null;
328    
329                    try {
330                            pattern = get(portletConfig, locale, pattern);
331    
332                            if (ArrayUtil.isNotEmpty(arguments)) {
333                                    pattern = _escapePattern(pattern);
334    
335                                    Object[] formattedArguments = new Object[arguments.length];
336    
337                                    for (int i = 0; i < arguments.length; i++) {
338                                            if (translateArguments) {
339                                                    formattedArguments[i] = get(
340                                                            locale, arguments[i].toString());
341                                            }
342                                            else {
343                                                    formattedArguments[i] = arguments[i];
344                                            }
345                                    }
346    
347                                    value = MessageFormat.format(pattern, formattedArguments);
348                            }
349                            else {
350                                    value = pattern;
351                            }
352                    }
353                    catch (Exception e) {
354                            if (_log.isWarnEnabled()) {
355                                    _log.warn(e, e);
356                            }
357                    }
358    
359                    return value;
360            }
361    
362            @Override
363            public String get(Locale locale, String key) {
364                    return get(locale, key, key);
365            }
366    
367            @Override
368            public String get(Locale locale, String key, String defaultValue) {
369                    if (PropsValues.TRANSLATIONS_DISABLED) {
370                            return key;
371                    }
372    
373                    if (key == null) {
374                            return null;
375                    }
376    
377                    String value = LanguageResources.getMessage(locale, key);
378    
379                    while ((value == null) || value.equals(defaultValue)) {
380                            if ((key.length() > 0) &&
381                                    (key.charAt(key.length() - 1) == CharPool.CLOSE_BRACKET)) {
382    
383                                    int pos = key.lastIndexOf(CharPool.OPEN_BRACKET);
384    
385                                    if (pos != -1) {
386                                            key = key.substring(0, pos);
387    
388                                            value = LanguageResources.getMessage(locale, key);
389    
390                                            continue;
391                                    }
392                            }
393    
394                            break;
395                    }
396    
397                    if (value == null) {
398                            value = defaultValue;
399                    }
400    
401                    return value;
402            }
403    
404            @Override
405            public String get(PageContext pageContext, String key) {
406                    return get(pageContext, key, key);
407            }
408    
409            @Override
410            public String get(
411                    PageContext pageContext, String key, String defaultValue) {
412    
413                    try {
414                            return _get(pageContext, null, null, key, defaultValue);
415                    }
416                    catch (Exception e) {
417                            if (_log.isWarnEnabled()) {
418                                    _log.warn(e, e);
419                            }
420    
421                            return defaultValue;
422                    }
423            }
424    
425            @Override
426            public String get(PortletConfig portletConfig, Locale locale, String key) {
427                    return get(portletConfig, locale, key, key);
428            }
429    
430            @Override
431            public String get(
432                    PortletConfig portletConfig, Locale locale, String key,
433                    String defaultValue) {
434    
435                    try {
436                            return _get(null, portletConfig, locale, key, defaultValue);
437                    }
438                    catch (Exception e) {
439                            if (_log.isWarnEnabled()) {
440                                    _log.warn(e, e);
441                            }
442    
443                            return defaultValue;
444                    }
445            }
446    
447            @Override
448            public Locale[] getAvailableLocales() {
449                    return _getInstance()._locales;
450            }
451    
452            @Override
453            public Locale[] getAvailableLocales(long groupId) {
454                    if (groupId <= 0) {
455                            return getAvailableLocales();
456                    }
457    
458                    try {
459                            if (isInheritLocales(groupId)) {
460                                    return getAvailableLocales();
461                            }
462                    }
463                    catch (Exception e) {
464                    }
465    
466                    Locale[] locales = _groupLocalesMap.get(groupId);
467    
468                    if (locales != null) {
469                            return locales;
470                    }
471    
472                    _initGroupLocales(groupId);
473    
474                    return _groupLocalesMap.get(groupId);
475            }
476    
477            @Override
478            public String getBCP47LanguageId(HttpServletRequest request) {
479                    Locale locale = PortalUtil.getLocale(request);
480    
481                    return getBCP47LanguageId(locale);
482            }
483    
484            @Override
485            public String getBCP47LanguageId(Locale locale) {
486                    return LocaleUtil.toBCP47LanguageId(locale);
487            }
488    
489            @Override
490            public String getBCP47LanguageId(PortletRequest portletRequest) {
491                    Locale locale = PortalUtil.getLocale(portletRequest);
492    
493                    return getBCP47LanguageId(locale);
494            }
495    
496            @Override
497            public String getCharset(Locale locale) {
498                    return _getInstance()._getCharset(locale);
499            }
500    
501            @Override
502            public String getLanguageId(HttpServletRequest request) {
503                    String languageId = ParamUtil.getString(request, "languageId");
504    
505                    if (Validator.isNotNull(languageId)) {
506                            if (_localesMap.containsKey(languageId) ||
507                                    _charEncodings.containsKey(languageId)) {
508    
509                                    return languageId;
510                            }
511                    }
512    
513                    Locale locale = PortalUtil.getLocale(request);
514    
515                    return getLanguageId(locale);
516            }
517    
518            @Override
519            public String getLanguageId(Locale locale) {
520                    return LocaleUtil.toLanguageId(locale);
521            }
522    
523            @Override
524            public String getLanguageId(PortletRequest portletRequest) {
525                    HttpServletRequest request = PortalUtil.getHttpServletRequest(
526                            portletRequest);
527    
528                    return getLanguageId(request);
529            }
530    
531            @Override
532            public Locale getLocale(String languageCode) {
533                    return _getInstance()._getLocale(languageCode);
534            }
535    
536            @Override
537            public Locale[] getSupportedLocales() {
538                    List<Locale> supportedLocales = new ArrayList<Locale>();
539    
540                    Locale[] locales = getAvailableLocales();
541    
542                    for (Locale locale : locales) {
543                            if (!isBetaLocale(locale)) {
544                                    supportedLocales.add(locale);
545                            }
546                    }
547    
548                    return supportedLocales.toArray(new Locale[supportedLocales.size()]);
549            }
550    
551            @Override
552            public String getTimeDescription(Locale locale, long milliseconds) {
553                    return getTimeDescription(locale, milliseconds, false);
554            }
555    
556            @Override
557            public String getTimeDescription(
558                    Locale locale, long milliseconds, boolean approximate) {
559    
560                    String description = Time.getDescription(milliseconds, approximate);
561    
562                    String value = null;
563    
564                    try {
565                            int pos = description.indexOf(CharPool.SPACE);
566    
567                            String x = description.substring(0, pos);
568    
569                            value = x.concat(StringPool.SPACE).concat(
570                                    get(
571                                            locale,
572                                            StringUtil.toLowerCase(
573                                                    description.substring(pos + 1, description.length()))));
574                    }
575                    catch (Exception e) {
576                            if (_log.isWarnEnabled()) {
577                                    _log.warn(e, e);
578                            }
579                    }
580    
581                    return value;
582            }
583    
584            @Override
585            public String getTimeDescription(Locale locale, Long milliseconds) {
586                    return getTimeDescription(locale, milliseconds.longValue());
587            }
588    
589            @Override
590            public String getTimeDescription(
591                    PageContext pageContext, long milliseconds) {
592    
593                    return getTimeDescription(pageContext, milliseconds, false);
594            }
595    
596            @Override
597            public String getTimeDescription(
598                    PageContext pageContext, long milliseconds, boolean approximate) {
599    
600                    String description = Time.getDescription(milliseconds, approximate);
601    
602                    String value = null;
603    
604                    try {
605                            int pos = description.indexOf(CharPool.SPACE);
606    
607                            String x = description.substring(0, pos);
608    
609                            value = x.concat(StringPool.SPACE).concat(
610                                    get(
611                                            pageContext,
612                                            StringUtil.toLowerCase(
613                                                    description.substring(pos + 1, description.length()))));
614                    }
615                    catch (Exception e) {
616                            if (_log.isWarnEnabled()) {
617                                    _log.warn(e, e);
618                            }
619                    }
620    
621                    return value;
622            }
623    
624            @Override
625            public String getTimeDescription(
626                    PageContext pageContext, Long milliseconds) {
627    
628                    return getTimeDescription(pageContext, milliseconds.longValue());
629            }
630    
631            @Override
632            public void init() {
633                    _instances.clear();
634            }
635    
636            @Override
637            public boolean isAvailableLanguageCode(String languageCode) {
638                    return _getInstance()._localesMap.containsKey(languageCode);
639            }
640    
641            @Override
642            public boolean isAvailableLocale(Locale locale) {
643                    return _getInstance()._localesSet.contains(locale);
644            }
645    
646            @Override
647            public boolean isAvailableLocale(long groupId, Locale locale) {
648                    if (groupId <= 0) {
649                            return isAvailableLocale(locale);
650                    }
651    
652                    try {
653                            if (isInheritLocales(groupId)) {
654                                    return isAvailableLocale(locale);
655                            }
656                    }
657                    catch (Exception e) {
658                    }
659    
660                    Set<Locale> localesSet = _groupLocalesSet.get(groupId);
661    
662                    if (localesSet != null) {
663                            return localesSet.contains(locale);
664                    }
665    
666                    _initGroupLocales(groupId);
667    
668                    localesSet = _groupLocalesSet.get(groupId);
669    
670                    return localesSet.contains(locale);
671            }
672    
673            @Override
674            public boolean isAvailableLocale(long groupId, String languageId) {
675                    Locale[] locales = getAvailableLocales(groupId);
676    
677                    for (Locale locale : locales) {
678                            if (languageId.equals(locale.toString())) {
679                                    return true;
680                            }
681                    }
682    
683                    return false;
684            }
685    
686            @Override
687            public boolean isAvailableLocale(String languageId) {
688                    Locale[] locales = getAvailableLocales();
689    
690                    for (Locale locale : locales) {
691                            if (languageId.equals(locale.toString())) {
692                                    return true;
693                            }
694                    }
695    
696                    return false;
697            }
698    
699            @Override
700            public boolean isBetaLocale(Locale locale) {
701                    return _getInstance()._localesBetaSet.contains(locale);
702            }
703    
704            @Override
705            public boolean isDuplicateLanguageCode(String languageCode) {
706                    return _getInstance()._duplicateLanguageCodes.contains(languageCode);
707            }
708    
709            @Override
710            public boolean isInheritLocales(long groupId)
711                    throws PortalException, SystemException {
712    
713                    Group group = GroupLocalServiceUtil.getGroup(groupId);
714    
715                    if (group.isStagingGroup()) {
716                            group = group.getLiveGroup();
717                    }
718    
719                    if (!group.isSite() || group.isCompany()) {
720                            return true;
721                    }
722    
723                    return GetterUtil.getBoolean(
724                            group.getTypeSettingsProperty("inheritLocales"), true);
725            }
726    
727            @Override
728            public void resetAvailableGroupLocales(long groupId) {
729                    _resetAvailableGroupLocales(groupId);
730            }
731    
732            @Override
733            public void resetAvailableLocales(long companyId) {
734                    _resetAvailableLocales(companyId);
735            }
736    
737            @Override
738            public void updateCookie(
739                    HttpServletRequest request, HttpServletResponse response,
740                    Locale locale) {
741    
742                    String languageId = LocaleUtil.toLanguageId(locale);
743    
744                    Cookie languageIdCookie = new Cookie(
745                            CookieKeys.GUEST_LANGUAGE_ID, languageId);
746    
747                    languageIdCookie.setPath(StringPool.SLASH);
748                    languageIdCookie.setMaxAge(CookieKeys.MAX_AGE);
749    
750                    CookieKeys.addCookie(request, response, languageIdCookie);
751            }
752    
753            private static LanguageImpl _getInstance() {
754                    Long companyId = CompanyThreadLocal.getCompanyId();
755    
756                    LanguageImpl instance = _instances.get(companyId);
757    
758                    if (instance == null) {
759                            instance = new LanguageImpl(companyId);
760    
761                            _instances.put(companyId, instance);
762                    }
763    
764                    return instance;
765            }
766    
767            private LanguageImpl() {
768                    this(CompanyConstants.SYSTEM);
769            }
770    
771            private LanguageImpl(long companyId) {
772                    String[] languageIds = PropsValues.LOCALES;
773    
774                    if (companyId != CompanyConstants.SYSTEM) {
775                            try {
776                                    languageIds = PrefsPropsUtil.getStringArray(
777                                            companyId, PropsKeys.LOCALES, StringPool.COMMA,
778                                            PropsValues.LOCALES_ENABLED);
779                            }
780                            catch (SystemException se) {
781                                    languageIds = PropsValues.LOCALES_ENABLED;
782                            }
783                    }
784    
785                    _charEncodings = new HashMap<String, String>();
786                    _duplicateLanguageCodes = new HashSet<String>();
787                    _locales = new Locale[languageIds.length];
788                    _localesMap = new HashMap<String, Locale>(languageIds.length);
789                    _localesSet = new HashSet<Locale>(languageIds.length);
790    
791                    for (int i = 0; i < languageIds.length; i++) {
792                            String languageId = languageIds[i];
793    
794                            Locale locale = LocaleUtil.fromLanguageId(languageId, false);
795    
796                            _charEncodings.put(locale.toString(), StringPool.UTF8);
797    
798                            String language = languageId;
799    
800                            int pos = languageId.indexOf(CharPool.UNDERLINE);
801    
802                            if (pos > 0) {
803                                    language = languageId.substring(0, pos);
804                            }
805    
806                            if (_localesMap.containsKey(language)) {
807                                    _duplicateLanguageCodes.add(language);
808                            }
809    
810                            _locales[i] = locale;
811    
812                            if (!_localesMap.containsKey(language)) {
813                                    _localesMap.put(language, locale);
814                            }
815    
816                            _localesSet.add(locale);
817                    }
818    
819                    String[] localesBetaArray = PropsValues.LOCALES_BETA;
820    
821                    _localesBetaSet = new HashSet<Locale>(localesBetaArray.length);
822    
823                    for (String languageId : localesBetaArray) {
824                            Locale locale = LocaleUtil.fromLanguageId(languageId, false);
825    
826                            _localesBetaSet.add(locale);
827                    }
828            }
829    
830            private String _escapePattern(String pattern) {
831                    return StringUtil.replace(
832                            pattern, StringPool.APOSTROPHE, StringPool.DOUBLE_APOSTROPHE);
833            }
834    
835            private String _get(
836                            PageContext pageContext, PortletConfig portletConfig, Locale locale,
837                            String key, String defaultValue)
838                    throws Exception {
839    
840                    if (PropsValues.TRANSLATIONS_DISABLED) {
841                            return key;
842                    }
843    
844                    if (key == null) {
845                            return null;
846                    }
847    
848                    String value = null;
849    
850                    if (pageContext != null) {
851                            HttpServletRequest request =
852                                    (HttpServletRequest)pageContext.getRequest();
853    
854                            ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
855                                    WebKeys.THEME_DISPLAY);
856    
857                            if (themeDisplay != null) {
858                                    locale = themeDisplay.getLocale();
859                            }
860                            else {
861                                    locale = request.getLocale();
862    
863                                    if (!isAvailableLocale(locale)) {
864                                            locale = LocaleUtil.getDefault();
865                                    }
866                            }
867    
868                            portletConfig = (PortletConfig)request.getAttribute(
869                                    JavaConstants.JAVAX_PORTLET_CONFIG);
870                    }
871    
872                    if (portletConfig != null) {
873                            ResourceBundle resourceBundle = portletConfig.getResourceBundle(
874                                    locale);
875    
876                            value = ResourceBundleUtil.getString(resourceBundle, key);
877    
878                            // LEP-7393
879    
880                            String portletName = portletConfig.getPortletName();
881    
882                            if (((value == null) || value.equals(defaultValue)) &&
883                                    portletName.equals(PortletKeys.PORTLET_CONFIGURATION)) {
884    
885                                    value = _getPortletConfigurationValue(pageContext, locale, key);
886                            }
887    
888                            if (value != null) {
889                                    value = LanguageResources.fixValue(value);
890                            }
891                    }
892    
893                    if ((value == null) || value.equals(defaultValue)) {
894                            value = LanguageResources.getMessage(locale, key);
895                    }
896    
897                    if ((value == null) || value.equals(defaultValue)) {
898                            if ((key.length() > 0) &&
899                                    (key.charAt(key.length() - 1) == CharPool.CLOSE_BRACKET)) {
900    
901                                    int pos = key.lastIndexOf(CharPool.OPEN_BRACKET);
902    
903                                    if (pos != -1) {
904                                            key = key.substring(0, pos);
905    
906                                            return _get(
907                                                    pageContext, portletConfig, locale, key, defaultValue);
908                                    }
909                            }
910                    }
911    
912                    if ((value == null) || value.equals(key)) {
913                            value = defaultValue;
914                    }
915    
916                    return value;
917            }
918    
919            private String _getCharset(Locale locale) {
920                    return StringPool.UTF8;
921            }
922    
923            private Locale _getLocale(String languageCode) {
924                    return _localesMap.get(languageCode);
925            }
926    
927            private String _getPortletConfigurationValue(
928                            PageContext pageContext, Locale locale, String key)
929                    throws Exception {
930    
931                    if (PropsValues.TRANSLATIONS_DISABLED) {
932                            return key;
933                    }
934    
935                    HttpServletRequest request =
936                            (HttpServletRequest)pageContext.getRequest();
937    
938                    String portletResource = ParamUtil.getString(
939                            request, "portletResource");
940    
941                    long companyId = PortalUtil.getCompanyId(request);
942    
943                    Portlet portlet = PortletLocalServiceUtil.getPortletById(
944                            companyId, portletResource);
945    
946                    PortletConfig portletConfig = PortletConfigFactoryUtil.create(
947                            portlet, pageContext.getServletContext());
948    
949                    ResourceBundle resourceBundle = portletConfig.getResourceBundle(locale);
950    
951                    return ResourceBundleUtil.getString(resourceBundle, key);
952            }
953    
954            private void _initGroupLocales(long groupId) {
955                    String[] languageIds = null;
956    
957                    try {
958                            Group group = GroupLocalServiceUtil.getGroup(groupId);
959    
960                            UnicodeProperties typeSettingsProperties =
961                                    group.getTypeSettingsProperties();
962    
963                            languageIds = StringUtil.split(
964                                    typeSettingsProperties.getProperty(PropsKeys.LOCALES));
965                    }
966                    catch (Exception e) {
967                            languageIds = PropsValues.LOCALES_ENABLED;
968                    }
969    
970                    Locale[] locales = new Locale[languageIds.length];
971                    Map<String, Locale> localesMap = new HashMap<String, Locale>(
972                            languageIds.length);
973                    Set<Locale> localesSet = new HashSet<Locale>(languageIds.length);
974    
975                    for (int i = 0; i < languageIds.length; i++) {
976                            String languageId = languageIds[i];
977    
978                            Locale locale = LocaleUtil.fromLanguageId(languageId, false);
979    
980                            String language = languageId;
981    
982                            int pos = languageId.indexOf(CharPool.UNDERLINE);
983    
984                            if (pos > 0) {
985                                    language = languageId.substring(0, pos);
986                            }
987    
988                            locales[i] = locale;
989    
990                            if (!localesMap.containsKey(language)) {
991                                    localesMap.put(language, locale);
992                            }
993    
994                            localesSet.add(locale);
995                    }
996    
997                    _groupLocalesMap.put(groupId, locales);
998                    _groupLocalesSet.put(groupId, localesSet);
999            }
1000    
1001            private void _resetAvailableGroupLocales(long groupId) {
1002                    _groupLocalesMap.remove(groupId);
1003                    _groupLocalesSet.remove(groupId);
1004            }
1005    
1006            private void _resetAvailableLocales(long companyId) {
1007                    _instances.remove(companyId);
1008            }
1009    
1010            private static Log _log = LogFactoryUtil.getLog(LanguageImpl.class);
1011    
1012            private static Map<Long, LanguageImpl> _instances =
1013                    new ConcurrentHashMap<Long, LanguageImpl>();
1014    
1015            private Map<String, String> _charEncodings;
1016            private Set<String> _duplicateLanguageCodes;
1017            private Map<Long, Locale[]> _groupLocalesMap =
1018                    new HashMap<Long, Locale[]>();
1019            private Map<Long, Set<Locale>> _groupLocalesSet =
1020                    new HashMap<Long, Set<Locale>>();
1021            private Locale[] _locales;
1022            private Set<Locale> _localesBetaSet;
1023            private Map<String, Locale> _localesMap;
1024            private Set<Locale> _localesSet;
1025    
1026    }