Internationalisierung

In Qt ist es relativ einfach eine Anwendung zu übersetzen. Unterstützt wird man dabei vom Qt-Linguist.

Strings

Um ein Programm in mehreren Sprachen verfügbar zu machen, müssen alle zu übersetzenden Strings an die Methode QObject::tr() übergeben werden. Diese gibt den String in der ausgewählten Sprache zurück. Beispiel:

QPushButton *button = new QPushButton( QObject::tr( "Quit" );

Befindet man sich innerhalb des QObject-Namespaces (in allen von QObject und damit auch QWidget abgeleiteten Klassen der Fall), kann das QObject:: weggelassen werden:

QPushButton *button = new QPushButton( tr( "Quit" ) ) );

Bei dynamischen Strings sollte unbedingt QString::arg() anstatt des +-Operators verwendet werden, da sich der Satzbau in den Sprachen unterscheidet. Also nicht:

label->setText( tr( QString::number( numTries ) + " tries remaining!" ) );

sondern:

label->setText( tr( "%1 tries remaining!" ).arg( numTries ) );

Übersetzungsdateien erstellen

Zuerst muss der Pfad und die Namen der Übersetzungsdateien manuell am Ende der Projektdatei (*.pro) eingetragen werden. Als Beispiel nennen wir unser Programm proggen:

// proggen.pro
TRANSLATIONS    = lang/files/proggen_en.ts \
                  lang/files/proggen_de.ts

Nun werden über das Programm lupdate die Übersetzungsdateien erstellt. Dabei muss das Programm mit der Projektdatei als Parameter aufgerufen werden:

lupdate proggen.pro

Jetzt haben wir die in der Projektdatei genannten *.ts-Dateien. Das sind lediglich XML-Dateien, die auch mit einem normalen Texteditor geöffnet werden können. Wesentlich einfacher ist es aber sie mit dem Qt-Linguist zu öffnen und zu bearbeiten.
FIXME bearbeiten
Sind wir damit fertig, können wir lrelease auf das Projekt ausführen.

lrelease proggen.pro

Damit haben wir optimierte *.qm-Dateien, die wir im Programm verwenden können.

Übersetzungsdateien im Programm verwenden

Um die Übersetzungsdateien im Programm zu verwenden, müssen sie über die Klasse QTranslator geladen und installiert werden. Dies muss geschehen bevor sichtbarer Text über tr() abgefragt wird. Eine Integration über dein Resource Compiler ist ebenfalls möglich und auch sehr praktisch.

QApplication app( argc, argv );
QTranslator translator;
translator.load( ":/proggen_de" );
app.installTranslator( &translator );

Danach gibt tr() den jeweiligen Text aus der Übersetzungsdatei zurück.

Dynamische Übersetzungen

Eine Änderung der Sprache während das Programm läuft ist etwas komplizierter. Wie bereits erwähnt, verändert das QTranslator-Objekt den von tr() zurückgegebenen Text. Dieser Text wird aber normalerweise nur ein einziges Mal abgefragt. Ändern wir im laufenden Programm die Sprache, gibt zwar tr() den richtigen Text zurück, jedoch werden Widgets (bzw. Variablen allgemein) nicht automatisch aktualisiert.
Um dieses Problem zu umgehen, können wir einen Event-Handler festlegen, der bei Änderung der Sprache aufgerufen wird. In diesem muss dann der Text der Widgets neu abgefragt und übernommen werden.

void MyWidget::changeEvent( QEvent *event )
{
  if( event->type() == QEvent::LanguageChange )
    updateWidgetLanguage();
  else
    QWidget::changeEvent( event );
}
 
void MyWidget::updateWidgetLanguage()
{
  // ...
}