src/hbcore/i18n/hblocaleutil.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 04 Oct 2010 00:38:12 +0300
changeset 30 80e4d18b72f5
parent 23 e6ad4ef83b23
permissions -rw-r--r--
Revision: 201037 Kit: 201039

/****************************************************************************
**
** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (developer.feedback@nokia.com)
**
** This file is part of the HbCore module of the UI Extensions for Mobile.
**
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at developer.feedback@nokia.com.
**
****************************************************************************/

#include <QFile>
#include <QLocale>
#include <QTimer>
#include <QHash>
#include <QHashIterator>
#include <QTextStream>
#include <QTranslator>
#include <QTextCodec>
#include <QCoreApplication>
#include <QStringList>

#if defined(Q_OS_SYMBIAN)
#include <e32lang.h>
#include <e32property.h>
#include <centralrepository.h> 
#include <hal.h>
#include <syslangutil.h>
#include <CommonEngineDomainCRKeys.h> //Ui language
#endif // Q_OS_SYMBIAN

#include <hbglobal.h>
#include <hblocaleutil.h>

#if defined(Q_OS_SYMBIAN)
#define LANGUAGE_LIST_FILE "/resource/hbi18n/translations/language_list.txt"
#define LANGUAGE_MAPPINGS_FILE "/resource/hbi18n/translations/locale_mappings.txt"
#define LANGUAGE_ID_PREFIX "txt_language"
#define LANGUAGE_TRANSLATOR_PATH "/resource/hbi18n/translations/languages"

#define REGION_LIST_FILE "z:/resource/bootdata/regions.txt"
#define REGION_ID_PREFIX "txt_region"
#define REGION_TRANSLATOR_PATH "/resource/hbi18n/translations/regions"
#define REGION_DLL_PREFIX "elocl_reg."

#define COLLATION_LIST_FILE "z:/resource/bootdata/collations.txt"
#define COLLATION_ID_PREFIX "txt_collation"
#define COLLATION_TRANSLATOR_PATH "/resource/hbi18n/translations/collations"
#define COLLATION_DLL_PREFIX "elocl_col."
#define COLLATION_DLL_PREFIX_POSITION 3
#endif // Q_OS_SYMBIAN

/*!
    @beta
    @hbcore
    \class HbLocaleUtil
    \brief The HbLocaleUtil class supports querying the supported languages, regions and collations, and activating them.
     
    With HbLocaleUtil, you can query the supported languages, regions and 
    collations from the device, and the ones currently set in the device. You 
    can then use this data to activate the language, region and collation in the 
    device; either individually, or as a set determined by the specified 
    language.
    
    HbLocaleUtil returns the data from the device as identifiers.
    The language and collation identifiers typically correspond to two-letter ISO 639 language codes. 
    However, some languages and collations use a combination of an ISO 639 language code 
    and an ISO 3166 country code which are separated by the underscore character. 
    Region identifiers always correspond to a two-letter ISO 3166 country code.
    
    HbLocaleUtil also provides functions for converting language, region and 
    collation identifiers to their localized names. 
    
    Example:
    \snippet{unittest_hblocaleutil/unittest_hblocaleutil.cpp,1}
    
    
    \sa HbStringUtil, HbExtendedLocale
    
*/

#if defined(Q_OS_SYMBIAN)

struct HbLocaleMapping
{
    int symLangValue;
    QString languageDllId;
    QString collationDllId;
    QString regionDllId;
    QString langName;
    QString regName;
    QString collName;
};

QList<HbLocaleMapping> mappingList;
QList<int> regions;
QStringList availRegions;
QHash<QString, QString> locRegionNames;
QList<int> collations;
QStringList availCollations;
QHash<QString, QString> locCollationNames;

