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 an app using C, you can use the locale.h library and the region.h (BPS library) to determine the display language and region settings of the device. You can use the clock.h library to determine when the date or time zone changes on the device.

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_ */

To retrieve the locale settings from the device, call the locale_get() function from the locale.h library.

To listen for changes to locale settings, register your app to receive locale events, and then call bps_get_event() to retrieve your app's next event.

When you retrieve the event, you need to confirm that it is a locale event. First, you should verify the domain of the event to make sure that it has the locale domain. Then you need to verify the code for the event. In this case, look for events of the LOCALE_INFO type since these events are generated whenever the current language or country changes. When you determine that this event is a locale event, you can retrieve the language and country from the event and respond to the change.

#include <bps/bps.h>
#include <bps/locale.h>

char* country = NULL;
char* language = NULL;

// Initialize the bps libary
bps_initialize();

// Retrieve the locale settings from the device
locale_get(&language, &country);

while (!shutdown) {
    bps_event_t *event = NULL;

	// Block while waiting for an event
    bps_get_event(&event, -1); 

    if (event) {
        if (bps_event_get_domain(event) == locale_get_domain()) {
            if (LOCALE_INFO == bps_event_get_code(event)) {

                language = locale_event_get_language(event);
                country = locale_event_get_country(event);

                // Handle the locale information
            }
        }
    }
}

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 );

If you are developing your app in C, you can use the region.h API to retrieve the region settings.

#include <bps/region.h>
 
BPS_API int region_get_region(char **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.

Not applicable

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

Not applicable

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

Not applicable

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)
char* quotestring(char* const str, const char* const quotestylestring);

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)

Not applicable

If you are developing an app using Cascades, you can use the RelativeDateFormatter class to format objects relative to the current date and time. You can use the CustomDateFormatter class to format QDateTime objects using date and time patterns.

The table below shows the Qt equivalencies for supported ICU date characters that you can use in date and time patterns. To see samples of date formatting using these patterns, see Sample skeleton patterns.

Supported ICU date characters

An asterisk (*) in the left column indicates that this character may be repeated to pad the output with 0s.

ICU pattern Qt pattern Description US English example Notes
G AD era designator AD  
GGGG   era designator Anno Domini  
y yyyy year 1996 You can also use yyyy for ICU
yy yy 2-digit year 96 00 through 99
Y   of year 1997 3rd month of year 1997 becomes March 1996
YY   of 2-digit year 97 00 through 99
u   extended year 4601 Based on region locale calendar
U   cyclic year name ren-chen Falls back to number (29) for many locales
Q   quarter 2 Use QQ to pad with 0s
QQQ   quarter Q2  
QQQQ   quarter 2nd quarter  
qqq   standalone quarter Q2  
qqqq   quarter 2nd quarter  
M M month in year 8  
MM MM month in year 08  
MMM MMM month in year Aug  
MMMM MMMM month in year August  
LLL   standalone month Aug  
LLLL   standalone month August  
* w   week in year 33  
* W   week in month 3  
* F   weekday in month 3 For example, 3rd Tuesday in August
* g   Julian day 2451370  
* D   day in year 226  
* d d day in month 9  
e   day of week 2 Numeric: 1 through 7
ee   day of week 02 Numeric: 01 through 07
E ddd day of week Tue  
eeee   day of week Tues  
EEEE dddd day of week Tuesday  
ccc   standalone day Tue  
cccc   standalone day Tuesday  
* H h hour in day 0 0 through 23
* k   hour of day 24 1 through 24; the <n>th hour of the day
a AP am/pm marker PM Qt uses AP for AM/PM and ap for am/am
* h h hour of am/pm 12 1 through 12; Qt checks for presence of AP/ap
* K   hour in am/pm 0 0 through 11
* m m minute in hour 30  
* s s second in minute 55  
S   decisecond 9 Tenths of the next second: 0 through 9
SS   centisecond 97 Hundredths of the next second: 00 through 99
SSS zzz millisecond 978 Thousandths of the next second: 000 through 999
* A   ms in day 69540000  
z   timezone PST  
zzzz   timezone Pacific Standard Time  
Z   timezone -0800 RFC 822
ZZZZ t timezone GMT-08:00  
ZZZZZ   timezone -08:00 ISO 8601
v   timezone PT Short wall (generic) time
vvvv   timezone Pacific Time Long wall (generic) time
V   timezone PST  
VVVV   timezone United States Time (Los Angeles) Location

Sample skeleton patterns

Skeleton United States (English) Spain (Catalan) Liechtenstein (German)
MMMMEEEEd Tuesday, October 30 dimarts 30 d'octubre Dienstag, 30. Oktober
MMMMEd Tue, October 30 dt. 30 d'octubre Di., 30. Oktober
MMMEd Tue, Oct 30 dt. 30 d'oct. Di., 30. Okt
yMMMM October 2012 octubre de 2012 Oktober 2012
MMMd Oct 30 30 d'oct. 30. Okt
Ehma Tue 7:46 PM dt. 19.46 Di. 19:46

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)

Not applicable

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)

Not applicable

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: 2015-03-31



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

comments powered by Disqus