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