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                                            description.substring(
573                                                    pos + 1, description.length()).toLowerCase()));
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                                            description.substring(
613                                                    pos + 1, description.length()).toLowerCase()));
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                    Group liveGroup = group;
716    
717                    if (group.isStagingGroup()) {
718                            liveGroup = group.getLiveGroup();
719                    }
720    
721                    UnicodeProperties groupTypeSettings =
722                            liveGroup.getTypeSettingsProperties();
723    
724                    return GetterUtil.getBoolean(
725                            groupTypeSettings.getProperty("inheritLocales"), true);
726            }
727    
728            @Override
729            public void resetAvailableGroupLocales(long groupId) {
730                    _resetAvailableGroupLocales(groupId);
731            }
732    
733            @Override
734            public void resetAvailableLocales(long companyId) {
735                    _resetAvailableLocales(companyId);
736            }
737    
738            @Override
739            public void updateCookie(
740                    HttpServletRequest request, HttpServletResponse response,
741                    Locale locale) {
742    
743                    String languageId = LocaleUtil.toLanguageId(locale);
744    
745                    Cookie languageIdCookie = new Cookie(
746                            CookieKeys.GUEST_LANGUAGE_ID, languageId);
747    
748                    languageIdCookie.setPath(StringPool.SLASH);
749                    languageIdCookie.setMaxAge(CookieKeys.MAX_AGE);
750    
751                    CookieKeys.addCookie(request, response, languageIdCookie);
752            }
753    
754            private static LanguageImpl _getInstance() {
755                    Long companyId = CompanyThreadLocal.getCompanyId();
756    
757                    LanguageImpl instance = _instances.get(companyId);
758    
759                    if (instance == null) {
760                            instance = new LanguageImpl(companyId);
761    
762                            _instances.put(companyId, instance);
763                    }
764    
765                    return instance;
766            }
767    
768            private LanguageImpl() {
769                    this(CompanyConstants.SYSTEM);
770            }
771    
772            private LanguageImpl(long companyId) {
773                    String[] languageIds = PropsValues.LOCALES;
774    
775                    if (companyId != CompanyConstants.SYSTEM) {
776                            try {
777                                    languageIds = PrefsPropsUtil.getStringArray(
778                                            companyId, PropsKeys.LOCALES, StringPool.COMMA,
779                                            PropsValues.LOCALES_ENABLED);
780                            }
781                            catch (SystemException se) {
782                                    languageIds = PropsValues.LOCALES_ENABLED;
783                            }
784                    }
785    
786                    _charEncodings = new HashMap<String, String>();
787                    _duplicateLanguageCodes = new HashSet<String>();
788                    _locales = new Locale[languageIds.length];
789                    _localesMap = new HashMap<String, Locale>(languageIds.length);
790                    _localesSet = new HashSet<Locale>(languageIds.length);
791    
792                    for (int i = 0; i < languageIds.length; i++) {
793                            String languageId = languageIds[i];
794    
795                            Locale locale = LocaleUtil.fromLanguageId(languageId, false);
796    
797                            _charEncodings.put(locale.toString(), StringPool.UTF8);
798    
799                            String language = languageId;
800    
801                            int pos = languageId.indexOf(CharPool.UNDERLINE);
802    
803                            if (pos > 0) {
804                                    language = languageId.substring(0, pos);
805                            }
806    
807                            if (_localesMap.containsKey(language)) {
808                                    _duplicateLanguageCodes.add(language);
809                            }
810    
811                            _locales[i] = locale;
812    
813                            if (!_localesMap.containsKey(language)) {
814                                    _localesMap.put(language, locale);
815                            }
816    
817                            _localesSet.add(locale);
818                    }
819    
820                    String[] localesBetaArray = PropsValues.LOCALES_BETA;
821    
822                    _localesBetaSet = new HashSet<Locale>(localesBetaArray.length);
823    
824                    for (String languageId : localesBetaArray) {
825                            Locale locale = LocaleUtil.fromLanguageId(languageId, false);
826    
827                            _localesBetaSet.add(locale);
828                    }
829            }
830    
831            private String _escapePattern(String pattern) {
832                    return StringUtil.replace(
833                            pattern, StringPool.APOSTROPHE, StringPool.DOUBLE_APOSTROPHE);
834            }
835    
836            private String _get(
837                            PageContext pageContext, PortletConfig portletConfig, Locale locale,
838                            String key, String defaultValue)
839                    throws Exception {
840    
841                    if (PropsValues.TRANSLATIONS_DISABLED) {
842                            return key;
843                    }
844    
845                    if (key == null) {
846                            return null;
847                    }
848    
849                    String value = null;
850    
851                    if (pageContext != null) {
852                            HttpServletRequest request =
853                                    (HttpServletRequest)pageContext.getRequest();
854    
855                            ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
856                                    WebKeys.THEME_DISPLAY);
857    
858                            if (themeDisplay != null) {
859                                    locale = themeDisplay.getLocale();
860                            }
861                            else {
862                                    locale = request.getLocale();
863    
864                                    if (!isAvailableLocale(locale)) {
865                                            locale = LocaleUtil.getDefault();
866                                    }
867                            }
868    
869                            portletConfig = (PortletConfig)request.getAttribute(
870                                    JavaConstants.JAVAX_PORTLET_CONFIG);
871                    }
872    
873                    if (portletConfig != null) {
874                            ResourceBundle resourceBundle = portletConfig.getResourceBundle(
875                                    locale);
876    
877                            value = ResourceBundleUtil.getString(resourceBundle, key);
878    
879                            // LEP-7393
880    
881                            String portletName = portletConfig.getPortletName();
882    
883                            if (((value == null) || value.equals(defaultValue)) &&
884                                    portletName.equals(PortletKeys.PORTLET_CONFIGURATION)) {
885    
886                                    value = _getPortletConfigurationValue(pageContext, locale, key);
887                            }
888    
889                            if (value != null) {
890                                    value = LanguageResources.fixValue(value);
891                            }
892                    }
893    
894                    if ((value == null) || value.equals(defaultValue)) {
895                            value = LanguageResources.getMessage(locale, key);
896                    }
897    
898                    if ((value == null) || value.equals(defaultValue)) {
899                            if ((key.length() > 0) &&
900                                    (key.charAt(key.length() - 1) == CharPool.CLOSE_BRACKET)) {
901    
902                                    int pos = key.lastIndexOf(CharPool.OPEN_BRACKET);
903    
904                                    if (pos != -1) {
905                                            key = key.substring(0, pos);
906    
907                                            return _get(
908                                                    pageContext, portletConfig, locale, key, defaultValue);
909                                    }
910                            }
911                    }
912    
913                    if ((value == null) || value.equals(key)) {
914                            value = defaultValue;
915                    }
916    
917                    return value;
918            }
919    
920            private String _getCharset(Locale locale) {
921                    return StringPool.UTF8;
922            }
923    
924            private Locale _getLocale(String languageCode) {
925                    return _localesMap.get(languageCode);
926            }
927    
928            private String _getPortletConfigurationValue(
929                            PageContext pageContext, Locale locale, String key)
930                    throws Exception {
931    
932                    if (PropsValues.TRANSLATIONS_DISABLED) {
933                            return key;
934                    }
935    
936                    HttpServletRequest request =
937                            (HttpServletRequest)pageContext.getRequest();
938    
939                    String portletResource = ParamUtil.getString(
940                            request, "portletResource");
941    
942                    long companyId = PortalUtil.getCompanyId(request);
943    
944                    Portlet portlet = PortletLocalServiceUtil.getPortletById(
945                            companyId, portletResource);
946    
947                    PortletConfig portletConfig = PortletConfigFactoryUtil.create(
948                            portlet, pageContext.getServletContext());
949    
950                    ResourceBundle resourceBundle = portletConfig.getResourceBundle(locale);
951    
952                    return ResourceBundleUtil.getString(resourceBundle, key);
953            }
954    
955            private void _initGroupLocales(long groupId) {
956                    String[] languageIds = null;
957    
958                    try {
959                            Group group = GroupLocalServiceUtil.getGroup(groupId);
960    
961                            UnicodeProperties typeSettingsProperties =
962                                    group.getTypeSettingsProperties();
963    
964                            languageIds = StringUtil.split(
965                                    typeSettingsProperties.getProperty(PropsKeys.LOCALES));
966                    }
967                    catch (Exception e) {
968                            languageIds = PropsValues.LOCALES_ENABLED;
969                    }
970    
971                    Locale[] locales = new Locale[languageIds.length];
972                    Map<String, Locale> localesMap = new HashMap<String, Locale>(
973                            languageIds.length);
974                    Set<Locale> localesSet = new HashSet<Locale>(languageIds.length);
975    
976                    for (int i = 0; i < languageIds.length; i++) {
977                            String languageId = languageIds[i];
978    
979                            Locale locale = LocaleUtil.fromLanguageId(languageId, false);
980    
981                            String language = languageId;
982    
983                            int pos = languageId.indexOf(CharPool.UNDERLINE);
984    
985                            if (pos > 0) {
986                                    language = languageId.substring(0, pos);
987                            }
988    
989                            locales[i] = locale;
990    
991                            if (!localesMap.containsKey(language)) {
992                                    localesMap.put(language, locale);
993                            }
994    
995                            localesSet.add(locale);
996                    }
997    
998                    _groupLocalesMap.put(groupId, locales);
999                    _groupLocalesSet.put(groupId, localesSet);
1000            }
1001    
1002            private void _resetAvailableGroupLocales(long groupId) {
1003                    _groupLocalesMap.remove(groupId);
1004                    _groupLocalesSet.remove(groupId);
1005            }
1006    
1007            private void _resetAvailableLocales(long companyId) {
1008                    _instances.remove(companyId);
1009            }
1010    
1011            private static Log _log = LogFactoryUtil.getLog(LanguageImpl.class);
1012    
1013            private static Map<Long, LanguageImpl> _instances =
1014                    new ConcurrentHashMap<Long, LanguageImpl>();
1015    
1016            private Map<String, String> _charEncodings;
1017            private Set<String> _duplicateLanguageCodes;
1018            private Map<Long, Locale[]> _groupLocalesMap =
1019                    new HashMap<Long, Locale[]>();
1020            private Map<Long, Set<Locale>> _groupLocalesSet =
1021                    new HashMap<Long, Set<Locale>>();
1022            private Locale[] _locales;
1023            private Set<Locale> _localesBetaSet;
1024            private Map<String, Locale> _localesMap;
1025            private Set<Locale> _localesSet;
1026    
1027    }