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