1 /*
2 * Copyright (c) 2002-2025, City of Paris
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice
10 * and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright notice
13 * and the following disclaimer in the documentation and/or other materials
14 * provided with the distribution.
15 *
16 * 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 *
32 * License 1.0
33 */
34 package fr.paris.lutece.portal.web.l10n;
35
36 import fr.paris.lutece.portal.service.datastore.DatastoreService;
37 import fr.paris.lutece.portal.service.util.AppLogService;
38 import fr.paris.lutece.portal.service.util.AppPropertiesService;
39 import java.util.ArrayList;
40 import java.util.List;
41
42 import java.util.Locale;
43
44 import javax.servlet.http.HttpServletRequest;
45 import javax.servlet.http.HttpSession;
46
47 /**
48 * LocaleService
49 */
50 public final class LocaleService
51 {
52 private static final String ATTRIBUTE_SELECTED_LOCALE = "LUTECE_ATTRIBUTE_USER_SELECTED_LOCALE";
53 private static final String DSKEY_LANGUAGE_DEFAULT = "portal.site.site_property.locale.default";
54 private static final String PROPERTY_LANG_LIST = "lutece.i18n.availableLocales";
55 private static final String PROPERTY_LANG_DEFAULT = "lutece.i18n.defaultLocale";
56 private static Locale _locale;
57 private static List<Locale> _supportedLocales;
58
59 /**
60 * Private constructor
61 */
62 private LocaleService( )
63 {
64 }
65
66 /**
67 * Set the locale selected by the user in the front office. The user may select a language without been authenticated.
68 *
69 * @param request
70 * The request
71 * @param locale
72 * The locale
73 */
74 public static void setUserSelectedLocale( HttpServletRequest request, Locale locale )
75 {
76 HttpSession session = request.getSession( true );
77 session.setAttribute( ATTRIBUTE_SELECTED_LOCALE, locale );
78 }
79
80 /**
81 * Get a Locale selected by the user in front office
82 *
83 * @param request
84 * The HTTP request
85 * @return The locale selected, or the default jvm locale if no locale has been selected
86 */
87 public static Locale getUserSelectedLocale( HttpServletRequest request )
88 {
89 Locale locale = LocaleService.getDefault( );
90 HttpSession session = request.getSession( );
91
92 if ( session != null )
93 {
94 Locale localeSession = (Locale) session.getAttribute( ATTRIBUTE_SELECTED_LOCALE );
95
96 if ( localeSession != null )
97 {
98 locale = localeSession;
99 }
100 }
101
102 return locale;
103 }
104
105 /**
106 * Return a Lutece defined default Locale
107 *
108 * @return The locale
109 */
110 public static synchronized Locale getDefault( )
111 {
112 if ( _locale != null )
113 {
114 return _locale;
115 }
116 else
117 {
118 String dsLang = DatastoreService.getInstanceDataValue( DSKEY_LANGUAGE_DEFAULT, null );
119
120 if ( dsLang != null )
121 {
122 for ( String strISOLang : Locale.getISOLanguages( ) )
123 {
124 if ( strISOLang.equals( dsLang ) )
125 {
126 _locale = new Locale( dsLang );
127 AppLogService.info( "LocaleService : default locale set to : {}", dsLang );
128
129 return _locale;
130 }
131 }
132 }
133
134 // otherwise, get the default locale from properties
135 _locale = new Locale( AppPropertiesService.getProperty( PROPERTY_LANG_DEFAULT ) );
136 AppLogService.error( "LocaleService : invalid defined locale {} - default set to {}", dsLang, _locale.getLanguage( ) );
137
138 return _locale;
139 }
140 }
141
142 /**
143 * Retrieve the best supported locale for the user's session Priority order : 1- selected locale session attribute 2- browser locale (if supported) 3-
144 * default server locale
145 *
146 * @param request
147 * The HTTP request
148 * @return The locale
149 */
150 public static Locale getContextUserLocale( HttpServletRequest request )
151 {
152 // consider the current session locale
153 if ( request != null )
154 {
155 HttpSession session = request.getSession( false );
156 if ( session != null )
157 {
158 Locale userSessionLocale = (Locale) session.getAttribute( ATTRIBUTE_SELECTED_LOCALE );
159 if ( userSessionLocale != null )
160 {
161 if ( isSupported( userSessionLocale ) )
162 {
163 return userSessionLocale;
164 }
165 }
166 }
167 }
168
169 // consider the browser language
170 Locale locale = new Locale( request.getLocale( ).getLanguage( ).substring( 0, 2 ) );
171 if ( isSupported( locale ) )
172 {
173 return locale;
174 }
175
176 // otherwise consider the server default
177 return getDefault( );
178 }
179
180 /**
181 * check if Locale is supported according to locale list in lutece properties
182 *
183 * @param locale
184 * @return true if supported
185 */
186 public static boolean isSupported( Locale locale )
187 {
188 if ( _supportedLocales == null )
189 {
190 getSupportedLangList( );
191 }
192
193 // check if the mandatory language is supported
194 for ( Locale supportedLocale : _supportedLocales )
195 {
196 if ( supportedLocale.equals( locale ) )
197 {
198 return true;
199 }
200 }
201
202 return false;
203 }
204
205 /**
206 * get Supported Lang List
207 *
208 * @return the Supported Lang List
209 */
210 public static synchronized List<Locale> getSupportedLangList( )
211 {
212 if ( _supportedLocales == null )
213 {
214 String [ ] strLangList = AppPropertiesService.getProperty( PROPERTY_LANG_LIST ).split( "," );
215 _supportedLocales = new ArrayList<>( );
216 for ( String lang : strLangList )
217 {
218 _supportedLocales.add( new Locale( lang ) );
219 }
220 }
221
222 return _supportedLocales;
223 }
224 }