1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
|
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en_US" lang="en_US">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- linguist-manual.qdoc -->
<title>Qt 4.8: Qt Linguist Manual: Programmers</title>
<link rel="stylesheet" type="text/css" href="style/offline.css" />
</head>
<body>
<div class="header" id="qtdocheader">
<div class="content">
<a href="index.html" class="qtref"><span>Qt Reference Documentation</span></a>
</div>
<div class="breadcrumb toolblock">
<ul>
<li class="first"><a href="index.html">Home</a></li>
<!-- Breadcrumbs go here -->
<li>Qt Linguist Manual: Programmers</li>
</ul>
</div>
</div>
<div class="content mainContent">
<link rel="prev" href="linguist-translators.html" />
<link rel="next" href="linguist-ts-file-format.html" />
<p class="naviNextPrevious headerNavi">
<a class="prevPage" href="linguist-translators.html">Qt Linguist Manual: Translators</a>
<a class="nextPage" href="linguist-ts-file-format.html">Qt Linguist Manual: TS File Format</a>
</p><p/>
<div class="toc">
<h3><a name="toc">Contents</a></h3>
<ul>
<li class="level1"><a href="#making-the-application-translation-aware">Making the Application Translation-Aware</a></li>
<li class="level2"><a href="#creating-translation-files">Creating Translation Files</a></li>
<li class="level2"><a href="#loading-translations">Loading Translations</a></li>
<li class="level2"><a href="#making-the-application-translate-user-visible-strings">Making the Application Translate User-Visible Strings</a></li>
<li class="level2"><a href="#distinguishing-between-identical-translatable-strings">Distinguishing Between Identical Translatable Strings</a></li>
<li class="level2"><a href="#helping-the-translator-with-navigation-information">Helping the Translator with Navigation Information</a></li>
<li class="level2"><a href="#handling-plural-forms">Handling Plural Forms</a></li>
<li class="level2"><a href="#coping-with-c-namespaces">Coping With C++ Namespaces</a></li>
<li class="level2"><a href="#translating-text-that-is-outside-of-a-qobject-subclass">Translating Text That is Outside of a QObject Subclass</a></li>
<li class="level3"><a href="#using-qcoreapplication-translate">Using QCoreApplication::translate()</a></li>
<li class="level3"><a href="#using-qt-tr-noop-and-qt-translate-noop">Using QT_TR_NOOP() and QT_TRANSLATE_NOOP()</a></li>
<li class="level1"><a href="#tutorials">Tutorials</a></li>
</ul>
</div>
<h1 class="title">Qt Linguist Manual: Programmers</h1>
<span class="subtitle"></span>
<!-- $$$linguist-programmers.html-description -->
<div class="descr"> <a name="details"></a>
<p>Support for multiple languages is extremely simple in Qt applications, and adds little overhead to the programmer's workload.</p>
<p>Qt minimizes the performance cost of using translations by translating the phrases for each window as they are created. In most applications the main window is created just once. Dialogs are often created once and then shown and hidden as required. Once the initial translation has taken place there is no further runtime overhead for the translated windows. Only those windows that are created, destroyed and subsequently created will have a translation performance cost.</p>
<p>Creating applications that can switch language at runtime is possible with Qt, but requires a certain amount of programmer intervention and will of course incur some runtime performance cost.</p>
<a name="making-the-application-translation-aware"></a>
<h2>Making the Application Translation-Aware</h2>
<p>Programmers should make their application look for and load the appropriate translation file and mark user-visible text and Ctrl keyboard accelerators as targets for translation.</p>
<p>Each piece of text that requires translating requires context to help the translator identify where in the program the text occurs. In the case of multiple identical texts that require different translations, the translator also requires some information to disambiguate the source texts. Marking text for translation will automatically cause the class name to be used as basic context information. In some cases the programmer may be required to add additional information to help the translator.</p>
<a name="creating-translation-files"></a>
<h3>Creating Translation Files</h3>
<p>Translation files consist of all the user-visible text and Ctrl key accelerators in an application and translations of that text. Translation files are created as follows:</p>
<ol class="1">
<li>Run <a href="linguist-manager.html#lupdate">lupdate</a> initially to generate the first set of TS translation source files with all the user-visible text but no translations.</li>
<li>The TS files are given to the translator who adds translations using <i>Qt Linguist</i>. <i>Qt Linguist</i> takes care of any changed or deleted source text.</li>
<li>Run <a href="linguist-manager.html#lupdate">lupdate</a> to incorporate any new text added to the application. <a href="linguist-manager.html#lupdate">lupdate</a> synchronizes the user-visible text from the application with the translations; it does not destroy any data.</li>
<li>Steps 2 and 3 are repeated as often as necessary.</li>
<li>When a release of the application is needed <a href="linguist-manager.html#lrelease">lrelease</a> is run to read the TS files and produce the QM files used by the application at runtime.</li>
</ol>
<p>For <a href="linguist-manager.html#lupdate">lupdate</a> to work successfully, it must know which translation files to produce. The files are simply listed in the application's <tt>.pro</tt> Qt project file, for example:</p>
<pre class="cpp"> TRANSLATIONS = arrowpad_fr.ts \
arrowpad_nl.ts</pre>
<p>If your sources contain genuine non-Latin1 strings, <a href="linguist-manager.html#lupdate">lupdate</a> needs to be told about it in the <tt>.pro</tt> file by using, for example, the following line:</p>
<pre class="cpp"> CODECFORTR <span class="operator">=</span> UTF<span class="operator">-</span><span class="number">8</span></pre>
<p>See the <a href="linguist-manager.html#lupdate">lupdate</a> and <a href="linguist-manager.html#lrelease">lrelease</a> sections.</p>
<a name="loading-translations"></a>
<h3>Loading Translations</h3>
<pre class="cpp"> <span class="type">int</span> main(<span class="type">int</span> argc<span class="operator">,</span> <span class="type">char</span> <span class="operator">*</span>argv<span class="operator">[</span><span class="operator">]</span>)
{
<span class="type"><a href="qapplication.html">QApplication</a></span> app(argc<span class="operator">,</span> argv);</pre>
<p>This is how a simple <tt>main()</tt> function of a Qt application begins.</p>
<pre class="cpp"> <span class="type">int</span> main(<span class="type">int</span> argc<span class="operator">,</span> <span class="type">char</span> <span class="operator">*</span>argv<span class="operator">[</span><span class="operator">]</span>)
{
<span class="type"><a href="qapplication.html">QApplication</a></span> app(argc<span class="operator">,</span> argv);
<span class="type"><a href="qtranslator.html">QTranslator</a></span> translator;
translator<span class="operator">.</span>load(<span class="string">"hellotr_la"</span>);
app<span class="operator">.</span>installTranslator(<span class="operator">&</span>translator);</pre>
<p>For a translation-aware application a translator object is created, a translation is loaded and the translator object installed into the application.</p>
<pre class="cpp"> <span class="type">int</span> main(<span class="type">int</span> argc<span class="operator">,</span> <span class="type">char</span> <span class="operator">*</span>argv<span class="operator">[</span><span class="operator">]</span>)
{
<span class="type"><a href="qapplication.html">QApplication</a></span> app(argc<span class="operator">,</span> argv);
<span class="type"><a href="qstring.html">QString</a></span> locale <span class="operator">=</span> <span class="type"><a href="qlocale.html">QLocale</a></span><span class="operator">::</span>system()<span class="operator">.</span>name();
<span class="type"><a href="qtranslator.html">QTranslator</a></span> translator;
translator<span class="operator">.</span>load(<span class="type"><a href="qstring.html">QString</a></span>(<span class="string">"arrowpad_"</span>) <span class="operator">+</span> locale);
app<span class="operator">.</span>installTranslator(<span class="operator">&</span>translator);</pre>
<p>For non-Latin1 strings in the sources you will also need for example:</p>
<pre class="cpp"> <span class="type"><a href="qtextcodec.html">QTextCodec</a></span><span class="operator">::</span>setCodecForTr(<span class="type"><a href="qtextcodec.html">QTextCodec</a></span><span class="operator">::</span>codecForName(<span class="string">"utf8"</span>));</pre>
<p>In production applications a more flexible approach, for example, loading translations according to locale, might be more appropriate. If the TS files are all named according to a convention such as <i>appname_locale</i>, e.g. <tt>tt2_fr</tt>, <tt>tt2_de</tt> etc, then the code above will load the current locale's translation at runtime.</p>
<p>If there is no translation file for the current locale the application will fall back to using the original source text.</p>
<p>Note that if you need to programmatically add translations at runtime, you can reimplement <a href="qtranslator.html#translate">QTranslator::translate</a>().</p>
<a name="making-the-application-translate-user-visible-strings"></a>
<h3>Making the Application Translate User-Visible Strings</h3>
<p>User-visible strings are marked as translation targets by wrapping them in a <tt>tr()</tt> call, for example:</p>
<pre class="cpp"> button <span class="operator">=</span> <span class="keyword">new</span> <span class="type"><a href="qpushbutton.html">QPushButton</a></span>(<span class="string">"&Quit"</span><span class="operator">,</span> <span class="keyword">this</span>);</pre>
<p>would become</p>
<pre class="cpp"> button <span class="operator">=</span> <span class="keyword">new</span> <span class="type"><a href="qpushbutton.html">QPushButton</a></span>(tr(<span class="string">"&Quit"</span>)<span class="operator">,</span> <span class="keyword">this</span>);</pre>
<p>All <a href="qobject.html">QObject</a> subclasses that use the <tt>Q_OBJECT</tt> macro implement the <tt>tr()</tt> function.</p>
<p>Although the <tt>tr()</tt> call is normally made directly since it is usually called as a member function of a <a href="qobject.html">QObject</a> subclass, in other cases an explicit class name can be supplied, for example:</p>
<pre class="cpp"> <span class="type"><a href="qpushbutton.html">QPushButton</a></span><span class="operator">::</span>tr(<span class="string">"&Quit"</span>)</pre>
<p>or</p>
<pre class="cpp"> <span class="type"><a href="qobject.html">QObject</a></span><span class="operator">::</span>tr(<span class="string">"&Quit"</span>)</pre>
<a name="distinguishing-between-identical-translatable-strings"></a>
<h3>Distinguishing Between Identical Translatable Strings</h3>
<p>The <a href="linguist-manager.html#lupdate">lupdate</a> program automatically provides a <i>context</i> for every source text. This context is the class name of the class that contains the <tt>tr()</tt> call. This is sufficient in the vast majority of cases. Sometimes however, the translator will need further information to uniquely identify a source text; for example, a dialog that contained two separate frames, each of which contained an "Enabled" option would need each identified because in some languages the translation would differ between the two. This is easily achieved using the two argument form of the <tt>tr()</tt> call, e.g.</p>
<pre class="cpp"> rbc <span class="operator">=</span> <span class="keyword">new</span> <span class="type"><a href="qradiobutton.html">QRadioButton</a></span>(tr(<span class="string">"Enabled"</span><span class="operator">,</span> <span class="string">"Color frame"</span>)<span class="operator">,</span> <span class="keyword">this</span>);</pre>
<p>and</p>
<pre class="cpp"> rbh <span class="operator">=</span> <span class="keyword">new</span> <span class="type"><a href="qradiobutton.html">QRadioButton</a></span>(tr(<span class="string">"Enabled"</span><span class="operator">,</span> <span class="string">"Hue frame"</span>)<span class="operator">,</span> <span class="keyword">this</span>);</pre>
<p>Ctrl key accelerators are also translatable:</p>
<pre class="cpp"> exitAct <span class="operator">=</span> <span class="keyword">new</span> <span class="type"><a href="qaction.html">QAction</a></span>(tr(<span class="string">"E&xit"</span>)<span class="operator">,</span> <span class="keyword">this</span>);
exitAct<span class="operator">-</span><span class="operator">></span>setShortcut(tr(<span class="string">"Ctrl+Q"</span><span class="operator">,</span> <span class="string">"Quit"</span>));</pre>
<p>It is strongly recommended that the two argument form of <tt>tr()</tt> is used for Ctrl key accelerators. The second argument is the only clue the translator has as to the function performed by the accelerator.</p>
<a name="helping-the-translator-with-navigation-information"></a>
<h3>Helping the Translator with Navigation Information</h3>
<p>In large complex applications it may be difficult for the translator to see where a particular source text comes from. This problem can be solved by adding a comment using the keyword <i>TRANSLATOR</i> which describes the navigation steps to reach the text in question; e.g.</p>
<pre class="cpp"> <span class="comment">/*
TRANSLATOR FindDialog
Choose Edit|Find from the menu bar or press Ctrl+F to pop up the
Find dialog.
...
*/</span></pre>
<p>These comments are particularly useful for widget classes.</p>
<a name="handling-plural-forms"></a>
<h3>Handling Plural Forms</h3>
<p>Qt includes a <tt>tr()</tt> overload that will make it very easy to write "plural-aware" internationalized applications. This overload has the following signature:</p>
<pre class="cpp"> <span class="type"><a href="qstring.html">QString</a></span> tr(<span class="keyword">const</span> <span class="type">char</span> <span class="operator">*</span>text<span class="operator">,</span> <span class="keyword">const</span> <span class="type">char</span> <span class="operator">*</span>comment<span class="operator">,</span> <span class="type">int</span> n);</pre>
<p>Depending on the value of <tt>n</tt>, the <tt>tr()</tt> function will return a different translation, with the correct grammatical number for the target language. Also, any occurrence of <tt>%n</tt> is replaced with <tt>n</tt>'s value. For example:</p>
<pre class="cpp"> tr(<span class="string">"%n item(s) replaced"</span><span class="operator">,</span> <span class="string">""</span><span class="operator">,</span> count);</pre>
<p>If a French translation is loaded, this will expand to "0 item remplacé", "1 item remplacé", "2 items remplacés", etc., depending on <tt>n</tt>'s value. And if no translation is loaded, the original string is used, with <tt>%n</tt> replaced with count's value (e.g., "6 item(s) replaced").</p>
<p>To handle plural forms in the native language, you need to load a translation file for this language, too. <a href="linguist-manager.html#lupdate">lupdate</a> has the <tt>-pluralonly</tt> command line option, which allows the creation of TS files containing only entries with plural forms.</p>
<p>See the <a href="http://doc.qt.nokia.com/qq/">Qt Quarterly</a> Article <a href="http://doc.qt.nokia.com/qq/qq19-plurals.html">Plural Forms in Translations</a> for further details on this issue.</p>
<a name="coping-with-c-namespaces"></a>
<h3>Coping With C++ Namespaces</h3>
<p>C++ namespaces and the <tt>using namespace</tt> statement can confuse <a href="linguist-manager.html#lupdate">lupdate</a>. It will interpret <tt>MyClass::tr()</tt> as meaning just that, not as <tt>MyNamespace::MyClass::tr()</tt>, even if <tt>MyClass</tt> is defined in the <tt>MyNamespace</tt> namespace. Runtime translation of these strings will fail because of that.</p>
<p>You can work around this limitation by putting a <i>TRANSLATOR</i> comment at the beginning of the source files that use <tt>MyClass::tr()</tt>:</p>
<pre class="cpp"> <span class="comment">/*
TRANSLATOR MyNamespace::MyClass
Necessary for lupdate.
...
*/</span></pre>
<p>After the comment, all references to <tt>MyClass::tr()</tt> will be understood as meaning <tt>MyNamespace::MyClass::tr()</tt>.</p>
<a name="translating-text-that-is-outside-of-a-qobject-subclass"></a>
<h3>Translating Text That is Outside of a QObject Subclass</h3>
<a name="using-qcoreapplication-translate"></a>
<h4>Using QCoreApplication::translate()</h4>
<p>If the quoted text is not in a member function of a <a href="qobject.html">QObject</a> subclass, use either the tr() function of an appropriate class, or the <a href="qcoreapplication.html#translate">QCoreApplication::translate</a>() function directly:</p>
<pre class="cpp"> <span class="type">void</span> some_global_function(LoginWidget <span class="operator">*</span>logwid)
{
<span class="type"><a href="qlabel.html">QLabel</a></span> <span class="operator">*</span>label <span class="operator">=</span> <span class="keyword">new</span> <span class="type"><a href="qlabel.html">QLabel</a></span>(
LoginWidget<span class="operator">::</span>tr(<span class="string">"Password:"</span>)<span class="operator">,</span> logwid);
}
<span class="type">void</span> same_global_function(LoginWidget <span class="operator">*</span>logwid)
{
<span class="type"><a href="qlabel.html">QLabel</a></span> <span class="operator">*</span>label <span class="operator">=</span> <span class="keyword">new</span> <span class="type"><a href="qlabel.html">QLabel</a></span>(
qApp<span class="operator">-</span><span class="operator">></span>translate(<span class="string">"LoginWidget"</span><span class="operator">,</span> <span class="string">"Password:"</span>)<span class="operator">,</span>
logwid);
}</pre>
<a name="using-qt-tr-noop-and-qt-translate-noop"></a>
<h4>Using QT_TR_NOOP() and QT_TRANSLATE_NOOP()</h4>
<p>If you need to have translatable text completely outside a function, there are two macros to help: <a href="qtglobal.html#QT_TR_NOOP">QT_TR_NOOP</a>() and <a href="qtglobal.html#QT_TRANSLATE_NOOP">QT_TRANSLATE_NOOP</a>(). These macros merely mark the text for extraction by <a href="linguist-manager.html#lupdate">lupdate</a>. The macros expand to just the text (without the context).</p>
<p>Example of <a href="qtglobal.html#QT_TR_NOOP">QT_TR_NOOP</a>():</p>
<pre class="cpp"> <span class="type"><a href="qstring.html">QString</a></span> FriendlyConversation<span class="operator">::</span>greeting(<span class="type">int</span> greet_type)
{
<span class="keyword">static</span> <span class="keyword">const</span> <span class="type">char</span><span class="operator">*</span> greeting_strings<span class="operator">[</span><span class="operator">]</span> <span class="operator">=</span> {
QT_TR_NOOP(<span class="string">"Hello"</span>)<span class="operator">,</span>
QT_TR_NOOP(<span class="string">"Goodbye"</span>)
};
<span class="keyword">return</span> tr(greeting_strings<span class="operator">[</span>greet_type<span class="operator">]</span>);
}</pre>
<p>Example of <a href="qtglobal.html#QT_TRANSLATE_NOOP">QT_TRANSLATE_NOOP</a>():</p>
<pre class="cpp"> <span class="keyword">static</span> <span class="keyword">const</span> <span class="type">char</span><span class="operator">*</span> greeting_strings<span class="operator">[</span><span class="operator">]</span> <span class="operator">=</span> {
QT_TRANSLATE_NOOP(<span class="string">"FriendlyConversation"</span><span class="operator">,</span> <span class="string">"Hello"</span>)<span class="operator">,</span>
QT_TRANSLATE_NOOP(<span class="string">"FriendlyConversation"</span><span class="operator">,</span> <span class="string">"Goodbye"</span>)
};
<span class="type"><a href="qstring.html">QString</a></span> FriendlyConversation<span class="operator">::</span>greeting(<span class="type">int</span> greet_type)
{
<span class="keyword">return</span> tr(greeting_strings<span class="operator">[</span>greet_type<span class="operator">]</span>);
}
<span class="type"><a href="qstring.html">QString</a></span> global_greeting(<span class="type">int</span> greet_type)
{
<span class="keyword">return</span> qApp<span class="operator">-</span><span class="operator">></span>translate(<span class="string">"FriendlyConversation"</span><span class="operator">,</span>
greeting_strings<span class="operator">[</span>greet_type<span class="operator">]</span>);
}</pre>
<a name="tutorials"></a>
<h2>Tutorials</h2>
<p>Three tutorials are presented:</p>
<ol class="1">
<li><a href="linguist-hellotr.html">Hello tr()</a> demonstrates the creation of a <a href="qtranslator.html">QTranslator</a> object. It also shows the simplest use of the <tt>tr()</tt> function to mark user-visible source text for translation.</li>
<li><a href="linguist-arrowpad.html">Arrow Pad</a> explains how to make the application load the translation file applicable to the current locale. It also shows the use of the two-argument form of <tt>tr()</tt> which provides additional information to the translator.</li>
<li><a href="linguist-trollprint.html">Troll Print</a> explains how identical source texts can be distinguished even when they occur in the same context. This tutorial also discusses how the translation tools help minimize the translator's work when an application is upgraded.</li>
</ol>
<p>These tutorials cover all that you need to know to prepare your Qt applications for translation.</p>
<p>At the beginning of a project add the translation source files to be used to the project file and add calls to <a href="linguist-manager.html#lupdate">lupdate</a> and <a href="linguist-manager.html#lrelease">lrelease</a> to the Makefile.</p>
<p>During the project all the programmer must do is wrap any user-visible text in <tt>tr()</tt> calls. They should also use the two argument form for Ctrl key accelerators, or when asked by the translator for the cases where the same text translates into two different forms in the same context. The programmer should also include <tt>TRANSLATION</tt> comments to help the translator navigate the application.</p>
</div>
<!-- @@@linguist-programmers.html -->
<p class="naviNextPrevious footerNavi">
<a class="prevPage" href="linguist-translators.html">Qt Linguist Manual: Translators</a>
<a class="nextPage" href="linguist-ts-file-format.html">Qt Linguist Manual: TS File Format</a>
</p>
<div class="ft">
<span></span>
</div>
</div>
<div class="footer">
<p>
<acronym title="Copyright">©</acronym> 2012 Nokia Corporation and/or its
subsidiaries. Documentation contributions included herein are the copyrights of
their respective owners.</p>
<br />
<p>
The documentation provided herein is licensed under the terms of the
<a href="http://www.gnu.org/licenses/fdl.html">GNU Free Documentation
License version 1.3</a> as published by the Free Software Foundation.</p>
<p>
Documentation sources may be obtained from <a href="http://www.qt-project.org">
www.qt-project.org</a>.</p>
<br />
<p>
Nokia, Qt and their respective logos are trademarks of Nokia Corporation
in Finland and/or other countries worldwide. All other trademarks are property
of their respective owners. <a title="Privacy Policy"
href="http://en.gitorious.org/privacy_policy/">Privacy Policy</a></p>
</div>
</body>
</html>
|