xref: /aoo4110/main/desktop/source/app/langselect.cxx (revision b1cdbd2c)
1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25*b1cdbd2cSJim Jagielski #include "precompiled_desktop.hxx"
26*b1cdbd2cSJim Jagielski 
27*b1cdbd2cSJim Jagielski #include "app.hxx"
28*b1cdbd2cSJim Jagielski #include "langselect.hxx"
29*b1cdbd2cSJim Jagielski #include "cmdlineargs.hxx"
30*b1cdbd2cSJim Jagielski #include <stdio.h>
31*b1cdbd2cSJim Jagielski 
32*b1cdbd2cSJim Jagielski #include <rtl/string.hxx>
33*b1cdbd2cSJim Jagielski #include <rtl/bootstrap.hxx>
34*b1cdbd2cSJim Jagielski #include <unotools/pathoptions.hxx>
35*b1cdbd2cSJim Jagielski #include <tools/resid.hxx>
36*b1cdbd2cSJim Jagielski #include <tools/config.hxx>
37*b1cdbd2cSJim Jagielski #include <i18npool/mslangid.hxx>
38*b1cdbd2cSJim Jagielski #include <comphelper/processfactory.hxx>
39*b1cdbd2cSJim Jagielski #include <com/sun/star/container/XNameAccess.hpp>
40*b1cdbd2cSJim Jagielski #include <com/sun/star/lang/XComponent.hpp>
41*b1cdbd2cSJim Jagielski #include <com/sun/star/beans/NamedValue.hpp>
42*b1cdbd2cSJim Jagielski #include <com/sun/star/util/XChangesBatch.hpp>
43*b1cdbd2cSJim Jagielski #include <com/sun/star/uno/Any.hxx>
44*b1cdbd2cSJim Jagielski #include <com/sun/star/lang/XLocalizable.hpp>
45*b1cdbd2cSJim Jagielski #include <com/sun/star/lang/Locale.hpp>
46*b1cdbd2cSJim Jagielski #include "com/sun/star/util/XFlushable.hpp"
47*b1cdbd2cSJim Jagielski #include <rtl/locale.hxx>
48*b1cdbd2cSJim Jagielski #include <rtl/instance.hxx>
49*b1cdbd2cSJim Jagielski #include <osl/process.h>
50*b1cdbd2cSJim Jagielski #include <osl/file.hxx>
51*b1cdbd2cSJim Jagielski 
52*b1cdbd2cSJim Jagielski using namespace rtl;
53*b1cdbd2cSJim Jagielski using namespace com::sun::star::uno;
54*b1cdbd2cSJim Jagielski using namespace com::sun::star::lang;
55*b1cdbd2cSJim Jagielski using namespace com::sun::star::container;
56*b1cdbd2cSJim Jagielski using namespace com::sun::star::beans;
57*b1cdbd2cSJim Jagielski using namespace com::sun::star::util;
58*b1cdbd2cSJim Jagielski 
59*b1cdbd2cSJim Jagielski namespace desktop {
60*b1cdbd2cSJim Jagielski 
61*b1cdbd2cSJim Jagielski static char const SOFFICE_BOOTSTRAP[] = "Bootstrap";
62*b1cdbd2cSJim Jagielski static char const SOFFICE_STARTLANG[] = "STARTLANG";
63*b1cdbd2cSJim Jagielski 
64*b1cdbd2cSJim Jagielski sal_Bool LanguageSelection::bFoundLanguage = sal_False;
65*b1cdbd2cSJim Jagielski OUString LanguageSelection::aFoundLanguage;
66*b1cdbd2cSJim Jagielski LanguageSelection::LanguageSelectionStatus LanguageSelection::m_eStatus = LS_STATUS_OK;
67*b1cdbd2cSJim Jagielski 
68*b1cdbd2cSJim Jagielski const OUString LanguageSelection::usFallbackLanguage = OUString::createFromAscii("en-US");
69*b1cdbd2cSJim Jagielski 
existsURL(OUString const & sURL)70*b1cdbd2cSJim Jagielski static sal_Bool existsURL( OUString const& sURL )
71*b1cdbd2cSJim Jagielski {
72*b1cdbd2cSJim Jagielski     using namespace osl;
73*b1cdbd2cSJim Jagielski 	DirectoryItem aDirItem;
74*b1cdbd2cSJim Jagielski 
75*b1cdbd2cSJim Jagielski     if (sURL.getLength() != 0)
76*b1cdbd2cSJim Jagielski         return ( DirectoryItem::get( sURL, aDirItem ) == DirectoryItem::E_None );
77*b1cdbd2cSJim Jagielski 
78*b1cdbd2cSJim Jagielski     return sal_False;
79*b1cdbd2cSJim Jagielski }
80*b1cdbd2cSJim Jagielski 
81*b1cdbd2cSJim Jagielski // locate soffice.ini/.rc file
locateSofficeIniFile()82*b1cdbd2cSJim Jagielski static OUString locateSofficeIniFile()
83*b1cdbd2cSJim Jagielski {
84*b1cdbd2cSJim Jagielski 	OUString aUserDataPath;
85*b1cdbd2cSJim Jagielski 	OUString aSofficeIniFileURL;
86*b1cdbd2cSJim Jagielski 
87*b1cdbd2cSJim Jagielski 	// Retrieve the default file URL for the soffice.ini/rc
88*b1cdbd2cSJim Jagielski 	rtl::Bootstrap().getIniName( aSofficeIniFileURL );
89*b1cdbd2cSJim Jagielski 
90*b1cdbd2cSJim Jagielski 	if ( utl::Bootstrap::locateUserData( aUserDataPath ) == utl::Bootstrap::PATH_EXISTS )
91*b1cdbd2cSJim Jagielski 	{
92*b1cdbd2cSJim Jagielski 		const char CONFIG_DIR[] = "/config";
93*b1cdbd2cSJim Jagielski 
94*b1cdbd2cSJim Jagielski 		sal_Int32 nIndex = aSofficeIniFileURL.lastIndexOf( '/');
95*b1cdbd2cSJim Jagielski 		if ( nIndex > 0 )
96*b1cdbd2cSJim Jagielski 		{
97*b1cdbd2cSJim Jagielski 			OUString		aUserSofficeIniFileURL;
98*b1cdbd2cSJim Jagielski 			OUStringBuffer	aBuffer( aUserDataPath );
99*b1cdbd2cSJim Jagielski 			aBuffer.appendAscii( CONFIG_DIR );
100*b1cdbd2cSJim Jagielski 			aBuffer.append( aSofficeIniFileURL.copy( nIndex ));
101*b1cdbd2cSJim Jagielski 			aUserSofficeIniFileURL = aBuffer.makeStringAndClear();
102*b1cdbd2cSJim Jagielski 
103*b1cdbd2cSJim Jagielski 			if ( existsURL( aUserSofficeIniFileURL ))
104*b1cdbd2cSJim Jagielski 				return aUserSofficeIniFileURL;
105*b1cdbd2cSJim Jagielski 		}
106*b1cdbd2cSJim Jagielski 	}
107*b1cdbd2cSJim Jagielski 	// Fallback try to use the soffice.ini/rc from program folder
108*b1cdbd2cSJim Jagielski 	return aSofficeIniFileURL;
109*b1cdbd2cSJim Jagielski }
110*b1cdbd2cSJim Jagielski 
IsoStringToLocale(const OUString & str)111*b1cdbd2cSJim Jagielski Locale LanguageSelection::IsoStringToLocale(const OUString& str)
112*b1cdbd2cSJim Jagielski {
113*b1cdbd2cSJim Jagielski     Locale l;
114*b1cdbd2cSJim Jagielski     sal_Int32 index=0;
115*b1cdbd2cSJim Jagielski     l.Language = str.getToken(0, '-', index);
116*b1cdbd2cSJim Jagielski     if (index >= 0) l.Country = str.getToken(0, '-', index);
117*b1cdbd2cSJim Jagielski     if (index >= 0) l.Variant = str.getToken(0, '-', index);
118*b1cdbd2cSJim Jagielski     return l;
119*b1cdbd2cSJim Jagielski }
120*b1cdbd2cSJim Jagielski 
prepareLanguage()121*b1cdbd2cSJim Jagielski bool LanguageSelection::prepareLanguage()
122*b1cdbd2cSJim Jagielski {
123*b1cdbd2cSJim Jagielski     m_eStatus = LS_STATUS_OK;
124*b1cdbd2cSJim Jagielski     OUString sConfigSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider");
125*b1cdbd2cSJim Jagielski     Reference< XMultiServiceFactory > theMSF = comphelper::getProcessServiceFactory();
126*b1cdbd2cSJim Jagielski     Reference< XLocalizable > theConfigProvider;
127*b1cdbd2cSJim Jagielski     try
128*b1cdbd2cSJim Jagielski     {
129*b1cdbd2cSJim Jagielski         theConfigProvider = Reference< XLocalizable >(theMSF->createInstance( sConfigSrvc ),UNO_QUERY_THROW );
130*b1cdbd2cSJim Jagielski     }
131*b1cdbd2cSJim Jagielski     catch(const Exception&)
132*b1cdbd2cSJim Jagielski     {
133*b1cdbd2cSJim Jagielski         m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN;
134*b1cdbd2cSJim Jagielski     }
135*b1cdbd2cSJim Jagielski 
136*b1cdbd2cSJim Jagielski     if(!theConfigProvider.is())
137*b1cdbd2cSJim Jagielski         return false;
138*b1cdbd2cSJim Jagielski 
139*b1cdbd2cSJim Jagielski     sal_Bool bSuccess = sal_False;
140*b1cdbd2cSJim Jagielski 
141*b1cdbd2cSJim Jagielski     // #i42730#get the windows 16Bit locale - it should be preferred over the UI language
142*b1cdbd2cSJim Jagielski     try
143*b1cdbd2cSJim Jagielski     {
144*b1cdbd2cSJim Jagielski         Reference< XPropertySet > xProp(getConfigAccess("org.openoffice.System/L10N/", sal_False), UNO_QUERY_THROW);
145*b1cdbd2cSJim Jagielski         Any aWin16SysLocale = xProp->getPropertyValue(OUString::createFromAscii("SystemLocale"));
146*b1cdbd2cSJim Jagielski         ::rtl::OUString sWin16SysLocale;
147*b1cdbd2cSJim Jagielski         aWin16SysLocale >>= sWin16SysLocale;
148*b1cdbd2cSJim Jagielski         if( sWin16SysLocale.getLength())
149*b1cdbd2cSJim Jagielski             setDefaultLanguage(sWin16SysLocale);
150*b1cdbd2cSJim Jagielski     }
151*b1cdbd2cSJim Jagielski     catch(const Exception&)
152*b1cdbd2cSJim Jagielski     {
153*b1cdbd2cSJim Jagielski         m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN;
154*b1cdbd2cSJim Jagielski     }
155*b1cdbd2cSJim Jagielski 
156*b1cdbd2cSJim Jagielski     // #i32939# use system locale to set document default locale
157*b1cdbd2cSJim Jagielski     try
158*b1cdbd2cSJim Jagielski     {
159*b1cdbd2cSJim Jagielski         OUString usLocale;
160*b1cdbd2cSJim Jagielski         Reference< XPropertySet > xLocaleProp(getConfigAccess(
161*b1cdbd2cSJim Jagielski             "org.openoffice.System/L10N", sal_True), UNO_QUERY_THROW);
162*b1cdbd2cSJim Jagielski         xLocaleProp->getPropertyValue(OUString::createFromAscii("Locale")) >>= usLocale;
163*b1cdbd2cSJim Jagielski             setDefaultLanguage(usLocale);
164*b1cdbd2cSJim Jagielski     }
165*b1cdbd2cSJim Jagielski     catch (Exception&)
166*b1cdbd2cSJim Jagielski     {
167*b1cdbd2cSJim Jagielski         m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN;
168*b1cdbd2cSJim Jagielski     }
169*b1cdbd2cSJim Jagielski 
170*b1cdbd2cSJim Jagielski     // get the selected UI language as string
171*b1cdbd2cSJim Jagielski     bool     bCmdLanguage( false );
172*b1cdbd2cSJim Jagielski     bool     bIniLanguage( false );
173*b1cdbd2cSJim Jagielski     OUString aEmpty;
174*b1cdbd2cSJim Jagielski     OUString aLocaleString = getUserUILanguage();
175*b1cdbd2cSJim Jagielski 
176*b1cdbd2cSJim Jagielski     if ( aLocaleString.getLength() == 0 )
177*b1cdbd2cSJim Jagielski     {
178*b1cdbd2cSJim Jagielski         CommandLineArgs* pCmdLineArgs = Desktop::GetCommandLineArgs();
179*b1cdbd2cSJim Jagielski         if ( pCmdLineArgs )
180*b1cdbd2cSJim Jagielski         {
181*b1cdbd2cSJim Jagielski             pCmdLineArgs->GetLanguage(aLocaleString);
182*b1cdbd2cSJim Jagielski             if (isInstalledLanguage(aLocaleString, sal_False))
183*b1cdbd2cSJim Jagielski             {
184*b1cdbd2cSJim Jagielski                 bCmdLanguage   = true;
185*b1cdbd2cSJim Jagielski                 bFoundLanguage = true;
186*b1cdbd2cSJim Jagielski                 aFoundLanguage = aLocaleString;
187*b1cdbd2cSJim Jagielski             }
188*b1cdbd2cSJim Jagielski             else
189*b1cdbd2cSJim Jagielski                 aLocaleString = aEmpty;
190*b1cdbd2cSJim Jagielski         }
191*b1cdbd2cSJim Jagielski 
192*b1cdbd2cSJim Jagielski         if ( !bCmdLanguage )
193*b1cdbd2cSJim Jagielski         {
194*b1cdbd2cSJim Jagielski             OUString aSOfficeIniURL = locateSofficeIniFile();
195*b1cdbd2cSJim Jagielski 	        Config aConfig(aSOfficeIniURL);
196*b1cdbd2cSJim Jagielski 	        aConfig.SetGroup( SOFFICE_BOOTSTRAP );
197*b1cdbd2cSJim Jagielski             OString sLang = aConfig.ReadKey( SOFFICE_STARTLANG );
198*b1cdbd2cSJim Jagielski             aLocaleString = OUString( sLang.getStr(), sLang.getLength(), RTL_TEXTENCODING_ASCII_US );
199*b1cdbd2cSJim Jagielski             if (isInstalledLanguage(aLocaleString, sal_False))
200*b1cdbd2cSJim Jagielski             {
201*b1cdbd2cSJim Jagielski                 bIniLanguage   = true;
202*b1cdbd2cSJim Jagielski                 bFoundLanguage = true;
203*b1cdbd2cSJim Jagielski                 aFoundLanguage = aLocaleString;
204*b1cdbd2cSJim Jagielski             }
205*b1cdbd2cSJim Jagielski             else
206*b1cdbd2cSJim Jagielski                 aLocaleString = aEmpty;
207*b1cdbd2cSJim Jagielski         }
208*b1cdbd2cSJim Jagielski     }
209*b1cdbd2cSJim Jagielski 
210*b1cdbd2cSJim Jagielski     // user further fallbacks for the UI language
211*b1cdbd2cSJim Jagielski     if ( aLocaleString.getLength() == 0 )
212*b1cdbd2cSJim Jagielski         aLocaleString = getLanguageString();
213*b1cdbd2cSJim Jagielski 
214*b1cdbd2cSJim Jagielski     if ( aLocaleString.getLength() > 0 )
215*b1cdbd2cSJim Jagielski     {
216*b1cdbd2cSJim Jagielski         try
217*b1cdbd2cSJim Jagielski         {
218*b1cdbd2cSJim Jagielski             // prepare default config provider by localizing it to the selected locale
219*b1cdbd2cSJim Jagielski             // this will ensure localized configuration settings to be selected accoring to the
220*b1cdbd2cSJim Jagielski             // UI language.
221*b1cdbd2cSJim Jagielski             Locale loc = LanguageSelection::IsoStringToLocale(aLocaleString);
222*b1cdbd2cSJim Jagielski             // flush any data already written to the configuration (which
223*b1cdbd2cSJim Jagielski             // currently uses independent caches for different locales and thus
224*b1cdbd2cSJim Jagielski             // would ignore data written to another cache):
225*b1cdbd2cSJim Jagielski             Reference< XFlushable >(theConfigProvider, UNO_QUERY_THROW)->
226*b1cdbd2cSJim Jagielski                 flush();
227*b1cdbd2cSJim Jagielski             theConfigProvider->setLocale(loc);
228*b1cdbd2cSJim Jagielski 
229*b1cdbd2cSJim Jagielski             Reference< XPropertySet > xProp(getConfigAccess("org.openoffice.Setup/L10N/", sal_True), UNO_QUERY_THROW);
230*b1cdbd2cSJim Jagielski             if ( !bCmdLanguage )
231*b1cdbd2cSJim Jagielski             {
232*b1cdbd2cSJim Jagielski                 // Store language only
233*b1cdbd2cSJim Jagielski                 xProp->setPropertyValue(OUString::createFromAscii("ooLocale"), makeAny(aLocaleString));
234*b1cdbd2cSJim Jagielski                 Reference< XChangesBatch >(xProp, UNO_QUERY_THROW)->commitChanges();
235*b1cdbd2cSJim Jagielski             }
236*b1cdbd2cSJim Jagielski 
237*b1cdbd2cSJim Jagielski             if ( bIniLanguage )
238*b1cdbd2cSJim Jagielski             {
239*b1cdbd2cSJim Jagielski                 // Store language only
240*b1cdbd2cSJim Jagielski                 Reference< XPropertySet > xProp2(getConfigAccess("org.openoffice.Office.Linguistic/General/", sal_True), UNO_QUERY_THROW);
241*b1cdbd2cSJim Jagielski                 xProp2->setPropertyValue(OUString::createFromAscii("UILocale"), makeAny(aLocaleString));
242*b1cdbd2cSJim Jagielski                 Reference< XChangesBatch >(xProp2, UNO_QUERY_THROW)->commitChanges();
243*b1cdbd2cSJim Jagielski             }
244*b1cdbd2cSJim Jagielski 
245*b1cdbd2cSJim Jagielski             MsLangId::setConfiguredSystemUILanguage( MsLangId::convertLocaleToLanguage(loc) );
246*b1cdbd2cSJim Jagielski 
247*b1cdbd2cSJim Jagielski 			OUString sLocale;
248*b1cdbd2cSJim Jagielski 			xProp->getPropertyValue(OUString::createFromAscii("ooSetupSystemLocale")) >>= sLocale;
249*b1cdbd2cSJim Jagielski 			if ( sLocale.getLength() )
250*b1cdbd2cSJim Jagielski 			{
251*b1cdbd2cSJim Jagielski 				loc = LanguageSelection::IsoStringToLocale(sLocale);
252*b1cdbd2cSJim Jagielski 				MsLangId::setConfiguredSystemLanguage( MsLangId::convertLocaleToLanguage(loc) );
253*b1cdbd2cSJim Jagielski 			}
254*b1cdbd2cSJim Jagielski 			else
255*b1cdbd2cSJim Jagielski 				MsLangId::setConfiguredSystemLanguage( MsLangId::getSystemLanguage() );
256*b1cdbd2cSJim Jagielski 
257*b1cdbd2cSJim Jagielski             bSuccess = sal_True;
258*b1cdbd2cSJim Jagielski         }
259*b1cdbd2cSJim Jagielski         catch ( PropertyVetoException& )
260*b1cdbd2cSJim Jagielski         {
261*b1cdbd2cSJim Jagielski             // we are not allowed to change this
262*b1cdbd2cSJim Jagielski         }
263*b1cdbd2cSJim Jagielski         catch (Exception& e)
264*b1cdbd2cSJim Jagielski         {
265*b1cdbd2cSJim Jagielski             OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US);
266*b1cdbd2cSJim Jagielski             OSL_ENSURE(sal_False, aMsg.getStr());
267*b1cdbd2cSJim Jagielski 
268*b1cdbd2cSJim Jagielski         }
269*b1cdbd2cSJim Jagielski     }
270*b1cdbd2cSJim Jagielski 
271*b1cdbd2cSJim Jagielski     // #i32939# setting of default document locale
272*b1cdbd2cSJim Jagielski     // #i32939# this should not be based on the UI language
273*b1cdbd2cSJim Jagielski     setDefaultLanguage(aLocaleString);
274*b1cdbd2cSJim Jagielski 
275*b1cdbd2cSJim Jagielski     return bSuccess;
276*b1cdbd2cSJim Jagielski }
277*b1cdbd2cSJim Jagielski 
setDefaultLanguage(const OUString & sLocale)278*b1cdbd2cSJim Jagielski void LanguageSelection::setDefaultLanguage(const OUString& sLocale)
279*b1cdbd2cSJim Jagielski {
280*b1cdbd2cSJim Jagielski     // #i32939# setting of default document language
281*b1cdbd2cSJim Jagielski     //
282*b1cdbd2cSJim Jagielski     // See #i42730# for rules for determining source of settings
283*b1cdbd2cSJim Jagielski 
284*b1cdbd2cSJim Jagielski     // determine script type of locale
285*b1cdbd2cSJim Jagielski     LanguageType nLang = MsLangId::convertIsoStringToLanguage(sLocale);
286*b1cdbd2cSJim Jagielski     sal_uInt16 nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage(nLang);
287*b1cdbd2cSJim Jagielski 
288*b1cdbd2cSJim Jagielski     switch (nScriptType)
289*b1cdbd2cSJim Jagielski     {
290*b1cdbd2cSJim Jagielski         case SCRIPTTYPE_ASIAN:
291*b1cdbd2cSJim Jagielski             MsLangId::setConfiguredAsianFallback( nLang );
292*b1cdbd2cSJim Jagielski             break;
293*b1cdbd2cSJim Jagielski         case SCRIPTTYPE_COMPLEX:
294*b1cdbd2cSJim Jagielski             MsLangId::setConfiguredComplexFallback( nLang );
295*b1cdbd2cSJim Jagielski             break;
296*b1cdbd2cSJim Jagielski         default:
297*b1cdbd2cSJim Jagielski             MsLangId::setConfiguredWesternFallback( nLang );
298*b1cdbd2cSJim Jagielski             break;
299*b1cdbd2cSJim Jagielski     }
300*b1cdbd2cSJim Jagielski }
301*b1cdbd2cSJim Jagielski 
getUserUILanguage()302*b1cdbd2cSJim Jagielski OUString LanguageSelection::getUserUILanguage()
303*b1cdbd2cSJim Jagielski {
304*b1cdbd2cSJim Jagielski     // check whether the user has selected a specific language
305*b1cdbd2cSJim Jagielski     OUString aUserLanguage = getUserLanguage();
306*b1cdbd2cSJim Jagielski     if (aUserLanguage.getLength() > 0 )
307*b1cdbd2cSJim Jagielski     {
308*b1cdbd2cSJim Jagielski         if (isInstalledLanguage(aUserLanguage))
309*b1cdbd2cSJim Jagielski         {
310*b1cdbd2cSJim Jagielski             // all is well
311*b1cdbd2cSJim Jagielski             bFoundLanguage = sal_True;
312*b1cdbd2cSJim Jagielski             aFoundLanguage = aUserLanguage;
313*b1cdbd2cSJim Jagielski             return aFoundLanguage;
314*b1cdbd2cSJim Jagielski         }
315*b1cdbd2cSJim Jagielski         else
316*b1cdbd2cSJim Jagielski         {
317*b1cdbd2cSJim Jagielski             // selected language is not/no longer installed
318*b1cdbd2cSJim Jagielski             resetUserLanguage();
319*b1cdbd2cSJim Jagielski         }
320*b1cdbd2cSJim Jagielski     }
321*b1cdbd2cSJim Jagielski 
322*b1cdbd2cSJim Jagielski     return aUserLanguage;
323*b1cdbd2cSJim Jagielski }
324*b1cdbd2cSJim Jagielski 
getLanguageString()325*b1cdbd2cSJim Jagielski OUString LanguageSelection::getLanguageString()
326*b1cdbd2cSJim Jagielski {
327*b1cdbd2cSJim Jagielski     // did we already find a language?
328*b1cdbd2cSJim Jagielski     if (bFoundLanguage)
329*b1cdbd2cSJim Jagielski         return aFoundLanguage;
330*b1cdbd2cSJim Jagielski 
331*b1cdbd2cSJim Jagielski     // check whether the user has selected a specific language
332*b1cdbd2cSJim Jagielski     OUString aUserLanguage = getUserUILanguage();
333*b1cdbd2cSJim Jagielski     if (aUserLanguage.getLength() > 0 )
334*b1cdbd2cSJim Jagielski         return aUserLanguage ;
335*b1cdbd2cSJim Jagielski 
336*b1cdbd2cSJim Jagielski     // try to use system default
337*b1cdbd2cSJim Jagielski     aUserLanguage = getSystemLanguage();
338*b1cdbd2cSJim Jagielski     if (aUserLanguage.getLength() > 0 )
339*b1cdbd2cSJim Jagielski     {
340*b1cdbd2cSJim Jagielski         if (isInstalledLanguage(aUserLanguage, sal_False))
341*b1cdbd2cSJim Jagielski         {
342*b1cdbd2cSJim Jagielski             // great, system default language is available
343*b1cdbd2cSJim Jagielski             bFoundLanguage = sal_True;
344*b1cdbd2cSJim Jagielski             aFoundLanguage = aUserLanguage;
345*b1cdbd2cSJim Jagielski             return aFoundLanguage;
346*b1cdbd2cSJim Jagielski         }
347*b1cdbd2cSJim Jagielski     }
348*b1cdbd2cSJim Jagielski     // fallback 1: en-US
349*b1cdbd2cSJim Jagielski     OUString usFB = usFallbackLanguage;
350*b1cdbd2cSJim Jagielski     if (isInstalledLanguage(usFB))
351*b1cdbd2cSJim Jagielski     {
352*b1cdbd2cSJim Jagielski         bFoundLanguage = sal_True;
353*b1cdbd2cSJim Jagielski         aFoundLanguage = usFallbackLanguage;
354*b1cdbd2cSJim Jagielski         return aFoundLanguage;
355*b1cdbd2cSJim Jagielski     }
356*b1cdbd2cSJim Jagielski 
357*b1cdbd2cSJim Jagielski     // fallback didn't work use first installed language
358*b1cdbd2cSJim Jagielski     aUserLanguage = getFirstInstalledLanguage();
359*b1cdbd2cSJim Jagielski 
360*b1cdbd2cSJim Jagielski     bFoundLanguage = sal_True;
361*b1cdbd2cSJim Jagielski     aFoundLanguage = aUserLanguage;
362*b1cdbd2cSJim Jagielski     return aFoundLanguage;
363*b1cdbd2cSJim Jagielski }
364*b1cdbd2cSJim Jagielski 
getConfigAccess(const sal_Char * pPath,sal_Bool bUpdate)365*b1cdbd2cSJim Jagielski Reference< XNameAccess > LanguageSelection::getConfigAccess(const sal_Char* pPath, sal_Bool bUpdate)
366*b1cdbd2cSJim Jagielski {
367*b1cdbd2cSJim Jagielski     Reference< XNameAccess > xNameAccess;
368*b1cdbd2cSJim Jagielski     try{
369*b1cdbd2cSJim Jagielski         OUString sConfigSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider");
370*b1cdbd2cSJim Jagielski         OUString sAccessSrvc;
371*b1cdbd2cSJim Jagielski         if (bUpdate)
372*b1cdbd2cSJim Jagielski             sAccessSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationUpdateAccess");
373*b1cdbd2cSJim Jagielski         else
374*b1cdbd2cSJim Jagielski             sAccessSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationAccess");
375*b1cdbd2cSJim Jagielski 
376*b1cdbd2cSJim Jagielski         OUString sConfigURL = OUString::createFromAscii(pPath);
377*b1cdbd2cSJim Jagielski 
378*b1cdbd2cSJim Jagielski         // get configuration provider
379*b1cdbd2cSJim Jagielski         Reference< XMultiServiceFactory > theMSF = comphelper::getProcessServiceFactory();
380*b1cdbd2cSJim Jagielski         if (theMSF.is()) {
381*b1cdbd2cSJim Jagielski             Reference< XMultiServiceFactory > theConfigProvider = Reference< XMultiServiceFactory > (
382*b1cdbd2cSJim Jagielski                 theMSF->createInstance( sConfigSrvc ),UNO_QUERY_THROW );
383*b1cdbd2cSJim Jagielski 
384*b1cdbd2cSJim Jagielski             // access the provider
385*b1cdbd2cSJim Jagielski             Sequence< Any > theArgs(1);
386*b1cdbd2cSJim Jagielski             theArgs[ 0 ] <<= sConfigURL;
387*b1cdbd2cSJim Jagielski             xNameAccess = Reference< XNameAccess > (
388*b1cdbd2cSJim Jagielski                 theConfigProvider->createInstanceWithArguments(
389*b1cdbd2cSJim Jagielski                     sAccessSrvc, theArgs ), UNO_QUERY_THROW );
390*b1cdbd2cSJim Jagielski         }
391*b1cdbd2cSJim Jagielski     } catch (com::sun::star::uno::Exception& e)
392*b1cdbd2cSJim Jagielski     {
393*b1cdbd2cSJim Jagielski         OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US);
394*b1cdbd2cSJim Jagielski         OSL_ENSURE(sal_False, aMsg.getStr());
395*b1cdbd2cSJim Jagielski     }
396*b1cdbd2cSJim Jagielski     return xNameAccess;
397*b1cdbd2cSJim Jagielski }
398*b1cdbd2cSJim Jagielski 
getInstalledLanguages()399*b1cdbd2cSJim Jagielski Sequence< OUString > LanguageSelection::getInstalledLanguages()
400*b1cdbd2cSJim Jagielski {
401*b1cdbd2cSJim Jagielski     Sequence< OUString > seqLanguages;
402*b1cdbd2cSJim Jagielski     Reference< XNameAccess > xAccess = getConfigAccess("org.openoffice.Setup/Office/InstalledLocales", sal_False);
403*b1cdbd2cSJim Jagielski     if (!xAccess.is()) return seqLanguages;
404*b1cdbd2cSJim Jagielski     seqLanguages = xAccess->getElementNames();
405*b1cdbd2cSJim Jagielski     return seqLanguages;
406*b1cdbd2cSJim Jagielski }
407*b1cdbd2cSJim Jagielski 
408*b1cdbd2cSJim Jagielski // FIXME
409*b1cdbd2cSJim Jagielski // it's not very clever to handle language fallbacks here, but
410*b1cdbd2cSJim Jagielski // right now, there is no place that handles those fallbacks globally
_getFallbackLocales(const OUString & aIsoLang)411*b1cdbd2cSJim Jagielski static Sequence< OUString > _getFallbackLocales(const OUString& aIsoLang)
412*b1cdbd2cSJim Jagielski {
413*b1cdbd2cSJim Jagielski     Sequence< OUString > seqFallbacks;
414*b1cdbd2cSJim Jagielski     if (aIsoLang.equalsAscii("zh-HK")) {
415*b1cdbd2cSJim Jagielski         seqFallbacks = Sequence< OUString >(1);
416*b1cdbd2cSJim Jagielski         seqFallbacks[0] = OUString::createFromAscii("zh-TW");
417*b1cdbd2cSJim Jagielski     }
418*b1cdbd2cSJim Jagielski     return seqFallbacks;
419*b1cdbd2cSJim Jagielski }
420*b1cdbd2cSJim Jagielski 
isInstalledLanguage(OUString & usLocale,sal_Bool bExact)421*b1cdbd2cSJim Jagielski sal_Bool LanguageSelection::isInstalledLanguage(OUString& usLocale, sal_Bool bExact)
422*b1cdbd2cSJim Jagielski {
423*b1cdbd2cSJim Jagielski     sal_Bool bInstalled = sal_False;
424*b1cdbd2cSJim Jagielski     Sequence< OUString > seqLanguages = getInstalledLanguages();
425*b1cdbd2cSJim Jagielski     for (sal_Int32 i=0; i<seqLanguages.getLength(); i++)
426*b1cdbd2cSJim Jagielski     {
427*b1cdbd2cSJim Jagielski         if (usLocale.equals(seqLanguages[i]))
428*b1cdbd2cSJim Jagielski         {
429*b1cdbd2cSJim Jagielski             bInstalled = sal_True;
430*b1cdbd2cSJim Jagielski             break;
431*b1cdbd2cSJim Jagielski         }
432*b1cdbd2cSJim Jagielski     }
433*b1cdbd2cSJim Jagielski 
434*b1cdbd2cSJim Jagielski     if (!bInstalled && !bExact)
435*b1cdbd2cSJim Jagielski     {
436*b1cdbd2cSJim Jagielski         // try fallback locales
437*b1cdbd2cSJim Jagielski         Sequence< OUString > seqFallbacks = _getFallbackLocales(usLocale);
438*b1cdbd2cSJim Jagielski         for (sal_Int32 j=0; j<seqFallbacks.getLength(); j++)
439*b1cdbd2cSJim Jagielski         {
440*b1cdbd2cSJim Jagielski             for (sal_Int32 i=0; i<seqLanguages.getLength(); i++)
441*b1cdbd2cSJim Jagielski             {
442*b1cdbd2cSJim Jagielski                 if (seqFallbacks[j].equals(seqLanguages[i]))
443*b1cdbd2cSJim Jagielski                 {
444*b1cdbd2cSJim Jagielski                     bInstalled = sal_True;
445*b1cdbd2cSJim Jagielski                     usLocale = seqFallbacks[j];
446*b1cdbd2cSJim Jagielski                     break;
447*b1cdbd2cSJim Jagielski                 }
448*b1cdbd2cSJim Jagielski             }
449*b1cdbd2cSJim Jagielski         }
450*b1cdbd2cSJim Jagielski     }
451*b1cdbd2cSJim Jagielski 
452*b1cdbd2cSJim Jagielski     if (!bInstalled && !bExact)
453*b1cdbd2cSJim Jagielski     {
454*b1cdbd2cSJim Jagielski         // no exact match was found, well try to find a substitute
455*b1cdbd2cSJim Jagielski         OUString aInstalledLocale;
456*b1cdbd2cSJim Jagielski         for (sal_Int32 i=0; i<seqLanguages.getLength(); i++)
457*b1cdbd2cSJim Jagielski         {
458*b1cdbd2cSJim Jagielski             if (usLocale.indexOf(seqLanguages[i]) == 0)
459*b1cdbd2cSJim Jagielski             {
460*b1cdbd2cSJim Jagielski                 // requested locale starts with the installed locale
461*b1cdbd2cSJim Jagielski                 // (i.e. installed locale has index 0 in requested locale)
462*b1cdbd2cSJim Jagielski                 bInstalled = sal_True;
463*b1cdbd2cSJim Jagielski                 usLocale   = seqLanguages[i];
464*b1cdbd2cSJim Jagielski                 break;
465*b1cdbd2cSJim Jagielski             }
466*b1cdbd2cSJim Jagielski         }
467*b1cdbd2cSJim Jagielski     }
468*b1cdbd2cSJim Jagielski     return bInstalled;
469*b1cdbd2cSJim Jagielski }
470*b1cdbd2cSJim Jagielski 
getFirstInstalledLanguage()471*b1cdbd2cSJim Jagielski OUString LanguageSelection::getFirstInstalledLanguage()
472*b1cdbd2cSJim Jagielski {
473*b1cdbd2cSJim Jagielski     OUString aLanguage;
474*b1cdbd2cSJim Jagielski     Sequence< OUString > seqLanguages = getInstalledLanguages();
475*b1cdbd2cSJim Jagielski     if (seqLanguages.getLength() > 0)
476*b1cdbd2cSJim Jagielski         aLanguage = seqLanguages[0];
477*b1cdbd2cSJim Jagielski     return aLanguage;
478*b1cdbd2cSJim Jagielski }
479*b1cdbd2cSJim Jagielski 
getUserLanguage()480*b1cdbd2cSJim Jagielski OUString LanguageSelection::getUserLanguage()
481*b1cdbd2cSJim Jagielski {
482*b1cdbd2cSJim Jagielski     OUString aUserLanguage;
483*b1cdbd2cSJim Jagielski     Reference< XNameAccess > xAccess(getConfigAccess("org.openoffice.Office.Linguistic/General", sal_False));
484*b1cdbd2cSJim Jagielski     if (xAccess.is())
485*b1cdbd2cSJim Jagielski     {
486*b1cdbd2cSJim Jagielski         try
487*b1cdbd2cSJim Jagielski         {
488*b1cdbd2cSJim Jagielski             xAccess->getByName(OUString::createFromAscii("UILocale")) >>= aUserLanguage;
489*b1cdbd2cSJim Jagielski         }
490*b1cdbd2cSJim Jagielski         catch ( NoSuchElementException const & )
491*b1cdbd2cSJim Jagielski         {
492*b1cdbd2cSJim Jagielski             m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN;
493*b1cdbd2cSJim Jagielski             return OUString();
494*b1cdbd2cSJim Jagielski         }
495*b1cdbd2cSJim Jagielski         catch ( WrappedTargetException const & )
496*b1cdbd2cSJim Jagielski         {
497*b1cdbd2cSJim Jagielski             m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN;
498*b1cdbd2cSJim Jagielski             return OUString();
499*b1cdbd2cSJim Jagielski         }
500*b1cdbd2cSJim Jagielski     }
501*b1cdbd2cSJim Jagielski     return aUserLanguage;
502*b1cdbd2cSJim Jagielski }
503*b1cdbd2cSJim Jagielski 
getSystemLanguage()504*b1cdbd2cSJim Jagielski OUString LanguageSelection::getSystemLanguage()
505*b1cdbd2cSJim Jagielski {
506*b1cdbd2cSJim Jagielski     OUString aUserLanguage;
507*b1cdbd2cSJim Jagielski     Reference< XNameAccess > xAccess(getConfigAccess("org.openoffice.System/L10N", sal_False));
508*b1cdbd2cSJim Jagielski     if (xAccess.is())
509*b1cdbd2cSJim Jagielski     {
510*b1cdbd2cSJim Jagielski         try
511*b1cdbd2cSJim Jagielski         {
512*b1cdbd2cSJim Jagielski             xAccess->getByName(OUString::createFromAscii("UILocale")) >>= aUserLanguage;
513*b1cdbd2cSJim Jagielski         }
514*b1cdbd2cSJim Jagielski         catch ( NoSuchElementException const & )
515*b1cdbd2cSJim Jagielski         {
516*b1cdbd2cSJim Jagielski             m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN;
517*b1cdbd2cSJim Jagielski             return OUString();
518*b1cdbd2cSJim Jagielski         }
519*b1cdbd2cSJim Jagielski         catch ( WrappedTargetException const & )
520*b1cdbd2cSJim Jagielski         {
521*b1cdbd2cSJim Jagielski             m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN;
522*b1cdbd2cSJim Jagielski             return OUString();
523*b1cdbd2cSJim Jagielski         }
524*b1cdbd2cSJim Jagielski     }
525*b1cdbd2cSJim Jagielski     return aUserLanguage;
526*b1cdbd2cSJim Jagielski }
527*b1cdbd2cSJim Jagielski 
528*b1cdbd2cSJim Jagielski 
resetUserLanguage()529*b1cdbd2cSJim Jagielski void LanguageSelection::resetUserLanguage()
530*b1cdbd2cSJim Jagielski {
531*b1cdbd2cSJim Jagielski     try
532*b1cdbd2cSJim Jagielski     {
533*b1cdbd2cSJim Jagielski         Reference< XPropertySet > xProp(getConfigAccess("org.openoffice.Office.Linguistic/General", sal_True), UNO_QUERY_THROW);
534*b1cdbd2cSJim Jagielski         xProp->setPropertyValue(OUString::createFromAscii("UILocale"), makeAny(OUString::createFromAscii("")));
535*b1cdbd2cSJim Jagielski         Reference< XChangesBatch >(xProp, UNO_QUERY_THROW)->commitChanges();
536*b1cdbd2cSJim Jagielski     }
537*b1cdbd2cSJim Jagielski     catch ( PropertyVetoException& )
538*b1cdbd2cSJim Jagielski     {
539*b1cdbd2cSJim Jagielski         // we are not allowed to change this
540*b1cdbd2cSJim Jagielski     }
541*b1cdbd2cSJim Jagielski     catch ( Exception& e)
542*b1cdbd2cSJim Jagielski     {
543*b1cdbd2cSJim Jagielski         OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US);
544*b1cdbd2cSJim Jagielski         OSL_ENSURE(sal_False, aMsg.getStr());
545*b1cdbd2cSJim Jagielski         m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN;
546*b1cdbd2cSJim Jagielski     }
547*b1cdbd2cSJim Jagielski }
548*b1cdbd2cSJim Jagielski 
getStatus()549*b1cdbd2cSJim Jagielski LanguageSelection::LanguageSelectionStatus LanguageSelection::getStatus()
550*b1cdbd2cSJim Jagielski {
551*b1cdbd2cSJim Jagielski     return m_eStatus;
552*b1cdbd2cSJim Jagielski }
553*b1cdbd2cSJim Jagielski 
554*b1cdbd2cSJim Jagielski } // namespace desktop
555