/*!
    \relates HbLocaleUtil
    
    Reads language, region and collation mappings.
*/
void readMappings()
{
    QString path = "c:";
    path += QString(LANGUAGE_MAPPINGS_FILE);
    QFile* file = new QFile(path);
    if (!file->exists() ) {
        path = "z:";
        path += QString(LANGUAGE_MAPPINGS_FILE);
        delete file;
        file = new QFile(path);
    }
    if (!file->open(QIODevice::ReadOnly | QIODevice::Text)) {
        delete file;
        return;
    }
    QTextStream in(file);
    while (!in.atEnd()) {
        QString line = in.readLine(256);
        if (!line.isEmpty()) {
            QStringList list = line.split(',', QString::SkipEmptyParts);
            if (list.count() < 7) {
                continue;
            }
            QString strCode = list[0];
            QString strLang = list[1];
            QString strRegion = list[2];
            QString strCollation = list[3];
            QString lanName = list[4]; //en_GB
            QString region = list[5]; //en_GB
            QString collation = list[6]; //en_GB
            
            bool ok;
            int code = strCode.toUInt(&ok);
            if (!ok) {
                continue;
            }
            
            HbLocaleMapping map;
            map.symLangValue = code;
            map.languageDllId = strLang;
            map.collationDllId = strCollation;
            map.regionDllId = strRegion;
            map.langName = lanName;
            map.regName = region;
            map.collName = collation;
            mappingList.append(map);
        }
    }
    delete file;
    return;
}
#endif // Q_OS_SYMBIAN

#if defined(Q_OS_SYMBIAN)

/*!
    \relates HbLocaleUtil
    
    Changes the system UI language.
          
    \param dllExtension The extension of the locale DLL.
    
    \return True if successful, otherwise false.
    
*/
bool setLocale( const QString &dllExtension )
{
    TExtendedLocale dummy;
    dummy.LoadSystemSettings();
    QString name = QString( "elocl_lan." ).append( dllExtension );
    TPtrC nameptr(name.utf16());
    
    TInt err = dummy.LoadLocaleAspect( nameptr );
    if( err != KErrNone )
        return false;
    dummy.SaveSystemSettings();
    // cause localeprivate update on next qlocale object( glp->m_language_id = 0 )
    QSystemLocale dummy2;
    return true;
}
#endif //Q_OS_SYMBIAN

/*!

    Returns the identifier of the current UI language. 
    Identifier is typically two-letter ISO 639 code, like "en" for universal english, 
    but for some languages such United States english it is combination of an ISO 639 code and an ISO 3166 code ("en_US")
    
    \attention Only fully implemented on the Symbian platform. For other 
    platforms, always returns an empty QString.
    
    \sa supportedLanguages(), localisedLanguageName(), changeLanguage()

*/ 
QString HbLocaleUtil::currentLanguage()
{
#if defined(Q_OS_SYMBIAN)
    TLanguage l = User::Language();
    
    if(mappingList.isEmpty()) {
        readMappings();
    }
    
    for (int i = 0; i < mappingList.count(); ++i) {
        HbLocaleMapping mapping = mappingList.at(i);
        if (mapping.symLangValue == l) {
            return mapping.langName;
        }
    }
#endif
   return QString();
}

/*!
    
    Returns the identifiers of the languages supported on the device. The 
    language identifier can be either a two-letter ISO 639 language code, or a 
    combination of an ISO 639 language code and an ISO 3166 country code. For 
    example, for UK English, this returns "en", and for US English, this returns 
    "en_US".
    
    \attention Only fully implemented on the Symbian platform. For other 
    platforms, always returns an empty QStringList.
    
    \sa localisedLanguageName(), currentLanguage(), changeLanguage(), changeLocale()
    
*/
QStringList HbLocaleUtil::supportedLanguages()
{
#if defined(Q_OS_SYMBIAN)   
    QStringList languages; 
    CArrayFixFlat<TInt>* systemEpocLanguageCodes = 0;
    TInt error = SysLangUtil::GetInstalledLanguages( systemEpocLanguageCodes );
    if ( error != KErrNone ) {
        delete systemEpocLanguageCodes;
        return languages;
    }
    
    if(mappingList.isEmpty()) {
        readMappings();
    }
    
    for (int i = 0; i < systemEpocLanguageCodes->Count(); ++i) {
        int code = systemEpocLanguageCodes->At(i);
        for (int j = 0; j < mappingList.count(); ++j) {
            HbLocaleMapping map = mappingList.at(j);
            if (map.symLangValue == code) {
                languages.append(map.langName);
                break;
            }
        }
    }
    
    delete systemEpocLanguageCodes;
    return languages;
#else 
    return QStringList();
#endif
}

