xref: /trunk/main/comphelper/source/misc/locale.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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