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_comphelper.hxx" 26 #include <comphelper/locale.hxx> 27 28 //_______________________________________________ 29 // includes 30 #include <rtl/ustrbuf.hxx> 31 32 //_______________________________________________ 33 // namespace 34 35 namespace comphelper{ 36 37 //----------------------------------------------- 38 const sal_Unicode Locale::SEPERATOR_LC = (sal_Unicode)'-'; 39 const sal_Unicode Locale::SEPERATOR_CV = (sal_Unicode)'_'; 40 const sal_Unicode Locale::SEPERATOR_CV_LINUX = (sal_Unicode)'.'; 41 42 //----------------------------------------------- 43 const Locale& Locale::X_DEFAULT() 44 { 45 static Locale aLocale( 46 ::rtl::OUString::createFromAscii("x"), 47 ::rtl::OUString::createFromAscii("default")); 48 return aLocale; 49 } 50 51 //----------------------------------------------- 52 const Locale& Locale::EN() 53 { 54 static Locale aLocale( 55 ::rtl::OUString::createFromAscii("en"), 56 ::rtl::OUString()); 57 return aLocale; 58 } 59 60 //----------------------------------------------- 61 const Locale& Locale::EN_US() 62 { 63 static Locale aLocale( 64 ::rtl::OUString::createFromAscii("en"), 65 ::rtl::OUString::createFromAscii("US")); 66 return aLocale; 67 } 68 69 //----------------------------------------------- 70 const Locale& Locale::DE_DE() 71 { 72 static Locale aLocale( 73 ::rtl::OUString::createFromAscii("de"), 74 ::rtl::OUString::createFromAscii("DE")); 75 return aLocale; 76 } 77 78 //----------------------------------------------- 79 const Locale& Locale::DE_CH() 80 { 81 static Locale aLocale( 82 ::rtl::OUString::createFromAscii("de"), 83 ::rtl::OUString::createFromAscii("CH")); 84 return aLocale; 85 } 86 87 //----------------------------------------------- 88 const Locale& Locale::DE_AT() 89 { 90 static Locale aLocale( 91 ::rtl::OUString::createFromAscii("de"), 92 ::rtl::OUString::createFromAscii("AT")); 93 return aLocale; 94 } 95 96 //----------------------------------------------- 97 const Locale& Locale::AR() 98 { 99 static Locale aLocale( 100 ::rtl::OUString::createFromAscii("ar"), 101 ::rtl::OUString()); 102 return aLocale; 103 } 104 105 //----------------------------------------------- 106 const Locale& Locale::CA() 107 { 108 static Locale aLocale( 109 ::rtl::OUString::createFromAscii("ca"), 110 ::rtl::OUString()); 111 return aLocale; 112 } 113 114 //----------------------------------------------- 115 const Locale& Locale::CS() 116 { 117 static Locale aLocale( 118 ::rtl::OUString::createFromAscii("cs"), 119 ::rtl::OUString()); 120 return aLocale; 121 } 122 123 //----------------------------------------------- 124 const Locale& Locale::DA() 125 { 126 static Locale aLocale( 127 ::rtl::OUString::createFromAscii("da"), 128 ::rtl::OUString()); 129 return aLocale; 130 } 131 132 //----------------------------------------------- 133 const Locale& Locale::EL() 134 { 135 static Locale aLocale( 136 ::rtl::OUString::createFromAscii("el"), 137 ::rtl::OUString()); 138 return aLocale; 139 } 140 141 //----------------------------------------------- 142 const Locale& Locale::ES() 143 { 144 static Locale aLocale( 145 ::rtl::OUString::createFromAscii("es"), 146 ::rtl::OUString()); 147 return aLocale; 148 } 149 150 //----------------------------------------------- 151 const Locale& Locale::FI() 152 { 153 static Locale aLocale( 154 ::rtl::OUString::createFromAscii("fi"), 155 ::rtl::OUString()); 156 return aLocale; 157 } 158 159 //----------------------------------------------- 160 const Locale& Locale::FR() 161 { 162 static Locale aLocale( 163 ::rtl::OUString::createFromAscii("fr"), 164 ::rtl::OUString()); 165 return aLocale; 166 } 167 168 //----------------------------------------------- 169 const Locale& Locale::HE() 170 { 171 static Locale aLocale( 172 ::rtl::OUString::createFromAscii("he"), 173 ::rtl::OUString()); 174 return aLocale; 175 } 176 177 //----------------------------------------------- 178 const Locale& Locale::HI_IN() 179 { 180 static Locale aLocale( 181 ::rtl::OUString::createFromAscii("hi"), 182 ::rtl::OUString::createFromAscii("IN")); 183 return aLocale; 184 } 185 186 //----------------------------------------------- 187 const Locale& Locale::HU() 188 { 189 static Locale aLocale( 190 ::rtl::OUString::createFromAscii("hu"), 191 ::rtl::OUString()); 192 return aLocale; 193 } 194 195 //----------------------------------------------- 196 const Locale& Locale::IT() 197 { 198 static Locale aLocale( 199 ::rtl::OUString::createFromAscii("it"), 200 ::rtl::OUString()); 201 return aLocale; 202 } 203 204 //----------------------------------------------- 205 const Locale& Locale::JA() 206 { 207 static Locale aLocale( 208 ::rtl::OUString::createFromAscii("ja"), 209 ::rtl::OUString()); 210 return aLocale; 211 } 212 213 //----------------------------------------------- 214 const Locale& Locale::KO() 215 { 216 static Locale aLocale( 217 ::rtl::OUString::createFromAscii("ko"), 218 ::rtl::OUString()); 219 return aLocale; 220 } 221 222 //----------------------------------------------- 223 const Locale& Locale::NL() 224 { 225 static Locale aLocale( 226 ::rtl::OUString::createFromAscii("nl"), 227 ::rtl::OUString()); 228 return aLocale; 229 } 230 231 //----------------------------------------------- 232 const Locale& Locale::PL() 233 { 234 static Locale aLocale( 235 ::rtl::OUString::createFromAscii("pl"), 236 ::rtl::OUString()); 237 return aLocale; 238 } 239 240 //----------------------------------------------- 241 const Locale& Locale::PT() 242 { 243 static Locale aLocale( 244 ::rtl::OUString::createFromAscii("pt"), 245 ::rtl::OUString()); 246 return aLocale; 247 } 248 249 //----------------------------------------------- 250 const Locale& Locale::PT_BR() 251 { 252 static Locale aLocale( 253 ::rtl::OUString::createFromAscii("pt"), 254 ::rtl::OUString::createFromAscii("BR")); 255 return aLocale; 256 } 257 258 //----------------------------------------------- 259 const Locale& Locale::RU() 260 { 261 static Locale aLocale( 262 ::rtl::OUString::createFromAscii("ru"), 263 ::rtl::OUString()); 264 return aLocale; 265 } 266 267 //----------------------------------------------- 268 const Locale& Locale::SK() 269 { 270 static Locale aLocale( 271 ::rtl::OUString::createFromAscii("sk"), 272 ::rtl::OUString()); 273 return aLocale; 274 } 275 276 //----------------------------------------------- 277 const Locale& Locale::SL() 278 { 279 static Locale aLocale( 280 ::rtl::OUString::createFromAscii("sl"), 281 ::rtl::OUString()); 282 return aLocale; 283 } 284 285 //----------------------------------------------- 286 const Locale& Locale::SV() 287 { 288 static Locale aLocale( 289 ::rtl::OUString::createFromAscii("sv"), 290 ::rtl::OUString()); 291 return aLocale; 292 } 293 294 //----------------------------------------------- 295 const Locale& Locale::TH() 296 { 297 static Locale aLocale( 298 ::rtl::OUString::createFromAscii("th"), 299 ::rtl::OUString()); 300 return aLocale; 301 } 302 303 //----------------------------------------------- 304 const Locale& Locale::TR() 305 { 306 static Locale aLocale( 307 ::rtl::OUString::createFromAscii("tr"), 308 ::rtl::OUString()); 309 return aLocale; 310 } 311 312 //----------------------------------------------- 313 const Locale& Locale::X_COMMENT() 314 { 315 static Locale aLocale( 316 ::rtl::OUString::createFromAscii("x"), 317 ::rtl::OUString::createFromAscii("comment")); 318 return aLocale; 319 } 320 321 //----------------------------------------------- 322 const Locale& Locale::X_TRANSLATE() 323 { 324 static Locale aLocale( 325 ::rtl::OUString::createFromAscii("x"), 326 ::rtl::OUString::createFromAscii("translate")); 327 return aLocale; 328 } 329 330 //----------------------------------------------- 331 const Locale& Locale::X_NOTRANSLATE() 332 { 333 static Locale aLocale( 334 ::rtl::OUString::createFromAscii("x"), 335 ::rtl::OUString::createFromAscii("notranslate")); 336 return aLocale; 337 } 338 339 //----------------------------------------------- 340 const Locale& Locale::ZH_CN() 341 { 342 static Locale aLocale( 343 ::rtl::OUString::createFromAscii("zh"), 344 ::rtl::OUString::createFromAscii("CN")); 345 return aLocale; 346 } 347 348 //----------------------------------------------- 349 const Locale& Locale::ZH_TW() 350 { 351 static Locale aLocale( 352 ::rtl::OUString::createFromAscii("zh"), 353 ::rtl::OUString::createFromAscii("TW")); 354 return aLocale; 355 } 356 357 //----------------------------------------------- 358 Locale::Locale(const ::rtl::OUString& sISO) 359 { 360 fromISO(sISO); 361 } 362 363 //----------------------------------------------- 364 Locale::Locale(const ::rtl::OUString& sLanguage, 365 const ::rtl::OUString& sCountry , 366 const ::rtl::OUString& sVariant ) 367 { 368 // Use set methods to check values too! 369 setLanguage(sLanguage); 370 setCountry (sCountry ); 371 setVariant (sVariant ); 372 } 373 374 //----------------------------------------------- 375 Locale::Locale() 376 { 377 // Initialize instance... otherwise users will 378 // maybe get exceptions if he e.g. copies this instance... 379 (*this) = X_NOTRANSLATE(); 380 } 381 382 //----------------------------------------------- 383 Locale::Locale(const Locale& aCopy) 384 { 385 (*this) = aCopy; // recycle assign operator 386 } 387 388 //----------------------------------------------- 389 ::rtl::OUString Locale::getLanguage() const 390 { 391 return m_sLanguage; 392 } 393 394 //----------------------------------------------- 395 ::rtl::OUString Locale::getCountry() const 396 { 397 return m_sCountry; 398 } 399 400 //----------------------------------------------- 401 ::rtl::OUString Locale::getVariant() const 402 { 403 return m_sVariant; 404 } 405 406 //----------------------------------------------- 407 void Locale::setLanguage(const ::rtl::OUString& sLanguage) 408 { 409 m_sLanguage = sLanguage; 410 } 411 412 //----------------------------------------------- 413 void Locale::setCountry(const ::rtl::OUString& sCountry) 414 { 415 m_sCountry = sCountry; 416 } 417 418 //----------------------------------------------- 419 void Locale::setVariant(const ::rtl::OUString& sVariant) 420 { 421 m_sVariant = sVariant; 422 } 423 424 //----------------------------------------------- 425 /* Attention: Use own interface methods to set the 426 different parts of this locale. Because they 427 check the incoming value and throw an exception 428 automatically... 429 */ 430 void Locale::fromISO(const ::rtl::OUString& sISO) 431 { 432 m_sLanguage = ::rtl::OUString(); 433 m_sCountry = ::rtl::OUString(); 434 m_sVariant = ::rtl::OUString(); 435 436 ::rtl::OUString sParser(sISO); 437 sParser.trim(); 438 439 sal_Int32 nStart = 0; 440 sal_Int32 nEnd = 0; 441 442 // extract language part 443 nEnd = sParser.indexOf(SEPERATOR_LC, nStart); 444 if (nEnd<0) 445 { 446 setLanguage(sParser); 447 return; 448 } 449 setLanguage(sParser.copy(nStart, nEnd-nStart)); 450 nStart = nEnd+1; 451 452 // extract country 453 nEnd = sParser.indexOf(SEPERATOR_CV, nStart); 454 if (nEnd<0) 455 nEnd = sParser.indexOf(SEPERATOR_CV_LINUX, nStart); 456 if (nEnd<0) 457 { 458 setCountry(sParser.copy(nStart, sParser.getLength()-nStart)); 459 return; 460 } 461 nStart = nEnd+1; 462 463 // extract variant 464 setVariant(sParser.copy(nStart, sParser.getLength()-nStart)); 465 } 466 467 //----------------------------------------------- 468 ::rtl::OUString Locale::toISO() const 469 { 470 ::rtl::OUStringBuffer sISO(64); 471 472 sISO.append(m_sLanguage); 473 if ( !m_sCountry.isEmpty() ) 474 { 475 sISO.append(SEPERATOR_LC); 476 sISO.append(m_sCountry); 477 478 if ( !m_sVariant.isEmpty() ) 479 { 480 sISO.append(SEPERATOR_CV); 481 sISO.append(m_sVariant); 482 } 483 } 484 485 return sISO.makeStringAndClear(); 486 } 487 488 //----------------------------------------------- 489 sal_Bool Locale::equals(const Locale& aComparable) const 490 { 491 return ( 492 m_sLanguage.equals(aComparable.m_sLanguage) && 493 m_sCountry.equals (aComparable.m_sCountry ) && 494 m_sVariant.equals (aComparable.m_sVariant ) 495 ); 496 } 497 498 //----------------------------------------------- 499 sal_Bool Locale::similar(const Locale& aComparable) const 500 { 501 return (m_sLanguage.equals(aComparable.m_sLanguage)); 502 } 503 504 //----------------------------------------------- 505 ::std::vector< ::rtl::OUString >::const_iterator Locale::getFallback(const ::std::vector< ::rtl::OUString >& lISOList , 506 const ::rtl::OUString& sReferenceISO) 507 { 508 Locale aReference(sReferenceISO); 509 510 // Note: The same language or "en"/"en-US" should be preferred as fallback. 511 // On the other side some localized variables don't use localization in real. 512 // Maybe they use a "fix" value only... marked as X-DEFAULT or X-NOTRANSLATE. 513 // At least it can be discussed, if any language is a valid fallback... 514 // But in case some office functionality depends on that (that means real functionality instead 515 // of pure UI descriptions) we should do anything, so it can work. 516 517 ::std::vector< ::rtl::OUString >::const_iterator pSimilar = lISOList.end(); 518 ::std::vector< ::rtl::OUString >::const_iterator pEN_US = lISOList.end(); 519 ::std::vector< ::rtl::OUString >::const_iterator pEN = lISOList.end(); 520 ::std::vector< ::rtl::OUString >::const_iterator pXDefault = lISOList.end(); 521 ::std::vector< ::rtl::OUString >::const_iterator pXNoTranslate = lISOList.end(); 522 ::std::vector< ::rtl::OUString >::const_iterator pAny = lISOList.end(); 523 524 ::std::vector< ::rtl::OUString >::const_iterator pIt; 525 for ( pIt = lISOList.begin(); 526 pIt != lISOList.end() ; 527 ++pIt ) 528 { 529 Locale aCheck(*pIt); 530 // found Locale, which match with 100% => return it 531 if (aCheck.equals(aReference)) 532 return pIt; 533 534 // found similar Locale => save it as possible fallback 535 if ( 536 (pSimilar == lISOList.end()) && 537 (aCheck.similar(aReference)) 538 ) 539 { 540 pSimilar = pIt; 541 } 542 else 543 // found en-US => save it as fallback 544 if ( 545 (pEN_US == lISOList.end()) && 546 (aCheck.equals(EN_US()) ) 547 ) 548 { 549 pEN_US = pIt; 550 } 551 else 552 // found en[-XX] => save it as fallback 553 if ( 554 (pEN == lISOList.end() ) && 555 (aCheck.similar(EN_US())) 556 ) 557 { 558 pEN = pIt; 559 } 560 else 561 // found an explicit default value(!) => save it as fallback 562 if ( 563 (pXDefault == lISOList.end()) && 564 (aCheck.equals(X_DEFAULT()) ) 565 ) 566 { 567 pXDefault = pIt; 568 } 569 else 570 // found an implicit default value(!) => save it as fallback 571 if ( 572 (pXNoTranslate == lISOList.end()) && 573 (aCheck.equals(X_NOTRANSLATE()) ) 574 ) 575 { 576 pXNoTranslate = pIt; 577 } 578 else 579 // save the first locale, which isn't an explicit fallback 580 // as "last possible fallback" 581 if (pAny == lISOList.end()) 582 pAny = pIt; 583 } 584 585 if (pSimilar != lISOList.end()) 586 return pSimilar; 587 588 if (pEN_US != lISOList.end()) 589 return pEN_US; 590 591 if (pEN != lISOList.end()) 592 return pEN; 593 594 if (pXDefault != lISOList.end()) 595 return pXDefault; 596 597 if (pXNoTranslate != lISOList.end()) 598 return pXNoTranslate; 599 600 if (pAny != lISOList.end()) 601 return pAny; 602 603 return lISOList.end(); 604 } 605 606 //----------------------------------------------- 607 sal_Bool Locale::getFallback(Locale& aLocale) 608 { 609 // a) 610 // this was our last fallback! 611 // break any further calls to this method... 612 if (aLocale.equals(X_NOTRANSLATE())) 613 return sal_False; 614 615 // b) 616 // switch from X_DEFAULT to X_NOTRANSLATE 617 // next time we will go to a) 618 if (aLocale.equals(X_DEFAULT())) 619 { 620 aLocale = X_NOTRANSLATE(); 621 return sal_True; 622 } 623 624 // c) 625 // switch from EN to X_DEFAULT 626 // next time we will go to b) 627 if (aLocale.equals(EN())) 628 { 629 aLocale = X_DEFAULT(); 630 return sal_True; 631 } 632 633 // d) remove country from incoming locale 634 // e.g. "de-DE" => "de" or "en-US" => "en"! 635 if ( !aLocale.getCountry().isEmpty()) 636 { 637 aLocale.setCountry(::rtl::OUString()); 638 return sal_True; 639 } 640 641 // e) "en-US" possible? 642 if (!aLocale.equals(EN_US())) 643 { 644 aLocale = EN_US(); 645 return sal_True; 646 } 647 648 // f) no more fallbacks 649 return sal_False; 650 } 651 652 //----------------------------------------------- 653 void Locale::operator=(const Locale& rCopy) 654 { 655 // Take over these values without checking... 656 // They were already checked if the copy was constructed 657 // and must be valid now! 658 m_sLanguage = rCopy.m_sLanguage; 659 m_sCountry = rCopy.m_sCountry; 660 m_sVariant = rCopy.m_sVariant; 661 } 662 663 //----------------------------------------------- 664 sal_Bool Locale::operator==(const Locale& aComparable) const 665 { 666 return equals(aComparable); 667 } 668 669 //----------------------------------------------- 670 sal_Bool Locale::operator!=(const Locale& aComparable) const 671 { 672 return !equals(aComparable); 673 } 674 675 } // namespace comphelper 676