/*!
    
    Returns the localised language name for the specified language identifier. 
    If the translation fails, returns an empty QString.
    
    \param language The two- or five-letter language identifier that correspond to an identifier returned by supportedLanguages()
    
    \attention Only fully implemented on the Symbian platform. For other 
    platforms, always returns an empty QString.
    
    \sa changeLanguage(), currentLanguage()
 
*/ 
QString HbLocaleUtil::localisedLanguageName( const QString &language )
{
#if defined(Q_OS_SYMBIAN)   
    QTranslator translator;
    QString path = "c:";
    path += QString(LANGUAGE_TRANSLATOR_PATH);
    if (!translator.load(path)) {
        path = "z:";
        path += QString(LANGUAGE_TRANSLATOR_PATH);
        if (!translator.load(path)) {
            return QString("");
        } 
    } 
    
    QCoreApplication::installTranslator(&translator);
    QString languageName = QString(LANGUAGE_ID_PREFIX);
    languageName += '_';
    languageName += language;
    QString translated = hbTrId(languageName.toAscii().constData());  
    if (translated == languageName) {
        return QString("");
    }
    return translated;
#else 
    Q_UNUSED(language); 
    return QString();
#endif
}

/*!

    Changes the system language to the one specified in \a language.
  
    \param language The language identifier. This must correspond to an 
    identifier returned by supportedLanguages().
    
    \return True if successful, otherwise false.
    
    \attention Only fully implemented on the Symbian platform. For other 
    platforms, always returns false.
    
    \sa localisedLanguageName(), currentLanguage()
    
*/ 
bool HbLocaleUtil::changeLanguage( const QString &language )
{
#if defined(Q_OS_SYMBIAN)
    if(mappingList.isEmpty()) {
        readMappings();
    }
    
    int lanCode = -1;
    QString dllExt = "";
    for (int i = 0;  i < mappingList.count(); ++i) {
        HbLocaleMapping map = mappingList.at(i);
        if (map.langName == language) {
            lanCode = map.symLangValue;
            dllExt = map.languageDllId;
            break;
        }
    }
    
    if (lanCode == -1) {
        return false;
    }
    
    CRepository* commonEngineRepository = 0;
    TRAPD( err1, commonEngineRepository = CRepository::NewL( KCRUidCommonEngineKeys ) );    
    if ( err1 != KErrNone ) { 
        return false;
    }
    
    if (!setLocale(dllExt)) {
        delete commonEngineRepository;
        return false;
    }
        
    // Never set Language code 0 to HAL
    if ( language !=0 ) {
        if ( HAL::Set( HAL::ELanguageIndex, lanCode ) != KErrNone ) {
            delete commonEngineRepository;
            return false;
        }
    }
    if ( commonEngineRepository->Set( KGSDisplayTxtLang, lanCode ) != KErrNone ) {
        delete commonEngineRepository;
        return false;
    }
    delete commonEngineRepository;
    return true;

#else
    Q_UNUSED(language);
    return false;
#endif
}

#if defined(Q_OS_SYMBIAN)  
/*!
    \brief reads the regions.txt file and reads the list of symbian region codes 
*/
void readRegions()
{
    QFile* file = new QFile(REGION_LIST_FILE);
    if (!file->exists() ) 
    {
        delete file;
        return;
    }
    if (!file->open(QIODevice::ReadOnly | QIODevice::Text))
    {
        delete file;
        return;
    } 
    QTextStream in(file);
    while (!in.atEnd())
    {
        QString line = in.readLine(256);
        if (!line.isEmpty())
        {
            int regCode = line.toUInt();
            regions.append(regCode);
        }
    }
    return;
}
#endif

/*!
    
    Returns the identifiers of regions supported on the device. The region 
    identifier is a two-letter ISO 3166 code, for example, "GB" for United 
    Kingdom.
    
    \attention Only fully implemented on the Symbian platform. For other 
    platforms, always returns an empty QStringList.
    
    \sa localisedRegionName(), currentRegion(), changeRegion()

*/
QStringList HbLocaleUtil::supportedRegions()
{
#if defined(Q_OS_SYMBIAN)
    if(!availRegions.isEmpty())
    {
        return availRegions;
    }

    if(regions.isEmpty())
    {
        readRegions();
    }
    
    if(mappingList.isEmpty())
    {
        readMappings();
    }
    int regCount = regions.count();
    for(int i = 0; i < regCount; i++)
    {
        int region = regions.at(i);
        int count = mappingList.count();
        for (int j = 0; j < count; j++)
        {
            HbLocaleMapping mapping = mappingList.at(j);
            QString regCode = mapping.regionDllId;
            if(region == regCode.toUInt())
            {
                availRegions.append(mapping.regName);
                break;
            }
        }
    }
    return availRegions;
#else
    return QStringList();
#endif
}

/*!

    Returns the localised region name for the given two-letter region 
    identifier. If the translation fails, returns an empty String. ###QString?
    
    \param region The region identifier that correspond to an identifier 
    returned by supportedRegions()
    
    \attention Only fully implemented on the Symbian platform. For other 
    platforms, always returns an empty QString.
    
    \sa currentRegion(), changeRegion()
  
*/ 
QString HbLocaleUtil::localisedRegionName( const QString &region ) 
{
#if defined(Q_OS_SYMBIAN)       
    if(locRegionNames.isEmpty())
    {
        QTranslator translator;
        QString path = "c:";
        path += QString(REGION_TRANSLATOR_PATH);
        if (!translator.load(path)) {
            path = "z:";
            path += QString(REGION_TRANSLATOR_PATH);
            if (!translator.load(path)) {
                return QString("");
            } 
        } 

        QCoreApplication::installTranslator(&translator);
            
        if(mappingList.isEmpty()) 
        {
            readMappings();
        }
        int cnt = mappingList.count();
        for(int i = 0 ; i < cnt; i++ )
        {
            HbLocaleMapping map = mappingList.at(i);
            QString regionName = QString(REGION_ID_PREFIX);
            regionName += '_';
            regionName += map.regName;
            QString locRegName = hbTrId(regionName.toAscii().constData());
            if(locRegName != regionName)
                locRegionNames.insert(map.regName, locRegName);
        }
    }
    
    return locRegionNames.value(region);
#else
    Q_UNUSED(region);
    return QString();
#endif    
}

/*!
    Changes the system region to the one specified in \a region.

    \param region The region identifier. This must correspond to an identifier 
    returned by supportedRegions().
    
    \return True if successful, otherwise false.
    
    \attention Only fully implemented on the Symbian platform. For other 
    platforms, always returns false.
    
    \sa localisedRegionName(), currentRegion()
    
*/ 
bool HbLocaleUtil::changeRegion( const QString &region )
{
#if defined(Q_OS_SYMBIAN)   
    TExtendedLocale dummy;
    QString regDllName = QString( "elocl_reg." );
    
    if(mappingList.isEmpty())
    {
        readMappings();
    }
    int count = mappingList.count();
    for (int j = 0; j < count; j++)
    {
        HbLocaleMapping mapping = mappingList.at(j);
        QString name = mapping.regName;
        if(name == region)
        {
            dummy.LoadSystemSettings();
            regDllName += mapping.regionDllId;
            TPtrC nameptr(regDllName.utf16());
            TInt err = dummy.LoadLocaleAspect( nameptr );
            if( err != KErrNone )
                return false;
            dummy.SaveSystemSettings();
            // cause localeprivate update on next qlocale object
            QSystemLocale dummy2;
            
            // Update region to cent rep
            bool ok;
            int regionCode = mapping.regionDllId.toInt(&ok);
            if (!ok) {
                return false;
            }
            
            CRepository* commonEngineRepository = 0;
            TRAPD( err1, commonEngineRepository = CRepository::NewL( KCRUidCommonEngineKeys ) );    
            if ( err1 != KErrNone ) { 
                return false;
            }
                
            if ( commonEngineRepository->Set( KGSRegion, regionCode ) != KErrNone ) {
                delete commonEngineRepository;
                return false;
            }
            delete commonEngineRepository;
            
            return true; 
        }
    }
    return false;
#else
    Q_UNUSED(region);
    return false;
#endif    
}

/*!
    
    Returns the identifier of the current region.

    \attention Only fully implemented on the Symbian platform. For other 
    platforms, always returns an empty QString.
    
    \sa supportedRegions(), localisedRegionName(), changeRegion()

*/ 
QString HbLocaleUtil::currentRegion()
{
#if defined(Q_OS_SYMBIAN)      
    if(mappingList.isEmpty())
    {
        readMappings();
    }
    TRegionCode reg = User::RegionCode();
    int cnt = mappingList.count();
    for(int i = 0; i < cnt; i++)
    {
        HbLocaleMapping mapping = mappingList.at(i);
        int dllid = mapping.regionDllId.toInt();
        if(dllid == reg)
        {
            return mapping.regName;
        }
    }
#endif    
    return QString();
}

#if defined(Q_OS_SYMBIAN)      
/*!
    \brief reads the collations.txt file and reads the list of symbian collation codes 
*/
void readCollations()
{
    QFile* file = new QFile(COLLATION_LIST_FILE);
    if (!file->exists() ) 
    {
        delete file;
        return ;
    }
    if (!file->open(QIODevice::ReadOnly | QIODevice::Text))
    {
        delete file;
        return ;
    } 
    QTextStream in(file);
    while (!in.atEnd())
    {
        QString line = in.readLine(256);
        if (!line.isEmpty())
        {
            int colCode = line.toUInt();
            collations.append(colCode);
        }
    }
    return ;
}
#endif

/*!
    
    Returns the identifiers of the collations supported on a device. The 
    collation identifier is either an ISO 639 language code, or a combination of 
    an ISO 639 language code and an ISO 3166 country code.
    
    \attention Only fully implemented on the Symbian platform. For other 
    platforms, always returns an empty QStringList.
    
    \sa localisedCollationName(), currentCollation(), changeCollation()
 
*/
QStringList HbLocaleUtil::supportedCollations()
{
#if defined(Q_OS_SYMBIAN)
    if(!availCollations.isEmpty())
    {
        return availCollations;
    }

    if(collations.isEmpty())
    {
        readCollations();
    }
    
    if(mappingList.isEmpty())
    {
        readMappings();
    }
    int colCount = collations.count();
    for(int i = 0; i < colCount; i++)
    {
        int collation = collations.at(i);
        int count = mappingList.count();
        for (int j = 0; j < count; j++)
        {
            HbLocaleMapping mapping = mappingList.at(j);
            QString colCode = mapping.collationDllId;
            if(collation == colCode.toUInt())
            {
                availCollations.append(mapping.collName);
                break;
            }
        }
    }
    return availCollations;
#else
    return QStringList();
#endif
}

/*!
    
    Returns the localised collation name for the given collation identifier. If 
    the translation fails, returns an empty QString.
    
    \param collation The region collation identifier corresponding to an 
    identifier returned by supportedCollations().
    
    \attention Only fully implemented on the Symbian platform. For other 
    platforms, always returns an empty QString.
    
    \sa currentCollation(), changeCollation()
  
*/ 
QString HbLocaleUtil::localisedCollationName( const QString &collation ) 
{
#if defined(Q_OS_SYMBIAN)       
    if(locCollationNames.isEmpty())
    {
        QTranslator translator;
        QString path = "c:";
        path += QString(COLLATION_TRANSLATOR_PATH);
        if (!translator.load(path)) {
            path = "z:";
            path += QString(COLLATION_TRANSLATOR_PATH);
            if (!translator.load(path)) {
                return QString("");
            } 
        } 

        QCoreApplication::installTranslator(&translator);
            
        if(mappingList.isEmpty()) 
        {
            readMappings();
        }
        int cnt = mappingList.count();
        for(int i = 0 ; i < cnt; i++ )
        {
            HbLocaleMapping map = mappingList.at(i);
            QString collationName = QString(COLLATION_ID_PREFIX);
            collationName += '_';
            collationName += map.collName;
            QString locColName = hbTrId(collationName.toAscii().constData());
            if(locColName != collationName)
                locCollationNames.insert(map.collName, locColName);
        }
    }
    
    return locCollationNames.value(collation);
#else
    Q_UNUSED(collation);
    return QString();
#endif    
}

/*!
    
    Changes the system collation to the one specified \a collation.
    
    \param collation The collation identifier. This must correspond to an 
    identifier returned by supportedCollations(). 
    
    \return True if successful, otherwise false.
    
    \attention Only fully implemented on the Symbian platform. For other 
    platforms, always returns false.
    
    \sa localisedCollationName(), currentCollation()
*/ 
bool HbLocaleUtil::changeCollation( const QString &collation )
{
#if defined(Q_OS_SYMBIAN) 
    TExtendedLocale dummy;
    QString colDllName = QString( "elocl_col." );
    
    if(mappingList.isEmpty())
    {
        readMappings();
    }
    int count = mappingList.count();
    for (int j = 0; j < count; j++)
    {
        HbLocaleMapping mapping = mappingList.at(j);
        QString name = mapping.collName;
        if(name == collation)
        {
            dummy.LoadSystemSettings();
            colDllName += mapping.collationDllId;
            TPtrC nameptr(colDllName.utf16());
            TInt err = dummy.LoadLocaleAspect( nameptr );
            if( err != KErrNone )
                return false;
            dummy.SaveSystemSettings();
            // cause localeprivate update on next qlocale object
            QSystemLocale dummy2;
            // Update collation to cent rep
            bool ok;
            int colCode = mapping.collationDllId.toInt(&ok);
            if (!ok) {
                return false;
            }
            
            CRepository* commonEngineRepository = 0;
            TRAPD( err1, commonEngineRepository = CRepository::NewL( KCRUidCommonEngineKeys ) );    
            if ( err1 != KErrNone ) { 
                return false;
            }
                
            if ( commonEngineRepository->Set( KGSCollation, colCode ) != KErrNone ) {
                delete commonEngineRepository;
                return false;
            }
            delete commonEngineRepository;
            
            return true; 
        }
    }
    return false;
#else
    Q_UNUSED(collation);
    return false;
#endif    
}

/*!
    
    Returns the identifier of the current collation. 
    Typically an identifier is ISO 639 code.

    \attention Only fully implemented on the Symbian platform. For other 
    platforms, always returns an empty QString.
    
    \sa supportedCollations(), localisedCollationName(), changeCollation()
*/ 
QString HbLocaleUtil::currentCollation()
{
#if defined(Q_OS_SYMBIAN)      
    if(mappingList.isEmpty())
    {
        readMappings();
    }
    TExtendedLocale dummy;
    dummy.LoadSystemSettings();
    TBuf<256> name;
    dummy.GetLocaleDllName(ELocaleCollateSetting,name);

    QString dllname;
#ifdef QT_NO_UNICODE
    dllname = QString::fromLocal8Bit(name.Ptr(), name.Length());
#else
    dllname = QString::fromUtf16(name.Ptr(), name.Length());
#endif    
    
    dllname = dllname.right(COLLATION_DLL_PREFIX_POSITION);
    int cnt = mappingList.count();
    for(int i = 0; i < cnt; i++)
    {
        HbLocaleMapping mapping = mappingList.at(i);
        QString dllid = mapping.collationDllId;
        if(dllid == dllname)
        {
            return mapping.collName;
        }
    }
#endif    
    return QString();    
}

/*!

    Changes the system language, region and collation as specified by \a 
    language. The region and collation are selected automatically based on the 
    specified language.

    \param language The language identifier. This must correspond to an 
    identifier returned by supportedLanguages().
  
    \return True if successful, otherwise false.
    
    \attention Only fully implemented on the Symbian platform. For other 
    platforms, always returns false.
    
    \sa supportedRegions(), supportedCollations()
 
*/ 
bool HbLocaleUtil::changeLocale( const QString &language )
{
#if defined(Q_OS_SYMBIAN) 
    if(mappingList.isEmpty()) {
        readMappings();
    }

    for (int i = 0;  i < mappingList.count(); ++i) {
        HbLocaleMapping map = mappingList.at(i);
        if (map.langName == language) {
            if (!changeLanguage(map.langName)) {
                return false;
            } 
            if (!changeRegion(map.regName)) {
                return false;
            } 
            if (!changeCollation(map.collName)) {
                return false;
            } 
            return true;
        }
    }
#else
    Q_UNUSED(language);
#endif // Q_OS_SYMBIAN
    return false;   
}

/*!
    Returns list of language, region and collation ID mappings.
    For example for UK english entry have "en" as language, "GB" as region and "en" as collation. 
    Similar values for US english are "en_US", "US" and "en_US"
        
    Returned list may contain languages which does not have corresponding region, then HbLanguageRegionMapping struct has an empty region QString.
    List may also contain regions which does not have corresponding language and collation, then HbLanguageRegionMapping struct contains an empty language and collation QStrings.
        
    Example:
    \snippet{unittest_hblocaleutil/unittest_hblocaleutil.cpp,2}
  
    \attention Symbian specific API
    
    \param onlySupported Should return mappings only for those languages, regions and collations which are supported on the device 
    true - returns mappings only for those languages, regions and collations which are available on device. 
    false - returns all know languages, regions and collations.   
    
    \return Symbian - list of language, region and collation mappings
    \return other platforms - an empty list   
*/ 
QList<HbLanguageRegionMapping> HbLocaleUtil::languageRegionMappings( bool onlySupported )
{
    QList<HbLanguageRegionMapping> mps;
#if defined(Q_OS_SYMBIAN) 
    if (mappingList.isEmpty()) {
        readMappings();
    }
   
    QStringList supportedLanguages;
    QStringList supportedRegions;
    if (onlySupported) {
        supportedLanguages = HbLocaleUtil::supportedLanguages();
        supportedRegions = HbLocaleUtil::supportedRegions();
    }
    
    for (int i = 0;  i < mappingList.count(); ++i) {

        HbLocaleMapping map = mappingList.at(i);

        HbLanguageRegionMapping mapping;
        mapping.languageId = map.langName;
        mapping.regionId = map.regName;
        mapping.collationId = map.collName;

        if (onlySupported) {
            bool langSupported = supportedLanguages.contains(map.langName);
            bool regSupported = supportedRegions.contains(map.regName);
            if (!langSupported && !regSupported) {
                continue;
            }
            if (!langSupported) {
                mapping.languageId = "";
            }
            if (!regSupported) {
                mapping.regionId = "";
            }
        }

        mps.append(mapping);

    }
#else
    Q_UNUSED(onlySupported);
#endif // Q_OS_SYMBIAN
    return mps;
}