translating qt applications
DESCRIPTION
Supporting several languages is a key point to increase the audience of an application. We will see what is needed in Qt to enable internationalization and how to ensure all the components can be translated. We will also see the tools available for the translators and how to use them. Presentation by Benjamin Poulain held during Qt Developer Days 2009. http://qt.nokia.com/developer/learning/elearningTRANSCRIPT
09/12/09
Translating Qt applicationsIt does not have to be boring ;-)
Who is Benjamin Poulain at Nokia?
2
• first support engineer
– Linux and Mac OS X
• now Webkit developer
• pet projects
– graphical tablet
– Cocoa support
What do I do after work?
• some hacking
– web applications
• lots of sport: running, cycling, climbing
I am not so good on a snowboard
Why do I work on translations?
• my family do not speak english
➡need for localized software
• work on
– tutorial in french
– translation of Qt Creator
– french community of Qt
What are we gonna do today?
• Why bother?
• Translating your application
• Tools for translators
• Going further
• Conclusion
What are we gonna do today?
• Why bother?
• Translating your application
• Tools for translators
• Going further
• Conclusion
Translations increase your user base
Everybody speaks English. right?
Do not understand English
Secondary
Native speaker
writing an application is difficult ➜ spread it
What are we gonna do today?
• Why bother?• Translating your application
– Simple application– UI– Source– Integrate the translation
• Tools for translators• Going further• Conclusion
Ugly Snake is a mini game in Qt
How do we translate the application?
1) write code ready for translation
2) extract strings
3) translate
4) compile strings
Internationalization workflow:
What are we gonna do today?
• Why bother?• Translating your application
– Simple application– UI– Source– Integrate the translation
• Tools for translators• Going further• Conclusion
The .ui files are the biggest part
• most strings are in the .ui
• this is what is seen by the user
• good news: work out of the box
- string extraction
- translation
What are we gonna do today?
• Why bother?• Translating your application
– Simple application– UI– Source– Integrate the translation
• Tools for translators• Going further• Conclusion
Translate the strings with tr()
• QObject::tr() translate a string:trayIcon.showMessage("new message", "you have too many mail");
• works great with QString::arg():
tr("%n user(s) online").arg(userCount);
QString::number(userCount) + "users online";
trayIcon.showMessage(tr("new message"), tr("you have too many mail"));
Provide some context for short strings
tr("The %1 is %2").arg(...);What are 1, 2?
Provide some context for short strings
3 ways to add context:
– luck
– context in tr():
– comment in code
tr("The %1 is %2").arg(...);What are 1, 2?
tr("The %1 is %2", "The <extension> is <state>").arg(...);
//: The <extension> is <state>tr("The %1 is %2").arg(...);
How to mark strings for translations?
• tr() returns QString
• QT_TR_NOOP marks for translation
• translated later with tr()
char *const EDITOR = QT_TR_NOOP("emacs");
void function() { (...) QString editor = tr(EDITOR); (...)}
example:
What are we gonna do today?
• Why bother?• Translating your application
– Simple application– UI– Source– Integrate the translation
• Tools for translators• Going further• Conclusion
Applications use a compiled version of the translation
• lrelease compiles .ts in .qm
• .qm is the binary format for release
• fast lookup
• not into the binary
A translator must be installed
• QTranslator
- translate the strings
- load the .qm file:
QTranslator uglySnakeTranslator;uglySnakeTranslator.load("uglysnake_" + QLocale::system().name(), QCoreApplication::applicationDirPath());app.installTranslator(&uglySnakeTranslator);
What are we gonna do today?
• Why bother?
• Translating your application
• Tools for translators
• Going further
• Conclusion
There are two kinds of tools for translators
• offline ➜ Qt Linguist
• online ➜ Pootle, ...
Presentation of Linguist
Linguist is great but need to be distributed
• support multiple languages (simultaneously)
• great integration with Qt
• integration with the UI files:
• errors are spoted imediately
• full context
but: need to be distributed
Presentation of Pootle
Pootle is great, but offer no integration
• no need to distribute
• easier for amateur
but: no integration (ui files!)
What are we gonna do today?
• Why bother?• Translating your application• Tools for translators• Going further
– “context”– tricky UI– change the language– pitfalls
• Conclusion
One word, multiple concepts
edit
édition
éditer
noun
verb
tr("edit", "verb");tr("edit", "noun");
• short text ➜ context
• also in designer
Comments does not disambiguate the strings
QString a = tr("edit", "N97");QString b = tr("edit", "N900");
• works:
• do not work//: N97QString a = tr("edit");
//: N900QString b = tr("edit");
• why?
Understanding context and disambiguation
QPushButton::tr("edit", "verb");
context
disambiguation
QCoreApplication::translate("QPushButton", "edit", "verb");
QTranslator::translate("QPushButton", "edit", "verb");
context source disambiguation ➜ result
QPushButton edit verb ➜ editer
QPushButton edit ➜
source
Comments does not disambiguate the strings
QString a = tr("edit", "N97");QString b = tr("edit", "N900");
• works:
• do not work://: N97QString a = tr("edit");
//: N900QString b = tr("edit");
• solution://: N97QString a = tr("edit", "phoneA");
//: N900QString b = tr("edit", "phoneB");
What are we gonna do today?
• Why bother?• Translating your application• Tools for translators• Going further
– “context”– tricky UI– change the language– pitfalls
• Conclusion
The translation should fit the widgets
• the layouts adapt the widgets
• problems:
- fixed size- phone screen
Some images need a translation
• localize icons, images, etc
• qresource support locale:
<qresource lang="fr"> <file>burnIcon.png</file></qresource>
What if you want multiple UI?
• cultural conventions
• phone screens
• right to left interface
✓ Solution: QUiLoader to load the UI
X difficult to maintain
X difficult to document
What are we gonna do today?
• Why bother?• Translating your application• Tools for translators• Going further
– “context”– tricky UI– change the language– pitfalls
• Conclusion
What if the language is changed after the start?
• examples:
- phone
- public terminal
- MS Windows applications
Everything needs a new translation
• LanguageChange event on ::installTranslator()
• QWidget::changeEvent() to catch the event
• UI responds to retranslateUI()
• manual update for the code
void SettingsPanel::changeEvent(QEvent *e){ if (e->type() == QEvent::LanguageChange) { ui->retranslateUi(this); updateSpeedDescription(); } QWidget::changeEvent(e);}
When to change the translators?
• LocaleChange event to the active window
➡ install event filter on QApplication
➡ change the translators
What are we gonna do today?
• Why bother?• Translating your application• Tools for translators• Going further
– “context”– tricky UI– change the language– pitfalls
• Conclusion
Translate on painting is not a good strategy
char languageList[] = { QT_TR_NOOP("english"), QT_TR_NOOP("german") };
if (language == "english”) { ...
void paintEvent(QEvent *) { QString toShow = tr(m_language); ...}
list sorted alphabetically:
✓ Solution: use classes for identity, not strings
The source might not be in Latin 1
• tr() uses Latin 1 by default
✓ Solution 1: use English for the source
✓ Solution 2:
- QTextCodec::setCodecForTr()
- CODECFORTR = UTF-8
tr("Qt est génial"); // might fail
Mac uses an ordered list of language
• Mac OS X
- ordered list of languages
• language selection:QTranslator uglySnakeTranslator;uglySnakeTranslator.load("uglysnake_" + QLocale::system().name(), QCoreApplication::applicationDirPath());app.installTranslator(&uglySnakeTranslator);
Not accurate
✓ Solution: iterate over the languages of core foundation
What are we gonna do today?
• Why bother?
• Translating your application
• Tools for translators
• Going further
• Conclusion
Qt makes translation easy
• Internationalization is important
• Qt already solves the problems
• Minimal changes are needed in the code
– tr() every string
– provide context for short strings
➡ think about it when you develop