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