Internationalization

Internationalization is the process of developing an app so that it can be adapted to various languages and regions without any code changes. Your app should handle translation of text, rearranging controls, and using different layouts to suit the readers in different locales. The internationalization APIs in the BlackBerry 10 Native SDK include support for many locales, which reduces maintenance and translation costs.

BlackBerry 10 devices have separate settings for display language and region. For example, users can set their display language to French, and their region to Estonia (Estonian).

Screen showing the display language and region settings on a BlackBerry 10 device.

With these settings, the user interface is displayed in the display language, but numbers, dates, and currency are displayed using the cultural preferences of the region. This separation means that users can still use the cultural preferences of their language and region, even if BlackBerry 10 doesn't provide a UI translation for that language. It also means that you must retrieve and use two different locale settings, one for the display language, and one for the region.

If you are developing a Cascades app, Qt provides most internationalization APIs to localize content. One of the most important Qt APIs is the QLocale class, which contains functions for internationalization. The standard empty template for Cascades projects configures your app for translation automatically. For more information, see Localizing your UI. Qt also contains functions for formatting numbers, currency, quotes, date and time, lists, and measurement systems (metric or imperial). For more information, see Formatting.

Although Qt provides a set of APIs for you to localize content, the BlackBerry 10 OS supplements these Qt APIs where they lack functionality. You can use the i18N classes to format text for dates, time, and currency. For more information, see Region.

Display language

You can access the locale settings to determine the display language associated with a user's BlackBerry 10 device so that you can display UI elements in the appropriate language.

Not applicable

The standard empty template for Cascades projects includes all the setup that you need for internationalization. The template includes code for finding the display language of the device running your app, and installing a translator for a new locale.

In the applicationui.cpp file, you set up the localization of your content before you create any of the application UI. You create a QTranslator object to handle localization of any text output in your app and a LocaleHandler to listen for changes to the locale of the device that is running your app. You also connect the systemLanguageChanged() signal to a slot that you define in your main.cpp file.

#include "applicationui.hpp"

#include <bb/cascades/Application>
#include <bb/cascades/QmlDocument>
#include <bb/cascades/AbstractPane>
#include <bb/cascades/LocaleHandler>

using namespace bb::cascades;

ApplicationUI::ApplicationUI() :
        QObject()
{
    // prepare the localization
    m_pTranslator = new QTranslator(this);
    m_pLocaleHandler = new LocaleHandler(this);

    bool res = QObject::connect(m_pLocaleHandler, 
        SIGNAL(systemLanguageChanged()), 
        this, 
        SLOT(onSystemLanguageChanged()));

    // This is only available in Debug builds
    Q_ASSERT(res);
    // Since the variable is not used in the app, 
    // this is added to avoid a compiler warning.
    Q_UNUSED(res);

    // initial load
    onSystemLanguageChanged();
}

The systemLanguageChanged() slot removes any existing translators attached to your app, finds the current country and language of the device running your app, and installs a translator for the new locale.

void ApplicationUI::onSystemLanguageChanged()
{
   QCoreApplication::instance()->removeTranslator(m_pTranslator);
   // Initiate, load and install the application translation files.
   QString locale_string = QLocale().name();
   QString file_name = QString("MyFirstApp_%1").arg(locale_string);
   if (m_pTranslator->load(file_name, "app/native/qm")) {
       QCoreApplication::instance()
           ->installTranslator(m_pTranslator);
   }
}

In the applicationui.hpp file that is created with the standard empty template, you can see all of the declarations that you need to use these classes as well as two private global declarations for the QTranslator and LocaleHandler that your app uses. You don't need to change these classes or declarations.

#ifndef ApplicationUI_HPP_
#define ApplicationUI_HPP_

#include <QObject>

namespace bb
{
    namespace cascades
    {
        class LocaleHandler;
    }
}

class QTranslator;

/*!
 * @brief Application UI object
 */
class ApplicationUI : public QObject
{
    Q_OBJECT
public:
    ApplicationUI();
    virtual ~ApplicationUI() {}
private slots:
    void onSystemLanguageChanged();
private:
    QTranslator* m_pTranslator;
    bb::cascades::LocaleHandler* m_pLocaleHandler;
};

#endif /* ApplicationUI_HPP_ */

Region

The BlackBerry 10 OS allows you to separate regional formatting settings for a specified locale and the UI settings for a specified locale. These settings are useful when a user wants to change the local calendar but the UI translations for that locale are not available. A user might also prefer to see the UI in English but wants to use the region settings to display measurements in the metric system and currency in Euros.

Because the user might have selected a region that is different from the display language setting, you should use the region settings to display region-dependent formats such as date, time, and numbers.

Not applicable

To support this functionality, Cascades provides an accessory function and a Qt signal, both of which require a locale type defined by the bb::system::LocaleType::Type.

The QLocale class can retrieve only the display language setting from the device. If you use QLocale to format the date, time, and numbers, you can retrieve the region using a LocaleHandler, and then pass that locale to QLocale.

To get started, add the following line in your .pro file:

LIBS += -lbbsystem -lbbutilityi18n

#include <bb/system/LocaleHandler>

bb::system::LocaleHandler region( bb::system::LocaleType::Region );

The QLocale class offers mostly ShortFormat and LongFormat formatting types. The BlackBerry 10 OS further extends these formatting types to date, time, and percentage. The following methods return the localized format:

bb::utility::i18n::dateFormat(DateFormat::Type)
bb::utility::i18n::timeFormat(DateFormat::Type)
bb::utility::i18n::dateTimeFormat(DateFormat::Type)

The type of date format can be short, medium, long, or full. Also, the functions above accept QLocale as a first parameter. Here's some sample code that prints ICU styled data and time formats in English-US, French, Arabic, and Hindi locales.

Not applicable

QDateTime currTime = QDateTime::currentDateTime();
 
    QLocale US(QLocale::English, QLocale::UnitedStates);
    QLocale FRANCE(QLocale::French, QLocale::France);
    QLocale SAUDI(QLocale::Arabic, QLocale::SaudiArabia);
    QLocale INDIA(QLocale::Hindi, QLocale::India);
    QList<QLocale>locales;
    locales << US << FRANCE << SAUDI << INDIA;
 
    
QString RLM = QString::fromUtf8("\u200F");
text += qApp->translate("MyFormatAppContext" , 
    "\n\n DateTime Format Example \n\n");
 
foreach(QLocale currLocale , locales){
    text += QLocale::countryToString(currLocale.country())+ "\n";

    text += qApp->translate("MyFormatAppContext","SHORT: ") + RLM;

    text += currLocale.toString( currTime, 
        bb::utility::i18n::dateTimeFormat
        ( currLocale, bb::utility::i18n::DateFormat::Short ) ) + "\n";

    text += qApp->translate("MyFormatAppContext","MEDIUM: ") + RLM;

    text += currLocale.toString( currTime, 
        bb::utility::i18n::dateTimeFormat
        ( currLocale, bb::utility::i18n::DateFormat::Medium ) ) + "\n";

    text += qApp->translate("MyFormatAppContext","LONG: ") + RLM;

    text += currLocale.toString( currTime, 
        bb::utility::i18n::dateTimeFormat
        ( currLocale, bb::utility::i18n::DateFormat::Long ) ) + "\n";

    text += qApp->translate("MyFormatAppContext","FULL: " ) + RLM;

    text += currLocale.toString( currTime, 
        bb::utility::i18n::dateTimeFormat
        ( currLocale, bb::utility::i18n::DateFormat::Full ) ) + "\n\n";}
}

Here's the output:

Screen showing the output from the code sample.

Formatting

You can use Qt classes and functions to format numbers, currency, quotes, calendar data, and measurements (metric or imperial) for a given locale.

Numbers

You can print or parse numbers in different formats according to locale. For example, you can use QLocale::toString(int n) to format an integer as a string according to the current locale. You can also format numbers differently for a given locale.

Not applicable

Here's an example that shows how to use the Qt number formatting API for a given locale. In this example, a random number is formatted using English-US, French, Hindi, Thai, and Arabic locales.

QLocale US(QLocale::English, QLocale::UnitedStates);
QLocale FRANCE(QLocale::French, QLocale::France);
QLocale INDIA(QLocale::Hindi, QLocale::India);
QLocale THAILAND(QLocale::Thai, QLocale::Thailand);
QLocale SAUDI(QLocale::Arabic, QLocale::SaudiArabia);
 
