update dev300-m58
[ooovba.git] / desktop / source / app / langselect.cxx
blob995b6b0efcfe065e1d944e67be3fa14c53e542b0
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: langselect.cxx,v $
10 * $Revision: 1.22 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_desktop.hxx"
34 #include "app.hxx"
35 #include "langselect.hxx"
36 #include <stdio.h>
38 #ifndef _RTL_STRING_HXX
39 #include <rtl/string.hxx>
40 #endif
41 #ifndef _SVTOOLS_PATHOPTIONS_HXX
42 #include <svtools/pathoptions.hxx>
43 #endif
44 #include <tools/resid.hxx>
45 #include <i18npool/mslangid.hxx>
46 #include <comphelper/processfactory.hxx>
47 #include <com/sun/star/container/XNameAccess.hpp>
48 #include <com/sun/star/lang/XComponent.hpp>
49 #include <com/sun/star/beans/NamedValue.hpp>
50 #include <com/sun/star/util/XChangesBatch.hpp>
51 #include <com/sun/star/uno/Any.hxx>
52 #include <com/sun/star/lang/XLocalizable.hpp>
53 #include <com/sun/star/lang/Locale.hpp>
54 #include "com/sun/star/util/XFlushable.hpp"
55 #include <rtl/locale.hxx>
56 #include <rtl/instance.hxx>
57 #include <osl/process.h>
59 using namespace rtl;
60 using namespace com::sun::star::uno;
61 using namespace com::sun::star::lang;
62 using namespace com::sun::star::container;
63 using namespace com::sun::star::beans;
64 using namespace com::sun::star::util;
66 namespace desktop {
68 sal_Bool LanguageSelection::bFoundLanguage = sal_False;
69 OUString LanguageSelection::aFoundLanguage;
70 const OUString LanguageSelection::usFallbackLanguage = OUString::createFromAscii("en-US");
72 Locale LanguageSelection::IsoStringToLocale(const OUString& str)
74 Locale l;
75 sal_Int32 index=0;
76 l.Language = str.getToken(0, '-', index);
77 if (index >= 0) l.Country = str.getToken(0, '-', index);
78 if (index >= 0) l.Variant = str.getToken(0, '-', index);
79 return l;
82 bool LanguageSelection::prepareLanguage()
84 OUString sConfigSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider");
85 Reference< XMultiServiceFactory > theMSF = comphelper::getProcessServiceFactory();
86 Reference< XLocalizable > theConfigProvider;
87 try
89 theConfigProvider = Reference< XLocalizable >(theMSF->createInstance( sConfigSrvc ),UNO_QUERY_THROW );
91 catch(const Exception&)
94 if(!theConfigProvider.is())
95 return false;
97 sal_Bool bSuccess = sal_False;
99 // #i42730#get the windows 16Bit locale - it should be preferred over the UI language
102 Reference< XPropertySet > xProp(getConfigAccess("org.openoffice.System/L10N/", sal_False), UNO_QUERY_THROW);
103 Any aWin16SysLocale = xProp->getPropertyValue(OUString::createFromAscii("SystemLocale"));
104 ::rtl::OUString sWin16SysLocale;
105 aWin16SysLocale >>= sWin16SysLocale;
106 if( sWin16SysLocale.getLength())
107 setDefaultLocale(sWin16SysLocale);
109 catch(const Exception&)
113 // #i32939# use system locale to set document default locale
114 try
116 OUString usLocale;
117 Reference< XPropertySet > xLocaleProp(getConfigAccess(
118 "org.openoffice.System/L10N", sal_True), UNO_QUERY_THROW);
119 // "org.openoffice.Office.Linguistic/General", sal_True), UNO_QUERY_THROW);
120 xLocaleProp->getPropertyValue(OUString::createFromAscii("Locale")) >>= usLocale;
121 setDefaultLocale(usLocale);
123 catch (Exception&)
126 // get the selected UI language as string
127 OUString aLocaleString = getLanguageString();
128 if ( aLocaleString.getLength() > 0 )
132 // prepare default config provider by localizing it to the selected locale
133 // this will ensure localized configuration settings to be selected accoring to the
134 // UI language.
135 Locale loc = LanguageSelection::IsoStringToLocale(aLocaleString);
136 // flush any data already written to the configuration (which
137 // currently uses independent caches for different locales and thus
138 // would ignore data written to another cache):
139 Reference< XFlushable >(theConfigProvider, UNO_QUERY_THROW)->
140 flush();
141 theConfigProvider->setLocale(loc);
143 Reference< XPropertySet > xProp(getConfigAccess("org.openoffice.Setup/L10N/", sal_True), UNO_QUERY_THROW);
144 xProp->setPropertyValue(OUString::createFromAscii("ooLocale"), makeAny(aLocaleString));
145 Reference< XChangesBatch >(xProp, UNO_QUERY_THROW)->commitChanges();
147 bSuccess = sal_True;
149 catch ( PropertyVetoException& )
151 // we are not allowed to change this
153 catch (Exception& e)
155 OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US);
156 OSL_ENSURE(sal_False, aMsg.getStr());
161 // #i32939# setting of default document locale
162 // #i32939# this should not be based on the UI language
163 setDefaultLocale(aLocaleString);
165 // fallback: set en-US as default Western locale if no Western locale is set
166 OUString usWesternName = OUString::createFromAscii("DefaultLocale");
169 Reference< XPropertySet > xProp(getConfigAccess(
170 "org.openoffice.Office.Linguistic/General/", sal_True), UNO_QUERY_THROW);
171 OUString usValue;
172 xProp->getPropertyValue(usWesternName) >>= usValue;
173 if (usValue.getLength() == 0)
175 // there is no western document language selected
176 // if the selected locale is a western locale, this
177 // will become the default western docuemnt language
178 // otherwise, fall back to en-US
179 OUString usDefault = OUString::createFromAscii("en-US");
182 xProp->setPropertyValue(usWesternName, makeAny(usDefault));
183 Reference< XChangesBatch >(xProp,UNO_QUERY_THROW)->commitChanges();
185 catch ( PropertyVetoException )
187 // we are not allowed to change this
191 catch ( Exception& )
195 return bSuccess;
198 void LanguageSelection::setDefaultLocale(const OUString& usUILocale)
200 // #i32939# setting of default document locale
201 // org.openoffice.Office.Linguistic/General/DefaultLocale
202 // org.openoffice.Office.Linguistic/General/DefaultLocale_CJK
203 // org.openoffice.Office.Linguistic/General/DefaultLocale_CTL
205 // determine script type of UI locale
206 LanguageType ltUILocale = MsLangId::convertIsoStringToLanguage(usUILocale);
207 sal_uInt16 nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage(ltUILocale);
211 Reference< XPropertySet > xProp(getConfigAccess(
212 "org.openoffice.Office.Linguistic/General/", sal_True), UNO_QUERY_THROW);
213 OUString usName = OUString::createFromAscii("DefaultLocale");
214 switch (nScriptType)
216 case SCRIPTTYPE_ASIAN:
217 usName = OUString::createFromAscii("DefaultLocale_CJK");
218 break;
219 case SCRIPTTYPE_COMPLEX:
220 usName = OUString::createFromAscii("DefaultLocale_CTL");
221 break;
223 OUString usValue;
224 xProp->getPropertyValue(usName) >>= usValue;
225 if (usValue.getLength() == 0)
227 // there is no document language set, for the script type selected
228 // in the UI
229 // covert the LanguageType we've got from the LanguageTable back to
230 // an iso string and store it
231 OUString usDefault = MsLangId::convertLanguageToIsoString(ltUILocale);
234 xProp->setPropertyValue(usName, makeAny(usDefault));
235 Reference< XChangesBatch >(xProp, UNO_QUERY_THROW)->commitChanges();
237 catch ( PropertyVetoException )
239 // we are not allowed to change this
243 catch ( Exception& )
248 OUString LanguageSelection::getLanguageString()
250 // did we already find a language?
251 if (bFoundLanguage)
252 return aFoundLanguage;
253 // check whether the user has selected a specific language
254 OUString aUserLanguage = getUserLanguage();
255 if (aUserLanguage.getLength() > 0 )
257 if (isInstalledLanguage(aUserLanguage))
259 // all is well
260 bFoundLanguage = sal_True;
261 aFoundLanguage = aUserLanguage;
262 return aFoundLanguage;
264 else
266 // selected language is not/no longer installed
267 resetUserLanguage();
270 // try to use system default
271 aUserLanguage = getSystemLanguage();
272 if (aUserLanguage.getLength() > 0 )
274 if (isInstalledLanguage(aUserLanguage, sal_False))
276 // great, system default language is available
277 bFoundLanguage = sal_True;
278 aFoundLanguage = aUserLanguage;
279 return aFoundLanguage;
282 // fallback 1: en-US
283 OUString usFB = usFallbackLanguage;
284 if (isInstalledLanguage(usFB))
286 bFoundLanguage = sal_True;
287 aFoundLanguage = usFallbackLanguage;
288 return aFoundLanguage;
290 // fallback didn't work use first installed language
291 aUserLanguage = getFirstInstalledLanguage();
292 bFoundLanguage = sal_True;
293 aFoundLanguage = aUserLanguage;
294 return aFoundLanguage;
297 Reference< XNameAccess > LanguageSelection::getConfigAccess(const sal_Char* pPath, sal_Bool bUpdate)
299 Reference< XNameAccess > xNameAccess;
300 try{
301 OUString sConfigSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider");
302 OUString sAccessSrvc;
303 if (bUpdate)
304 sAccessSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationUpdateAccess");
305 else
306 sAccessSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationAccess");
308 OUString sConfigURL = OUString::createFromAscii(pPath);
310 // get configuration provider
311 Reference< XMultiServiceFactory > theMSF = comphelper::getProcessServiceFactory();
312 if (theMSF.is()) {
313 Reference< XMultiServiceFactory > theConfigProvider = Reference< XMultiServiceFactory > (
314 theMSF->createInstance( sConfigSrvc ),UNO_QUERY_THROW );
316 // access the provider
317 Sequence< Any > theArgs(1);
318 theArgs[ 0 ] <<= sConfigURL;
319 xNameAccess = Reference< XNameAccess > (
320 theConfigProvider->createInstanceWithArguments(
321 sAccessSrvc, theArgs ), UNO_QUERY_THROW );
323 } catch (com::sun::star::uno::Exception& e)
325 OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US);
326 OSL_ENSURE(sal_False, aMsg.getStr());
328 return xNameAccess;
331 Sequence< OUString > LanguageSelection::getInstalledLanguages()
333 Sequence< OUString > seqLanguages;
334 Reference< XNameAccess > xAccess = getConfigAccess("org.openoffice.Setup/Office/InstalledLocales", sal_False);
335 if (!xAccess.is()) return seqLanguages;
336 seqLanguages = xAccess->getElementNames();
337 return seqLanguages;
340 // FIXME
341 // it's not very clever to handle language fallbacks here, but
342 // right now, there is no place that handles those fallbacks globally
343 static Sequence< OUString > _getFallbackLocales(const OUString& aIsoLang)
345 Sequence< OUString > seqFallbacks;
346 if (aIsoLang.equalsAscii("zh-HK")) {
347 seqFallbacks = Sequence< OUString >(1);
348 seqFallbacks[0] = OUString::createFromAscii("zh-TW");
350 return seqFallbacks;
353 sal_Bool LanguageSelection::isInstalledLanguage(OUString& usLocale, sal_Bool bExact)
355 sal_Bool bInstalled = sal_False;
356 Sequence< OUString > seqLanguages = getInstalledLanguages();
357 for (sal_Int32 i=0; i<seqLanguages.getLength(); i++)
359 if (usLocale.equals(seqLanguages[i]))
361 bInstalled = sal_True;
362 break;
366 if (!bInstalled && !bExact)
368 // try fallback locales
369 Sequence< OUString > seqFallbacks = _getFallbackLocales(usLocale);
370 for (sal_Int32 j=0; j<seqFallbacks.getLength(); j++)
372 for (sal_Int32 i=0; i<seqLanguages.getLength(); i++)
374 if (seqFallbacks[j].equals(seqLanguages[i]))
376 bInstalled = sal_True;
377 usLocale = seqFallbacks[j];
378 break;
384 if (!bInstalled && !bExact)
386 // no exact match was found, well try to find a substitute
387 OUString aInstalledLocale;
388 for (sal_Int32 i=0; i<seqLanguages.getLength(); i++)
390 if (usLocale.indexOf(seqLanguages[i]) == 0)
392 // requested locale starts with the installed locale
393 // (i.e. installed locale has index 0 in requested locale)
394 bInstalled = sal_True;
395 usLocale = seqLanguages[i];
396 break;
400 return bInstalled;
403 OUString LanguageSelection::getFirstInstalledLanguage()
405 OUString aLanguage;
406 Sequence< OUString > seqLanguages = getInstalledLanguages();
407 if (seqLanguages.getLength() > 0)
408 aLanguage = seqLanguages[0];
409 return aLanguage;
412 OUString LanguageSelection::getUserLanguage()
414 OUString aUserLanguage;
415 Reference< XNameAccess > xAccess(getConfigAccess("org.openoffice.Office.Linguistic/General", sal_False));
416 if (xAccess.is())
420 xAccess->getByName(OUString::createFromAscii("UILocale")) >>= aUserLanguage;
422 catch ( NoSuchElementException const & )
424 return OUString();
426 catch ( WrappedTargetException const & )
428 return OUString();
431 return aUserLanguage;
434 OUString LanguageSelection::getSystemLanguage()
436 OUString aUserLanguage;
437 Reference< XNameAccess > xAccess(getConfigAccess("org.openoffice.System/L10N", sal_False));
438 if (xAccess.is())
442 xAccess->getByName(OUString::createFromAscii("UILocale")) >>= aUserLanguage;
444 catch ( NoSuchElementException const & )
446 return OUString();
448 catch ( WrappedTargetException const & )
450 return OUString();
453 return aUserLanguage;
457 void LanguageSelection::resetUserLanguage()
461 Reference< XPropertySet > xProp(getConfigAccess("org.openoffice.Office.Linguistic/General", sal_True), UNO_QUERY_THROW);
462 xProp->setPropertyValue(OUString::createFromAscii("UILocale"), makeAny(OUString::createFromAscii("")));
463 Reference< XChangesBatch >(xProp, UNO_QUERY_THROW)->commitChanges();
465 catch ( PropertyVetoException& )
467 // we are not allowed to change this
469 catch ( Exception& e)
471 OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US);
472 OSL_ENSURE(sal_False, aMsg.getStr());
478 } // namespace desktop