| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_comphelper.hxx" |
| #include <comphelper/locale.hxx> |
| |
| //_______________________________________________ |
| // includes |
| #include <rtl/ustrbuf.hxx> |
| |
| //_______________________________________________ |
| // namespace |
| |
| namespace comphelper{ |
| |
| //----------------------------------------------- |
| const sal_Unicode Locale::SEPERATOR_LC = (sal_Unicode)'-'; |
| const sal_Unicode Locale::SEPERATOR_CV = (sal_Unicode)'_'; |
| const sal_Unicode Locale::SEPERATOR_CV_LINUX = (sal_Unicode)'.'; |
| |
| //----------------------------------------------- |
| const Locale& Locale::X_DEFAULT() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("x"), |
| ::rtl::OUString::createFromAscii("default")); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::EN() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("en"), |
| ::rtl::OUString()); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::EN_US() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("en"), |
| ::rtl::OUString::createFromAscii("US")); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::DE_DE() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("de"), |
| ::rtl::OUString::createFromAscii("DE")); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::DE_CH() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("de"), |
| ::rtl::OUString::createFromAscii("CH")); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::DE_AT() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("de"), |
| ::rtl::OUString::createFromAscii("AT")); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::AR() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("ar"), |
| ::rtl::OUString()); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::CA() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("ca"), |
| ::rtl::OUString()); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::CS() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("cs"), |
| ::rtl::OUString()); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::DA() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("da"), |
| ::rtl::OUString()); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::EL() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("el"), |
| ::rtl::OUString()); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::ES() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("es"), |
| ::rtl::OUString()); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::FI() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("fi"), |
| ::rtl::OUString()); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::FR() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("fr"), |
| ::rtl::OUString()); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::HE() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("he"), |
| ::rtl::OUString()); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::HI_IN() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("hi"), |
| ::rtl::OUString::createFromAscii("IN")); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::HU() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("hu"), |
| ::rtl::OUString()); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::IT() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("it"), |
| ::rtl::OUString()); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::JA() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("ja"), |
| ::rtl::OUString()); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::KO() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("ko"), |
| ::rtl::OUString()); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::NL() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("nl"), |
| ::rtl::OUString()); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::PL() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("pl"), |
| ::rtl::OUString()); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::PT() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("pt"), |
| ::rtl::OUString()); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::PT_BR() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("pt"), |
| ::rtl::OUString::createFromAscii("BR")); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::RU() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("ru"), |
| ::rtl::OUString()); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::SK() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("sk"), |
| ::rtl::OUString()); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::SL() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("sl"), |
| ::rtl::OUString()); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::SV() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("sv"), |
| ::rtl::OUString()); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::TH() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("th"), |
| ::rtl::OUString()); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::TR() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("tr"), |
| ::rtl::OUString()); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::X_COMMENT() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("x"), |
| ::rtl::OUString::createFromAscii("comment")); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::X_TRANSLATE() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("x"), |
| ::rtl::OUString::createFromAscii("translate")); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::X_NOTRANSLATE() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("x"), |
| ::rtl::OUString::createFromAscii("notranslate")); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::ZH_CN() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("zh"), |
| ::rtl::OUString::createFromAscii("CN")); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| const Locale& Locale::ZH_TW() |
| { |
| static Locale aLocale( |
| ::rtl::OUString::createFromAscii("zh"), |
| ::rtl::OUString::createFromAscii("TW")); |
| return aLocale; |
| } |
| |
| //----------------------------------------------- |
| Locale::Locale(const ::rtl::OUString& sISO) |
| throw(Locale::MalFormedLocaleException) |
| { |
| fromISO(sISO); |
| } |
| |
| //----------------------------------------------- |
| Locale::Locale(const ::rtl::OUString& sLanguage, |
| const ::rtl::OUString& sCountry , |
| const ::rtl::OUString& sVariant ) |
| { |
| // Use set methods to check values too! |
| setLanguage(sLanguage); |
| setCountry (sCountry ); |
| setVariant (sVariant ); |
| } |
| |
| //----------------------------------------------- |
| Locale::Locale() |
| { |
| // Initialize instance ... otherwhise user will |
| // may be get exceptions if he e.g. copy this instance ... |
| (*this) = X_NOTRANSLATE(); |
| } |
| |
| //----------------------------------------------- |
| Locale::Locale(const Locale& aCopy) |
| { |
| (*this) = aCopy; // recycle assign operator |
| } |
| |
| //----------------------------------------------- |
| ::rtl::OUString Locale::getLanguage() const |
| { |
| return m_sLanguage; |
| } |
| |
| //----------------------------------------------- |
| ::rtl::OUString Locale::getCountry() const |
| { |
| return m_sCountry; |
| } |
| |
| //----------------------------------------------- |
| ::rtl::OUString Locale::getVariant() const |
| { |
| return m_sVariant; |
| } |
| |
| //----------------------------------------------- |
| void Locale::setLanguage(const ::rtl::OUString& sLanguage) |
| { |
| m_sLanguage = sLanguage; |
| } |
| |
| //----------------------------------------------- |
| void Locale::setCountry(const ::rtl::OUString& sCountry) |
| { |
| m_sCountry = sCountry; |
| } |
| |
| //----------------------------------------------- |
| void Locale::setVariant(const ::rtl::OUString& sVariant) |
| { |
| m_sVariant = sVariant; |
| } |
| |
| //----------------------------------------------- |
| /* Attention: Use own interface methods to set the |
| different parts of this locale. Because the |
| check the incoming value and throw an exception |
| automaticly ... |
| */ |
| void Locale::fromISO(const ::rtl::OUString& sISO) |
| throw(Locale::MalFormedLocaleException) |
| { |
| m_sLanguage = ::rtl::OUString(); |
| m_sCountry = ::rtl::OUString(); |
| m_sVariant = ::rtl::OUString(); |
| |
| ::rtl::OUString sParser(sISO); |
| sParser.trim(); |
| |
| sal_Int32 nStart = 0; |
| sal_Int32 nEnd = 0; |
| |
| // extract language part |
| nEnd = sParser.indexOf(SEPERATOR_LC, nStart); |
| if (nEnd<0) |
| { |
| setLanguage(sParser); |
| return; |
| } |
| setLanguage(sParser.copy(nStart, nEnd-nStart)); |
| nStart = nEnd+1; |
| |
| // extract country |
| nEnd = sParser.indexOf(SEPERATOR_CV, nStart); |
| if (nEnd<0) |
| nEnd = sParser.indexOf(SEPERATOR_CV_LINUX, nStart); |
| if (nEnd<0) |
| { |
| setCountry(sParser.copy(nStart, sParser.getLength()-nStart)); |
| return; |
| } |
| nStart = nEnd+1; |
| |
| // extract variant |
| setVariant(sParser.copy(nStart, sParser.getLength()-nStart)); |
| } |
| |
| //----------------------------------------------- |
| ::rtl::OUString Locale::toISO() const |
| { |
| ::rtl::OUStringBuffer sISO(64); |
| |
| sISO.append(m_sLanguage); |
| if ( !m_sCountry.isEmpty() ) |
| { |
| sISO.append(SEPERATOR_LC); |
| sISO.append(m_sCountry); |
| |
| if ( !m_sVariant.isEmpty() ) |
| { |
| sISO.append(SEPERATOR_CV); |
| sISO.append(m_sVariant); |
| } |
| } |
| |
| return sISO.makeStringAndClear(); |
| } |
| |
| //----------------------------------------------- |
| sal_Bool Locale::equals(const Locale& aComparable) const |
| { |
| return ( |
| m_sLanguage.equals(aComparable.m_sLanguage) && |
| m_sCountry.equals (aComparable.m_sCountry ) && |
| m_sVariant.equals (aComparable.m_sVariant ) |
| ); |
| } |
| |
| //----------------------------------------------- |
| sal_Bool Locale::similar(const Locale& aComparable) const |
| { |
| return (m_sLanguage.equals(aComparable.m_sLanguage)); |
| } |
| |
| //----------------------------------------------- |
| ::std::vector< ::rtl::OUString >::const_iterator Locale::getFallback(const ::std::vector< ::rtl::OUString >& lISOList , |
| const ::rtl::OUString& sReferenceISO) |
| throw(Locale::MalFormedLocaleException) |
| { |
| Locale aReference(sReferenceISO); |
| |
| // Note: The same language or "en"/"en-US" should be preferred as fallback. |
| // On the other side some localized variables doesnt use localzation in real. |
| // May be the use a "fix" value only ... marked as X-DEFAULT or X-NOTRANSLATE. |
| // At least it can be discussed, if any language is a valid fallback ... |
| // But in case some office functionality depends on that (that means real functionality instead |
| // of pure UI descriptions) we should do anything, so it can work. |
| |
| ::std::vector< ::rtl::OUString >::const_iterator pSimilar = lISOList.end(); |
| ::std::vector< ::rtl::OUString >::const_iterator pEN_US = lISOList.end(); |
| ::std::vector< ::rtl::OUString >::const_iterator pEN = lISOList.end(); |
| ::std::vector< ::rtl::OUString >::const_iterator pXDefault = lISOList.end(); |
| ::std::vector< ::rtl::OUString >::const_iterator pXNoTranslate = lISOList.end(); |
| ::std::vector< ::rtl::OUString >::const_iterator pAny = lISOList.end(); |
| |
| ::std::vector< ::rtl::OUString >::const_iterator pIt; |
| for ( pIt = lISOList.begin(); |
| pIt != lISOList.end() ; |
| ++pIt ) |
| { |
| Locale aCheck(*pIt); |
| // found Locale, which match with 100% => return it |
| if (aCheck.equals(aReference)) |
| return pIt; |
| |
| // found similar Locale => safe it as possible fallback |
| if ( |
| (pSimilar == lISOList.end()) && |
| (aCheck.similar(aReference)) |
| ) |
| { |
| pSimilar = pIt; |
| } |
| else |
| // found en-US => safe it as fallback |
| if ( |
| (pEN_US == lISOList.end()) && |
| (aCheck.equals(EN_US()) ) |
| ) |
| { |
| pEN_US = pIt; |
| } |
| else |
| // found en[-XX] => safe it as fallback |
| if ( |
| (pEN == lISOList.end() ) && |
| (aCheck.similar(EN_US())) |
| ) |
| { |
| pEN = pIt; |
| } |
| else |
| // found an explicit default value(!) => safe it as fallback |
| if ( |
| (pXDefault == lISOList.end()) && |
| (aCheck.equals(X_DEFAULT()) ) |
| ) |
| { |
| pXDefault = pIt; |
| } |
| else |
| // found an implicit default value(!) => safe it as fallback |
| if ( |
| (pXNoTranslate == lISOList.end()) && |
| (aCheck.equals(X_NOTRANSLATE()) ) |
| ) |
| { |
| pXNoTranslate = pIt; |
| } |
| else |
| // safe the first locale, which isn't an explicit fallback |
| // as "last possible fallback" |
| if (pAny == lISOList.end()) |
| pAny = pIt; |
| } |
| |
| if (pSimilar != lISOList.end()) |
| return pSimilar; |
| |
| if (pEN_US != lISOList.end()) |
| return pEN_US; |
| |
| if (pEN != lISOList.end()) |
| return pEN; |
| |
| if (pXDefault != lISOList.end()) |
| return pXDefault; |
| |
| if (pXNoTranslate != lISOList.end()) |
| return pXNoTranslate; |
| |
| if (pAny != lISOList.end()) |
| return pAny; |
| |
| return lISOList.end(); |
| } |
| |
| //----------------------------------------------- |
| sal_Bool Locale::getFallback(Locale& aLocale) |
| { |
| // a) |
| // this was our last fallback! |
| // break any further calls to this method ... |
| if (aLocale.equals(X_NOTRANSLATE())) |
| return sal_False; |
| |
| // b) |
| // switch from X_DEFAULT to X_NOTRANSLATE |
| // next time we will go to a) |
| if (aLocale.equals(X_DEFAULT())) |
| { |
| aLocale = X_NOTRANSLATE(); |
| return sal_True; |
| } |
| |
| // c) |
| // switch from EN to X_DEFAULT |
| // next time we will go to b) |
| if (aLocale.equals(EN())) |
| { |
| aLocale = X_DEFAULT(); |
| return sal_True; |
| } |
| |
| // d) remove country from incoming locale |
| // e.g. "de-DE" => "de" or "en-US" => "en"! |
| if ( !aLocale.getCountry().isEmpty()) |
| { |
| aLocale.setCountry(::rtl::OUString()); |
| return sal_True; |
| } |
| |
| // e) "en-US" possible? |
| if (!aLocale.equals(EN_US())) |
| { |
| aLocale = EN_US(); |
| return sal_True; |
| } |
| |
| // f) no more fallbacks |
| return sal_False; |
| } |
| |
| //----------------------------------------------- |
| void Locale::operator=(const Locale& rCopy) |
| { |
| // Take over these values without checking ... |
| // They was already checked if the copy was constructed |
| // and must be valid now! |
| m_sLanguage = rCopy.m_sLanguage; |
| m_sCountry = rCopy.m_sCountry; |
| m_sVariant = rCopy.m_sVariant; |
| } |
| |
| //----------------------------------------------- |
| sal_Bool Locale::operator==(const Locale& aComparable) const |
| { |
| return equals(aComparable); |
| } |
| |
| //----------------------------------------------- |
| sal_Bool Locale::operator!=(const Locale& aComparable) const |
| { |
| return !equals(aComparable); |
| } |
| |
| } // namespace comphelper |
| |