QList<QLocale> locales;
locales << US << FRANCE << INDIA << THAILAND << SAUDI;
 
QString text = qApp->translate("MyNumberFormatAppContext",
"Qt Number Format Example\n\n");

double randomNumber = -123456789.340;
foreach(QLocale currLocale , locales)

{
    text += QLocale::countryToString(currLocale.country())+ "\n" +
    qApp->translate("MyNumberFormatAppContext","Random Number: ") 
    + currLocale.toString(randomNumber,'f',3) + "\n\n";
}

Here's the output:

Number format sample
Locale: French

Random Number: 12875
Decimal Point: ,
Negative Sign: -
Positive Sign +
Zero Digit: 0

Currency

You can format currency values according to a specified locale. For example, you can use QLocale::toCurrencyString() to format a string as currency according to the current locale.

Not applicable

Here's an example that shows various currency formatting in English-US, Chinese, and Hindi locales.

QLocale US(QLocale::English, QLocale::UnitedStates);
QLocale CHINA(QLocale::Chinese, QLocale::China);
 
QList<QLocale> locales;
locales << US << CHINA;
 
float randomPrice = 14.99;
QString text = qApp->translate("MyCurrencyAppContext",
"Qt Currency Support Example\n\n");

foreach(QLocale currentLocale , locales){
    text +=  "\n" + QLocale::countryToString(currentLocale.country())+ "\n";
    foreach (QLocale currencyLocale, locales)
{
    //We recommend you use the standardized QLocale::CurrencyIsoCode 
    //instead of QLocale::CurrencySymbol. i.e. 14.99 USD vs $14.99
    text +=  currentLocale.toCurrencyString(randomPrice,
    currencyLocale.currencySymbol(QLocale::CurrencyIsoCode)) + "\n";
    }
}

Here's the output:

Qt currency support example

UnitedStates
USD14.99
CNY14.99

China
USD14.99
CNY14.99

Quoted strings

You can display quoted strings based on the specified locale.

Not applicable

The following Qt method supports quoting strings based on the specified locale:

QString QLocale::quoteString(const QString & str, 
    QuotationStyle style = StandardQuotation)

Date and time

You can represent dates and times according to a specified locale.

Not applicable

The following sample uses Qt methods to represent date and times in different locales:

QDate QLocale::toDate(const QString & string, 
    FormatType format = LongFormat)

QTime QLocale::toTime(const QString & string, 
    FormatType format = LongFormat)

QDateTime QLocale::toDateTime(const QString & string, 
    FormatType format = LongFormat)

QString QLocale::toString(const QDate & date, 
    const QString & format)

QString QLocale::toString(const QDateTime & dateTime, 
    FormatType format = LongFormat)

You can also use RelativeDateFormatter and CustomDateFormatter to format QDateTime objects relative to the current date and time or using date and time patterns.

Lists

You can construct a list of strings separated by a locale-based separator.

Not applicable

The following Qt method provides support for constructing a list of strings separated by a locale-based separator:

QString QLocale::createSeparatedList(const QStringList & list)

Calendar data

You can format the day, week, and month for a specified locale. Only the Gregorian calendar is used in the calendar support.

Not applicable

QLocale::weekdays()
QLocale::firstDayOfWeek()
QLocale::dayName(int day, FormatType type = LongFormat)
QLocale::monthName(int month, FormatType type = LongFormat)

Measurements

You can handle measurement units for the current locale. For example, QLocale::measurementSystem() returns the measurement units (metric or imperial) of a specified locale.

Collation support

The BlackBerry 10 OS uses QtCollator, which is part of Qt 5.0, as a basic string sorting and comparison engine in Cascades. Here are some important QtCollator methods:

  • int compare(QString &s1, QString &s2): Allows localized comparison between two strings.
  • QtCollator(QLocale &locale = QLocale()): Allows you to specify the locale in the constructor.
  • void setLocale(const QLocale &locale): Allows you to set a locale.
  • void setStrength(Strength): Performs case-insensitive comparisons.

Related resources

Last modified: 2014-09-30



Got questions about leaving a comment? Get answers from our Disqus FAQ.

comments powered by Disqus