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 //-----------------------------------------------
X_DEFAULT()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 //-----------------------------------------------
EN()52 const Locale& Locale::EN()
53 {
54 static Locale aLocale(
55 ::rtl::OUString::createFromAscii("en"),
56 ::rtl::OUString());
57 return aLocale;
58 }
59
60 //-----------------------------------------------
EN_US()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 //-----------------------------------------------
DE_DE()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 //-----------------------------------------------
DE_CH()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 //-----------------------------------------------
DE_AT()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 //-----------------------------------------------
AR()97 const Locale& Locale::AR()
98 {
99 static Locale aLocale(
100 ::rtl::OUString::createFromAscii("ar"),
101 ::rtl::OUString());
102 return aLocale;
103 }
104
105 //-----------------------------------------------
CA()106 const Locale& Locale::CA()
107 {
108 static Locale aLocale(
109 ::rtl::OUString::createFromAscii("ca"),
110 ::rtl::OUString());
111 return aLocale;
112 }
113
114 //-----------------------------------------------
CS()115 const Locale& Locale::CS()
116 {
117 static Locale aLocale(
118 ::rtl::OUString::createFromAscii("cs"),
119 ::rtl::OUString());
120 return aLocale;
121 }
122
123 //-----------------------------------------------
DA()124 const Locale& Locale::DA()
125 {
126 static Locale aLocale(
127 ::rtl::OUString::createFromAscii("da"),
128 ::rtl::OUString());
129 return aLocale;
130 }
131
132 //-----------------------------------------------
EL()133 const Locale& Locale::EL()
134 {
135 static Locale aLocale(
136 ::rtl::OUString::createFromAscii("el"),
137 ::rtl::OUString());
138 return aLocale;
139 }
140
141 //-----------------------------------------------
ES()142 const Locale& Locale::ES()
143 {
144 static Locale aLocale(
145 ::rtl::OUString::createFromAscii("es"),
146 ::rtl::OUString());
147 return aLocale;
148 }
149
150 //-----------------------------------------------
FI()151 const Locale& Locale::FI()
152 {
153 static Locale aLocale(
154 ::rtl::OUString::createFromAscii("fi"),
155 ::rtl::OUString());
156 return aLocale;
157 }
158
159 //-----------------------------------------------
FR()160 const Locale& Locale::FR()
161 {
162 static Locale aLocale(
163 ::rtl::OUString::createFromAscii("fr"),
164 ::rtl::OUString());
165 return aLocale;
166 }
167
168 //-----------------------------------------------
HE()169 const Locale& Locale::HE()
170 {
171 static Locale aLocale(
172 ::rtl::OUString::createFromAscii("he"),
173 ::rtl::OUString());
174 return aLocale;
175 }
176
177 //-----------------------------------------------
HI_IN()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 //-----------------------------------------------
HU()187 const Locale& Locale::HU()
188 {
189 static Locale aLocale(
190 ::rtl::OUString::createFromAscii("hu"),
191 ::rtl::OUString());
192 return aLocale;
193 }
194
195 //-----------------------------------------------
IT()196 const Locale& Locale::IT()
197 {
198 static Locale aLocale(
199 ::rtl::OUString::createFromAscii("it"),
200 ::rtl::OUString());
201 return aLocale;
202 }
203
204 //-----------------------------------------------
JA()205 const Locale& Locale::JA()
206 {
207 static Locale aLocale(
208 ::rtl::OUString::createFromAscii("ja"),
209 ::rtl::OUString());
210 return aLocale;
211 }
212
213 //-----------------------------------------------
KO()214 const Locale& Locale::KO()
215 {
216 static Locale aLocale(
217 ::rtl::OUString::createFromAscii("ko"),
218 ::rtl::OUString());
219 return aLocale;
220 }
221
222 //-----------------------------------------------
NL()223 const Locale& Locale::NL()
224 {
225 static Locale aLocale(
226 ::rtl::OUString::createFromAscii("nl"),
227 ::rtl::OUString());
228 return aLocale;
229 }
230
231 //-----------------------------------------------
PL()232 const Locale& Locale::PL()
233 {
234 static Locale aLocale(
235 ::rtl::OUString::createFromAscii("pl"),
236 ::rtl::OUString());
237 return aLocale;
238 }
239
240 //-----------------------------------------------
PT()241 const Locale& Locale::PT()
242 {
243 static Locale aLocale(
244 ::rtl::OUString::createFromAscii("pt"),
245 ::rtl::OUString());
246 return aLocale;
247 }
248
249 //-----------------------------------------------
PT_BR()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 //-----------------------------------------------
RU()259 const Locale& Locale::RU()
260 {
261 static Locale aLocale(
262 ::rtl::OUString::createFromAscii("ru"),
263 ::rtl::OUString());
264 return aLocale;
265 }
266
267 //-----------------------------------------------
SK()268 const Locale& Locale::SK()
269 {
270 static Locale aLocale(
271 ::rtl::OUString::createFromAscii("sk"),
272 ::rtl::OUString());
273 return aLocale;
274 }
275
276 //-----------------------------------------------
SL()277 const Locale& Locale::SL()
278 {
279 static Locale aLocale(
280 ::rtl::OUString::createFromAscii("sl"),
281 ::rtl::OUString());
282 return aLocale;
283 }
284
285 //-----------------------------------------------
SV()286 const Locale& Locale::SV()
287 {
288 static Locale aLocale(
289 ::rtl::OUString::createFromAscii("sv"),
290 ::rtl::OUString());
291 return aLocale;
292 }
293
294 //-----------------------------------------------
TH()295 const Locale& Locale::TH()
296 {
297 static Locale aLocale(
298 ::rtl::OUString::createFromAscii("th"),
299 ::rtl::OUString());
300 return aLocale;
301 }
302
303 //-----------------------------------------------
TR()304 const Locale& Locale::TR()
305 {
306 static Locale aLocale(
307 ::rtl::OUString::createFromAscii("tr"),
308 ::rtl::OUString());
309 return aLocale;
310 }
311
312 //-----------------------------------------------
X_COMMENT()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 //-----------------------------------------------
X_TRANSLATE()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 //-----------------------------------------------
X_NOTRANSLATE()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 //-----------------------------------------------
ZH_CN()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 //-----------------------------------------------
ZH_TW()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 //-----------------------------------------------
Locale(const::rtl::OUString & sISO)358 Locale::Locale(const ::rtl::OUString& sISO)
359 {
360 fromISO(sISO);
361 }
362
363 //-----------------------------------------------
Locale(const::rtl::OUString & sLanguage,const::rtl::OUString & sCountry,const::rtl::OUString & sVariant)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 //-----------------------------------------------
Locale()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 //-----------------------------------------------
Locale(const Locale & aCopy)383 Locale::Locale(const Locale& aCopy)
384 {
385 (*this) = aCopy; // recycle assign operator
386 }
387
388 //-----------------------------------------------
getLanguage() const389 ::rtl::OUString Locale::getLanguage() const
390 {
391 return m_sLanguage;
392 }
393
394 //-----------------------------------------------
getCountry() const395 ::rtl::OUString Locale::getCountry() const
396 {
397 return m_sCountry;
398 }
399
400 //-----------------------------------------------
getVariant() const401 ::rtl::OUString Locale::getVariant() const
402 {
403 return m_sVariant;
404 }
405
406 //-----------------------------------------------
setLanguage(const::rtl::OUString & sLanguage)407 void Locale::setLanguage(const ::rtl::OUString& sLanguage)
408 {
409 m_sLanguage = sLanguage;
410 }
411
412 //-----------------------------------------------
setCountry(const::rtl::OUString & sCountry)413 void Locale::setCountry(const ::rtl::OUString& sCountry)
414 {
415 m_sCountry = sCountry;
416 }
417
418 //-----------------------------------------------
setVariant(const::rtl::OUString & sVariant)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 */
fromISO(const::rtl::OUString & sISO)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 //-----------------------------------------------
toISO() const468 ::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 //-----------------------------------------------
equals(const Locale & aComparable) const489 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 //-----------------------------------------------
similar(const Locale & aComparable) const499 sal_Bool Locale::similar(const Locale& aComparable) const
500 {
501 return (m_sLanguage.equals(aComparable.m_sLanguage));
502 }
503
504 //-----------------------------------------------
getFallback(const::std::vector<::rtl::OUString> & lISOList,const::rtl::OUString & sReferenceISO)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 //-----------------------------------------------
getFallback(Locale & aLocale)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 //-----------------------------------------------
operator =(const Locale & rCopy)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 //-----------------------------------------------
operator ==(const Locale & aComparable) const664 sal_Bool Locale::operator==(const Locale& aComparable) const
665 {
666 return equals(aComparable);
667 }
668
669 //-----------------------------------------------
operator !=(const Locale & aComparable) const670 sal_Bool Locale::operator!=(const Locale& aComparable) const
671 {
672 return !equals(aComparable);
673 }
674
675 } // namespace comphelper
676