[Qt-qml] Writing i18n applications
Donald Carr
donald.carr at nokia.com
Fri Jul 30 01:18:25 CEST 2010
Good morning,
I am trying to advise external groups on how to make optimal use of QML's
i18n support, in the context of Meego's i18n guidelines:
https://files.maemo.org/repository/harmattan/documentation/doc/libmeegotouch/html/i18n.html
(I will attach this file as both html and text, since viewing requires
membership)
The QML translation documentation clearly documents raw string translation:
http://doc.qt.nokia.com/4.7-snapshot/qdeclarativei18n.html
and the i18n example demonstrates equally clearly. Having looked at the
qmlviewer source, I have seen that the standard QTranslator mechanism is still
used, and hence for the most part the Meego infrastructure built on this
should function as intended.
I am currently imagining that we would recommend one QML implementation per
language family within the context of a common pool of translated strings.
People clearly shouldn't write an interface per language, but a right to
left application should pay more attention to (re) design than simply
mirroring the original left to right application. Is this the intended
approach to i18n in QML? Are there going to be any (further) convenience
structures for (QML) code reuse in the context of multiple (per language
family) QML interface implementations.
Yours sincerely,
Donald Carr
Consultancy Service Engineer
ph: +1650 454 5842
http://labs.qt.nokia.com/page/Main_Page
-------------- next part --------------
_H_o_m_e ? _A_l_l_ _C_l_a_s_s_e_s ? _M_a_i_n_ _C_l_a_s_s_e_s ? _D_e_p_r_e_c_a_t_e_d
************ IInntteerrnnaattiioonnaalliissaattiioonn GGuuiiddeelliinneess ************
********** IInnttrroodduuccttiioonn **********
This document provides guidelines on developing locale-aware applications for
the MeeGo Touch UI Framework. Developers, translators, and user interface
designers are the main target audience of this document.
Generally, as the MeeGo Touch UI Framework uses Qt as it?s base, some of the
Qt internationalisation practices also apply. However, the MeeGo Touch UI
Framework provides additional functionalities, hence it is recommended that
developers always use MeeGo Touch UI Framework classes to achieve full
internationalisation support in their applications.
This document discusses several general internationalisation guidelines for
user interface designers. They are general enough and may also be applicable in
another projects and vice versa.
********** AArrcchhiitteeccttuurree **********
[i18n-class.png]
********** SSuuppppoorrtteedd LLaanngguuaaggeess aanndd ccaalleennddaarr ssyysstteemmss **********
Below is the list of officially supported languages both for writing systems
and text rendering:
* American English
* Arabic
* _B_a_s_q_u_e
* Brazilian Portuguese
* British English
* Canadian French
* Catalan
* Chinese Simplified
* Chinese Traditional
* Chinese Hongkong
* Danish
* Dutch
* Finnish
* French
* Galician
* German
* Greek
* Hebrew
* Hindi
* _I_n_d_o_n_e_s_i_a_n
* Italian
* Latin American Spanish
* _M_a_l_a_y
* Norwegian
* _P_e_r_s_i_a_n
* Portuguese
* Russian
* Spanish
* Swedish
* Thai
* Turkish
* Ukranian
* Urdu
Although the implementation contains support for several calendar systems,
officially the MeeGo Touch UI Framework currently supports only Gregorian and
Islamic calendar.
********** LLooccaallee ssyysstteemm **********
******** SSeettttiinnggss ********
The MeeGo Touch UI locale system uses the following main settings:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _MM_LL_oo_cc_aa_ll_ee_ _mm_aa_ii_nn_ _ss_ee_tt_tt_ii_nn_gg_ss_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|_gg_cc_oo_nn_ff_ _kk_ee_yy_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_dd_ee_ss_cc_rr_ii_pp_tt_ii_oo_nn_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ee_xx_aa_mm_pp_ll_ee_ _vv_aa_ll_uu_ee_ _ _ _ _ _ _ _ _ _ _ _ |
|_/_m_e_e_g_o_t_o_u_c_h_/_i_1_8_n_/_l_a_n_g_u_a_g_e_|_m_a_i_n_ _l_a_n_g_u_a_g_e_ _s_e_t_t_i_n_g_ _ _ _ _|_e_n___U_S_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|/meegotouch/i18n/lc_time |for date, time, and |ar at calendar=islamic |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_c_a_l_e_n_d_a_r_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|/meegotouch/i18n/ |for sorting |de_DE at collation=phonebook|
|_l_c___c_o_l_l_a_t_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|/meegotouch/i18n/ |formatting of numbers |hi |
|_l_c___n_u_m_e_r_i_c_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|/meegotouch/i18n/ |for formatting of amounts|fi_FI at currency=EUR |
|_l_c___m_o_n_e_t_a_r_y_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_o_f_ _m_o_n_e_y_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
Each of these settings can be set to a ICU locale specifier as described in the
_I_C_U_ _U_s_e_r_ _G_u_i_d_e.
The value of /meegotouch/i18n/language (?Language?) tells the locale system
about the UI language of the device. This affects all UI texts, writing
direction and widget layouts (It does not affect the user content, i.e. it does
not affect things like the browser content language etc.).
?Language? is also used as the default for time, date, calendar, sorting,
number formatting, and currency formatting if the more specific settings are
empty.
?LcTime? selects how time and date are formatted. If it is left empty the
value of ?Language? is used. Examples: ar at calendar=islamic means to format
date and time the Arabic way using Islamic calendar, ar at calendar=gregorian
would use Arabic formatting but with Gregorian calendar, fi_FI would use
Finnish formatting rules for time and date.
?LcCollate? selects how textual data is sorted. If it is left empty the
value of ?Language? is used. Examples: de_DE at collation=phonebook sorts the
way German phone books are sorted, de_DE at collation=standard (or de_DE ) sorts
the ?normal? way German dictionaries are sorted. zh_CN at collation=pinyin
sorts Chinese according to the pinyin phonetics, zh_CN at collation=stroke sorts
Chinese according to the stroke count of the characters.
?LcNumeric? selects how numbers are formatted. If it is left empty the
value of ?Language? is used. Examples: hi formats numbers according to the
rules for the Hindi language, using localized digits, i.e. _D_e_v_a_n_a_g_a_r_i_ _n_u_m_e_r_a_l_s
(?,?,?,?,?,?,?,?,?,?), ar formats numbers using _E_a_s_t_e_r_n
_A_r_a_b_i_c_ _n_u_m_e_r_a_l_s (?,?,?,?,?,?,?,?,?,?), de_CH formats the Swiss German
way with apostrophes as thousands separators (12'345'670.89), and en_US formats
the American English way (12,345,670.89).
?LcMonetary? selects how currency amounts are formatted. If it is left
empty the value of ?Language? is used.
******** IInniittiiaalliissaattiioonn ********
A MeeGo Touch UI application is normally using the system default _M_L_o_c_a_l_e
object;
_M_L_o_c_a_l_e myLocale; // get the current locale
If the application needs to use different locale settings than the system
locale, then a _M_L_o_c_a_l_e is created by making an instance of a _M_L_o_c_a_l_e object:
_M_L_o_c_a_l_e locale ("fi_FI");
where "fi" and "FI" mean to use Finnish language in Finland.
******** CCoollllaattoorr ********
To do collation, get the comparator with _M_L_o_c_a_l_e_:_:_c_o_l_l_a_t_o_r_(_) method or create
it MCollator() for default locale collator. This object acts as a functor and
can be passed to Qt's qSort() or any other sorting methods. The comparator
basically does the comparison of two items as "lessThan" function and returns
true if the first parameter should come before the second one.
If other collation system than the locale's default is needed, then use
setCollation() method before getting the comparator. After all are set then the
sorting can be started by using Qt's qSort() function.
To use the default collation:
_Q_S_t_r_i_n_g_L_i_s_t sl; // This contains the strings which need to be sorted
...
MLocale myLocale; // get the current locale
_M_C_o_l_l_a_t_o_r c = myLocale._c_o_l_l_a_t_o_r(); // getting the comparator
...
qSort(sl.begin, sl.end, c); // start to sort!
...
To use the different collation:
_Q_S_t_r_i_n_g_L_i_s_t sl; // This contains the strings which need to be sorted
...
MLocale myLocale; // get the current locale
myLocale._s_e_t_C_o_l_l_a_t_i_o_n (_M_L_o_c_a_l_e_:_:_P_h_o_n_e_b_o_o_k_C_o_l_l_a_t_i_o_n); // sort using German's
phonebook sorting order
_M_C_o_l_l_a_t_o_r c = myLocale._c_o_l_l_a_t_o_r(); // getting the comparator
...
qSort(sl.begin, sl.end, c); // start to sort!
...
******** FFoorrmmaatttteerrss ********
MeeGo Touch UI comes with several formatters for several data types. (Almost)
Always use the formatters before displaying locale-dependant data to the screen
to achieve uniformity and consistency of the data presentation.
****** NNuummbbeerrss ******
To format a number use formatNumber() method. It works with qlonglong, short,
int, double, and float data types.
...
MLocale myLocale; // get the current locale
...
int number = 1234;
_Q_S_t_r_i_n_g formattedNumber = myLocale._f_o_r_m_a_t_N_u_m_b_e_r(number); // format the number,
the result is in QString
...
****** DDaattee aanndd ttiimmee ******
Use formatDateTime() to format the date and time.
...
MLocale myLocale; // get the current locale
...
QDateTime now = _Q_D_a_t_e_T_i_m_e_:_:_c_u_r_r_e_n_t_D_a_t_e_T_i_m_e();
_Q_S_t_r_i_n_g formattedDateTime = myLocale._f_o_r_m_a_t_D_a_t_e_T_i_m_e(now);
...
As mentioned previously, date format can also be affected by the device
language, region, and calendar settings.
...
MLocale myLocale; // get the current locale
...
QDateTime now = _Q_D_a_t_e_T_i_m_e_:_:_c_u_r_r_e_n_t_D_a_t_e_T_i_m_e();
_Q_S_t_r_i_n_g formattedDateTime = myLocale._f_o_r_m_a_t_D_a_t_e_T_i_m_e(now, _M_L_o_c_a_l_e_:_:
_I_s_l_a_m_i_c_C_a_l_e_n_d_a_r); // format using IslamicCalendar
...
Custom formatting is supported with ISO-14652 format (also used in libc's
strftime ) by using formatDateTime() .
****** PPeerrcceennttaaggee ******
formatPercent() is used to format a percentage value.
...
MLocale myLocale; // get the current locale
...
double percent = 0.29; // = 29%
int decimals = 2;
_Q_S_t_r_i_n_g formattedPercentage = myLocale._f_o_r_m_a_t_P_e_r_c_e_n_t(percent, decimals);
...
****** CCuurrrreennccyy ******
To format any amount of money with a currency, use formatCurrency() method.
...
MLocale myLocale; // get the current locale
...
double money = 150.40;
_Q_S_t_r_i_n_g currency = "EUR";
_Q_S_t_r_i_n_g formattedCurrency = myLocale._f_o_r_m_a_t_C_u_r_r_e_n_c_y(money, currency);
...
****** NNaammee ******
Use MName class to populate the name information, and use MLocale::formatName()
method to format the name.
****** AAddddrreessss ******
Use MAddress class to populate the address information, and use format() method
to format the name using the format specified as parameter.
******** CCaalleennddaarr ********
_M_L_o_c_a_l_e provides Gregorian as well as non-Gregorian calendar support. Use
formatDateTime() to format the date according to the custom of the selected
calendar. To set another calendar than the default Gregorian calendar, use
setCalendarType() method.
_M_L_o_c_a_l_e myLocale; // get the current locale
...
myLocale._s_e_t_C_a_l_e_n_d_a_r_T_y_p_e(_M_L_o_c_a_l_e_:_:_I_s_l_a_m_i_c_C_a_l_e_n_d_a_r); // set the calendar to use
Islamic calendar
...
Further date manipulations can be done using _M_C_a_l_e_n_d_a_r object.
******** IItteerraattiinngg wwoorrddss ********
On general case iterating words in a string is not possible by searching
whitespace: e.g. thai language just concatenates words and in chinese language
a character is a word. For this need a _M_B_r_e_a_k_I_t_e_r_a_t_o_r class can be used. It is
constructed with a locale and a string and provides an interface for iterating
word boundaries. Following example iterates word boundaries from beginning to
the end:
_M_L_o_c_a_l_e myLocale; // current locale
_Q_S_t_r_i_n_g text("this is text to be iterated");
_M_B_r_e_a_k_I_t_e_r_a_t_o_r _i_t_e_r_a_t_o_r(myLocale, text, _M_B_r_e_a_k_I_t_e_r_a_t_o_r_:_:_W_o_r_d_I_t_e_r_a_t_o_r);
while (_i_t_e_r_a_t_o_r.hasNext()) {
int next = _i_t_e_r_a_t_o_r.next();
...
}
********** TTrraannssllaattiioonn ssyysstteemm **********
******** LLooggiiccaall IIDD aanndd eennggiinneeeerriinngg EEnngglliisshh ********
The MeeGo Touch UI Framework can use both the Qt standard tr() method or the
idbased _q_t_T_r_I_d_(_) method. For the Nokia internal localisation process, only
qtTrId() should be used. Other parties using logical IDs instead of engineering
English IDs for the UI messages might also find qtTrId() useful.
Contrary to the approach of using engineering English as the message ids, which
is commonly used in the open source community, the logical ID approach uses
message ids which are guaranteed to be globally unique.
With qtTrId(), the logical ID is an argument of the function and the
engineering English is supplied as a comment above. See the example in the Qt
documentation of _q_t_T_r_I_d_(_), reproduced here for convenience:
//% "%Ln fooish bar(s) found.\n"
//% "Do you want to continue?"
_Q_S_t_r_i_n_g text = qtTrId("qtn_foo_bar", n);
******** GGeenneerraattiinngg tthhee eennggiinneeeerriinngg EEnngglliisshh ..qqmm ffiilleess ********
If no translation files at all are available, qtTrId() would return the logical
ID which looks pretty ugly and is not nice for testing the user interface.
But from code which uses qtTrId() with the special engineering English
comments, .qm files with engineering English translations can be generated
automatically. This can be done as follows:
Create a subdirectory translations/ somewhere in your source tree. In that
folder, create a translations.pro file with the contents:
LANGUAGES = # empty if only engineering English is needed!
CATALOGNAME = foobar # what ever catalog name you want to use
SOURCEDIR = $$PWD/.. # more then one directory is possible
TRANSLATIONDIR = $$PWD
include($$[QT_INSTALL_DATA]/mkspecs/features/meegotouch_defines.prf)
include($$[QT_INSTALL_DATA]/mkspecs/features/meegotouch_translations.prf)
Introducing the extra translations/translations.pro file makes it necessary to
add the translations/ directory to the list of sub-directories in a .pro file
higher up in the directory hierarchy. I.e. you usually need something like
SUBDIRS = \
src \
translations \
...
After doing that, a foobar.ts and a foobar.qm file which contain the
engineering English translations will be automatically generated when calling
?make? for your project. And ?make install? will install foobar.qm to
the usual place as described in section _T_r_a_n_s_l_a_t_i_o_n_ _d_a_t_a_ _s_t_o_r_a_g_e.
Minor detail: with the above setup, when creating foobar.qm from foobar.ts,
lrelease uses the option -markuntranslated to prepend the string ?!! ? at
the beginning of each engineering English string. I.e. if the engineering
English string in the source code is ?Hello?, it will be written as ?!!
Hello? into the foobar.qm file and will be displayed as ?!! Hello? at
runtime. This is to make it obvious that engineering English for testing
purposes is displayed and not the ?real? English which is done by the
translators.
******** TTrraannssllaattiioonn ssyysstteemm sseettuupp ********
To setup the translation system using qtTrId(), you can use the following code
snippets in your main function:
By default, the system uses the name of the application executable (without the
directory path) as the name for the file of the translation catalog and loads
this catalog automatically. So you can start using qtTrId() immediately:
...
int main(int argc, char** argv){
...
_M_A_p_p_l_i_c_a_t_i_o_n app (argc, argv);
...
//% "hello"
qtTrId("xxx_hello");
...
}
...
In the above example, if the application executable is for example /usr/bin/
foo, i.e. the base file name of the executable is foo, the translation catalog
<top-directory>/foo_<locale-code>.qm will be used.
If you need to specify a file for the translation catalog wich differs from the
name of the executable you can use the optional third parameter appIdentifier
of the _M_A_p_p_l_i_c_a_t_i_o_n constructor as in this example:
...
int main(int argc, char** argv){
...
_M_A_p_p_l_i_c_a_t_i_o_n application(argc, argv, "bar");
...
//% "hello"
qtTrId("xxx_hello");
...
}
...
In the above example, the translation catalog <top-directory>/bar_<locale-
code>.qm will be used no matter what the file name of the application
executable is.
But note that the appIdentifier is used not only for localization files but
also for themes. I.e. changing the appIdentifier will also affect themes.
Usually this should be no problem because in most cases these should be kept
the same, if possible.
When it is not possible to use the appIdentifier to specify the translation
catalog which should be loaded, one can use the installTrCatalog() function to
load a translation catalog with a completely different name as in this example:
...
int main(int argc, char** argv){
...
_M_A_p_p_l_i_c_a_t_i_o_n app (argc, argv);
// create a MLocale. Without parameters in the constructor,
// it gets a copy of the system default locale, which may already
// have some translation catalogs, for example it usually already
// has the ?common? translation catalog.
_M_L_o_c_a_l_e locale;
// add a different translation catalog for this locale.
// This catalog is added to the list of already loaded catalogs.
// Catalogs loaded last are used with highest priority.
locale._i_n_s_t_a_l_l_T_r_C_a_t_a_l_o_g("othercatalog");
// the order is important, set the locale as the default *after*
// installing the translation catalog:
_M_L_o_c_a_l_e_:_:_s_e_t_D_e_f_a_u_l_t(locale);
...
// Now the following call to qtTrId() will use messages
// from the translation catalog file othercatalog_<locale-code>.qm
// with highest priority:
//% "hello"
qtTrId("xxx_hello");
...
}
...
To setup your translation using the tr() method known from regular Qt programs,
you can use the installTrCatalog() method as in the following example:
...
int main(int argc, char** argv){
...
_M_A_p_p_l_i_c_a_t_i_o_n app (argc, argv);
// create a MLocale. Without parameters in the constructor,
// it gets a copy of the system default locale, which may already
// have some translation catalogs, for example it usually already
// has the ?common? translation catalog.
_M_L_o_c_a_l_e locale;
// install the catalog for use with tr(). It is probably
// a good idea to use the application name for "mycatalog":
locale._i_n_s_t_a_l_l_T_r_C_a_t_a_l_o_g("mycatalog");
// Make the locale the default to enable the message catalog just
// installed above for tr(). The order is important, do this *after*
// installing the translation catalog:
_M_L_o_c_a_l_e_:_:_s_e_t_D_e_f_a_u_l_t(locale);
...
// Now you can use tr() as in regular Qt programs:
tr("hello");
...
}
...
******** TTrraannssllaattiioonn ssyysstteemm sseettuupp iinn lliibbrraarriieess ********
Let?s say there is an _M_A_p_p_l_i_c_a_t_i_o_n ?foo? which uses a library
?libbar?. And the library ?libbar? also uses the MeeGo Touch Framwork
and has some translations of its own which are in files like
libbar_<locale_name>.qm.
Now the question is how to load the ?libbar? translation catalog.
On way to do it would be to let the application ?foo? load it, i.e.
?foo? would do something like
...
int main(int argc, char** argv){
...
_M_A_p_p_l_i_c_a_t_i_o_n app (argc, argv);
...
// translations from the ?foo? translation catalog
// can already be used without any setup when the binary
// name is identical to the catalog name:
//% "hello"
qtTrId("qtn_foo_hello");
...
// get a copy of the system default locale
// which already has the translation catalogs for ?common? and ?foo?
// installed:create a MLocale. Without parameters in the constructor,
_M_L_o_c_a_l_e locale;
// add a the ?libbar? translation catalog:
locale._i_n_s_t_a_l_l_T_r_C_a_t_a_l_o_g("libbar");
// set the locale with the ?libbar? catalog added as the
// new system default:
_M_L_o_c_a_l_e_:_:_s_e_t_D_e_f_a_u_l_t(locale);
...
// and a call of a function in the library ?libbar?
// may use messages from the ?libbar? translation catalog:
...
libbar_some_function();
...
}
...
The disadvantage of this way of doing it is that the application ?foo?
needs to know how the translation catalog of ?libbar? is called and maybe
even require an packages like ?libbar-l10n-*?. That creates unnecessary
dependencies between ?foo? and ?libbar?. To avoid this, the recommended
way of loading the ?libbar? translations is letting the ?libbar?
library take care of this. I.e. ?libbar? somewhere has an initialization
function like
...
void libbar_init() {
...
_M_L_o_c_a_l_e locale; // get copy of system locale
locale._i_n_s_t_a_l_l_T_r_C_a_t_a_l_o_g("libbar"); // add a the ?libbar? translation
catalog
_M_L_o_c_a_l_e_:_:_s_e_t_D_e_f_a_u_l_t(locale); // set new system default with ?libbar?
catalog added
...
// other initialization stuff if necessary
...
}
...
The application ?foo? then does not have to load the translations for
?libbar? and only does:
...
int main(int argc, char** argv){
...
_M_A_p_p_l_i_c_a_t_i_o_n app (argc, argv);
...
// translations from the ?foo? translation catalog
// can already be used without any setup when the binary
// name is identical to the catalog name:
//% "hello"
qtTrId("qtn_foo_hello");
...
// initialize ?libbar? which also installs the ?libbar?
// catalog into the default system locale:
libbar_init();
// now a call of a function in the library ?libbar?
// may use messages from the ?libbar? translation catalog:
...
libbar_some_function();
...
}
...
Instead of having a public initialization function in ?libbar? one could
also make ?libbar? call some internal initialization code when any public
function of ?libbar? is used for the first time, i.e. one could design
?libbar? to make the following code already work:
...
int main(int argc, char** argv){
...
_M_A_p_p_l_i_c_a_t_i_o_n app (argc, argv);
...
// translations from the ?foo? translation catalog
// can already be used without any setup when the binary
// name is identical to the catalog name:
//% "hello"
qtTrId("qtn_foo_hello");
...
// Calling any public function in the library ?libbar?
// triggers installation of the ?libbar? translation catalog
// into the default system locale and ?libbar? can then
// use messages from its translation catalog:
...
libbar_some_function();
...
}
...
Whether a special initialization function is used or not, the important thing
is that ?libbar? does the installing of its translation catalog into the
system default locale. The application ?foo? then does not need to know how
the catalog is called and does not need to require translation packages of
?libbar?. ?libbar? should require its translation package of course.
But this way of doing it reduces the dependencies between ?foo? and
?libbar?.
******** TTrraannssllaattiinngg mmeessssaaggeess ********
qtTrId() is used to translate the UI messages.
_Q_S_t_r_i_n_g qtTrId ( const char * id, int n = -1 )
id is the logical name for a UI message which needs to be translated. If n >=
0, all occurrences of %Ln or %n in the resulting string are replaced with a
decimal representation of n. In addition, depending on n?s value, the
translation text may vary.
The difference between %Ln and %n is that %Ln may be replaced using localized
numerals like Arabic-Indic numerals in Arabic locales whereas %n is always
replaced using Arabic (= Western) numerals.
_q_t_T_r_I_d_(_) is useful only if the project is using logical names as the UI
message. If your project is using English string then use tr() instead.
******** PPaarraammeetteerrss iinn ttrraannssllaattiioonnss ********
The positional parameters %1 to %99 and %L1 to %L99 which are used in _Q_S_t_r_i_n_g
can also be used in translations for the MeeGo Touch UI Framework. For a
description of %L1 to %L99 see also the documentation of _Q_L_o_c_a_l_e.
For parameters which are integer numbers, %L1 to %L99 is a better choice than
%1 to %99 because %L1 to %L99 automatically do locale specific number
formatting which achieves the same results as using MLocale?s formatNumber()
for the current system locale.
Let?s illustrate the behaviour in detail with an example. We assume that an
application is running with the language locale settings set to Arabic to get
Arabic translations (for example if the gconf key ?/meegotouch/i18n/
language? is set to ?ar?) and the numeric locale settings are also set to
Arabic to get Arabic number formatting (for example if the gconf key ?/
meegotouch/i18n/lc_numeric? is also set to ?ar? or is empty and this the
numeric locale settings are inherited from the language settings).
Now a message id is translated using qtTrId("xx_some_message_id"). And let?s
assume that the Arabic translation of this happens to be ?%L1 %2?.
The following example code illustrates how numbers used as parameters would be
formatted in that case:
_Q_S_t_r_i_n_g translation = qtTrId("xx_some_message_id");
// ?translation? now contains ?%L1 %2?.
translation._a_r_g("123456.7").arg("123456.7");
// The line above returns ?123456.7 123456.7?.
//
// I.e. if strings are used as the arguments
// there is no difference in the behaviour of %L1 and %2.
translation._a_r_g(123456).arg(123456);
// The line above returns ???????? 123457?
//
// Here the arguments are numbers and we can see the
// difference: In case of %L1 the number is formatted
// by using QLocale which is set by MLocale to the numeric
// settings of MLocale. Therefore, %L1 is replaced by
// Arabic-Indic numerals here. However, %2 is still replaced
// by Western-Arabic numerals, and has no thousands separators either.
// In English locale the replacement for %2 would be ?123457?
// and not ?123,456?, the place holders %1 to %99
// never do any automatic locale specific number formatting.
translation._a_r_g(123456.7).arg(123456.7);
// The line above returns ???????? 123457?
//
// Note that the formatted result shows only the integer part of the
// floating point numbers.
// Number formatting using %L1 to %L99 or %1 to %99 works
// only for integers.
_M_L_o_c_a_l_e locale;
translation._a_r_g(locale._f_o_r_m_a_t_N_u_m_b_e_r(123456.7)).arg(locale._f_o_r_m_a_t_N_u_m_b_e_r
(123456.7));
// The line above returns ?????????? ??????????
//
// Here the number formatting is done using MLocale.
// locale.formatNumber(123456.7) already returns a QString
// containing ???????????, i.e. the arguments used for %L1
// and %2 in the translations are not numbers but QStrings.
// Therefore, no further formatting is done by %L1 and %2.
Passing an integer number as the argument from L1 and letting _Q_L_o_c_a_l_e format
that number always gives the same result as passing the the result of
formatNumber() using the system _M_L_o_c_a_l_e for that integer. The reason is that
the MeegoTouch framework always sets _Q_L_o_c_a_l_e to the value of the numeric
setting of the system default _M_L_o_c_a_l_e and both the number formatter in _M_L_o_c_a_l_e
and the number formatter in _Q_L_o_c_a_l_e use the CLDR data for the number format.
******** PPllaaccee hhoollddeerrss iinn mmeessssaaggee iiddss ********
Message ids do not have to indicate whether the translation for this id
contains place holders or not. For example if the message id is
?xx_greet_user" and the English translation is ?Hello 1?, then the
following code works fine:
// The following returns ?Hello Joe? if the translation is ?Hello
%1?.
// If no translation can be found it returns ?xx_greet_user?:
qTrId("xx_greet_user").arg("Joe");
It is possible to include place holders in message ids, for example if the
message id for the translation were ?xx_greet_user_1?, the following code
would work just as well:
// The following returns ?Hello Joe? if the translation is ?Hello
%1?
// If no translation can be found it returns ?xx_greet_user_Joe?:
qTrId("xx_greet_user_%1").arg("Joe");
So it doesn?t matter whether a message id for a translation which contains
place holders contains these place holders itself or not.
Although place holders in message ids are possible, the message ids used by
MeeGo Touch never contain any place holders. The message ids used in MeeGo
Touch only use lowercase letters from ?a? to ?z? and underscores
?_?.
This is perfectly OK and does not cause any problems for translations which use
place holders.
******** PPlluurraall mmeessssaaggeess ********
In a plural message, pass the number to select the correct plural translation
as the second argument n in qtTrId() (This works the same way with qtTrId() as
it does with tr()).
int n = messages.count();
//% "%Ln message(s) saved"
showMessage(qtTrId("xx_messages_saved", n));
Usually, the number of different translations used for plural, among which the
parameter ?n? selects the appropriate one, depends on the language, see
also the _??_?_Q_t_ _T_r_a_n_s_l_a_t_i_o_n_ _R_u_l_e_s_ _f_o_r_ _P_l_u_r_a_l_s_??_? and the _??_?_C_L_D_R_ _L_a_n_g_u_a_g_e_ _P_l_u_r_a_l
_R_u_l_e_s_??_?.
However, for the Meego Touch UI framework, it has been decided to use only 2
plural forms and only English rules. I.e. the .ts translation files used by the
Meego Touch UI framework aallwwaayyss contain oonnllyy ttwwoo different translations for
plural and are aallwwaayyss marked in the xml as English language translation files,
even if the language is not English.
For example if a .ts file for English translation contains something like
<?xml version="1.0" encoding="UTF-8"?>
<TS language="en" version="3.0">
<context>
<name>message_context</name>
...
<message id="xx_amount_events" numerus="yes">
<source>%Ln event</source>
<translation>
<numerusform>%Ln event</numerusform>
<numerusform>%Ln events</numerusform>
</translation>
</message>
...
<message id="xx_time_day" numerus="yes">
<source>%Ln day</source>
<translation>
<numerusform>%Ln day</numerusform>
<numerusform>%Ln days</numerusform>
</translation>
</message>
...
</context>
</TS>
the corresponding Russian translation file might contain something like:
<?xml version="1.0" encoding="UTF-8"?>
<TS language="en" version="3.0">
<context>
<name>message_context</name>
...
<message id="xx_amount_events" numerus="yes">
<source>%Ln event</source>
<translation>
<numerusform>%Ln ???????</numerusform>
<numerusform>???????: %Ln</numerusform>
</translation>
</message>
...
<message id="xx_time_day" numerus="yes">
<source>%Ln day</source>
<translation>
<numerusform>%Ln ????</numerusform>
<numerusform>%Ln ??.</numerusform>
</translation>
</message>
...
</context>
</TS>
Note that this Russian translation file has ?language="en"? in the header
and thus English rules are used to select the plural forms, i.e. the first
plural form is selected if ?n? is equal to 1, the second plural form for
all other cases.
Usually, Russian would use one plural form for??n? in 1, 21, 31, 41, 51,
61?, another one for ?n? in 2-4, 22-24, 32-34?, and yet another one for
?n? in 0, 5-20, 25-30, 35-40?.
If only 2 forms with English rules are used as above, i.e. only ?n? equal
to 1 is special cased, the second plural form has to be translated in a way
that it is acceptable for all other values of ?n?.
In the Russian example translation file above this is in one case achieved by
abbreviating, i.e. using ?%Ln ??.? for all ?n? not equal to one and
thus hide the different plural forms with the abbreviation dot. In the other
case, the number is grammatically ?detached?, i.e. by writing
????????: %Ln? the part of the translation before the ?:? is
detached from the part with the number and thus the word ?????????
does not need to change for different values of ?n?.
****** %%LLnn vveerrssuuss %%LL11 iinn pplluurraall mmeessssaaggeess ******
Messages using plural should use the place holder %Ln and not %L1, i.e. the
source code should should look like
int n = messages.count();
//% "%Ln message(s) saved"
showMessage(qtTrId("xx_messages_saved", n));
and the .ts file with the translations should look like:
<?xml version="1.0" encoding="UTF-8"?>
<TS language="en" version="3.0">
<context>
<name>message_context</name>
...
<message id="xx_amount_events" numerus="yes">
<source>%Ln event</source>
<translation>
<numerusform>%Ln message saved.</numerusform>
<numerusform>%Ln messages saved.</numerusform>
</translation>
</message>
...
</context>
</TS>
The second parameter ?n? of qtTrId() does two things:
* It selects the correct translation for this value of ?n? (note that
if no translation exists and the engineering English fallback is used,
the same message will be displayed for all values of ?n? because
there is only one version of the engineering English. I.e. in the above
example ?1 message(s) saved? would be shown if ?n? is 1 and ?2
message(s) saved? if ?n? is 2).
* It replaces the place holder %Ln with the value of the number ?n?,
formatted in the locale specific way, possibly using localized numerals
(%n would also be replaced by the value of ?n? but would not be
formatted in a locale specific way).
If %L1 were used instead of %Ln in the translation, the second parameter of
qtTrId() would still select the correct translation for the value of ?n?
but would not replace %L1, i.e. in this case the code
showMessage(qtTrId("xx_messages_saved", 2));
would display ?%L1 messages saved.?. If it is known that the plural
translations mistakenly use %L1 instead of %Ln, one can work around the issue
by using an extra .arg() in the code like this:
showMessage(qtTrId("xx_messages_saved", 2).arg(2));
In this example, the ?2? used as the second parameter of would select that
correct plural form, i.e. ?%L1 messages saved.? and the .arg(2) would
replace the %L1 with 2 so the final result would be ?2 messages saved.? as
desired. But as soon as the translation is fixed to use the correct %Ln this
code prints a warning
QString::arg: Argument missing: "2 messages saved." , 2
because the .arg(2) tries to replace a %L1 which is not there.
******** TTrraannssllaattiioonn ddaattaa ssttoorraaggee ********
The convention for the path to store the compiled translation data (in .qm
format) on the device is:
<top-directory>/<catalog-name>_<locale-code>.qm
top-directory can be anywhere on the device. locale-code is something like
en_US for US-English, en_GB for Britisch English, zh_CN for Simplified Chinese,
de_DE for German in Germany, de_CH for Swiss German, etc. <catalog-name> is
usually the name of the application. If a translation for a more specific
locale name like en_US cannot be found, a less specific locale name like en is
tried. For example, if the application name is foo and the locale name is
en_US, the first one of the following files which exists is used:
<top-directory>/foo_en_US.qm
<top-directory>/foo_en_US
<top-directory>/foo_en.qm
<top-directory>/foo_en
<top-directory>/foo.qm
<top-directory>/foo
See also the documentation of _Q_T_r_a_n_s_l_a_t_o_r_:_:_l_o_a_d_(_).
The top-directory used by default is /usr/share/l10n/meegotouch (This is
defined as M_TRANSLATION_DIR in meegotouch_defines.prf which can be found in ./
mkspecs/features/meegotouch_defines.prf` in the libmeegotouch source code).
`/usr/share/l10n/meegotouch` is also the default directory used by translation
packages to store the .qm files. Applications can set additional search paths
by using _M_L_o_c_a_l_e_:_:_s_e_t_T_r_a_n_s_l_a_t_i_o_n_P_a_t_h_s_(_) and _M_L_o_c_a_l_e_:_:_a_d_d_T_r_a_n_s_l_a_t_i_o_n_P_a_t_h_(_) .
This supports the variability needed for over-the-air translation installation
as well as for user defined translations.
******** TTrraannssllaattiioonn ddaattaa ppaacckkaaggiinngg ********
The packaging of translations into debian packages is illustrated here using
the demo application ?widgetsgallery? as an example.
_ _ _ _ _ _EE_xx_aa_mm_pp_ll_ee_ _ff_oo_rr_ _pp_aa_cc_kk_aa_gg_ee_ _nn_aa_mm_ee_ss_ _aa_nn_dd_ _cc_oo_nn_tt_ee_nn_tt_ss_ _oo_ff_ _tt_rr_aa_nn_ss_ll_aa_tt_ii_oo_nn_ _pp_aa_cc_kk_aa_gg_ee_ss_ _ _ _ _
|_PP_aa_cc_kk_aa_gg_ee_ _nn_aa_mm_ee_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_CC_oo_nn_tt_ee_nn_tt_ss_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| |/usr/share/l10n/meegotouch/ |
| |widgetsgallery.qm |
| |/usr/share/doc/meegotouch-demos-|
|meegotouch-demos-widgetsgallery-l10n- |widgetsgallery-l10n-engineering-|
|engineering-english |english/widgetsgallery.ts |
| |/usr/share/doc/meegotouch-demos-|
| |widgetsgallery-l10n-engineering-|
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_e_n_g_l_i_s_h_/_c_h_a_n_g_e_l_o_g_._D_e_b_i_a_n_._g_z_ _ _ _ _ |
| |/usr/share/l10n/meegotouch/ |
| |widgetsgallery_ar.qm |
|meegotouch-demos-widgetsgallery-l10n-ar|/usr/share/doc/meegotouch-demos-|
| |widgetsgallery-l10n-ar/ |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_c_h_a_n_g_e_l_o_g_._D_e_b_i_a_n_._g_z_ _ _ _ _ _ _ _ _ _ _ _ _ |
|_._._._ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_._._._ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| |/usr/share/l10n/meegotouch/ |
|meegotouch-demos-widgetsgallery-l10n- |widgetsgallery_zh_CN.qm |
|zh-cn |/usr/share/doc/meegotouch-demos-|
| |widgetsgallery-l10n-zh-cn/ |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_c_h_a_n_g_e_l_o_g_._D_e_b_i_a_n_._g_z_ _ _ _ _ _ _ _ _ _ _ _ _ |
Every application needing translations should supply also a debian package
containing the ?engineering English? translations. The package name for the
engineering English translations should end with -l10n-engineering-english as
in the above example. The package name ?...-engineering-english? should
make it clear that these are not real translations, instead they are completely
auto-generated from the source code.
In the above example, the package ?meegotouch-demos-widgetsgallery-l10n-
engineering-english? contains ?widgetsgallery.qm? and
?widgetsgallery.ts?. ?widgetsgallery? is the name of the application
executable. ?widgetsgallery.ts? is automatically generated from the source
code using ?lupdate?. ?widgetsgallery.qm? is automatically generated
from ?widgetsgallery.ts? using ?lrelease?. The make files in the
application source code should contain support to do this automatically when
building the application without extra effort (The current source code of
widgetsgallery already gives an example how this can be done).
The ?widgetsgallery.qm? file serves several purposes:
1. It is used at runtime by the application to display engineering English
instead of message ids to make testing the application easier while no
real translations are available yet.
2. It supplies fallback engineering English when real translations are
available but incomplete. Of course this should never happen in the final
product but it will happen during the development and testing and then
this fallback engineering English is useful.
3. It gives us an easy way to extract a list of ids which are actually used
in the source code. Using the tool ?lconvert? one can easily extract
all ids from a .qm file. If all meegotouch applications supply ?...-
l10n-engineering-english? packages, one can easily install all these
packages (for example with ?apt-get?) and then extract all ids which
are actually used. Then these ids can be used for cross-checking with the
ids used in the specifications and in the real translations.
?widgetsgallery? is only a test application used by the libmeegotouch
developers for testing and demos. Therefore, the localisation department will
not supply translations for ?widgetsgallery?. The libmeegotouch developers
supply some demo translations for ?widgetsgallery? to test their code and
to make sure the system works.
Only because of this, ?widgetsgallery? has some ?real? translation
packages like ?meegotouch-demos-widgetsgallery-l10n-zh-cn? containing ?/
usr/share/l10n/meegotouch/widgetsgallery_zh_CN.qm? (see the table above). In
that respect, ?widgetsgallery? is an exception.
For a ?real? application, say ?camera? which is intended to be shipped
to the customer, the ?real? translation packages are supplied by the
translation department, not by the developers. I.e. the developers will only
supply ?camera-l10n-engineering-english? and all the other packages
?camera-l10n-ar?, ?camera-l10n-zh-cn?, ..., will be supplied by the
translation department.
As long as the real translations are still missing, the engineering English is
displayed. As soon as the real translations are available and installed, they
are used automatically. As can be seen in the above table, there is no file
conflict between the engineering English packages and the real translations,
they can both be installed at the same time without problems.
For the final product, the engineering English packages can be omitted. If it
has been verified during the testing phase that the ?real? translations are
complete, the engineering English is not needed anymore.
******** TTrraannssllaattiioonn ffoorr ..ddeesskkttoopp ffiilleess ********
The translation of .desktop files for MeeGo Touch UI differs a bit from the
usual practise of Freedesktop.org. The rationale behind it is that we have
different localisation processes which make it impossible to modify the source
of .desktop files during build time. To accommodate the special needs of our
localisation processes, the .desktop file shall contain at least two extra
(key, value) pairs:
* X-MeeGo-Logical-Id=<logical name>: The value for this key provides the
logical name of the section name
* X-MeeGo-Translation-Catalog=<catalog name>: The value for this key
provides the catalog where the logical name exists
For example:
[Desktop Entry]
# engineering english
Name=Setting
# logical name of "Setting"
X-MeeGo-Logical-Id=xx_setting_something
# the catalog name
X-MeeGo-Translation-Catalog=meegotouchsettings
For the freedesktop specification of the .desktop files see
_h_t_t_p_:_/_/_s_t_a_n_d_a_r_d_s_._f_r_e_e_d_e_s_k_t_o_p_._o_r_g_/_d_e_s_k_t_o_p_-_e_n_t_r_y_-_s_p_e_c_/_l_a_t_e_s_t_/
In MeeGo Touch UI, such .desktop files are parsed using _M_D_e_s_k_t_o_p_E_n_t_r_y.
******** OOvveerr--tthhee--aaiirr ttrraannssllaattiioonn iinnssttaallllaattiioonn ********
FIXME: No settings available now
Translation data can be downloaded to the device and the translation system can
immediately use the new downloaded data.
********** UUII pprrooggrraammmmiinngg **********
******** RReeaaccttiinngg ttoo cchhaannggeess iinn tthhee llooccaallee sseettttiinnggss ********
The current language setting is stored in the gconf key /meegotouch/i18n/
language . From the command line, the current language can be queried using
gconftool-2 like this:
~$ gconftool-2 -g /meegotouch/i18n/language
ar
In the above example, the current language is Arabic. Setting the current
language from the command line can of course also be done with gconftool-2 :
~$ gconftool-2 -t string -s /meegotouch/i18n/language zh_CN
The above command sets the current language to simplified Chinese.
The preferred way to query the current language from a _M_A_p_p_l_i_c_a_t_i_o_n works like
this:
_M_L_o_c_a_l_e currentLocale;
_Q_S_t_r_i_n_g language = currentLocale._n_a_m_e();
_M_L_o_c_a_l_e currentLocale; gets a copy of the system default locale which is
connected to the gconf settings and follows the gconf settings.
Alternatively it is possible to read the gconf settings directly:
_M_G_C_o_n_f_I_t_e_m languageItem("/meegotouch/i18n/language");
_Q_S_t_r_i_n_g language = languageItem.value().toString();
This has the same effect as getting the current system locale and using
currentLocale.name().
Setting the current language permanently from a _M_A_p_p_l_i_c_a_t_i_o_n works like this:
_M_G_C_o_n_f_I_t_e_m languageItem("/meegotouch/i18n/language");
languageItem.set("zh_CN");
One can also set a new current language temporarily from a _M_A_p_p_l_i_c_a_t_i_o_n by
doing:
_M_L_o_c_a_l_e newLocale("zh_CN");
_M_L_o_c_a_l_e_:_:_s_e_t_D_e_f_a_u_l_t(newLocale);
This does not change the gconf settings and therefore this change will be lost
as soon as one of the locale related gconf keys changes again. And it will be
lost when the application restarts. Nevertheless this can be useful for
temporary changes for testing and it is currently the only way to change the
current language on systems without gconf like _W_i_n_d_o_w_s or _M_a_c_ _O_S_ _X.
If a the system locale changes, either because a locale related gconf key
changed or because _M_L_o_c_a_l_e_:_:_s_e_t_D_e_f_a_u_l_t_(_) has been called explicitly by the
application, the following things happen:
* All translation catalogs are reloaded according to the new locale
settings
* QEvent::LanguageChange will be sent to the Application, if necessary.
_M_W_i_n_d_o_w will propagate a QEvent::LanguageChange to all MWidgets on the
scene. A _M_W_i_d_g_e_t which receives this event by calls its retranslateUi()
method.
* QEvent::ApplicationLayoutDirectionChange will be sent to the Application,
if necessary. _M_W_i_n_d_o_w will propagate a QEvent::LayoutDirectionChange to
all MWidgets as appropriate to enable the widgets to change their layout
on the fly.
* The signal settingsChanged() will be emitted by the locale.
* The signal localeSettingsChanged() will be emitted by the _M_A_p_p_l_i_c_a_t_i_o_n .
In most cases, an application doesn?t have to use the above signals
settingsChanged() and localeSettingsChanged() because most stuff like reloading
the translation catalogs already happens automatically. If retranslateUi()
methods are implemented for the widgets used in the application, the language
of the user interface will already change automatically.
Optionally, an application can use these signals though, if it wants to do
additional special things which do not happen automatically. For example:
main.cpp:
#include "foohandlelocalechange.h"
...
int main (int argc, char **argv)
{
...
FooHandleLocaleChange fooHandleLocaleChange;
_Q_O_b_j_e_c_t_:_:_c_o_n_n_e_c_t(&application, SIGNAL(localeSettingsChanged()),
&fooHandleLocaleChange, SLOT(fooHandleLocaleChange()));
...
}
where the FooHandleLocaleChange class looks like:
foohandlelocalechange.h:
class FooHandleLocaleChange : public _Q_O_b_j_e_c_t
{
Q_OBJECT
public slots:
void fooHandleLocaleChange();
};
foohandlelocalechange.cpp:
void FooHandleLocaleChange::fooHandleLocaleChange()
{
// do whatever is needed when the system locale
// changes, but remember that the basic stuff like
// reloading the translation catalogs and changing the layout
// direction already happens automatically.
//
// Therefore, unless you have very special needs, you do not
// need to do anything here.
//
// In any case, do *not* do anything here which changes the
// system default locale again because this would trigger
// an endless loop.
}
******** TThhee rreettrraannssllaatteeUUii(()) mmeetthhoodd ooff MMWWiiddggeett ********
A _M_W_i_d_g_e_t which receives the QEvent::LanguageChange calls its virtual method
virtual void retranslateUi();
MWidgets can reimplement this retranslateUi() method to do whatever is
necessary to retranslate itself, as in the following example:
foopage.h
class FooPage : public _M_W_i_d_g_e_t
{
...
private:
...
_M_L_a_b_e_l* label;
...
};
foopage.cpp
void FooPage::createContent()
{
label = new _M_L_a_b_e_l();
retranslateUi();
}
void _F_o_o_P_a_g_e_:_:_r_e_t_r_a_n_s_l_a_t_e_U_i()
{
...
//% "Label Text"
propertiesLabel->setText(qtTrId("qtn_label_text"));
...
}
This can be quite tricky in some cases but makes it possible to re-translate
the user interface of an application on the fly if the locale settings change.
******** WWiiddggeett mmiirrrroorriinngg aanndd llaayyoouutt ddiirreeccttiioonn ********
Widget mirroring is the automatic behaviour of putting the widgets in the
reverse direction when the language is switched to Right-to-left languages
(such as Arabic or Hebrew). In this direction, the widgets are put following
the natural flow of text writing direction. Widget mirroring works
automatically when the widgets are arranged using _Q_G_r_a_p_h_i_c_s_L_a_y_o_u_t or _M_L_a_y_o_u_t,
with some exceptions with the specialist _M_L_a_y_o_u_t policies.
The layout direction will be automatically set to the correct value by
_M_A_p_p_l_i_c_a_t_i_o_n when the language is changed. The current layout direction can be
obtained from MApplication::layoutDirection() . Note that during the
application lifetime, the direction may change if the user changes it from the
global setting.
If you are developing a widget in which it does not make sense for the layout
to be reversed (for example, a number keypad), then use QGraphicsWidget::
setLayoutDirection() to override the layout direction. If you need to paint
your widget differently in right-to-left mode, simply call `qApp-
>layoutDirection()` and draw as appropriate. If you are implementing a custom
_M_A_b_s_t_r_a_c_t_L_a_y_o_u_t_P_o_l_i_c_y, however, you should use the _M_L_a_y_o_u_t_:_:_l_a_y_o_u_t_D_i_r_e_c_t_i_o_n_(_)
function instead so that the user can override it.
In advanced situations you can handle the QEvent::
ApplicationLayoutDirectionChange() event directly in your widget's event
handler.
********** CCuurrrreenntt ssttaattuuss ooff RRTTLL ssuuppppoorrtt iinn MMWWiiddggeettss **********
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _CC_uu_rr_rr_ee_nn_tt_ _ss_tt_aa_tt_uu_ss_ _oo_ff_ _RR_TT_LL_ _ss_uu_pp_pp_oo_rr_tt_ _ii_nn_ _MM_WW_ii_dd_gg_ee_tt_ss_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|_WW_ii_dd_gg_ee_tt_ _ _ _ _ _ _ _ _ _ _ _ _|_WW_oo_rr_kk_ss_ _ww_ii_tt_hh_ _RR_TT_LL_|_CC_oo_mm_mm_ee_nn_tt_ss_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|_M_A_n_i_m_a_t_e_d_I_c_o_n_ _ _ _ _ _|_O_K_ _ _ _ _ _ _ _ _ _ _ _ _|_N_o_t_h_i_n_g_ _t_o_ _d_o_ _f_o_r_ _R_T_L_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| | |In widgetsgallery, click "Application |
| | |Menu", then click "Application Menu" in the|
| | |navigation bar. A menu with offering the |
| | |names "Plato", "Twain", "Einstein", "Adams"|
| | |is openened. Hit Control-D to change the |
| | |layout direction, you see that the these |
|_M_A_p_p_l_i_c_a_t_i_o_n_M_e_n_u |broken? |names which were originally "almost" |
| | |centred are aligned right in RTL mode. They|
| | |should be aligned in a mirrored way, i.e. |
| | |if they are a bit left of the centre in LTR|
| | |mode, they should be a bit right of the |
| | |centre in RTL mode. Is this a problem with |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_M_A_p_p_l_i_c_a_t_i_o_n_M_e_n_u_ _o_r_ _w_i_t_h_ _M_A_c_t_i_o_n_?_ _ _ _ _ _ _ _ _ _ |
|_M_A_p_p_l_i_c_a_t_i_o_n_P_a_g_e_ _ _|_O_K_ _ _ _ _ _ _ _ _ _ _ _ _|_N_o_t_h_i_n_g_ _t_o_ _d_o_ _f_o_r_ _R_T_L_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|_M_A_p_p_l_i_c_a_t_i_o_n_W_i_n_d_o_w_|_O_K_ _ _ _ _ _ _ _ _ _ _ _ _|_N_o_t_h_i_n_g_ _t_o_ _d_o_ _f_o_r_ _R_T_L_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| | |But the switches in the switchpage of |
| | |widgetsgallery (which are MButtons) do not |
|_M_B_u_t_t_o_n |OK |reverse the alignment of their ON/OFF |
| | |texts. Problem in _M_B_u_t_t_o_n or somewhere |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_e_l_s_e_?_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|_M_B_u_t_t_o_n_G_r_o_u_p_ _ _ _ _ _ _|_O_K_ _ _ _ _ _ _ _ _ _ _ _ _|_N_o_t_h_i_n_g_ _t_o_ _d_o_ _f_o_r_ _R_T_L_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|_M_C_o_m_b_o_B_o_x_ _ _ _ _ _ _ _ _ _|_O_K_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|_M_C_o_n_t_a_i_n_e_r_ _ _ _ _ _ _ _ _|_O_K_ _ _ _ _ _ _ _ _ _ _ _ _|_N_o_t_h_i_n_g_ _t_o_ _d_o_ _f_o_r_ _R_T_L_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|_M_D_i_a_l_o_g_ _ _ _ _ _ _ _ _ _ _ _|_O_K_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|_M_D_o_c_k_W_i_d_g_e_t_ _ _ _ _ _ _ _|_O_K_ _ _ _ _ _ _ _ _ _ _ _ _|_N_o_t_h_i_n_g_ _t_o_ _d_o_ _f_o_r_ _R_T_L_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|_M_E_s_c_a_p_e_B_u_t_t_o_n_P_a_n_e_l_|_O_K_ _ _ _ _ _ _ _ _ _ _ _ _|_N_o_t_h_i_n_g_ _t_o_ _d_o_ _f_o_r_ _R_T_L_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| | |There seems to be a grid with gray squares |
| | |in the background and blue buttons in the |
| | |foreground in the widgetsgallery grid page.|
|MGrid |broken |In LTR mode, the gray squares align with |
| | |the blue buttons, i.e. on top of each gray |
| | |square is a blue button. In LTR mode, the |
| | |two arrays are shifted against each other. |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_T_h_i_s_ _d_o_e_s_n_'_t_ _l_o_o_k_ _r_i_g_h_t_._ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|_M_H_o_m_e_B_u_t_t_o_n_P_a_n_e_l_ _ _|_O_K_ _ _ _ _ _ _ _ _ _ _ _ _|_N_o_t_h_i_n_g_ _t_o_ _d_o_ _f_o_r_ _R_T_L_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|_M_I_m_a_g_e_ _ _ _ _ _ _ _ _ _ _ _ _|_O_K_ _ _ _ _ _ _ _ _ _ _ _ _|_N_o_t_h_i_n_g_ _t_o_ _d_o_ _f_o_r_ _R_T_L_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| | |Always slides in from the left side, see |
|_M_I_n_f_o_B_a_n_n_e_r |broken |"Dialogs and Notifications" page in |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_w_i_d_g_e_t_s_g_a_l_l_e_r_y_._ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| | |It did not change alignment on the fly |
|_M_L_a_b_e_l |OK |until recently but this is fixed now, see |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_N_B_#_1_4_4_3_7_7_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|_M_M_e_s_s_a_g_e_B_o_x_ _ _ _ _ _ _ _|_O_K_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|_M_M_o_d_a_l_S_c_e_n_e_W_i_n_d_o_w_ _|_O_K_ _ _ _ _ _ _ _ _ _ _ _ _|_N_o_t_h_i_n_g_ _t_o_ _d_o_ _f_o_r_ _R_T_L_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|_M_N_a_v_i_g_a_t_i_o_n_B_a_r |broken |Icon in the navigation bar is always on the|
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_l_e_f_t_ _s_i_d_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|_M_O_b_j_e_c_t_M_e_n_u_ _ _ _ _ _ _ _|_p_r_o_b_a_b_l_y_ _O_K_ _ _ _|_W_h_e_r_e_ _i_s_ _t_h_i_s_ _u_s_e_d_?_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|_M_P_a_n_n_a_b_l_e_V_i_e_w_p_o_r_t_ _|_O_K_ _ _ _ _ _ _ _ _ _ _ _ _|_P_o_s_i_t_i_o_n_ _i_n_d_i_c_a_t_o_r_ _c_o_r_r_e_c_t_l_y_ _c_h_a_n_g_e_s_ _s_i_d_e_ _ |
|_M_P_a_n_n_a_b_l_e_W_i_d_g_e_t_ _ _ _|_O_K_ _ _ _ _ _ _ _ _ _ _ _ _|_N_o_t_h_i_n_g_ _t_o_ _d_o_ _f_o_r_ _R_T_L_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|_M_P_o_p_u_p_L_i_s_t_ _ _ _ _ _ _ _ _|_O_K_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|_M_P_r_o_g_r_e_s_s_I_n_d_i_c_a_t_o_r_|_O_K_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|_M_P_o_s_i_t_i_o_n_I_n_d_i_c_a_t_o_r|broken |Is always on the right side. Can be seen on|
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_t_h_e_ _s_t_a_r_t_ _p_a_g_e_ _o_f_ _W_i_d_g_e_t_s_g_a_l_l_e_r_y_._ _ _ _ _ _ _ _ _ _ |
| | |slides correctly from the right in RTL mode|
|_M_S_e_e_k_B_a_r |broken |but the black area showing the "already" |
| | |downloaded stuff is only visible in LTR |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_m_o_d_e_._ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|_M_S_e_p_a_r_a_t_o_r_ _ _ _ _ _ _ _ _|_O_K_ _ _ _ _ _ _ _ _ _ _ _ _|_N_o_t_h_i_n_g_ _t_o_ _d_o_ _f_o_r_ _R_T_L_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|_M_S_l_i_d_e_r_ _ _ _ _ _ _ _ _ _ _ _|_O_K_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|_M_S_l_i_d_e_S_h_o_w_ _ _ _ _ _ _ _ _|_O_K_ _ _ _ _ _ _ _ _ _ _ _ _|_N_o_t_h_i_n_g_ _t_o_ _d_o_ _f_o_r_ _R_T_L_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|_M_T_e_x_t_E_d_i_t |OK |_N_B_#_1_0_4_3_9_7 is very obvious here, but this is|
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_n_o_t_ _t_h_e_ _f_a_u_l_t_ _o_f_ _M_T_e_x_t_E_d_i_t_._ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|_M_T_o_o_l_B_a_r_ _ _ _ _ _ _ _ _ _ _|_O_K_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|_M_W_i_n_d_o_w_ _ _ _ _ _ _ _ _ _ _ _|_O_K_ _ _ _ _ _ _ _ _ _ _ _ _|_N_o_t_h_i_n_g_ _t_o_ _d_o_ _f_o_r_ _R_T_L_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
********** CChhaarrsseett CCoonnvveerrssiioonnss **********
The MeeGo Touch UI Framework uses the Qt character set conversion mechanisms
directly. Therefore, developers can follow the Qt documentation to find out how
to use the character set conversion functionalities.
********** GGeenneerraall CChheecckklliisstt **********
******** GGeenneerraall ********
****** FFoonnttss ssiizzee ******
Some languages require bigger font size than the one used in the English text.
This may impact the layout design.
****** PPlluurraall ******
Some languages use plural and some do not. Some other languages use more than
one form of plurals.
****** SSoorrttiinngg ******
Sorting order is dependent on the language setting. Always use MeeGo Touch UI
collator to sort the strings.
****** WWoorrdd bboouunnddaarriieess ******
In some languages there is no space between words. In most cases the line
wrapping will work and the system will break the sentence into smaller chunks.
If it fails, translators shall use whitespace to force word boundaries.
****** WWoorrdd oorrddeerr,, vvaarriiaabblleess ******
When a sentence contains several variables, the order of the words in other
languages may be different. Use _Q_S_t_r_i_n_g place marker to define the order of the
variables.
//% "Download and install %1 from %2? (Size is %L3 MB)"
_Q_S_t_r_i_n_g s = qtTrId("xx_download_and_install_from_size_mb")
.arg(packageName).arg(repository).arg(size);
When translating, translators shall also keep the place markers and put them in
the correct places.
Note how L3 was used for the size parameter which is a number. Using L3 instead
of just 3 has the advantage that localized numerals may be used. For example if
the language of the locale is Arabic and the numeric settings of the locale do
not override it, L3 causes Arabic-Indic numerals to be used. If the translator
wants to disable this behaviour for this particular message and force usage of
Arabic (= Western) numerals always, no matter what the locale settings are, the
translator can use 3 instead of L3 on purpose.
******** DDeevveellooppeerrss ********
****** AAllwwaayyss uussee MMeeeeGGoo TToouucchh UUII FFrraammeewwoorrkk AAPPII ******
This is the general checklist which need to be confirmed during the
development. Use only MeeGo Touch UI Framework locale system API to gain full
internationalisation support. Use of POSIX and libc API is not recommended and
may cause discrepancies in the representation of the data.
To do sorting, never use Qt's _Q_S_t_r_i_n_g localeAwareCompare(), use MeeGo Touch UI
collation system instead.
****** AAvvooiidd hhaarrddccooddiinngg ******
Some data such as graphics, icons, sounds, etc sometimes need to be correctly
loaded dependent on the regional setting. In this case, never hard code the
data directory, instead use the regional setting information to build the
string to point to the correct directory containing the data.
****** NNeevveerr ccoonnccaatteennaattee ssttrriinnggss ******
If you need to construct a string involving variables, never concate the UI
strings. The string order is never guaranteed to the same in all languages.
Never do this:
_Q_S_t_r_i_n_g message = "You have " + numMessages + " messages";
Instead use a variable when constructing the string:
//% "You have %Ln messages"
_Q_S_t_r_i_n_g message = qtTrId("xx_you_have_messages", numMessages);
****** DDaattaa ffoorrmmaattttiinngg ******
Date, time, numbers, name, address, currency data are required to be formatted
before displayed on the screen. Never display unformatted data as it breaks the
data presentation consistency. Formatted data always use the correct
presentation according to the regional setting. Special case for address data,
it shall be formatted according to the customary of the country which stated in
the address.
******** UUII DDeessiiggnneerrss ********
****** AAbbbbrreevviiaattiioonnss ******
In general, avoid using abbreviations as part of the UI string. The
abbreviations ofter are misleading and confuse the translators. Instead, allow
for more text expansion
****** EEmmpphhaassiiss ******
Never use casing when indicating functionality or emphasis. Some languages do
not observe distinction between lowercase and uppercase. The translator may
have difficulties to find out how to emphasise the string when the original
English string uses uppercase for the emphasis.
Other methods such as using certain typeface to show emphasis also discouraged
as not all writing systems support them.
****** CChhaarraacctteerr rreeppeerrttooiirree ******
Never use characters outside the ASCII repertoire as part of original English
strings. The font needed to display the character may not available in the
device variant used for other languages.
****** CCoommppoouunnddss ******
Some languages create words by combining a few words together. The resulting
words are often longer than the original English string. Make sure that the UI
allows the text expansion in these languages.
****** DDiiggiittss ******
Some languages use their own digits (term: national digits) to show the
numbers. Allow the usage of national digits in some cases (for example when
displaying general strings containing numbers) and force the UI to only use the
Latin digits in other cases (for example when displaying IP addresses).
****** WWrriittiinngg ddiirreeccttiioonn ******
Some languages use different writing direction than the Latin based languages.
The UI presentation generally follows the natural flow of the writing
direction. Therefore, the widget layout and composition is mirrored when the
device language is set to the languages which use the right-to-left writing
direction. The mirroring is done automatically by the MeeGo Touch UI Framework.
If the automatic mirroring is not sufficient then consult the developers to
support different layout for right-to-left direction.
MeeGo Touch UI Framework currently only supports left-to-right and right-to-
left writing directions.
****** GGeennddeerr ******
Some languages use gender when referring to objects or words.
****** CCoolloouurr aanndd ggrraapphhiiccss ******
Colours often have different meanings and connotations in different cultures.
In Western culture, red is often used to indicate stop or danger. In China, red
is symbolic of celebration, luck and prosperity. White signifies purity,
virginity, or death. In Western culture it is the colour worn at weddings. In
parts of Japan and China the colour worn at funerals.
Never embed text and/or numbers in graphics, otherwise the graphics need to be
translated and it may be difficult and expensive.
Some icons or drawings considered offensive in some cultures.
****** SSpplliitt ssttrriinnggss wwhheenn ccoonnttaaiinniinngg ddaattee aanndd ttiimmee ffoorrmmaatt ******
See section "Translation involving date/time format" above.
===============================================================================
Copyright ? 2010 Nokia Corporation MeeGo Touch
-------------- next part --------------
A non-text attachment was scrubbed...
Name: meego-touch-i18n.zip
Type: application/zip
Size: 54426 bytes
Desc: not available
Url : http://lists.qt.nokia.com/pipermail/qt-qml/attachments/20100729/67c0ea72/attachment.zip
More information about the Qt-qml
mailing list