bump product version to 4.2.0.1
[LibreOffice.git] / i18nlangtag / source / isolang / mslangid.cxx
blob772822ea9652c3a2f937b227475a1be757172ecf
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
21 #include <rtl/ustring.hxx>
22 #include <rtl/string.hxx>
23 #include <com/sun/star/i18n/ScriptType.hpp>
25 #include "i18nlangtag/mslangid.hxx"
27 // Only very limited few functions that are guaranteed to not be called from
28 // LanguageTag may use LanguageTag ...
29 #include "i18nlangtag/languagetag.hxx"
32 LanguageType MsLangId::nConfiguredSystemLanguage = LANGUAGE_SYSTEM;
33 LanguageType MsLangId::nConfiguredSystemUILanguage = LANGUAGE_SYSTEM;
35 LanguageType MsLangId::nConfiguredWesternFallback = LANGUAGE_SYSTEM;
36 LanguageType MsLangId::nConfiguredAsianFallback = LANGUAGE_SYSTEM;
37 LanguageType MsLangId::nConfiguredComplexFallback = LANGUAGE_SYSTEM;
39 // static
40 void MsLangId::setConfiguredSystemLanguage( LanguageType nLang )
42 nConfiguredSystemLanguage = nLang;
46 // static
47 void MsLangId::setConfiguredSystemUILanguage( LanguageType nLang )
49 nConfiguredSystemUILanguage = nLang;
52 // static
53 void MsLangId::setConfiguredWesternFallback( LanguageType nLang )
55 nConfiguredWesternFallback = nLang;
58 // static
59 void MsLangId::setConfiguredAsianFallback( LanguageType nLang )
61 nConfiguredAsianFallback = nLang;
64 // static
65 void MsLangId::setConfiguredComplexFallback( LanguageType nLang )
67 nConfiguredComplexFallback = nLang;
70 // static
71 inline LanguageType MsLangId::simplifySystemLanguages( LanguageType nLang )
73 switch (nLang)
75 case LANGUAGE_PROCESS_OR_USER_DEFAULT :
76 case LANGUAGE_SYSTEM_DEFAULT :
77 case LANGUAGE_SYSTEM :
78 nLang = LANGUAGE_SYSTEM;
79 break;
80 default:
81 ; // nothing
83 return nLang;
86 // static
87 LanguageType MsLangId::getRealLanguage( LanguageType nLang )
89 switch (simplifySystemLanguages( nLang))
91 case LANGUAGE_SYSTEM :
92 if (nConfiguredSystemLanguage == LANGUAGE_SYSTEM)
93 nLang = getSystemLanguage();
94 else
95 nLang = nConfiguredSystemLanguage;
96 break;
97 case LANGUAGE_HID_HUMAN_INTERFACE_DEVICE :
98 if (nConfiguredSystemUILanguage == LANGUAGE_SYSTEM)
99 nLang = getSystemUILanguage();
100 else
101 nLang = nConfiguredSystemUILanguage;
102 break;
103 default:
104 /* TODO: would this be useful here? */
105 //nLang = MsLangId::getReplacementForObsoleteLanguage( nLang);
106 ; // nothing
108 if (nLang == LANGUAGE_DONTKNOW)
109 nLang = LANGUAGE_ENGLISH_US;
110 return nLang;
114 // static
115 LanguageType MsLangId::resolveSystemLanguageByScriptType( LanguageType nLang, sal_Int16 nType )
117 if (nLang == LANGUAGE_NONE)
118 return nLang;
120 nLang = getRealLanguage(nLang);
121 if (nType != ::com::sun::star::i18n::ScriptType::WEAK && getScriptType(nLang) != nType)
123 switch(nType)
125 case ::com::sun::star::i18n::ScriptType::ASIAN:
126 if (nConfiguredAsianFallback == LANGUAGE_SYSTEM)
127 nLang = LANGUAGE_CHINESE_SIMPLIFIED;
128 else
129 nLang = nConfiguredAsianFallback;
130 break;
131 case ::com::sun::star::i18n::ScriptType::COMPLEX:
132 if (nConfiguredComplexFallback == LANGUAGE_SYSTEM)
133 nLang = LANGUAGE_HINDI;
134 else
135 nLang = nConfiguredComplexFallback;
136 break;
137 default:
138 if (nConfiguredWesternFallback == LANGUAGE_SYSTEM)
139 nLang = LANGUAGE_ENGLISH_US;
140 else
141 nLang = nConfiguredWesternFallback;
142 break;
145 return nLang;
149 // static
150 ::com::sun::star::lang::Locale MsLangId::Conversion::convertLanguageToLocale(
151 LanguageType nLang, bool bResolveSystem )
153 ::com::sun::star::lang::Locale aLocale;
154 if (!bResolveSystem && simplifySystemLanguages( nLang) == LANGUAGE_SYSTEM)
155 ; // nothing => empty locale
156 else
158 // Still resolve LANGUAGE_DONTKNOW if resolving is not requested,
159 // but not LANGUAGE_SYSTEM or others.
160 LanguageType nOrigLang = nLang;
161 if (bResolveSystem || nLang == LANGUAGE_DONTKNOW)
162 nLang = MsLangId::getRealLanguage( nLang);
163 convertLanguageToLocaleImpl( nLang, aLocale, true);
164 if (bResolveSystem && aLocale.Language.isEmpty() && simplifySystemLanguages( nOrigLang) == LANGUAGE_SYSTEM)
166 // None found but resolve requested, last resort is "en-US".
167 aLocale.Language = "en";
168 aLocale.Country = "US";
169 aLocale.Variant = OUString();
172 return aLocale;
176 // static
177 LanguageType MsLangId::Conversion::convertLocaleToLanguage(
178 const ::com::sun::star::lang::Locale& rLocale )
180 // empty language => LANGUAGE_SYSTEM
181 if (rLocale.Language.isEmpty())
182 return LANGUAGE_SYSTEM;
184 return convertLocaleToLanguageImpl( rLocale);
188 // static
189 ::com::sun::star::lang::Locale MsLangId::getFallbackLocale(
190 const ::com::sun::star::lang::Locale & rLocale )
192 // empty language => LANGUAGE_SYSTEM
193 if (rLocale.Language.isEmpty())
194 return Conversion::lookupFallbackLocale( Conversion::convertLanguageToLocale( LANGUAGE_SYSTEM, true));
195 else
196 return Conversion::lookupFallbackLocale( rLocale);
199 // static
200 bool MsLangId::isRightToLeft( LanguageType nLang )
202 switch( nLang & LANGUAGE_MASK_PRIMARY )
204 case LANGUAGE_ARABIC_SAUDI_ARABIA & LANGUAGE_MASK_PRIMARY :
205 case LANGUAGE_HEBREW & LANGUAGE_MASK_PRIMARY :
206 case LANGUAGE_YIDDISH & LANGUAGE_MASK_PRIMARY :
207 case LANGUAGE_URDU_PAKISTAN & LANGUAGE_MASK_PRIMARY :
208 case LANGUAGE_FARSI & LANGUAGE_MASK_PRIMARY :
209 case LANGUAGE_KASHMIRI & LANGUAGE_MASK_PRIMARY :
210 case LANGUAGE_SINDHI & LANGUAGE_MASK_PRIMARY :
211 case LANGUAGE_UIGHUR_CHINA & LANGUAGE_MASK_PRIMARY :
212 case LANGUAGE_USER_KYRGYZ_CHINA & LANGUAGE_MASK_PRIMARY :
213 case LANGUAGE_USER_NKO & LANGUAGE_MASK_PRIMARY :
214 return true;
216 default:
217 break;
219 switch (nLang)
221 case LANGUAGE_USER_KURDISH_IRAN:
222 case LANGUAGE_OBSOLETE_USER_KURDISH_IRAQ:
223 case LANGUAGE_KURDISH_ARABIC_IRAQ:
224 case LANGUAGE_KURDISH_ARABIC_LSO:
225 case LANGUAGE_USER_KURDISH_SOUTHERN_IRAN:
226 case LANGUAGE_USER_KURDISH_SOUTHERN_IRAQ:
227 return true;
229 default:
230 break;
232 return false;
235 // static
236 bool MsLangId::isSimplifiedChinese( LanguageType nLang )
238 return isChinese(nLang) && !isTraditionalChinese(nLang);
241 // static
242 bool MsLangId::isSimplifiedChinese( const ::com::sun::star::lang::Locale & rLocale )
244 return rLocale.Language == "zh" && !isTraditionalChinese(rLocale);
247 // static
248 bool MsLangId::isTraditionalChinese( LanguageType nLang )
250 bool bRet = false;
251 switch (nLang)
253 case LANGUAGE_CHINESE_TRADITIONAL:
254 case LANGUAGE_CHINESE_HONGKONG:
255 case LANGUAGE_CHINESE_MACAU:
256 bRet = true;
257 default:
258 break;
260 return bRet;
263 // static
264 bool MsLangId::isTraditionalChinese( const ::com::sun::star::lang::Locale & rLocale )
266 return rLocale.Language == "zh" && (rLocale.Country == "TW" || rLocale.Country == "HK" || rLocale.Country == "MO");
269 //static
270 bool MsLangId::isChinese( LanguageType nLang )
272 return MsLangId::getPrimaryLanguage(nLang) == MsLangId::getPrimaryLanguage(LANGUAGE_CHINESE) ||
273 MsLangId::getPrimaryLanguage(nLang) == MsLangId::getPrimaryLanguage(LANGUAGE_YUE_CHINESE_HONGKONG);
276 //static
277 bool MsLangId::isKorean( LanguageType nLang )
279 return MsLangId::getPrimaryLanguage(nLang) == MsLangId::getPrimaryLanguage(LANGUAGE_KOREAN);
282 // static
283 bool MsLangId::isCJK( LanguageType nLang )
285 switch (nLang & LANGUAGE_MASK_PRIMARY)
287 case LANGUAGE_CHINESE & LANGUAGE_MASK_PRIMARY:
288 case LANGUAGE_YUE_CHINESE_HONGKONG & LANGUAGE_MASK_PRIMARY:
289 case LANGUAGE_JAPANESE & LANGUAGE_MASK_PRIMARY:
290 case LANGUAGE_KOREAN & LANGUAGE_MASK_PRIMARY:
291 return true;
292 default:
293 break;
295 return false;
298 // static
299 bool MsLangId::isFamilyNameFirst( LanguageType nLang )
301 return isCJK(nLang) || nLang == LANGUAGE_HUNGARIAN;
304 // static
305 bool MsLangId::hasForbiddenCharacters( LanguageType nLang )
307 return isCJK(nLang);
311 // static
312 bool MsLangId::needsSequenceChecking( LanguageType nLang )
314 switch (nLang & LANGUAGE_MASK_PRIMARY)
316 case LANGUAGE_BURMESE & LANGUAGE_MASK_PRIMARY:
317 case LANGUAGE_KHMER & LANGUAGE_MASK_PRIMARY:
318 case LANGUAGE_LAO & LANGUAGE_MASK_PRIMARY:
319 case LANGUAGE_THAI & LANGUAGE_MASK_PRIMARY:
320 return true;
321 default:
322 break;
324 return false;
328 // static
329 sal_Int16 MsLangId::getScriptType( LanguageType nLang )
331 sal_Int16 nScript;
332 switch( nLang )
334 // CTL
335 case LANGUAGE_MONGOLIAN_MONGOLIAN_MONGOLIA:
336 case LANGUAGE_MONGOLIAN_MONGOLIAN_CHINA:
337 case LANGUAGE_MONGOLIAN_MONGOLIAN_LSO:
338 case LANGUAGE_USER_KURDISH_IRAN:
339 case LANGUAGE_OBSOLETE_USER_KURDISH_IRAQ:
340 case LANGUAGE_KURDISH_ARABIC_IRAQ:
341 case LANGUAGE_KURDISH_ARABIC_LSO:
342 case LANGUAGE_USER_KURDISH_SOUTHERN_IRAN:
343 case LANGUAGE_USER_KURDISH_SOUTHERN_IRAQ:
344 case LANGUAGE_USER_KYRGYZ_CHINA:
345 nScript = ::com::sun::star::i18n::ScriptType::COMPLEX;
346 break;
348 // "Western"
349 case LANGUAGE_MONGOLIAN_CYRILLIC_MONGOLIA:
350 case LANGUAGE_MONGOLIAN_CYRILLIC_LSO:
351 case LANGUAGE_USER_KURDISH_SYRIA:
352 case LANGUAGE_USER_KURDISH_TURKEY:
353 nScript = ::com::sun::star::i18n::ScriptType::LATIN;
354 break;
356 // currently not knowing scripttype - defaulted to LATIN:
358 #define LANGUAGE_ARMENIAN 0x042B
359 #define LANGUAGE_INDONESIAN 0x0421
360 #define LANGUAGE_KAZAKH 0x043F
361 #define LANGUAGE_KONKANI 0x0457
362 #define LANGUAGE_MACEDONIAN 0x042F
363 #define LANGUAGE_TATAR 0x0444
366 default:
367 switch ( nLang & LANGUAGE_MASK_PRIMARY )
369 // CJK catcher
370 case LANGUAGE_CHINESE & LANGUAGE_MASK_PRIMARY:
371 case LANGUAGE_YUE_CHINESE_HONGKONG & LANGUAGE_MASK_PRIMARY:
372 case LANGUAGE_JAPANESE & LANGUAGE_MASK_PRIMARY:
373 case LANGUAGE_KOREAN & LANGUAGE_MASK_PRIMARY:
374 nScript = ::com::sun::star::i18n::ScriptType::ASIAN;
375 break;
377 // CTL catcher
378 case LANGUAGE_AMHARIC_ETHIOPIA & LANGUAGE_MASK_PRIMARY:
379 case LANGUAGE_ARABIC_SAUDI_ARABIA & LANGUAGE_MASK_PRIMARY:
380 case LANGUAGE_ASSAMESE & LANGUAGE_MASK_PRIMARY:
381 case LANGUAGE_BENGALI & LANGUAGE_MASK_PRIMARY:
382 case LANGUAGE_BURMESE & LANGUAGE_MASK_PRIMARY:
383 case LANGUAGE_DHIVEHI & LANGUAGE_MASK_PRIMARY:
384 case LANGUAGE_FARSI & LANGUAGE_MASK_PRIMARY:
385 case LANGUAGE_GUJARATI & LANGUAGE_MASK_PRIMARY:
386 case LANGUAGE_HEBREW & LANGUAGE_MASK_PRIMARY:
387 case LANGUAGE_HINDI & LANGUAGE_MASK_PRIMARY:
388 case LANGUAGE_KANNADA & LANGUAGE_MASK_PRIMARY:
389 case LANGUAGE_KASHMIRI & LANGUAGE_MASK_PRIMARY:
390 case LANGUAGE_KHMER & LANGUAGE_MASK_PRIMARY:
391 case LANGUAGE_LAO & LANGUAGE_MASK_PRIMARY:
392 case LANGUAGE_MALAYALAM & LANGUAGE_MASK_PRIMARY:
393 case LANGUAGE_MANIPURI & LANGUAGE_MASK_PRIMARY:
394 case LANGUAGE_MARATHI & LANGUAGE_MASK_PRIMARY:
395 case LANGUAGE_NEPALI & LANGUAGE_MASK_PRIMARY:
396 case LANGUAGE_ORIYA & LANGUAGE_MASK_PRIMARY:
397 case LANGUAGE_PUNJABI & LANGUAGE_MASK_PRIMARY:
398 case LANGUAGE_SANSKRIT & LANGUAGE_MASK_PRIMARY:
399 case LANGUAGE_SINDHI & LANGUAGE_MASK_PRIMARY:
400 case LANGUAGE_SINHALESE_SRI_LANKA & LANGUAGE_MASK_PRIMARY:
401 case LANGUAGE_SYRIAC & LANGUAGE_MASK_PRIMARY:
402 case LANGUAGE_TAMIL & LANGUAGE_MASK_PRIMARY:
403 case LANGUAGE_TELUGU & LANGUAGE_MASK_PRIMARY:
404 case LANGUAGE_THAI & LANGUAGE_MASK_PRIMARY:
405 case LANGUAGE_TIBETAN & LANGUAGE_MASK_PRIMARY: // also LANGUAGE_DZONGKHA
406 case LANGUAGE_UIGHUR_CHINA & LANGUAGE_MASK_PRIMARY:
407 case LANGUAGE_URDU_INDIA & LANGUAGE_MASK_PRIMARY:
408 case LANGUAGE_USER_BODO_INDIA & LANGUAGE_MASK_PRIMARY:
409 case LANGUAGE_USER_DOGRI_INDIA & LANGUAGE_MASK_PRIMARY:
410 case LANGUAGE_USER_LIMBU & LANGUAGE_MASK_PRIMARY:
411 case LANGUAGE_USER_MAITHILI_INDIA & LANGUAGE_MASK_PRIMARY:
412 case LANGUAGE_USER_NKO & LANGUAGE_MASK_PRIMARY:
413 case LANGUAGE_YIDDISH & LANGUAGE_MASK_PRIMARY:
414 nScript = ::com::sun::star::i18n::ScriptType::COMPLEX;
415 break;
417 // Western (actually not necessarily Latin but also Cyrillic,
418 // for example)
419 default:
420 nScript = ::com::sun::star::i18n::ScriptType::LATIN;
422 break;
424 return nScript;
428 // static
429 bool MsLangId::isNonLatinWestern( LanguageType nLang )
431 switch (nLang)
433 case LANGUAGE_AZERI_CYRILLIC:
434 case LANGUAGE_AZERI_CYRILLIC_LSO:
435 case LANGUAGE_BELARUSIAN:
436 case LANGUAGE_BOSNIAN_CYRILLIC_BOSNIA_HERZEGOVINA:
437 case LANGUAGE_BOSNIAN_CYRILLIC_LSO:
438 case LANGUAGE_BULGARIAN:
439 case LANGUAGE_GREEK:
440 case LANGUAGE_MONGOLIAN_CYRILLIC_LSO:
441 case LANGUAGE_MONGOLIAN_CYRILLIC_MONGOLIA:
442 case LANGUAGE_RUSSIAN:
443 case LANGUAGE_RUSSIAN_MOLDOVA:
444 case LANGUAGE_SERBIAN_CYRILLIC_BOSNIA_HERZEGOVINA:
445 case LANGUAGE_SERBIAN_CYRILLIC_LSO:
446 case LANGUAGE_SERBIAN_CYRILLIC_MONTENEGRO:
447 case LANGUAGE_SERBIAN_CYRILLIC_SAM:
448 case LANGUAGE_SERBIAN_CYRILLIC_SERBIA:
449 case LANGUAGE_UKRAINIAN:
450 case LANGUAGE_UZBEK_CYRILLIC:
451 case LANGUAGE_UZBEK_CYRILLIC_LSO:
452 return true;
453 default:
455 if (getScriptType( nLang) != com::sun::star::i18n::ScriptType::LATIN)
456 return false;
457 LanguageTag aLanguageTag( nLang);
458 if (aLanguageTag.hasScript())
459 return aLanguageTag.getScript() != "Latn";
462 return false;
466 // static
467 LanguageType MsLangId::getReplacementForObsoleteLanguage( LanguageType nLang, bool /*bUserInterfaceSelection*/ )
469 switch (nLang)
471 default:
472 break; // nothing
473 case LANGUAGE_OBSOLETE_USER_LATIN:
474 nLang = LANGUAGE_USER_LATIN_VATICAN;
475 break;
476 case LANGUAGE_OBSOLETE_USER_MAORI:
477 nLang = LANGUAGE_MAORI_NEW_ZEALAND;
478 break;
479 case LANGUAGE_OBSOLETE_USER_KINYARWANDA:
480 nLang = LANGUAGE_KINYARWANDA_RWANDA;
481 break;
482 case LANGUAGE_OBSOLETE_USER_UPPER_SORBIAN:
483 nLang = LANGUAGE_UPPER_SORBIAN_GERMANY;
484 break;
485 case LANGUAGE_OBSOLETE_USER_LOWER_SORBIAN:
486 nLang = LANGUAGE_LOWER_SORBIAN_GERMANY;
487 break;
488 case LANGUAGE_OBSOLETE_USER_OCCITAN:
489 nLang = LANGUAGE_OCCITAN_FRANCE;
490 break;
491 case LANGUAGE_OBSOLETE_USER_BRETON:
492 nLang = LANGUAGE_BRETON_FRANCE;
493 break;
494 case LANGUAGE_OBSOLETE_USER_KALAALLISUT:
495 nLang = LANGUAGE_KALAALLISUT_GREENLAND;
496 break;
497 case LANGUAGE_OBSOLETE_USER_LUXEMBOURGISH:
498 nLang = LANGUAGE_LUXEMBOURGISH_LUXEMBOURG;
499 break;
500 case LANGUAGE_OBSOLETE_USER_KABYLE:
501 nLang = LANGUAGE_TAMAZIGHT_LATIN_ALGERIA;
502 break;
503 case LANGUAGE_OBSOLETE_USER_CATALAN_VALENCIAN:
504 nLang = LANGUAGE_CATALAN_VALENCIAN;
505 break;
506 case LANGUAGE_OBSOLETE_USER_MALAGASY_PLATEAU:
507 nLang = LANGUAGE_MALAGASY_PLATEAU;
508 break;
509 case LANGUAGE_GAELIC_SCOTLAND_LEGACY:
510 nLang = LANGUAGE_GAELIC_SCOTLAND;
511 break;
512 case LANGUAGE_OBSOLETE_USER_TSWANA_BOTSWANA:
513 nLang = LANGUAGE_TSWANA_BOTSWANA;
514 break;
515 case LANGUAGE_OBSOLETE_USER_SERBIAN_LATIN_SERBIA:
516 nLang = LANGUAGE_SERBIAN_LATIN_SERBIA;
517 break;
518 case LANGUAGE_OBSOLETE_USER_SERBIAN_LATIN_MONTENEGRO:
519 nLang = LANGUAGE_SERBIAN_LATIN_MONTENEGRO;
520 break;
521 case LANGUAGE_OBSOLETE_USER_SERBIAN_CYRILLIC_SERBIA:
522 nLang = LANGUAGE_SERBIAN_CYRILLIC_SERBIA;
523 break;
524 case LANGUAGE_OBSOLETE_USER_SERBIAN_CYRILLIC_MONTENEGRO:
525 nLang = LANGUAGE_SERBIAN_CYRILLIC_MONTENEGRO;
526 break;
527 case LANGUAGE_OBSOLETE_USER_KURDISH_IRAQ:
528 nLang = LANGUAGE_KURDISH_ARABIC_IRAQ;
529 break;
531 // The following are not strictly obsolete but should be mapped to a
532 // replacement locale when encountered.
534 // no_NO is an alias for nb_NO
535 case LANGUAGE_NORWEGIAN:
536 nLang = LANGUAGE_NORWEGIAN_BOKMAL;
537 break;
539 // #i94435# A Spanish variant that differs only in collation details we
540 // do not support.
541 case LANGUAGE_SPANISH_DATED:
542 nLang = LANGUAGE_SPANISH_MODERN;
543 break;
545 return nLang;
548 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */