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 setDefaultLanguage(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 xLocaleProp
->getPropertyValue(OUString::createFromAscii("Locale")) >>= usLocale
;
120 setDefaultLanguage(usLocale
);
125 // get the selected UI language as string
126 OUString aLocaleString
= getLanguageString();
127 if ( aLocaleString
.getLength() > 0 )
131 // prepare default config provider by localizing it to the selected locale
132 // this will ensure localized configuration settings to be selected accoring to the
134 Locale loc
= LanguageSelection::IsoStringToLocale(aLocaleString
);
135 // flush any data already written to the configuration (which
136 // currently uses independent caches for different locales and thus
137 // would ignore data written to another cache):
138 Reference
< XFlushable
>(theConfigProvider
, UNO_QUERY_THROW
)->
140 theConfigProvider
->setLocale(loc
);
142 Reference
< XPropertySet
> xProp(getConfigAccess("org.openoffice.Setup/L10N/", sal_True
), UNO_QUERY_THROW
);
143 xProp
->setPropertyValue(OUString::createFromAscii("ooLocale"), makeAny(aLocaleString
));
144 Reference
< XChangesBatch
>(xProp
, UNO_QUERY_THROW
)->commitChanges();
148 catch ( PropertyVetoException
& )
150 // we are not allowed to change this
154 OString aMsg
= OUStringToOString(e
.Message
, RTL_TEXTENCODING_ASCII_US
);
155 OSL_ENSURE(sal_False
, aMsg
.getStr());
160 // #i32939# setting of default document locale
161 // #i32939# this should not be based on the UI language
162 setDefaultLanguage(aLocaleString
);
167 void LanguageSelection::setDefaultLanguage(const OUString
& sLocale
)
169 // #i32939# setting of default document language
171 // See #i42730# for rules for determining source of settings
173 // determine script type of locale
174 LanguageType nLang
= MsLangId::convertIsoStringToLanguage(sLocale
);
175 sal_uInt16 nScriptType
= SvtLanguageOptions::GetScriptTypeOfLanguage(nLang
);
179 case SCRIPTTYPE_ASIAN
:
180 MsLangId::setConfiguredAsianFallback( nLang
);
182 case SCRIPTTYPE_COMPLEX
:
183 MsLangId::setConfiguredComplexFallback( nLang
);
186 MsLangId::setConfiguredWesternFallback( nLang
);
191 OUString
LanguageSelection::getLanguageString()
193 // did we already find a language?
195 return aFoundLanguage
;
196 // check whether the user has selected a specific language
197 OUString aUserLanguage
= getUserLanguage();
198 if (aUserLanguage
.getLength() > 0 )
200 if (isInstalledLanguage(aUserLanguage
))
203 bFoundLanguage
= sal_True
;
204 aFoundLanguage
= aUserLanguage
;
205 return aFoundLanguage
;
209 // selected language is not/no longer installed
213 // try to use system default
214 aUserLanguage
= getSystemLanguage();
215 if (aUserLanguage
.getLength() > 0 )
217 if (isInstalledLanguage(aUserLanguage
, sal_False
))
219 // great, system default language is available
220 bFoundLanguage
= sal_True
;
221 aFoundLanguage
= aUserLanguage
;
222 return aFoundLanguage
;
226 OUString usFB
= usFallbackLanguage
;
227 if (isInstalledLanguage(usFB
))
229 bFoundLanguage
= sal_True
;
230 aFoundLanguage
= usFallbackLanguage
;
231 return aFoundLanguage
;
233 // fallback didn't work use first installed language
234 aUserLanguage
= getFirstInstalledLanguage();
235 bFoundLanguage
= sal_True
;
236 aFoundLanguage
= aUserLanguage
;
237 return aFoundLanguage
;
240 Reference
< XNameAccess
> LanguageSelection::getConfigAccess(const sal_Char
* pPath
, sal_Bool bUpdate
)
242 Reference
< XNameAccess
> xNameAccess
;
244 OUString sConfigSrvc
= OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider");
245 OUString sAccessSrvc
;
247 sAccessSrvc
= OUString::createFromAscii("com.sun.star.configuration.ConfigurationUpdateAccess");
249 sAccessSrvc
= OUString::createFromAscii("com.sun.star.configuration.ConfigurationAccess");
251 OUString sConfigURL
= OUString::createFromAscii(pPath
);
253 // get configuration provider
254 Reference
< XMultiServiceFactory
> theMSF
= comphelper::getProcessServiceFactory();
256 Reference
< XMultiServiceFactory
> theConfigProvider
= Reference
< XMultiServiceFactory
> (
257 theMSF
->createInstance( sConfigSrvc
),UNO_QUERY_THROW
);
259 // access the provider
260 Sequence
< Any
> theArgs(1);
261 theArgs
[ 0 ] <<= sConfigURL
;
262 xNameAccess
= Reference
< XNameAccess
> (
263 theConfigProvider
->createInstanceWithArguments(
264 sAccessSrvc
, theArgs
), UNO_QUERY_THROW
);
266 } catch (com::sun::star::uno::Exception
& e
)
268 OString aMsg
= OUStringToOString(e
.Message
, RTL_TEXTENCODING_ASCII_US
);
269 OSL_ENSURE(sal_False
, aMsg
.getStr());
274 Sequence
< OUString
> LanguageSelection::getInstalledLanguages()
276 Sequence
< OUString
> seqLanguages
;
277 Reference
< XNameAccess
> xAccess
= getConfigAccess("org.openoffice.Setup/Office/InstalledLocales", sal_False
);
278 if (!xAccess
.is()) return seqLanguages
;
279 seqLanguages
= xAccess
->getElementNames();
284 // it's not very clever to handle language fallbacks here, but
285 // right now, there is no place that handles those fallbacks globally
286 static Sequence
< OUString
> _getFallbackLocales(const OUString
& aIsoLang
)
288 Sequence
< OUString
> seqFallbacks
;
289 if (aIsoLang
.equalsAscii("zh-HK")) {
290 seqFallbacks
= Sequence
< OUString
>(1);
291 seqFallbacks
[0] = OUString::createFromAscii("zh-TW");
296 sal_Bool
LanguageSelection::isInstalledLanguage(OUString
& usLocale
, sal_Bool bExact
)
298 sal_Bool bInstalled
= sal_False
;
299 Sequence
< OUString
> seqLanguages
= getInstalledLanguages();
300 for (sal_Int32 i
=0; i
<seqLanguages
.getLength(); i
++)
302 if (usLocale
.equals(seqLanguages
[i
]))
304 bInstalled
= sal_True
;
309 if (!bInstalled
&& !bExact
)
311 // try fallback locales
312 Sequence
< OUString
> seqFallbacks
= _getFallbackLocales(usLocale
);
313 for (sal_Int32 j
=0; j
<seqFallbacks
.getLength(); j
++)
315 for (sal_Int32 i
=0; i
<seqLanguages
.getLength(); i
++)
317 if (seqFallbacks
[j
].equals(seqLanguages
[i
]))
319 bInstalled
= sal_True
;
320 usLocale
= seqFallbacks
[j
];
327 if (!bInstalled
&& !bExact
)
329 // no exact match was found, well try to find a substitute
330 OUString aInstalledLocale
;
331 for (sal_Int32 i
=0; i
<seqLanguages
.getLength(); i
++)
333 if (usLocale
.indexOf(seqLanguages
[i
]) == 0)
335 // requested locale starts with the installed locale
336 // (i.e. installed locale has index 0 in requested locale)
337 bInstalled
= sal_True
;
338 usLocale
= seqLanguages
[i
];
346 OUString
LanguageSelection::getFirstInstalledLanguage()
349 Sequence
< OUString
> seqLanguages
= getInstalledLanguages();
350 if (seqLanguages
.getLength() > 0)
351 aLanguage
= seqLanguages
[0];
355 OUString
LanguageSelection::getUserLanguage()
357 OUString aUserLanguage
;
358 Reference
< XNameAccess
> xAccess(getConfigAccess("org.openoffice.Office.Linguistic/General", sal_False
));
363 xAccess
->getByName(OUString::createFromAscii("UILocale")) >>= aUserLanguage
;
365 catch ( NoSuchElementException
const & )
369 catch ( WrappedTargetException
const & )
374 return aUserLanguage
;
377 OUString
LanguageSelection::getSystemLanguage()
379 OUString aUserLanguage
;
380 Reference
< XNameAccess
> xAccess(getConfigAccess("org.openoffice.System/L10N", sal_False
));
385 xAccess
->getByName(OUString::createFromAscii("UILocale")) >>= aUserLanguage
;
387 catch ( NoSuchElementException
const & )
391 catch ( WrappedTargetException
const & )
396 return aUserLanguage
;
400 void LanguageSelection::resetUserLanguage()
404 Reference
< XPropertySet
> xProp(getConfigAccess("org.openoffice.Office.Linguistic/General", sal_True
), UNO_QUERY_THROW
);
405 xProp
->setPropertyValue(OUString::createFromAscii("UILocale"), makeAny(OUString::createFromAscii("")));
406 Reference
< XChangesBatch
>(xProp
, UNO_QUERY_THROW
)->commitChanges();
408 catch ( PropertyVetoException
& )
410 // we are not allowed to change this
412 catch ( Exception
& e
)
414 OString aMsg
= OUStringToOString(e
.Message
, RTL_TEXTENCODING_ASCII_US
);
415 OSL_ENSURE(sal_False
, aMsg
.getStr());
421 } // namespace desktop