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 throw(Locale::MalFormedLocaleException) 360 { 361 fromISO(sISO); 362 } 363 364 //----------------------------------------------- 365 Locale::Locale(const ::rtl::OUString& sLanguage, 366 const ::rtl::OUString& sCountry , 367 const ::rtl::OUString& sVariant ) 368 { 369 // Use set methods to check values too! 370 setLanguage(sLanguage); 371 setCountry (sCountry ); 372 setVariant (sVariant ); 373 } 374 375 //----------------------------------------------- 376 Locale::Locale() 377 { 378 // Initialize instance ... otherwhise user will 379 // may be get exceptions if he e.g. copy this instance ... 380 (*this) = X_NOTRANSLATE(); 381 } 382 383 //----------------------------------------------- 384 Locale::Locale(const Locale& aCopy) 385 { 386 (*this) = aCopy; // recycle assign operator 387 } 388 389 //----------------------------------------------- 390 ::rtl::OUString Locale::getLanguage() const 391 { 392 return m_sLanguage; 393 } 394 395 //----------------------------------------------- 396 ::rtl::OUString Locale::getCountry() const 397 { 398 return m_sCountry; 399 } 400 401 //----------------------------------------------- 402 ::rtl::OUString Locale::getVariant() const 403 { 404 return m_sVariant; 405 } 406 407 //----------------------------------------------- 408 void Locale::setLanguage(const ::rtl::OUString& sLanguage) 409 { 410 m_sLanguage = sLanguage; 411 } 412 413 //----------------------------------------------- 414 void Locale::setCountry(const ::rtl::OUString& sCountry) 415 { 416 m_sCountry = sCountry; 417 } 418 419 //----------------------------------------------- 420 void Locale::setVariant(const ::rtl::OUString& sVariant) 421 { 422 m_sVariant = sVariant; 423 } 424 425 //----------------------------------------------- 426 /* Attention: Use own interface methods to set the 427 different parts of this locale. Because the 428 check the incoming value and throw an exception 429 automaticly ... 430 */ 431 void Locale::fromISO(const ::rtl::OUString& sISO) 432 throw(Locale::MalFormedLocaleException) 433 { 434 m_sLanguage = ::rtl::OUString(); 435 m_sCountry = ::rtl::OUString(); 436 m_sVariant = ::rtl::OUString(); 437 438 ::rtl::OUString sParser(sISO); 439 sParser.trim(); 440 441 sal_Int32 nStart = 0; 442 sal_Int32 nEnd = 0; 443 444 // extract language part 445 nEnd = sParser.indexOf(SEPERATOR_LC, nStart); 446 if (nEnd<0) 447 { 448 setLanguage(sParser); 449 return; 450 } 451 setLanguage(sParser.copy(nStart, nEnd-nStart)); 452 nStart = nEnd+1; 453 454 // extract country 455 nEnd = sParser.indexOf(SEPERATOR_CV, nStart); 456 if (nEnd<0) 457 nEnd = sParser.indexOf(SEPERATOR_CV_LINUX, nStart); 458 if (nEnd<0) 459 { 460 setCountry(sParser.copy(nStart, sParser.getLength()-nStart)); 461 return; 462 } 463 nStart = nEnd+1; 464 465 // extract variant 466 setVariant(sParser.copy(nStart, sParser.getLength()-nStart)); 467 } 468 469 //----------------------------------------------- 470 ::rtl::OUString Locale::toISO() const 471 { 472 ::rtl::OUStringBuffer sISO(64); 473 474 sISO.append(m_sLanguage); 475 if (m_sCountry.getLength()) 476 { 477 sISO.append(SEPERATOR_LC); 478 sISO.append(m_sCountry); 479 480 if (m_sVariant.getLength()) 481 { 482 sISO.append(SEPERATOR_CV); 483 sISO.append(m_sVariant); 484 } 485 } 486 487 return sISO.makeStringAndClear(); 488 } 489 490 //----------------------------------------------- 491 sal_Bool Locale::equals(const Locale& aComparable) const 492 { 493 return ( 494 m_sLanguage.equals(aComparable.m_sLanguage) && 495 m_sCountry.equals (aComparable.m_sCountry ) && 496 m_sVariant.equals (aComparable.m_sVariant ) 497 ); 498 } 499 500 //----------------------------------------------- 501 sal_Bool Locale::similar(const Locale& aComparable) const 502 { 503 return (m_sLanguage.equals(aComparable.m_sLanguage)); 504 } 505 506 //----------------------------------------------- 507 ::std::vector< ::rtl::OUString >::const_iterator Locale::getFallback(const ::std::vector< ::rtl::OUString >& lISOList , 508 const ::rtl::OUString& sReferenceISO) 509 throw(Locale::MalFormedLocaleException) 510 { 511 Locale aReference(sReferenceISO); 512 513 // Note: The same language or "en"/"en-US" should be preferred as fallback. 514 // On the other side some localized variables doesnt use localzation in real. 515 // May be the use a "fix" value only ... marked as X-DEFAULT or X-NOTRANSLATE. 516 // At least it can be discussed, if any language is a valid fallback ... 517 // But in case some office functionality depends on that (that means real functionality instead 518 // of pure UI descriptions) we should do anything, so it can work. 519 520 ::std::vector< ::rtl::OUString >::const_iterator pSimilar = lISOList.end(); 521 ::std::vector< ::rtl::OUString >::const_iterator pEN_US = lISOList.end(); 522 ::std::vector< ::rtl::OUString >::const_iterator pEN = lISOList.end(); 523 ::std::vector< ::rtl::OUString >::const_iterator pXDefault = lISOList.end(); 524 ::std::vector< ::rtl::OUString >::const_iterator pXNoTranslate = lISOList.end(); 525 ::std::vector< ::rtl::OUString >::const_iterator pAny = lISOList.end(); 526 527 ::std::vector< ::rtl::OUString >::const_iterator pIt; 528 for ( pIt = lISOList.begin(); 529 pIt != lISOList.end() ; 530 ++pIt ) 531 { 532 Locale aCheck(*pIt); 533 // found Locale, which match with 100% => return it 534 if (aCheck.equals(aReference)) 535 return pIt; 536 537 // found similar Locale => safe it as possible fallback 538 if ( 539 (pSimilar == lISOList.end()) && 540 (aCheck.similar(aReference)) 541 ) 542 { 543 pSimilar = pIt; 544 } 545 else 546 // found en-US => safe it as fallback 547 if ( 548 (pEN_US == lISOList.end()) && 549 (aCheck.equals(EN_US()) ) 550 ) 551 { 552 pEN_US = pIt; 553 } 554 else 555 // found en[-XX] => safe it as fallback 556 if ( 557 (pEN == lISOList.end() ) && 558 (aCheck.similar(EN_US())) 559 ) 560 { 561 pEN = pIt; 562 } 563 else 564 // found an explicit default value(!) => safe it as fallback 565 if ( 566 (pXDefault == lISOList.end()) && 567 (aCheck.equals(X_DEFAULT()) ) 568 ) 569 { 570 pXDefault = pIt; 571 } 572 else 573 // found an implicit default value(!) => safe it as fallback 574 if ( 575 (pXNoTranslate == lISOList.end()) && 576 (aCheck.equals(X_NOTRANSLATE()) ) 577 ) 578 { 579 pXNoTranslate = pIt; 580 } 581 else 582 // safe the first locale, which isn't an explicit fallback 583 // as "last possible fallback" 584 if (pAny == lISOList.end()) 585 pAny = pIt; 586 } 587 588 if (pSimilar != lISOList.end()) 589 return pSimilar; 590 591 if (pEN_US != lISOList.end()) 592 return pEN_US; 593 594 if (pEN != lISOList.end()) 595 return pEN; 596 597 if (pXDefault != lISOList.end()) 598 return pXDefault; 599 600 if (pXNoTranslate != lISOList.end()) 601 return pXNoTranslate; 602 603 if (pAny != lISOList.end()) 604 return pAny; 605 606 return lISOList.end(); 607 } 608 609 //----------------------------------------------- 610 sal_Bool Locale::getFallback(Locale& aLocale) 611 { 612 // a) 613 // this was our last fallback! 614 // break any further calls to this method ... 615 if (aLocale.equals(X_NOTRANSLATE())) 616 return sal_False; 617 618 // b) 619 // switch from X_DEFAULT to X_NOTRANSLATE 620 // next time we will go to a) 621 if (aLocale.equals(X_DEFAULT())) 622 { 623 aLocale = X_NOTRANSLATE(); 624 return sal_True; 625 } 626 627 // c) 628 // switch from EN to X_DEFAULT 629 // next time we will go to b) 630 if (aLocale.equals(EN())) 631 { 632 aLocale = X_DEFAULT(); 633 return sal_True; 634 } 635 636 // d) remove country from incoming locale 637 // e.g. "de-DE" => "de" or "en-US" => "en"! 638 if (aLocale.getCountry().getLength()) 639 { 640 aLocale.setCountry(::rtl::OUString()); 641 return sal_True; 642 } 643 644 // e) "en-US" possible? 645 if (!aLocale.equals(EN_US())) 646 { 647 aLocale = EN_US(); 648 return sal_True; 649 } 650 651 // f) no more fallbacks 652 return sal_False; 653 } 654 655 //----------------------------------------------- 656 void Locale::operator=(const Locale& rCopy) 657 { 658 // Take over these values without checking ... 659 // They was already checked if the copy was constructed 660 // and must be valid now! 661 m_sLanguage = rCopy.m_sLanguage; 662 m_sCountry = rCopy.m_sCountry; 663 m_sVariant = rCopy.m_sVariant; 664 } 665 666 //----------------------------------------------- 667 sal_Bool Locale::operator==(const Locale& aComparable) const 668 { 669 return equals(aComparable); 670 } 671 672 //----------------------------------------------- 673 sal_Bool Locale::operator!=(const Locale& aComparable) const 674 { 675 return !equals(aComparable); 676 } 677 678 } // namespace comphelper 679 680