xref: /aoo4110/main/comphelper/source/misc/locale.cxx (revision b1cdbd2c)
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    automaticly ...
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 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 //-----------------------------------------------
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