1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
;
40 void MsLangId::setConfiguredSystemLanguage( LanguageType nLang
)
42 nConfiguredSystemLanguage
= nLang
;
47 void MsLangId::setConfiguredSystemUILanguage( LanguageType nLang
)
49 nConfiguredSystemUILanguage
= nLang
;
53 void MsLangId::setConfiguredWesternFallback( LanguageType nLang
)
55 nConfiguredWesternFallback
= nLang
;
59 void MsLangId::setConfiguredAsianFallback( LanguageType nLang
)
61 nConfiguredAsianFallback
= nLang
;
65 void MsLangId::setConfiguredComplexFallback( LanguageType nLang
)
67 nConfiguredComplexFallback
= nLang
;
71 inline LanguageType
MsLangId::simplifySystemLanguages( LanguageType nLang
)
75 case LANGUAGE_PROCESS_OR_USER_DEFAULT
:
76 case LANGUAGE_SYSTEM_DEFAULT
:
77 case LANGUAGE_SYSTEM
:
78 nLang
= LANGUAGE_SYSTEM
;
87 LanguageType
MsLangId::getRealLanguage( LanguageType nLang
)
89 switch (simplifySystemLanguages( nLang
))
91 case LANGUAGE_SYSTEM
:
92 if (nConfiguredSystemLanguage
== LANGUAGE_SYSTEM
)
93 nLang
= getSystemLanguage();
95 nLang
= nConfiguredSystemLanguage
;
97 case LANGUAGE_HID_HUMAN_INTERFACE_DEVICE
:
98 if (nConfiguredSystemUILanguage
== LANGUAGE_SYSTEM
)
99 nLang
= getSystemUILanguage();
101 nLang
= nConfiguredSystemUILanguage
;
104 /* TODO: would this be useful here? */
105 //nLang = MsLangId::getReplacementForObsoleteLanguage( nLang);
108 if (nLang
== LANGUAGE_DONTKNOW
)
109 nLang
= LANGUAGE_ENGLISH_US
;
115 LanguageType
MsLangId::resolveSystemLanguageByScriptType( LanguageType nLang
, sal_Int16 nType
)
117 if (nLang
== LANGUAGE_NONE
)
120 nLang
= getRealLanguage(nLang
);
121 if (nType
!= ::com::sun::star::i18n::ScriptType::WEAK
&& getScriptType(nLang
) != nType
)
125 case ::com::sun::star::i18n::ScriptType::ASIAN
:
126 if (nConfiguredAsianFallback
== LANGUAGE_SYSTEM
)
127 nLang
= LANGUAGE_CHINESE_SIMPLIFIED
;
129 nLang
= nConfiguredAsianFallback
;
131 case ::com::sun::star::i18n::ScriptType::COMPLEX
:
132 if (nConfiguredComplexFallback
== LANGUAGE_SYSTEM
)
133 nLang
= LANGUAGE_HINDI
;
135 nLang
= nConfiguredComplexFallback
;
138 if (nConfiguredWesternFallback
== LANGUAGE_SYSTEM
)
139 nLang
= LANGUAGE_ENGLISH_US
;
141 nLang
= nConfiguredWesternFallback
;
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
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();
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
);
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));
196 return Conversion::lookupFallbackLocale( rLocale
);
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
:
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
:
236 bool MsLangId::isSimplifiedChinese( LanguageType nLang
)
238 return isChinese(nLang
) && !isTraditionalChinese(nLang
);
242 bool MsLangId::isSimplifiedChinese( const ::com::sun::star::lang::Locale
& rLocale
)
244 return rLocale
.Language
== "zh" && !isTraditionalChinese(rLocale
);
248 bool MsLangId::isTraditionalChinese( LanguageType nLang
)
253 case LANGUAGE_CHINESE_TRADITIONAL
:
254 case LANGUAGE_CHINESE_HONGKONG
:
255 case LANGUAGE_CHINESE_MACAU
:
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");
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
);
277 bool MsLangId::isKorean( LanguageType nLang
)
279 return MsLangId::getPrimaryLanguage(nLang
) == MsLangId::getPrimaryLanguage(LANGUAGE_KOREAN
);
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
:
299 bool MsLangId::isFamilyNameFirst( LanguageType nLang
)
301 return isCJK(nLang
) || nLang
== LANGUAGE_HUNGARIAN
;
305 bool MsLangId::hasForbiddenCharacters( LanguageType nLang
)
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
:
329 sal_Int16
MsLangId::getScriptType( LanguageType nLang
)
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
;
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
;
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
367 switch ( nLang
& LANGUAGE_MASK_PRIMARY
)
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
;
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
;
417 // Western (actually not necessarily Latin but also Cyrillic,
420 nScript
= ::com::sun::star::i18n::ScriptType::LATIN
;
429 bool MsLangId::isNonLatinWestern( LanguageType 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
:
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
:
455 if (getScriptType( nLang
) != com::sun::star::i18n::ScriptType::LATIN
)
457 LanguageTag
aLanguageTag( nLang
);
458 if (aLanguageTag
.hasScript())
459 return aLanguageTag
.getScript() != "Latn";
467 LanguageType
MsLangId::getReplacementForObsoleteLanguage( LanguageType nLang
, bool /*bUserInterfaceSelection*/ )
473 case LANGUAGE_OBSOLETE_USER_LATIN
:
474 nLang
= LANGUAGE_USER_LATIN_VATICAN
;
476 case LANGUAGE_OBSOLETE_USER_MAORI
:
477 nLang
= LANGUAGE_MAORI_NEW_ZEALAND
;
479 case LANGUAGE_OBSOLETE_USER_KINYARWANDA
:
480 nLang
= LANGUAGE_KINYARWANDA_RWANDA
;
482 case LANGUAGE_OBSOLETE_USER_UPPER_SORBIAN
:
483 nLang
= LANGUAGE_UPPER_SORBIAN_GERMANY
;
485 case LANGUAGE_OBSOLETE_USER_LOWER_SORBIAN
:
486 nLang
= LANGUAGE_LOWER_SORBIAN_GERMANY
;
488 case LANGUAGE_OBSOLETE_USER_OCCITAN
:
489 nLang
= LANGUAGE_OCCITAN_FRANCE
;
491 case LANGUAGE_OBSOLETE_USER_BRETON
:
492 nLang
= LANGUAGE_BRETON_FRANCE
;
494 case LANGUAGE_OBSOLETE_USER_KALAALLISUT
:
495 nLang
= LANGUAGE_KALAALLISUT_GREENLAND
;
497 case LANGUAGE_OBSOLETE_USER_LUXEMBOURGISH
:
498 nLang
= LANGUAGE_LUXEMBOURGISH_LUXEMBOURG
;
500 case LANGUAGE_OBSOLETE_USER_KABYLE
:
501 nLang
= LANGUAGE_TAMAZIGHT_LATIN_ALGERIA
;
503 case LANGUAGE_OBSOLETE_USER_CATALAN_VALENCIAN
:
504 nLang
= LANGUAGE_CATALAN_VALENCIAN
;
506 case LANGUAGE_OBSOLETE_USER_MALAGASY_PLATEAU
:
507 nLang
= LANGUAGE_MALAGASY_PLATEAU
;
509 case LANGUAGE_GAELIC_SCOTLAND_LEGACY
:
510 nLang
= LANGUAGE_GAELIC_SCOTLAND
;
512 case LANGUAGE_OBSOLETE_USER_TSWANA_BOTSWANA
:
513 nLang
= LANGUAGE_TSWANA_BOTSWANA
;
515 case LANGUAGE_OBSOLETE_USER_SERBIAN_LATIN_SERBIA
:
516 nLang
= LANGUAGE_SERBIAN_LATIN_SERBIA
;
518 case LANGUAGE_OBSOLETE_USER_SERBIAN_LATIN_MONTENEGRO
:
519 nLang
= LANGUAGE_SERBIAN_LATIN_MONTENEGRO
;
521 case LANGUAGE_OBSOLETE_USER_SERBIAN_CYRILLIC_SERBIA
:
522 nLang
= LANGUAGE_SERBIAN_CYRILLIC_SERBIA
;
524 case LANGUAGE_OBSOLETE_USER_SERBIAN_CYRILLIC_MONTENEGRO
:
525 nLang
= LANGUAGE_SERBIAN_CYRILLIC_MONTENEGRO
;
527 case LANGUAGE_OBSOLETE_USER_KURDISH_IRAQ
:
528 nLang
= LANGUAGE_KURDISH_ARABIC_IRAQ
;
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
;
539 // #i94435# A Spanish variant that differs only in collation details we
541 case LANGUAGE_SPANISH_DATED
:
542 nLang
= LANGUAGE_SPANISH_MODERN
;
548 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */