Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <sal/config.h>
21 : #include <rtl/ustring.hxx>
22 : #include <rtl/string.hxx>
23 : #include <com/sun/star/i18n/ScriptType.hpp>
24 :
25 : #include "i18nlangtag/mslangid.hxx"
26 :
27 :
28 : LanguageType MsLangId::nConfiguredSystemLanguage = LANGUAGE_SYSTEM;
29 : LanguageType MsLangId::nConfiguredSystemUILanguage = LANGUAGE_SYSTEM;
30 :
31 : LanguageType MsLangId::nConfiguredWesternFallback = LANGUAGE_SYSTEM;
32 : LanguageType MsLangId::nConfiguredAsianFallback = LANGUAGE_SYSTEM;
33 : LanguageType MsLangId::nConfiguredComplexFallback = LANGUAGE_SYSTEM;
34 :
35 : // static
36 196 : void MsLangId::setConfiguredSystemLanguage( LanguageType nLang )
37 : {
38 196 : nConfiguredSystemLanguage = nLang;
39 196 : }
40 :
41 :
42 : // static
43 83 : void MsLangId::setConfiguredSystemUILanguage( LanguageType nLang )
44 : {
45 83 : nConfiguredSystemUILanguage = nLang;
46 83 : }
47 :
48 : // static
49 249 : void MsLangId::setConfiguredWesternFallback( LanguageType nLang )
50 : {
51 249 : nConfiguredWesternFallback = nLang;
52 249 : }
53 :
54 : // static
55 0 : void MsLangId::setConfiguredAsianFallback( LanguageType nLang )
56 : {
57 0 : nConfiguredAsianFallback = nLang;
58 0 : }
59 :
60 : // static
61 0 : void MsLangId::setConfiguredComplexFallback( LanguageType nLang )
62 : {
63 0 : nConfiguredComplexFallback = nLang;
64 0 : }
65 :
66 : // static
67 1465597 : inline LanguageType MsLangId::simplifySystemLanguages( LanguageType nLang )
68 : {
69 1465597 : switch (nLang)
70 : {
71 : case LANGUAGE_PROCESS_OR_USER_DEFAULT :
72 : case LANGUAGE_SYSTEM_DEFAULT :
73 : case LANGUAGE_SYSTEM :
74 188367 : nLang = LANGUAGE_SYSTEM;
75 188367 : break;
76 : default:
77 : ; // nothing
78 : }
79 1465597 : return nLang;
80 : }
81 :
82 : // static
83 1465597 : LanguageType MsLangId::getRealLanguage( LanguageType nLang )
84 : {
85 1465597 : switch (simplifySystemLanguages( nLang))
86 : {
87 : case LANGUAGE_SYSTEM :
88 188367 : if (nConfiguredSystemLanguage == LANGUAGE_SYSTEM)
89 27 : nLang = getSystemLanguage();
90 : else
91 188340 : nLang = nConfiguredSystemLanguage;
92 188367 : break;
93 : case LANGUAGE_HID_HUMAN_INTERFACE_DEVICE :
94 0 : if (nConfiguredSystemUILanguage == LANGUAGE_SYSTEM)
95 0 : nLang = getSystemUILanguage();
96 : else
97 0 : nLang = nConfiguredSystemUILanguage;
98 0 : break;
99 : default:
100 : /* TODO: would this be useful here? */
101 : //nLang = MsLangId::getReplacementForObsoleteLanguage( nLang);
102 : ; // nothing
103 : }
104 1465597 : if (nLang == LANGUAGE_DONTKNOW)
105 480168 : nLang = LANGUAGE_ENGLISH_US;
106 1465597 : return nLang;
107 : }
108 :
109 :
110 : // static
111 42036 : LanguageType MsLangId::resolveSystemLanguageByScriptType( LanguageType nLang, sal_Int16 nType )
112 : {
113 42036 : if (nLang == LANGUAGE_NONE)
114 0 : return nLang;
115 :
116 42036 : nLang = getRealLanguage(nLang);
117 42036 : if (nType != ::com::sun::star::i18n::ScriptType::WEAK && getScriptType(nLang) != nType)
118 : {
119 28024 : switch(nType)
120 : {
121 : case ::com::sun::star::i18n::ScriptType::ASIAN:
122 14012 : if (nConfiguredAsianFallback == LANGUAGE_SYSTEM)
123 14012 : nLang = LANGUAGE_CHINESE_SIMPLIFIED;
124 : else
125 0 : nLang = nConfiguredAsianFallback;
126 14012 : break;
127 : case ::com::sun::star::i18n::ScriptType::COMPLEX:
128 14012 : if (nConfiguredComplexFallback == LANGUAGE_SYSTEM)
129 14012 : nLang = LANGUAGE_HINDI;
130 : else
131 0 : nLang = nConfiguredComplexFallback;
132 14012 : break;
133 : default:
134 0 : if (nConfiguredWesternFallback == LANGUAGE_SYSTEM)
135 0 : nLang = LANGUAGE_ENGLISH_US;
136 : else
137 0 : nLang = nConfiguredWesternFallback;
138 0 : break;
139 : }
140 : }
141 42036 : return nLang;
142 : }
143 :
144 : // static
145 1276852 : void MsLangId::Conversion::convertLanguageToLocale( LanguageType nLang,
146 : ::com::sun::star::lang::Locale & rLocale )
147 : {
148 1276852 : if (!rLocale.Variant.isEmpty())
149 0 : rLocale.Variant = OUString();
150 1276852 : convertLanguageToIsoNames( nLang, rLocale.Language, rLocale.Country);
151 : /* FIXME: this x-... is temporary until conversion will be moved up to
152 : * LanguageTag. Also handle the nasty "*" joker as privateuse. */
153 1276852 : if (rLocale.Language.startsWith( "x-") || (rLocale.Language == "*"))
154 : {
155 623 : rLocale.Variant = rLocale.Language;
156 623 : rLocale.Language = "qlt";
157 : }
158 1276852 : }
159 :
160 :
161 : // static
162 1276852 : ::com::sun::star::lang::Locale MsLangId::Conversion::convertLanguageToLocale(
163 : LanguageType nLang, bool bResolveSystem )
164 : {
165 1276852 : ::com::sun::star::lang::Locale aLocale;
166 1276852 : if (!bResolveSystem && simplifySystemLanguages( nLang) == LANGUAGE_SYSTEM)
167 : ; // nothing => empty locale
168 : else
169 : {
170 : // Still resolve LANGUAGE_DONTKNOW if resolving is not requested,
171 : // but not LANGUAGE_SYSTEM or others.
172 1276852 : if (bResolveSystem || nLang == LANGUAGE_DONTKNOW)
173 1276852 : nLang = MsLangId::getRealLanguage( nLang);
174 1276852 : convertLanguageToLocale( nLang, aLocale);
175 : }
176 1276852 : return aLocale;
177 : }
178 :
179 :
180 : // static
181 411448 : LanguageType MsLangId::Conversion::convertLocaleToLanguage(
182 : const ::com::sun::star::lang::Locale& rLocale )
183 : {
184 : // empty language => LANGUAGE_SYSTEM
185 411448 : if (rLocale.Language.isEmpty())
186 0 : return LANGUAGE_SYSTEM;
187 :
188 : /* FIXME: this x-... is temporary until conversion will be moved up to
189 : * LanguageTag. Also handle the nasty "*" joker as privateuse. */
190 411466 : LanguageType nRet = ((!rLocale.Variant.isEmpty() &&
191 32 : (rLocale.Variant.startsWithIgnoreAsciiCase( "x-") || (rLocale.Variant == "*"))) ?
192 7 : convertPrivateUseToLanguage( rLocale.Variant) :
193 411455 : convertIsoNamesToLanguage( rLocale.Language, rLocale.Country));
194 411448 : if (nRet == LANGUAGE_DONTKNOW)
195 8 : nRet = LANGUAGE_SYSTEM;
196 :
197 411448 : return nRet;
198 : }
199 :
200 :
201 : // static
202 38 : ::com::sun::star::lang::Locale MsLangId::Conversion::convertLanguageToLocaleWithFallback(
203 : LanguageType nLang )
204 : {
205 38 : return lookupFallbackLocale( MsLangId::getRealLanguage( nLang));
206 : }
207 :
208 :
209 : // static
210 372 : ::com::sun::star::lang::Locale MsLangId::getFallbackLocale(
211 : const ::com::sun::star::lang::Locale & rLocale )
212 : {
213 : // empty language => LANGUAGE_SYSTEM
214 372 : if (rLocale.Language.isEmpty())
215 38 : return Conversion::convertLanguageToLocaleWithFallback( LANGUAGE_SYSTEM);
216 :
217 334 : return Conversion::lookupFallbackLocale( rLocale);
218 : }
219 :
220 : // static
221 456827 : bool MsLangId::isRightToLeft( LanguageType nLang )
222 : {
223 456827 : switch( nLang & LANGUAGE_MASK_PRIMARY )
224 : {
225 : case LANGUAGE_ARABIC_SAUDI_ARABIA & LANGUAGE_MASK_PRIMARY :
226 : case LANGUAGE_HEBREW & LANGUAGE_MASK_PRIMARY :
227 : case LANGUAGE_YIDDISH & LANGUAGE_MASK_PRIMARY :
228 : case LANGUAGE_URDU & LANGUAGE_MASK_PRIMARY :
229 : case LANGUAGE_FARSI & LANGUAGE_MASK_PRIMARY :
230 : case LANGUAGE_KASHMIRI & LANGUAGE_MASK_PRIMARY :
231 : case LANGUAGE_SINDHI & LANGUAGE_MASK_PRIMARY :
232 : case LANGUAGE_UIGHUR_CHINA & LANGUAGE_MASK_PRIMARY :
233 : case LANGUAGE_USER_KYRGYZ_CHINA & LANGUAGE_MASK_PRIMARY :
234 : case LANGUAGE_USER_NKO & LANGUAGE_MASK_PRIMARY :
235 0 : return true;
236 :
237 : default:
238 456827 : break;
239 : }
240 456827 : return false;
241 : }
242 :
243 : // static
244 15720 : bool MsLangId::isSimplifiedChinese( LanguageType nLang )
245 : {
246 15720 : return isChinese(nLang) && !isTraditionalChinese(nLang);
247 : }
248 :
249 : // static
250 0 : bool MsLangId::isSimplifiedChinese( const ::com::sun::star::lang::Locale & rLocale )
251 : {
252 0 : return rLocale.Language == "zh" && !isTraditionalChinese(rLocale);
253 : }
254 :
255 : // static
256 203 : bool MsLangId::isTraditionalChinese( LanguageType nLang )
257 : {
258 203 : bool bRet = false;
259 203 : switch (nLang)
260 : {
261 : case LANGUAGE_CHINESE_TRADITIONAL:
262 : case LANGUAGE_CHINESE_HONGKONG:
263 : case LANGUAGE_CHINESE_MACAU:
264 0 : bRet = true;
265 : default:
266 203 : break;
267 : }
268 203 : return bRet;
269 : }
270 :
271 : // static
272 0 : bool MsLangId::isTraditionalChinese( const ::com::sun::star::lang::Locale & rLocale )
273 : {
274 0 : return rLocale.Language == "zh" && (rLocale.Country == "TW" || rLocale.Country == "HK" || rLocale.Country == "MO");
275 : }
276 :
277 : //static
278 15720 : bool MsLangId::isChinese( LanguageType nLang )
279 : {
280 15720 : return MsLangId::getPrimaryLanguage(nLang) == LANGUAGE_CHINESE;
281 : }
282 :
283 : //static
284 1494 : bool MsLangId::isKorean( LanguageType nLang )
285 : {
286 1494 : return MsLangId::getPrimaryLanguage(nLang) == LANGUAGE_KOREAN;
287 : }
288 :
289 : // static
290 316 : bool MsLangId::isCJK( LanguageType nLang )
291 : {
292 316 : switch (nLang & LANGUAGE_MASK_PRIMARY)
293 : {
294 : case LANGUAGE_CHINESE & LANGUAGE_MASK_PRIMARY:
295 : case LANGUAGE_JAPANESE & LANGUAGE_MASK_PRIMARY:
296 : case LANGUAGE_KOREAN & LANGUAGE_MASK_PRIMARY:
297 0 : return true;
298 : default:
299 316 : break;
300 : }
301 316 : return false;
302 : }
303 :
304 : // static
305 0 : bool MsLangId::isFamilyNameFirst( LanguageType nLang )
306 : {
307 0 : return isCJK(nLang) || nLang == LANGUAGE_HUNGARIAN;
308 : }
309 :
310 : // static
311 0 : bool MsLangId::hasForbiddenCharacters( LanguageType nLang )
312 : {
313 0 : return isCJK(nLang);
314 : }
315 :
316 :
317 : // static
318 0 : bool MsLangId::needsSequenceChecking( LanguageType nLang )
319 : {
320 0 : switch (nLang & LANGUAGE_MASK_PRIMARY)
321 : {
322 : case LANGUAGE_BURMESE & LANGUAGE_MASK_PRIMARY:
323 : case LANGUAGE_KHMER & LANGUAGE_MASK_PRIMARY:
324 : case LANGUAGE_LAO & LANGUAGE_MASK_PRIMARY:
325 : case LANGUAGE_THAI & LANGUAGE_MASK_PRIMARY:
326 0 : return true;
327 : default:
328 0 : break;
329 : }
330 0 : return false;
331 : }
332 :
333 :
334 : // static
335 1178540 : sal_Int16 MsLangId::getScriptType( LanguageType nLang )
336 : {
337 : sal_Int16 nScript;
338 1178540 : switch( nLang )
339 : {
340 : // CJK
341 : // all LANGUAGE_CHINESE_... are caught below
342 : case LANGUAGE_JAPANESE:
343 : case LANGUAGE_KOREAN:
344 : case LANGUAGE_KOREAN_JOHAB:
345 : case LANGUAGE_USER_KOREAN_NORTH:
346 0 : nScript = ::com::sun::star::i18n::ScriptType::ASIAN;
347 0 : break;
348 :
349 : // CTL
350 : // all LANGUAGE_ARABIC_... are caught below
351 : case LANGUAGE_AMHARIC_ETHIOPIA:
352 : case LANGUAGE_ASSAMESE:
353 : case LANGUAGE_BENGALI:
354 : case LANGUAGE_BENGALI_BANGLADESH:
355 : case LANGUAGE_BURMESE:
356 : case LANGUAGE_FARSI:
357 : case LANGUAGE_HEBREW:
358 : case LANGUAGE_YIDDISH:
359 : case LANGUAGE_USER_YIDDISH_US:
360 : case LANGUAGE_MARATHI:
361 : case LANGUAGE_PUNJABI:
362 : case LANGUAGE_GUJARATI:
363 : case LANGUAGE_HINDI:
364 : case LANGUAGE_KANNADA:
365 : case LANGUAGE_KASHMIRI:
366 : case LANGUAGE_KASHMIRI_INDIA:
367 : case LANGUAGE_KHMER:
368 : case LANGUAGE_LAO:
369 : case LANGUAGE_MALAYALAM:
370 : case LANGUAGE_MANIPURI:
371 : case LANGUAGE_MONGOLIAN_MONGOLIAN:
372 : case LANGUAGE_NEPALI:
373 : case LANGUAGE_NEPALI_INDIA:
374 : case LANGUAGE_ORIYA:
375 : case LANGUAGE_SANSKRIT:
376 : case LANGUAGE_SINDHI:
377 : case LANGUAGE_SINDHI_PAKISTAN:
378 : case LANGUAGE_SINHALESE_SRI_LANKA:
379 : case LANGUAGE_SYRIAC:
380 : case LANGUAGE_TAMIL:
381 : case LANGUAGE_TELUGU:
382 : case LANGUAGE_THAI:
383 : case LANGUAGE_TIBETAN:
384 : case LANGUAGE_DZONGKHA:
385 : case LANGUAGE_USER_TIBETAN_INDIA:
386 : case LANGUAGE_URDU:
387 : case LANGUAGE_URDU_PAKISTAN:
388 : case LANGUAGE_URDU_INDIA:
389 : case LANGUAGE_USER_KURDISH_IRAQ:
390 : case LANGUAGE_USER_KURDISH_IRAN:
391 : case LANGUAGE_DHIVEHI:
392 : case LANGUAGE_USER_BODO_INDIA:
393 : case LANGUAGE_USER_DOGRI_INDIA:
394 : case LANGUAGE_USER_MAITHILI_INDIA:
395 : case LANGUAGE_UIGHUR_CHINA:
396 : case LANGUAGE_USER_LIMBU:
397 : case LANGUAGE_USER_KYRGYZ_CHINA:
398 : case LANGUAGE_USER_NKO:
399 0 : nScript = ::com::sun::star::i18n::ScriptType::COMPLEX;
400 0 : break;
401 :
402 : // currently not knowing scripttype - defaulted to LATIN:
403 : /*
404 : #define LANGUAGE_ARMENIAN 0x042B
405 : #define LANGUAGE_INDONESIAN 0x0421
406 : #define LANGUAGE_KAZAKH 0x043F
407 : #define LANGUAGE_KONKANI 0x0457
408 : #define LANGUAGE_MACEDONIAN 0x042F
409 : #define LANGUAGE_TATAR 0x0444
410 : */
411 :
412 : default:
413 1178540 : switch ( nLang & LANGUAGE_MASK_PRIMARY )
414 : {
415 : // CJK catcher
416 : case LANGUAGE_CHINESE & LANGUAGE_MASK_PRIMARY:
417 714 : nScript = ::com::sun::star::i18n::ScriptType::ASIAN;
418 714 : break;
419 : // CTL catcher
420 : case LANGUAGE_ARABIC_SAUDI_ARABIA & LANGUAGE_MASK_PRIMARY:
421 0 : nScript = ::com::sun::star::i18n::ScriptType::COMPLEX;
422 0 : break;
423 : // Western (actually not necessarily Latin but also Cyrillic, for example)
424 : default:
425 1177826 : nScript = ::com::sun::star::i18n::ScriptType::LATIN;
426 : }
427 1178540 : break;
428 : }
429 1178540 : return nScript;
430 : }
431 :
432 :
433 : // static
434 264 : LanguageType MsLangId::getReplacementForObsoleteLanguage( LanguageType nLang, bool bUserInterfaceSelection )
435 : {
436 264 : switch (nLang)
437 : {
438 : default:
439 264 : break; // nothing
440 : case LANGUAGE_OBSOLETE_USER_LATIN:
441 0 : nLang = LANGUAGE_LATIN;
442 0 : break;
443 : case LANGUAGE_OBSOLETE_USER_MAORI:
444 0 : nLang = LANGUAGE_MAORI_NEW_ZEALAND;
445 0 : break;
446 : case LANGUAGE_OBSOLETE_USER_KINYARWANDA:
447 0 : nLang = LANGUAGE_KINYARWANDA_RWANDA;
448 0 : break;
449 : case LANGUAGE_OBSOLETE_USER_UPPER_SORBIAN:
450 0 : nLang = LANGUAGE_UPPER_SORBIAN_GERMANY;
451 0 : break;
452 : case LANGUAGE_OBSOLETE_USER_LOWER_SORBIAN:
453 0 : nLang = LANGUAGE_LOWER_SORBIAN_GERMANY;
454 0 : break;
455 : case LANGUAGE_OBSOLETE_USER_OCCITAN:
456 0 : nLang = LANGUAGE_OCCITAN_FRANCE;
457 0 : break;
458 : case LANGUAGE_OBSOLETE_USER_BRETON:
459 0 : nLang = LANGUAGE_BRETON_FRANCE;
460 0 : break;
461 : case LANGUAGE_OBSOLETE_USER_KALAALLISUT:
462 0 : nLang = LANGUAGE_KALAALLISUT_GREENLAND;
463 0 : break;
464 : case LANGUAGE_OBSOLETE_USER_LUXEMBOURGISH:
465 0 : nLang = LANGUAGE_LUXEMBOURGISH_LUXEMBOURG;
466 0 : break;
467 : case LANGUAGE_OBSOLETE_USER_KABYLE:
468 0 : nLang = LANGUAGE_TAMAZIGHT_LATIN;
469 0 : break;
470 :
471 : // The following are not strictly obsolete but should be mapped to a
472 : // replacement locale when encountered.
473 :
474 : // no_NO is an alias for nb_NO
475 : case LANGUAGE_NORWEGIAN:
476 0 : nLang = LANGUAGE_NORWEGIAN_BOKMAL;
477 0 : break;
478 :
479 : // #i94435# A Spanish variant that differs only in collation details we
480 : // do not support.
481 : case LANGUAGE_SPANISH_DATED:
482 0 : nLang = LANGUAGE_SPANISH_MODERN;
483 0 : break;
484 :
485 : // Do not use ca-XV for document content.
486 : /* TODO: remove in case we implement BCP47 language tags. */
487 : case LANGUAGE_USER_CATALAN_VALENCIAN:
488 0 : if (!bUserInterfaceSelection)
489 0 : nLang = LANGUAGE_CATALAN;
490 0 : break;
491 : }
492 264 : return nLang;
493 : }
494 :
495 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|