1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_i18npool.hxx"
30 #include <sal/config.h>
31 #include <rtl/ustring.hxx>
32 #include <rtl/string.hxx>
33 #include <com/sun/star/i18n/ScriptType.hpp>
34 
35 #include "i18npool/mslangid.hxx"
36 
37 
38 LanguageType MsLangId::nConfiguredSystemLanguage   = LANGUAGE_SYSTEM;
39 LanguageType MsLangId::nConfiguredSystemUILanguage = LANGUAGE_SYSTEM;
40 
41 LanguageType MsLangId::nConfiguredWesternFallback  = LANGUAGE_SYSTEM;
42 LanguageType MsLangId::nConfiguredAsianFallback    = LANGUAGE_SYSTEM;
43 LanguageType MsLangId::nConfiguredComplexFallback  = LANGUAGE_SYSTEM;
44 
45 // static
46 void MsLangId::setConfiguredSystemLanguage( LanguageType nLang )
47 {
48     nConfiguredSystemLanguage = nLang;
49 }
50 
51 
52 // static
53 void MsLangId::setConfiguredSystemUILanguage( LanguageType nLang )
54 {
55     nConfiguredSystemUILanguage = nLang;
56 }
57 
58 // static
59 void MsLangId::setConfiguredWesternFallback( LanguageType nLang )
60 {
61     nConfiguredWesternFallback = nLang;
62 }
63 
64 // static
65 void MsLangId::setConfiguredAsianFallback( LanguageType nLang )
66 {
67     nConfiguredAsianFallback = nLang;
68 }
69 
70 // static
71 void MsLangId::setConfiguredComplexFallback( LanguageType nLang )
72 {
73     nConfiguredComplexFallback = nLang;
74 }
75 
76 // static
77 inline LanguageType MsLangId::simplifySystemLanguages( LanguageType nLang )
78 {
79     switch (nLang)
80     {
81         case LANGUAGE_PROCESS_OR_USER_DEFAULT :
82         case LANGUAGE_SYSTEM_DEFAULT :
83         case LANGUAGE_SYSTEM :
84             nLang = LANGUAGE_SYSTEM;
85             break;
86         default:
87             ;   // nothing
88     }
89     return nLang;
90 }
91 
92 
93 // static
94 LanguageType MsLangId::getRealLanguageWithoutConfig( LanguageType nLang )
95 {
96     switch (simplifySystemLanguages( nLang))
97     {
98         case LANGUAGE_SYSTEM :
99             nLang = getSystemLanguage();
100             break;
101         case LANGUAGE_NONE :
102             nLang = getSystemUILanguage();
103             break;
104         default:
105             /* TODO: would this be useful here? */
106             //nLang = MsLangId::getReplacementForObsoleteLanguage( nLang);
107             ;   // nothing
108     }
109     if (nLang == LANGUAGE_DONTKNOW)
110         nLang = LANGUAGE_ENGLISH_US;
111     return nLang;
112 }
113 
114 
115 // static
116 LanguageType MsLangId::getRealLanguage( LanguageType nLang )
117 {
118     switch (simplifySystemLanguages( nLang))
119     {
120         case LANGUAGE_SYSTEM :
121             if (nConfiguredSystemLanguage == LANGUAGE_SYSTEM)
122                 nLang = getSystemLanguage();
123             else
124                 nLang = nConfiguredSystemLanguage;
125             break;
126         case LANGUAGE_NONE :
127             if (nConfiguredSystemUILanguage == LANGUAGE_SYSTEM)
128                 nLang = getSystemUILanguage();
129             else
130                 nLang = nConfiguredSystemUILanguage;
131             break;
132         default:
133             /* TODO: would this be useful here? */
134             //nLang = MsLangId::getReplacementForObsoleteLanguage( nLang);
135             ;   // nothing
136     }
137     if (nLang == LANGUAGE_DONTKNOW)
138         nLang = LANGUAGE_ENGLISH_US;
139     return nLang;
140 }
141 
142 
143 // static
144 LanguageType MsLangId::resolveSystemLanguageByScriptType( LanguageType nLang, sal_Int16 nType )
145 {
146     if (nLang == LANGUAGE_NONE)
147         return nLang;
148 
149     nLang = getRealLanguage(nLang);
150     if (nType != ::com::sun::star::i18n::ScriptType::WEAK && getScriptType(nLang) != nType)
151     {
152         switch(nType)
153         {
154             case ::com::sun::star::i18n::ScriptType::ASIAN:
155                 if (nConfiguredAsianFallback == LANGUAGE_SYSTEM)
156                     nLang = LANGUAGE_CHINESE_SIMPLIFIED;
157                 else
158                     nLang = nConfiguredAsianFallback;
159                 break;
160             case ::com::sun::star::i18n::ScriptType::COMPLEX:
161                 if (nConfiguredComplexFallback == LANGUAGE_SYSTEM)
162                     nLang = LANGUAGE_HINDI;
163                 else
164                     nLang = nConfiguredComplexFallback;
165                 break;
166             default:
167                 if (nConfiguredWesternFallback == LANGUAGE_SYSTEM)
168                     nLang = LANGUAGE_ENGLISH_US;
169                 else
170                     nLang = nConfiguredWesternFallback;
171                 break;
172         }
173     }
174     return nLang;
175 }
176 
177 // static
178 void MsLangId::convertLanguageToLocale( LanguageType nLang,
179         ::com::sun::star::lang::Locale & rLocale )
180 {
181     if (rLocale.Variant.getLength())
182         rLocale.Variant = rtl::OUString();
183     convertLanguageToIsoNames( nLang, rLocale.Language, rLocale.Country);
184 }
185 
186 
187 // static
188 ::com::sun::star::lang::Locale MsLangId::convertLanguageToLocale(
189         LanguageType nLang, bool bResolveSystem )
190 {
191     ::com::sun::star::lang::Locale aLocale;
192     if (!bResolveSystem && simplifySystemLanguages( nLang) == LANGUAGE_SYSTEM)
193         ;   // nothing => empty locale
194     else
195     {
196         // Still resolve LANGUAGE_DONTKNOW if resolving is not requested,
197         // but not LANGUAGE_NONE or others.
198         if (bResolveSystem || nLang == LANGUAGE_DONTKNOW)
199             nLang = MsLangId::getRealLanguage( nLang);
200         convertLanguageToLocale( nLang, aLocale);
201     }
202     return aLocale;
203 }
204 
205 
206 // static
207 LanguageType MsLangId::convertLocaleToLanguage(
208         const ::com::sun::star::lang::Locale& rLocale )
209 {
210     // empty language => LANGUAGE_SYSTEM
211     if (rLocale.Language.getLength() == 0)
212         return LANGUAGE_SYSTEM;
213 
214     LanguageType nRet = convertIsoNamesToLanguage( rLocale.Language,
215             rLocale.Country);
216     if (nRet == LANGUAGE_DONTKNOW)
217         nRet = LANGUAGE_SYSTEM;
218 
219     return nRet;
220 }
221 
222 
223 // static
224 LanguageType MsLangId::convertLocaleToLanguageWithFallback(
225             const ::com::sun::star::lang::Locale & rLocale )
226 {
227     // empty language => LANGUAGE_SYSTEM
228     if (rLocale.Language.getLength() == 0)
229         return lookupFallbackLanguage( LANGUAGE_SYSTEM);
230 
231     return lookupFallbackLanguage( rLocale);
232 }
233 
234 
235 // static
236 ::com::sun::star::lang::Locale MsLangId::convertLanguageToLocaleWithFallback(
237         LanguageType nLang )
238 {
239     return lookupFallbackLocale( MsLangId::getRealLanguage( nLang));
240 }
241 
242 
243 // static
244 ::com::sun::star::lang::Locale MsLangId::getFallbackLocale(
245             const ::com::sun::star::lang::Locale & rLocale )
246 {
247     // empty language => LANGUAGE_SYSTEM
248     if (rLocale.Language.getLength() == 0)
249         return convertLanguageToLocaleWithFallback( LANGUAGE_SYSTEM);
250 
251     return lookupFallbackLocale( rLocale);
252 }
253 
254 
255 // static
256 LanguageType MsLangId::getFallbackLanguage( LanguageType nLang )
257 {
258     return lookupFallbackLanguage( MsLangId::getRealLanguage( nLang));
259 }
260 
261 
262 // static
263 bool MsLangId::isRightToLeft( LanguageType nLang )
264 {
265     switch( nLang & LANGUAGE_MASK_PRIMARY )
266     {
267         case LANGUAGE_ARABIC_SAUDI_ARABIA & LANGUAGE_MASK_PRIMARY :
268         case LANGUAGE_HEBREW              & LANGUAGE_MASK_PRIMARY :
269         case LANGUAGE_YIDDISH             & LANGUAGE_MASK_PRIMARY :
270         case LANGUAGE_URDU                & LANGUAGE_MASK_PRIMARY :
271         case LANGUAGE_FARSI               & LANGUAGE_MASK_PRIMARY :
272         case LANGUAGE_KASHMIRI            & LANGUAGE_MASK_PRIMARY :
273         case LANGUAGE_SINDHI              & LANGUAGE_MASK_PRIMARY :
274         case LANGUAGE_UIGHUR_CHINA        & LANGUAGE_MASK_PRIMARY :
275             return true;
276 
277         default:
278             break;
279     }
280     return false;
281 }
282 
283 
284 // static
285 bool MsLangId::hasForbiddenCharacters( LanguageType nLang )
286 {
287     switch (nLang & LANGUAGE_MASK_PRIMARY)
288     {
289         case LANGUAGE_CHINESE  & LANGUAGE_MASK_PRIMARY:
290         case LANGUAGE_JAPANESE & LANGUAGE_MASK_PRIMARY:
291         case LANGUAGE_KOREAN   & LANGUAGE_MASK_PRIMARY:
292             return true;
293         default:
294             break;
295     }
296     return false;
297 }
298 
299 
300 // static
301 bool MsLangId::needsSequenceChecking( LanguageType nLang )
302 {
303     switch (nLang & LANGUAGE_MASK_PRIMARY)
304     {
305         case LANGUAGE_BURMESE & LANGUAGE_MASK_PRIMARY:
306         case LANGUAGE_KHMER   & LANGUAGE_MASK_PRIMARY:
307         case LANGUAGE_LAO     & LANGUAGE_MASK_PRIMARY:
308         case LANGUAGE_THAI    & LANGUAGE_MASK_PRIMARY:
309             return true;
310         default:
311             break;
312     }
313     return false;
314 }
315 
316 
317 // static
318 sal_Int16 MsLangId::getScriptType( LanguageType nLang )
319 {
320     sal_Int16 nScript;
321     switch( nLang )
322     {
323         // CJK
324         // all LANGUAGE_CHINESE_... are caught below
325         case LANGUAGE_JAPANESE:
326         case LANGUAGE_KOREAN:
327         case LANGUAGE_KOREAN_JOHAB:
328         case LANGUAGE_USER_KOREAN_NORTH:
329             nScript = ::com::sun::star::i18n::ScriptType::ASIAN;
330             break;
331 
332         // CTL
333         // all LANGUAGE_ARABIC_... are caught below
334         case LANGUAGE_AMHARIC_ETHIOPIA:
335         case LANGUAGE_ASSAMESE:
336         case LANGUAGE_BENGALI:
337         case LANGUAGE_BENGALI_BANGLADESH:
338         case LANGUAGE_BURMESE:
339         case LANGUAGE_FARSI:
340         case LANGUAGE_HEBREW:
341         case LANGUAGE_YIDDISH:
342         case LANGUAGE_USER_YIDDISH_US:
343         case LANGUAGE_MARATHI:
344         case LANGUAGE_PUNJABI:
345         case LANGUAGE_GUJARATI:
346         case LANGUAGE_HINDI:
347         case LANGUAGE_KANNADA:
348         case LANGUAGE_KASHMIRI:
349         case LANGUAGE_KASHMIRI_INDIA:
350         case LANGUAGE_KHMER:
351         case LANGUAGE_LAO:
352         case LANGUAGE_MALAYALAM:
353         case LANGUAGE_MANIPURI:
354         case LANGUAGE_MONGOLIAN_MONGOLIAN:
355         case LANGUAGE_NEPALI:
356         case LANGUAGE_NEPALI_INDIA:
357         case LANGUAGE_ORIYA:
358         case LANGUAGE_SANSKRIT:
359         case LANGUAGE_SINDHI:
360         case LANGUAGE_SINDHI_PAKISTAN:
361         case LANGUAGE_SINHALESE_SRI_LANKA:
362         case LANGUAGE_SYRIAC:
363         case LANGUAGE_TAMIL:
364         case LANGUAGE_TELUGU:
365         case LANGUAGE_THAI:
366         case LANGUAGE_TIBETAN:
367         case LANGUAGE_DZONGKHA:
368         case LANGUAGE_URDU:
369         case LANGUAGE_URDU_PAKISTAN:
370         case LANGUAGE_URDU_INDIA:
371         case LANGUAGE_USER_KURDISH_IRAQ:
372         case LANGUAGE_USER_KURDISH_IRAN:
373         case LANGUAGE_DHIVEHI:
374         case LANGUAGE_USER_BODO_INDIA:
375         case LANGUAGE_USER_DOGRI_INDIA:
376         case LANGUAGE_USER_MAITHILI_INDIA:
377         case LANGUAGE_UIGHUR_CHINA:
378         case LANGUAGE_USER_LIMBU:
379             nScript = ::com::sun::star::i18n::ScriptType::COMPLEX;
380             break;
381 
382 // currently not knowing scripttype - defaulted to LATIN:
383 /*
384 #define LANGUAGE_ARMENIAN                   0x042B
385 #define LANGUAGE_INDONESIAN                 0x0421
386 #define LANGUAGE_KAZAK                      0x043F
387 #define LANGUAGE_KONKANI                    0x0457
388 #define LANGUAGE_MACEDONIAN                 0x042F
389 #define LANGUAGE_TATAR                      0x0444
390 */
391 
392     default:
393         switch ( nLang & LANGUAGE_MASK_PRIMARY )
394         {
395             // CJK catcher
396             case LANGUAGE_CHINESE & LANGUAGE_MASK_PRIMARY:
397                 nScript = ::com::sun::star::i18n::ScriptType::ASIAN;
398                 break;
399             // CTL catcher
400             case LANGUAGE_ARABIC_SAUDI_ARABIA & LANGUAGE_MASK_PRIMARY:
401                 nScript = ::com::sun::star::i18n::ScriptType::COMPLEX;
402                 break;
403             // Western (actually not necessarily Latin but also Cyrillic, for example)
404             default:
405                 nScript = ::com::sun::star::i18n::ScriptType::LATIN;
406         }
407         break;
408     }
409     return nScript;
410 }
411 
412 
413 // static
414 LanguageType MsLangId::getReplacementForObsoleteLanguage( LanguageType nLang )
415 {
416     switch (nLang)
417     {
418         default:
419             break;  // nothing
420         case LANGUAGE_OBSOLETE_USER_LATIN:
421             nLang = LANGUAGE_LATIN;
422             break;
423         case LANGUAGE_OBSOLETE_USER_MAORI:
424             nLang = LANGUAGE_MAORI_NEW_ZEALAND;
425             break;
426         case LANGUAGE_OBSOLETE_USER_KINYARWANDA:
427             nLang = LANGUAGE_KINYARWANDA_RWANDA;
428             break;
429         case LANGUAGE_OBSOLETE_USER_UPPER_SORBIAN:
430             nLang = LANGUAGE_UPPER_SORBIAN_GERMANY;
431             break;
432         case LANGUAGE_OBSOLETE_USER_LOWER_SORBIAN:
433             nLang = LANGUAGE_LOWER_SORBIAN_GERMANY;
434             break;
435         case LANGUAGE_OBSOLETE_USER_OCCITAN:
436             nLang = LANGUAGE_OCCITAN_FRANCE;
437             break;
438         case LANGUAGE_OBSOLETE_USER_BRETON:
439             nLang = LANGUAGE_BRETON_FRANCE;
440             break;
441         case LANGUAGE_OBSOLETE_USER_KALAALLISUT:
442             nLang = LANGUAGE_KALAALLISUT_GREENLAND;
443             break;
444         case LANGUAGE_OBSOLETE_USER_LUXEMBOURGISH:
445             nLang = LANGUAGE_LUXEMBOURGISH_LUXEMBOURG;
446             break;
447 
448         // The following are not strictly obsolete but should be mapped to a
449         // replacement locale when encountered.
450 
451         // no_NO is an alias for nb_NO
452         case LANGUAGE_NORWEGIAN:
453             nLang = LANGUAGE_NORWEGIAN_BOKMAL;
454             break;
455 
456         // #i94435# A Spanish variant that differs only in collation details we
457         // do not support.
458         case LANGUAGE_SPANISH_DATED:
459             nLang = LANGUAGE_SPANISH_MODERN;
460             break;
461 
462          // Do not use ca-XV for document content.
463          /* TODO: remove in case we implement BCP47 language tags. */
464         case LANGUAGE_USER_CATALAN_VALENCIAN:
465             nLang = LANGUAGE_CATALAN;
466             break;
467     }
468     return nLang;
469 }
470