Update ooo320-m1
[ooovba.git] / desktop / source / app / langselect.cxx
blob2ad0b382e485da5b50de4f8bfc5af9b6759c6fb0
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 setDefaultLanguage(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 xLocaleProp->getPropertyValue(OUString::createFromAscii("Locale")) >>= usLocale;
120 setDefaultLanguage(usLocale);
122 catch (Exception&)
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
133 // UI language.
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)->
139 flush();
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();
146 bSuccess = sal_True;
148 catch ( PropertyVetoException& )
150 // we are not allowed to change this
152 catch (Exception& e)
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);
164 return bSuccess;
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);
177 switch (nScriptType)
179 case SCRIPTTYPE_ASIAN:
180 MsLangId::setConfiguredAsianFallback( nLang );
181 break;
182 case SCRIPTTYPE_COMPLEX:
183 MsLangId::setConfiguredComplexFallback( nLang );
184 break;
185 default:
186 MsLangId::setConfiguredWesternFallback( nLang );
187 break;
191 OUString LanguageSelection::getLanguageString()
193 // did we already find a language?
194 if (bFoundLanguage)
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))
202 // all is well
203 bFoundLanguage = sal_True;
204 aFoundLanguage = aUserLanguage;
205 return aFoundLanguage;
207 else
209 // selected language is not/no longer installed
210 resetUserLanguage();
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;
225 // fallback 1: en-US
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;
243 try{
244 OUString sConfigSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider");
245 OUString sAccessSrvc;
246 if (bUpdate)
247 sAccessSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationUpdateAccess");
248 else
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();
255 if (theMSF.is()) {
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());
271 return xNameAccess;
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();
280 return seqLanguages;
283 // FIXME
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");
293 return seqFallbacks;
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;
305 break;
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];
321 break;
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];
339 break;
343 return bInstalled;
346 OUString LanguageSelection::getFirstInstalledLanguage()
348 OUString aLanguage;
349 Sequence< OUString > seqLanguages = getInstalledLanguages();
350 if (seqLanguages.getLength() > 0)
351 aLanguage = seqLanguages[0];
352 return aLanguage;
355 OUString LanguageSelection::getUserLanguage()
357 OUString aUserLanguage;
358 Reference< XNameAccess > xAccess(getConfigAccess("org.openoffice.Office.Linguistic/General", sal_False));
359 if (xAccess.is())
363 xAccess->getByName(OUString::createFromAscii("UILocale")) >>= aUserLanguage;
365 catch ( NoSuchElementException const & )
367 return OUString();
369 catch ( WrappedTargetException const & )
371 return OUString();
374 return aUserLanguage;
377 OUString LanguageSelection::getSystemLanguage()
379 OUString aUserLanguage;
380 Reference< XNameAccess > xAccess(getConfigAccess("org.openoffice.System/L10N", sal_False));
381 if (xAccess.is())
385 xAccess->getByName(OUString::createFromAscii("UILocale")) >>= aUserLanguage;
387 catch ( NoSuchElementException const & )
389 return OUString();
391 catch ( WrappedTargetException const & )
393 return OUString();
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