Chapter 2: Two Custom Widgets


Screenshot of the English version of tutorial 2

We will now see a more complex example, with several contexts and several texts in each context. And we'll learn what a context is.

We will provide several translations, and define "several" as meaning "two". Namely, we will provide a French and a Dutch translation. The relevant lines of tt2.pro are

    HEADERS         = arrowpad.h \
                      mainwindow.h
    SOURCES         = arrowpad.cpp \
                      main.cpp \
                      mainwindow.cpp
    TRANSLATIONS    = tt2_fr.ts \
                      tt2_nl.ts

Now run lupdate. You should get two identical message files (tt2_fr.ts and tt2_nl.ts).

Line by Line Walk-Through

arrowpad.h

    class ArrowPad : public QGrid
    {
        Q_OBJECT

ArrowPad is a subclass of QWidget. On the screenshot above, the central widget with the four buttons is an ArrowPad.

"ArrowPad" is also a context: It is the context of the texts in the ArrowPad class. The Q_OBJECT macro defines tr(x) in ArrowPad like this:

    qApp->translate( "ArrowPad", x )

Knowing which class each text occurs enables the Qt Linguist to show the right texts together, which in turn eases the translation of the program.

arrowpad.cpp

        skip();
        (void) new QPushButton( tr("&Up"), this );
        skip();
        (void) new QPushButton( tr("&Left"), this );
        skip();
        (void) new QPushButton( tr("&Right"), this );
        skip();
        (void) new QPushButton( tr("&Down"), this );
        skip();

Here, we use ArrowPad::tr() four times.

mainwindow.h

    class MainWindow : public QMainWindow
    {
        Q_OBJECT

In the screenshot above, the whole window is a MainWindow. Here too, we use Q_OBJECT, so that MainWindow will become a context in the Qt Linguist.

mainwindow.cpp

    MainWindow::MainWindow( QWidget *parent, const char *name )
        : QMainWindow( parent, name )
    {
        ArrowPad *ap = new ArrowPad( this, "arrow pad" );
        setCentralWidget( ap );

In the MainWindow constructor, we create an ArrowPad.

        QPopupMenu *file = new QPopupMenu( this );
        file->insertItem( tr("E&xit"), qApp, SLOT(quit()),
                          QAccel::stringToKey(tr("Ctrl+Q")) );

Here we call MainWindow::tr() twice. Notice the use of QAccel::stringToKey() to support different keys in other languages. "Ctrl+Q" is a good choice for Quit in English, but a Dutch translator might want to use "Ctrl+A" (for Afsluiten) or a German translator "Strg+E" (for, strangely, Beenden).

main.cpp

        QTranslator tor( 0 );
        tor.load( QString("tt2_") + QTextCodec::locale(), "." );
        a.installTranslator( &tor );

Here, we determine which translation to use according to the current locale. QTextCodec::locale() can be influenced by setting the LANG environment variable, among others.

Translating to French and Dutch

Let's translate the example application to French first. Start Qt Linguist with tt2_fr.ts. You should get the seven source texts ("&Up", "&Left", etc.) grouped in two contexts ("ArrowPad" and "MainWindow").

Now, enter the following translations:

(Use the "Finish & Next" button to mark the current item as finished and to start editing an unfinished item.)

Save the file and do the same for Dutch:

Now, we have to convert t1_fr.ts and t1_nl.ts into .qm files. We could use Qt Linguist for that, as in chapter one, but then we would miss an opportunity to use the lrelease utility. lrelease produces .qm files from .ts files without user interaction. It's chiefly meant for use in makefiles.

Type

    lrelease tt2.pro

You should now have both tt2_fr.qm and tt2_nl.qm. Set the LANG environment variable to fr. In Unix, one of the two following commands should do it:

    export LANG=fr
    setenv LANG fr

In Windows, either modify autoexec.bat or run

    set LANG=fr

When you run the program, you should now get

Screenshot of the French version of tutorial 2

Now, try the same with Dutch, by setting LANG=nl. You should get

Screenshot of the Dutch version of tutorial 2

Exercices

Remove the Q_OBJECT macro from the header files, run lupdate and look at the result in Qt Linguist. What's different now?

Set LANG=fr_CA (French Canada) and run the example program again. Explain why the result is the same as with LANG=fr.

Let's go on to chapter three.

[Previous tutorial] [Next tutorial] [Main tutorial page]