From 3cf7f1e33f9906a0ad1776dd1cea4ad53345c9f5 Mon Sep 17 00:00:00 2001 From: Kuisma Salonen Date: Wed, 5 Jan 2011 18:05:41 +0200 Subject: Fixes: NB#217105 RevBy: TrustMe Details: Added two static methods to MLocale that allow to obtain endonym and primary script for a language. This is useful when one has to obtain a long list of these and instantiating MLocale each time is too heavy. --- src/corelib/i18n/mlocale.cpp | 95 +++++++++++++++++++++++++++++++++++++++++++- src/corelib/i18n/mlocale.h | 16 ++++++++ src/corelib/i18n/mlocale_p.h | 2 +- 3 files changed, 111 insertions(+), 2 deletions(-) diff --git a/src/corelib/i18n/mlocale.cpp b/src/corelib/i18n/mlocale.cpp index ef7e98d3..d29eb988 100644 --- a/src/corelib/i18n/mlocale.cpp +++ b/src/corelib/i18n/mlocale.cpp @@ -259,7 +259,7 @@ QStringList MLocalePrivate::translationPaths; QStringList MLocalePrivate::dataPaths; #ifdef HAVE_ICU -bool MLocalePrivate::truncateLocaleName(QString *localeName) const +bool MLocalePrivate::truncateLocaleName(QString *localeName) { // according to http://userguide.icu-project.org/locale the separators // that specify the parts of a locale are "_", "@", and ";", e.g. @@ -3086,6 +3086,99 @@ QStringList MLocale::dataPaths() return MLocalePrivate::dataPaths; } + +#ifdef HAVE_ICU +QString MLocale::localeScript(const QString &locale) +{ + QString s = MLocalePrivate::parseScript(locale); + + if(!s.isEmpty()) + return s; + + UErrorCode status = U_ZERO_ERROR; + UResourceBundle *res = ures_open(NULL, qPrintable(locale), &status); + if(U_FAILURE(status)) // TODO: error handling++ + return QString(); + + res = ures_getByKey(res, "LocaleScript", res, &status); + if(U_FAILURE(status)) { + ures_close(res); + return QString(); + } + + QString ret("Zyyy"); + + qint32 len; + const UChar *v; + v = ures_getNextString(res, &len, NULL, &status); + if(v && U_SUCCESS(status)) + ret = QString::fromUtf16(v, len); + + ures_close(res); + + return ret; +} + +QString MLocale::languageEndonym(const QString &locale) +{ + QString resourceBundleLocaleName = locale; + + do { + // Trying several resource bundles is a workaround for + // http://site.icu-project.org/design/resbund/issues + UErrorCode status = U_ZERO_ERROR; + UResourceBundle *res = ures_open(U_ICUDATA_NAME "-lang", + qPrintable(resourceBundleLocaleName), + &status); + if (U_FAILURE(status)) { + mDebug("MLocale") << "Error ures_open" << u_errorName(status); + ures_close(res); + return locale; + } + res = ures_getByKey(res, Languages, res, &status); + if (U_FAILURE(status)) { + mDebug("MLocale") << "Error ures_getByKey" << u_errorName(status); + ures_close(res); + return locale; + } + QString keyLocaleName = locale; + // it’s not nice if “zh_CN”, “zh_HK”, “zh_MO”, “zh_TW” all fall back to + // “zh” for the language endonym and display only “中文”. + // To make the fallbacks work better, insert the script: + if (keyLocaleName.startsWith(QLatin1String("zh_CN"))) + keyLocaleName = "zh_Hans_CN"; + else if (keyLocaleName.startsWith(QLatin1String("zh_SG"))) + keyLocaleName = "zh_Hans_SG"; + else if (keyLocaleName.startsWith(QLatin1String("zh_HK"))) + keyLocaleName = "zh_Hant_HK"; + else if (keyLocaleName.startsWith(QLatin1String("zh_MO"))) + keyLocaleName = "zh_Hant_MO"; + else if (keyLocaleName.startsWith(QLatin1String("zh_TW"))) + keyLocaleName = "zh_Hant_TW"; + do { // FIXME: this loop should probably be somewhere else + int len; + status = U_ZERO_ERROR; + const UChar *val = ures_getStringByKey(res, + qPrintable(keyLocaleName), + &len, + &status); + if (U_SUCCESS(status)) { + // found language endonym, return it: + ures_close(res); + return QString::fromUtf16(val, len); + } + } while (MLocalePrivate::truncateLocaleName(&keyLocaleName)); + // no language endonym found in this resource bundle and there + // is no way to shorten keyLocaleName, try the next resource + // bundle: + ures_close(res); + } while (MLocalePrivate::truncateLocaleName(&resourceBundleLocaleName)); + // no language endonym found at all, no other keys or resource + // bundles left to try, return the full locale name as a fallback: + return locale; +} +#endif + /////// // the static convenience methods for translation diff --git a/src/corelib/i18n/mlocale.h b/src/corelib/i18n/mlocale.h index c1ad7d32..25c9b5ca 100644 --- a/src/corelib/i18n/mlocale.h +++ b/src/corelib/i18n/mlocale.h @@ -1656,6 +1656,22 @@ public: */ void disconnectSettings(); + /*! + * \brief Static method to obtain primary script of locale. + * Can be used to obtain primary script without instantiating MLocale, + * useful when obtaining a list of scripts for a lot of languages. Primary + * script means a script returned by script() or first item in + * languageScripts(). + */ + static QString localeScript(const QString &locale); + + /*! + * \bried Static method to obtain endonym for locale. + * Can be used to obtain endonym without instantiating MLocale, useful + * when obtaining a list of endonyms for a lot of languages. + */ + static QString languageEndonym(const QString &locale); + Q_SIGNALS: void settingsChanged(); /*! diff --git a/src/corelib/i18n/mlocale_p.h b/src/corelib/i18n/mlocale_p.h index 8e08f4f1..84da4eaa 100644 --- a/src/corelib/i18n/mlocale_p.h +++ b/src/corelib/i18n/mlocale_p.h @@ -109,7 +109,7 @@ public: * as the parameter is left unchanged. I.e. if false is returned * there are no fallbacks left to try. */ - bool truncateLocaleName(QString *localeName) const; + static bool truncateLocaleName(QString *localeName); // creates an icu::Locale for specific category icu::Locale getCategoryLocale(MLocale::Category category) const; -- cgit v1.2.3