1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: langselect.cxx,v $
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"
35 #include "langselect.hxx"
38 #ifndef _RTL_STRING_HXX
39 #include <rtl/string.hxx>
41 #ifndef _SVTOOLS_PATHOPTIONS_HXX
42 #include <svtools/pathoptions.hxx>
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>
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
;
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
)
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
);
82 bool LanguageSelection::prepareLanguage()
84 OUString sConfigSrvc
= OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider");
85 Reference
< XMultiServiceFactory
> theMSF
= comphelper::getProcessServiceFactory();
86 Reference
< XLocalizable
> theConfigProvider
;
89 theConfigProvider
= Reference
< XLocalizable
>(theMSF
->createInstance( sConfigSrvc
),UNO_QUERY_THROW
);
91 catch(const Exception
&)
94 if(!theConfigProvider
.is())
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
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
);
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
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
)->
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();
149 catch ( PropertyVetoException
& )
151 // we are not allowed to change this
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
);
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
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");
216 case SCRIPTTYPE_ASIAN
:
217 usName
= OUString::createFromAscii("DefaultLocale_CJK");
219 case SCRIPTTYPE_COMPLEX
:
220 usName
= OUString::createFromAscii("DefaultLocale_CTL");
224 xProp
->getPropertyValue(usName
) >>= usValue
;
225 if (usValue
.getLength() == 0)
227 // there is no document language set, for the script type selected
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
248 OUString
LanguageSelection::getLanguageString()
250 // did we already find a language?
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
))
260 bFoundLanguage
= sal_True
;
261 aFoundLanguage
= aUserLanguage
;
262 return aFoundLanguage
;
266 // selected language is not/no longer installed
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
;
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
;
301 OUString sConfigSrvc
= OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider");
302 OUString sAccessSrvc
;
304 sAccessSrvc
= OUString::createFromAscii("com.sun.star.configuration.ConfigurationUpdateAccess");
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();
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());
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();
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");
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
;
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
];
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
];
403 OUString
LanguageSelection::getFirstInstalledLanguage()
406 Sequence
< OUString
> seqLanguages
= getInstalledLanguages();
407 if (seqLanguages
.getLength() > 0)
408 aLanguage
= seqLanguages
[0];
412 OUString
LanguageSelection::getUserLanguage()
414 OUString aUserLanguage
;
415 Reference
< XNameAccess
> xAccess(getConfigAccess("org.openoffice.Office.Linguistic/General", sal_False
));
420 xAccess
->getByName(OUString::createFromAscii("UILocale")) >>= aUserLanguage
;
422 catch ( NoSuchElementException
const & )
426 catch ( WrappedTargetException
const & )
431 return aUserLanguage
;
434 OUString
LanguageSelection::getSystemLanguage()
436 OUString aUserLanguage
;
437 Reference
< XNameAccess
> xAccess(getConfigAccess("org.openoffice.System/L10N", sal_False
));
442 xAccess
->getByName(OUString::createFromAscii("UILocale")) >>= aUserLanguage
;
444 catch ( NoSuchElementException
const & )
448 catch ( WrappedTargetException
const & )
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