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 throw(Locale::MalFormedLocaleException)
360 {
361 fromISO(sISO);
362 }
363
364 //-----------------------------------------------
Locale(const::rtl::OUString & sLanguage,const::rtl::OUString & sCountry,const::rtl::OUString & sVariant)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 //-----------------------------------------------
Locale()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 //-----------------------------------------------
Locale(const Locale & aCopy)384 Locale::Locale(const Locale& aCopy)
385 {
386 (*this) = aCopy; // recycle assign operator
387 }
388
389 //-----------------------------------------------
getLanguage() const390 ::rtl::OUString Locale::getLanguage() const
391 {
392 return m_sLanguage;
393 }
394
395 //-----------------------------------------------
getCountry() const396 ::rtl::OUString Locale::getCountry() const
397 {
398 return m_sCountry;
399 }
400
401 //-----------------------------------------------
getVariant() const402 ::rtl::OUString Locale::getVariant() const
403 {
404 return m_sVariant;
405 }
406
407 //-----------------------------------------------
setLanguage(const::rtl::OUString & sLanguage)408 void Locale::setLanguage(const ::rtl::OUString& sLanguage)
409 {
410 m_sLanguage = sLanguage;
411 }
412
413 //-----------------------------------------------
setCountry(const::rtl::OUString & sCountry)414 void Locale::setCountry(const ::rtl::OUString& sCountry)
415 {
416 m_sCountry = sCountry;
417 }
418
419 //-----------------------------------------------
setVariant(const::rtl::OUString & sVariant)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 automatically ...
430 */
fromISO(const::rtl::OUString & sISO)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 //-----------------------------------------------
toISO() const470 ::rtl::OUString Locale::toISO() const
471 {
472 ::rtl::OUStringBuffer sISO(64);
473
474 sISO.append(m_sLanguage);
475 if ( !m_sCountry.isEmpty() )
476 {
477 sISO.append(SEPERATOR_LC);
478 sISO.append(m_sCountry);
479
480 if ( !m_sVariant.isEmpty() )
481 {
482 sISO.append(SEPERATOR_CV);
483 sISO.append(m_sVariant);
484 }
485 }
486
487 return sISO.makeStringAndClear();
488 }
489
490 //-----------------------------------------------
equals(const Locale & aComparable) const491 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 //-----------------------------------------------
similar(const Locale & aComparable) const501 sal_Bool Locale::similar(const Locale& aComparable) const
502 {
503 return (m_sLanguage.equals(aComparable.m_sLanguage));
504 }
505
506 //-----------------------------------------------
getFallback(const::std::vector<::rtl::OUString> & lISOList,const::rtl::OUString & sReferenceISO)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 doesn't 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 //-----------------------------------------------
getFallback(Locale & aLocale)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().isEmpty())
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 //-----------------------------------------------
operator =(const Locale & rCopy)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 //-----------------------------------------------
operator ==(const Locale & aComparable) const667 sal_Bool Locale::operator==(const Locale& aComparable) const
668 {
669 return equals(aComparable);
670 }
671
672 //-----------------------------------------------
operator !=(const Locale & aComparable) const673 sal_Bool Locale::operator!=(const Locale& aComparable) const
674 {
675 return !equals(aComparable);
676 }
677
678 } // namespace comphelper
679
680