summaryrefslogtreecommitdiffstats
path: root/doc/html/linguist-manual-4.html
blob: 67fc44860ecf7c113c745f9855d00dc2aa97af50 (plain)
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
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- /home/espenr/tmp/qt-3.3.8-espenr-2499/qt-x11-free-3.3.8/tools/linguist/book/linguist-programmer.leaf:3 -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Programmers</title>
<style type="text/css"><!--
fn { margin-left: 1cm; text-indent: -1cm; }
a:link { color: #004faf; text-decoration: none }
a:visited { color: #672967; text-decoration: none }
body { background: #ffffff; color: black; }
--></style>
</head>
<body>

<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr bgcolor="#E5E5E5">
<td valign=center>
 <a href="index.html">
<font color="#004faf">Home</font></a>
 | <a href="classes.html">
<font color="#004faf">All&nbsp;Classes</font></a>
 | <a href="mainclasses.html">
<font color="#004faf">Main&nbsp;Classes</font></a>
 | <a href="annotated.html">
<font color="#004faf">Annotated</font></a>
 | <a href="groups.html">
<font color="#004faf">Grouped&nbsp;Classes</font></a>
 | <a href="functions.html">
<font color="#004faf">Functions</font></a>
</td>
<td align="right" valign="center"><img src="logo32.png" align="right" width="64" height="32" border="0"></td></tr></table><p align="right">[<a href="linguist-manual-3.html">Prev: Translators</a>] [<a href="linguist-manual.html">Home</a>]</p>
<h2 align="center">Programmers</h2>
<p>Support for multiple languages is extremely simple in TQt applications, and adds little overhead to the programmer's workload.</p>
<p>TQt 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 TQt, but requires a certain amount of programmer intervention and will of course incur some runtime performance cost.</p>
<h3><a name="1"></a>Making the Application Translation Aware</h3>
<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>
<h4><a name="1-1"></a>Creating Translation Files</h4>
<!-- index .ts Files --><!-- index Translation Source Files --><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>
<!-- index lupdate --><!-- index lrelease --><ol type=1><li><p>Run <a href="linguist-manual-2.html#2">lupdate</a> initially to generate the first set of <tt>.ts</tt> translation source files with all the user-visible text but no translations.</p>
<li><p>The <tt>.ts</tt> files are given to the translator who adds translations using <em>TQt Linguist</em>. <em>TQt Linguist</em> takes care of any changed or deleted source text.</p>
<li><p>Run <a href="linguist-manual-2.html#2">lupdate</a> to incorporate any new text added to the application. <a href="linguist-manual-2.html#2">lupdate</a> synchronizes the user-visible text from the application with the translations; it does not destroy any data.</p>
<li><p>Steps 2 and 3 are repeated as often as necessary.</p>
<li><p>When a release of the application is needed <a href="linguist-manual-2.html#3">lrelease</a> is run to read the <tt>.ts</tt> files and produce the <tt>.qm</tt> files used by the application at runtime.</p>
</ol><!-- index .pro Files --><!-- index Project Files --><!-- index qmake!Project Files --><p>For <a href="linguist-manual-2.html#2">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> TQt project file, for example:</p>
<pre>    TRANSLATIONS    = tt2_fr.ts \
                      tt2_nl.ts
</pre>
 <p>See the <a href="linguist-manual-2.html#2">"lupdate"</a> and <a href="linguist-manual-2.html#3">"lrelease"</a> sections.</p>
<h4><a name="1-2"></a>Loading Translations</h4>
<pre>    int main( int argc, char **argv )
    {
        <a href="ntqapplication.html">TQApplication</a> app( argc, argv );
</pre>
<!-- index main() --> <p>This is how a simple <tt>main()</tt> function of a TQt application begins.</p>
<!-- index TQTranslator!load() --><!-- index load()!TQTranslator --><!-- index TQApplication!installTranslator() --><!-- index installTranslator()!TQApplication --><pre>    int main( int argc, char **argv )
    {
        <a href="ntqapplication.html">TQApplication</a> app( argc, argv );

        <a href="tqtranslator.html">TQTranslator</a> translator( 0 );
        translator.<a href="tqtranslator.html#load">load</a>( "tt1_la", "." );
        app.<a href="ntqapplication.html#installTranslator">installTranslator</a>( &amp;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>    int main( int argc, char **argv )
    {
        <a href="ntqapplication.html">TQApplication</a> app( argc, argv );

        <a href="tqtranslator.html">TQTranslator</a> translator( 0 );
        translator.<a href="tqtranslator.html#load">load</a>( TQString("tt2_") + TQTextCodec::locale(), "." );
        app.<a href="ntqapplication.html#installTranslator">installTranslator</a>( &amp;translator );
</pre>
 <p>In production applications a more flexible approach, for example, loading translations according to locale, might be more appropriate. If the <tt>.ts</tt> files are all named according to a convention such as <em>appname_locale</em>, 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>
<h4><a name="1-3"></a>Making the Application Translate User-Visible Strings</h4>
<!-- index tr() --><!-- index TQObject!tr() --><p>User-visible strings are marked as translation targets by wrapping them in a <tt>tr()</tt> call, for example:</p>
<pre>
    button = new TQPushButton( "&amp;Quit", this );
</pre>
<p>would become</p>
<pre>
    button = new TQPushButton( tr("&amp;Quit"), this);
</pre>
<!-- index TQ_OBJECT --><p>All <a href="tqobject.html">TQObject</a> subclasses that use the <tt>TQ_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="tqobject.html">TQObject</a> subclass, in other cases an explicit class name can be supplied, for example:</p>
<pre>
    TQPushButton::tr("&amp;Quit")
</pre>
<p>or</p>
<pre>
    TQObject::tr("&amp;Quit")
</pre>
<h4><a name="1-4"></a>Distinguishing Identical Strings That Require Different Translations</h4>
<!-- index Translation Contexts --><!-- index Contexts!for Translation --><!-- index lupdate --><p>The <a href="linguist-manual-2.html#2">lupdate</a> program automatically provides a <em>context</em> 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>
    rbc = new TQRadioButton( tr("Enabled", "Color frame"), this );
</pre>
<p>and</p>
<pre>
    rbh = new TQRadioButton( tr("Enabled", "Hue frame"), this );
</pre>
<!-- index Ctrl Key --><p>Ctrl key accelerators are also translatable:</p>
<pre>        file-&gt;<a href="tqmenudata.html#insertItem">insertItem</a>( <a href="tqobject.html#tr">tr</a>("E&amp;xit"), tqApp, TQ_SLOT(<a href="ntqapplication.html#quit">quit</a>()),
                          <a href="tqobject.html#tr">tr</a>("Ctrl+Q", "Quit") );
</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>
<h4><a name="1-5"></a>Helping The Translator With Navigation Information</h4>
<!-- index TRANSLATOR!in Comments --><!-- index Translator Comments --><!-- index Comments!for Translators --><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 <em>TRANSLATOR</em> which describes the navigation steps to reach the text in question; e.g.</p>
<pre>
    /*  TRANSLATOR FindDialog

        Choose Edit|Find from the menu bar or press Ctrl+F to pop up the
        Find dialog.
    */
</pre>
<p>These comments are particularly useful for widget classes.</p>
<h4><a name="1-6"></a>Coping With C++ Namespaces</h4>
<!-- index Namespaces --><!-- index C++!Namespaces --><!-- index lupdate --><p>C++ namespaces and the <tt>using namespace</tt> statement can confuse <a href="linguist-manual-2.html#2">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>
<!-- index TRANSLATOR!in Comments --><!-- index Translator Comments --><!-- index Comments!for Translators --><p>You can work around this limitation by putting a <em>TRANSLATOR</em> comment at the beginning of the source files that use <tt>MyClass::tr()</tt>:</p>
<pre>
    /* TRANSLATOR MyNamespace::MyClass */
</pre>
<p>After the comment, all references to <tt>MyClass::tr()</tt> will be understood as meaning <tt>MyNamespace::MyClass::tr()</tt>.</p>
<h4><a name="1-7"></a>Translating Text that is Outside of a TQObject subclass</h4>
<h5><a name="1-7-1"></a>Using TQApplication::translate()</h5>
<p>If the quoted text is not in a member function of a TQObject subclass, use either the tr() function of an appropriate class, or the TQApplication::translate() function directly:</p>
<pre>
    void some_global_function( LoginWidget *logwid )
    {
        TQLabel *label = new TQLabel(
                LoginWidget::tr("Password:"), logwid );
    }

    void same_global_function( LoginWidget *logwid )
    {
        TQLabel *label = new TQLabel(
                tqApp-&gt;translate("LoginWidget", "Password:"),
                logwid );
    }
</pre>
<h5><a name="1-7-2"></a>Using TQT_TR_NOOP() and TQT_TRANSLATE_NOOP()</h5>
<p>If you need to have translatable text completely outside a function, there are two macros to help: TQT_TR_NOOP() and TQT_TRANSLATE_NOOP(). These macros merely mark the text for extraction by <a href="linguist-manual-2.html#2">lupdate</a>. The macros expand to just the text (without the context).</p>
<p>Example of TQT_TR_NOOP():</p>
<pre>
    TQString FriendlyConversation::greeting( int greet_type )
    {
        static const char* greeting_strings[] = {
            TQT_TR_NOOP( "Hello" ),
            TQT_TR_NOOP( "Goodbye" )
        };
        return tr( greeting_strings[greet_type] );
    }
</pre>
<p>Example of TQT_TRANSLATE_NOOP():</p>
<pre>
    static const char* greeting_strings[] = {
        TQT_TRANSLATE_NOOP( "FriendlyConversation", "Hello" ),
        TQT_TRANSLATE_NOOP( "FriendlyConversation", "Goodbye" )
    };

    TQString FriendlyConversation::greeting( int greet_type )
    {
        return tr( greeting_strings[greet_type] );
    }

    TQString global_greeting( int greet_type )
    {
        return tqApp-&gt;translate( "FriendlyConversation",
                                greeting_strings[greet_type] );
    }
</pre>
<h3><a name="2"></a>Tutorials</h3>
<p>Three tutorials are presented. The first demonstrates the creation of a <a href="tqtranslator.html">TQTranslator</a> object. It also shows the simplest use of the <tt>tr()</tt> function to mark user-visible source text for translation. The second tutorial 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. The third tutorial 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.</p>
<h4><a name="2-1"></a>Tutorial 1: Loading and Using Translations</h4>
<p align="center"><img align="middle" src="tt1_en.png" width="112" height="49">
</p>
<blockquote><p align="center"><em>Tutorial 1 Screenshot, English version</em></p></blockquote>
<pre>TEMPLATE        = app
CONFIG          += qt warn_on
SOURCES         = main.cpp
TRANSLATIONS    = tt1_la.ts
</pre>
<blockquote><p align="center"><em><tt>tt1.pro</tt></em></p></blockquote>
<pre>/****************************************************************
**
** Translation tutorial 1
**
****************************************************************/

#include &lt;<a href="qapplication-h.html">ntqapplication.h</a>&gt;
#include &lt;<a href="tqpushbutton-h.html">tqpushbutton.h</a>&gt;
#include &lt;<a href="tqtranslator-h.html">tqtranslator.h</a>&gt;


int main( int argc, char **argv )
{
    <a href="ntqapplication.html">TQApplication</a> app( argc, argv );

    <a href="tqtranslator.html">TQTranslator</a> translator( 0 );
    translator.<a href="tqtranslator.html#load">load</a>( "tt1_la", "." );
    app.<a href="ntqapplication.html#installTranslator">installTranslator</a>( &amp;translator );

    <a href="tqpushbutton.html">TQPushButton</a> hello( TQPushButton::<a href="tqobject.html#tr">tr</a>("Hello world!"), 0 );

    app.<a href="ntqapplication.html#setMainWidget">setMainWidget</a>( &amp;hello );
    hello.<a href="tqwidget.html#show">show</a>();
    return app.<a href="ntqapplication.html#exec">exec</a>();
}
</pre>
<blockquote><p align="center"><em><tt>main.cpp</tt></em></p></blockquote>
<p>This example is a reworking of the <a href="tutorial1-01.html">"hello-world"</a> example from <a href="tutorial.html">Tutorial #1</a>, with a Latin translation. The <em>Tutorial 1 Screenshot, English version</em>, above, shows the English version.</p>
<h5><a name="2-1-1"></a>Line by Line Walk-through</h5>
<pre>    #include &lt;<a href="tqtranslator-h.html">tqtranslator.h</a>&gt;
</pre>
<!-- index TQTranslator --> <p>This line includes the definition of the <a href="tqtranslator.html">TQTranslator</a> class. Objects of this class provide translations for user-visible text.</p>
<pre>        <a href="tqtranslator.html">TQTranslator</a> translator( 0 );
</pre>
 <p>Creates a <a href="tqtranslator.html">TQTranslator</a> object without a parent.</p>
<pre>        translator.<a href="tqtranslator.html#load">load</a>( "tt1_la", "." );
</pre>
<!-- index tt1_la.qm --> <p>Tries to load a file called <tt>tt1_la.qm</tt> (the <tt>.qm</tt> file extension is implicit) that contains Latin translations for the source texts used in the program. No error will occur if the file is not found.</p>
<!-- index TQApplication!installTranslator() --><!-- index installTranslator()!TQApplication --><pre>        app.<a href="ntqapplication.html#installTranslator">installTranslator</a>( &amp;translator );
</pre>
 <p>Adds the translations from <tt>tt1_la.qm</tt> to the pool of translations used by the program.</p>
<!-- index Hello World --><pre>        <a href="tqpushbutton.html">TQPushButton</a> hello( TQPushButton::<a href="tqobject.html#tr">tr</a>("Hello world!"), 0 );
</pre>
 <p>Creates a push button that displays "Hello world!". If <tt>tt1_la.qm</tt> was found and contains a translation for "Hello world!", the translation appears; if not, the source text appears.</p>
<!-- index tr() --><!-- index TQObject!tr() --><p>All classes that inherit <a href="tqobject.html">TQObject</a> have a <tt>tr()</tt> function. Inside a member function of a <a href="tqobject.html">TQObject</a> class, we simply write <tt>tr("Hello world!")</tt> instead of <tt>TQPushButton::tr("Hello world!")</tt> or <tt>TQObject::tr("Hello world!")</tt>.</p>
<h5><a name="2-1-2"></a>Running the Application in English</h5>
<!-- index English Language --><p>Since we haven't made the translation file <tt>tt1_la.qm</tt>, the source text is shown when we run the application:</p>
<p align="center"><img align="middle" src="tt1_en.png" width="112" height="49">
</p>
<blockquote><p align="center"><em>Tutorial 1 Screenshot, English version</em></p></blockquote>
<h5><a name="2-1-3"></a>Creating a Latin Message File</h5>
<!-- index tt1.pro --><!-- index Latin --><p>The first step is to create a project file, <tt>tt1.pro</tt>, that lists all the source files for the project. The project file can be a qmake project file, or even an ordinary makefile. Any file that contains</p>
<!-- index SOURCES!in Project Files --><!-- index TRANSLATIONS!in Project Files --><pre>    SOURCES         = main.cpp
    TRANSLATIONS    = tt1_la.ts
</pre>
 <p>will work. <em>TRANSLATIONS</em> specifies the message files we want to maintain. In this example, we just maintain one set of translations, namely Latin.</p>
<!-- index .ts Files --><!-- index Translation Source Files --><!-- index .qm Files --><!-- index TQt Message Files --><p>Note that the file extension is <tt>.ts</tt>, not <tt>.qm</tt>. The <tt>.ts</tt> translation source format is designed for use during the application's development. Programmers or release managers run the <a href="linguist-manual-2.html#2">lupdate</a> program to generate and update <tt>.ts</tt> files with the source text that is extracted from the source code. Translators read and update the <tt>.ts</tt> files using <em>TQt Linguist</em> adding and editing their translations.</p>
<!-- index XML --><p>The <tt>.ts</tt> format is human-readable XML that can be emailed directly and is easy to put under version control. If you edit this file manually, be aware that the default encoding for XML is UTF-8, not Latin-1 (ISO 8859-1). One way to type in a Latin-1 character such as '&oslash;' (Norwegian o with slash) is to use an XML entity: "&amp;#xf8;". This will work for any Unicode character.</p>
<p>Once the translations are complete the <a href="linguist-manual-2.html#3">lrelease</a> program is used to convert the <tt>.ts</tt> files into the <tt>.qm</tt> TQt message file format. The <tt>.qm</tt> format is a compact binary format designed to deliver very fast lookup performance. Both <a href="linguist-manual-2.html#2">lupdate</a> and <a href="linguist-manual-2.html#3">lrelease</a> read all the project's source and header files (as specified in the HEADERS and SOURCES lines of the project file) and extract the strings that appear in <tt>tr()</tt> function calls.</p>
<!-- index lupdate --><p><a href="linguist-manual-2.html#2">lupdate</a> is used to create and update the message files (<tt>tt1_la.ts</tt> in this case) to keep them in sync with the source code. It is safe to run <a href="linguist-manual-2.html#2">lupdate</a> at any time, as <a href="linguist-manual-2.html#2">lupdate</a> does not remove any information. For example, you can put it in the makefile, so the <tt>.ts</tt> files are updated whenever the source changes.</p>
<!-- index .ts Files --><!-- index Translation Source Files --><!-- index XML --><p>Try running <a href="linguist-manual-2.html#2">lupdate</a> right now, like this:</p>
<pre>
    lupdate -verbose tt1.pro
</pre>
<p>(The <tt>-verbose</tt> option instructs <tt>lupdate</tt> to display messages that explain what it is doing.) You should now have a file <tt>tt1_la.ts</tt> in the current directory, containing this:</p>
<pre>
    &lt;!DOCTYPE TS&gt;&lt;TS&gt;
    &lt;context&gt;
        &lt;name&gt;TQPushButton&lt;/name&gt;
        &lt;message&gt;
            &lt;source&gt;Hello world!&lt;/source&gt;
            &lt;translation type="unfinished"&gt;&lt;/translation&gt;
        &lt;/message&gt;
    &lt;/context&gt;
    &lt;/TS&gt;
</pre>
<p>You don't need to understand the file format since it is read and updated using tools (<a href="linguist-manual-2.html#2">lupdate</a>, <em>TQt Linguist</em>, <a href="linguist-manual-2.html#3">lrelease</a>).</p>
<h5><a name="2-1-4"></a>Translating to Latin with TQt Linguist</h5>
<!-- index TQt Linguist --><!-- index Linguist --><p>We will use <em>TQt Linguist</em> to provide the translation, although you can use any XML or plain text editor to enter a translation into a <tt>.ts</tt> file.</p>
<p>To start <em>TQt Linguist</em>, type</p>
<pre>
    linguist tt1_la.ts
</pre>
<p>You should now see the text "TQPushButton" in the top left pane. Double-click it, then click on "Hello world!" and enter "Orbis, te saluto!" in the <em>Translation</em> pane (the middle right of the window). Don't forget the exclamation mark!</p>
<p>Click the <em>Done</em> checkbox and choose <em>File|Save</em> from the menu bar. The <tt>.ts</tt> file will no longer contain</p>
<pre>
    &lt;translation type='unfinished'&gt;&lt;/translation&gt;
</pre>
<p>but instead will have</p>
<pre>
    &lt;translation&gt;Orbis, te saluto!&lt;/translation&gt;
</pre>
<h5><a name="2-1-5"></a>Running the Application in Latin</h5>
<!-- index Latin --><!-- index lrelease --><p>To see the application running in Latin, we have to generate a <tt>.qm</tt> file from the <tt>.ts</tt> file. Generating a <tt>.qm</tt> file can be achieved either from within <em>TQt Linguist</em> (for a single <tt>.ts</tt> file), or by using the command line program <a href="linguist-manual-2.html#3">lrelease</a> which will produce one <tt>.qm</tt> file for each of the <tt>.ts</tt> files listed in the project file. Generate <tt>tt1_la.qm</tt> from <tt>tt1_la.ts</tt> by choosing <em>File|Release</em> from <em>TQt Linguist</em>'s menu bar and pressing <em>Save</em> in the file save dialog that pops up. Now run the <em>tt1</em> example program again. This time the button will be labelled "Orbis, te saluto!".</p>
<p align="center"><img align="middle" src="tt1_la.png" width="112" height="49">
</p>
<blockquote><p align="center"><em>Tutorial 1 Screenshot, Latin version</em></p></blockquote>
<h4><a name="2-2"></a>Tutorial 2: Using Two or More Languages</h4>
<p align="center"><img align="middle" src="tt2_en.png" width="170" height="157">
</p>
<blockquote><p align="center"><em>Tutorial 2 Screenshot, English version</em></p></blockquote>
<!-- index .pro Files --><!-- index Project Files --><!-- index qmake!Project Files --><pre>TEMPLATE        = app
CONFIG          += qt warn_on
HEADERS         = arrowpad.h \
                  mainwindow.h
SOURCES         = arrowpad.cpp \
                  main.cpp \
                  mainwindow.cpp
TRANSLATIONS    = tt2_fr.ts \
                  tt2_nl.ts
</pre>
<blockquote><p align="center"><em>tt2.pro</em></p></blockquote>
<!-- index Translation Contexts --><!-- index Contexts!for Translation --><p>This example is a slightly more involved and introduces a key <em>TQt Linguist</em> concept: "contexts".</p>
<ul><li><p><tt>arrowpad.h</tt> contains the definition of <tt>ArrowPad</tt>, a custom widget;</p>
<li><p><tt>arrowpad.cpp</tt> contains the implementation of <tt>ArrowPad</tt>;</p>
<li><p><tt>mainwindow.h</tt> contains the definition of <tt>MainWindow</tt>, a subclass of <a href="tqmainwindow.html">TQMainWindow</a></p>
<li><p><tt>mainwindow.cpp</tt> contains the implementation of <tt>MainWindow</tt>;</p>
<li><p><tt>main.cpp</tt> contains main().</p>
</ul><!-- index tt2.pro --><!-- index French Language --><!-- index Dutch Language --><p>We will use two translations, French and Dutch, although there is no effective limit on the number of possible translations that can be used with an application. The relevant lines of <tt>tt2.pro</tt> are</p>
<pre>    HEADERS         = arrowpad.h \
                      mainwindow.h
    SOURCES         = arrowpad.cpp \
                      main.cpp \
                      mainwindow.cpp
    TRANSLATIONS    = tt2_fr.ts \
                      tt2_nl.ts
</pre>
<!-- index lupdate --><!-- index tt2_fr.ts --><!-- index tt2_nl.ts --> <p>Run <a href="linguist-manual-2.html#2">lupdate</a>; it should produce two identical message files <tt>tt2_fr.ts</tt> and <tt>tt2_nl.ts</tt>. These files will contain all the source texts marked for translation with <tt>tr()</tt> calls and their contexts.</p>
<h5><a name="2-2-1"></a>Line by Line Walk-through</h5>
<!-- index ArrowPad!in Translation Tutorial --><!-- index English Language --><p>In <tt>arrowpad.h</tt> we define the <tt>ArrowPad</tt> subclass which is a subclass of <a href="tqwidget.html">TQWidget</a>. In the <em>Tutorial 2 Screenshot, English version</em>, above, the central widget with the four buttons is an <tt>ArrowPad</tt>.</p>
<pre>    class ArrowPad : public <a href="tqgrid.html">TQGrid</a>
</pre>
<!-- index TQ_OBJECT --><!-- index tr() --><!-- index TQObject!tr() --><!-- index Translation Contexts --><!-- index Contexts!for Translation --> <p>When <a href="linguist-manual-2.html#2">lupdate</a> is run it not only extracts the source texts but it also groups them into contexts. A context is the name of the class in which the source text appears. Thus, in this example, "ArrowPad" is a context: it is the context of the texts in the <tt>ArrowPad</tt> class. The <tt>TQ_OBJECT</tt> macro defines <tt>tr(x)</tt> in <tt>ArrowPad</tt> like this</p>
<!-- index TQApplication!translate() --><!-- index translate()!TQApplication --><pre>
    tqApp-&gt;translate( "ArrowPad", x )
</pre>
<p>Knowing which class each source text appears in enables <em>TQt Linguist</em> to group texts that are logically related together, e.g. all the text in a dialog will have the context of the dialog's class name and will be shown together. This provides useful information for the translator since the context in which text appears may influence how it should be translated. For some translations keyboard accelerators may need to be changed and having all the source texts in a particular context (class) grouped together makes it easier for the translator to perform any accelerator changes without introducing conflicts.</p>
<p>In <tt>arrowpad.cpp</tt> we implement the <tt>ArrowPad</tt> class.</p>
<pre>        (void) new <a href="tqpushbutton.html">TQPushButton</a>( <a href="tqobject.html#tr">tr</a>("&amp;Up"), this );
</pre>
 <p>We call <tt>ArrowPad::tr()</tt> for each button's label since the labels are user-visible text.</p>
<p align="center"><img align="middle" src="tt2_en.png" width="170" height="157">
</p>
<blockquote><p align="center"><em>Tutorial 2 Screenshot, English version</em></p></blockquote>
<!-- index TQ_OBJECT --><!-- index MainWindow!in Translation Tutorial --><pre>    class MainWindow : public <a href="tqmainwindow.html">TQMainWindow</a>
    {
        TQ_OBJECT
</pre>
 <p>In the <em>Tutorial 2 Screenshot, English version</em>, above, the whole window is a <tt>MainWindow</tt>. This is defined in the <tt>mainwindow.h</tt> header file. Here too, we use <tt>TQ_OBJECT</tt>, so that <tt>MainWindow</tt> will become a context in <em>TQt Linguist</em>.</p>
<p>In the implementation of <tt>MainWindow</tt>, <tt>mainwindow.cpp</tt>, we create an instance of our <tt>ArrowPad</tt> class</p>
<pre>        ArrowPad *ap = new ArrowPad( this, "arrow pad" );
</pre>
 <p>We also call <tt>MainWindow::tr()</tt> twice, once for the menu item and once for the accelerator.</p>
<!-- index Ctrl Key --><!-- index Alt Key --><pre>        file-&gt;<a href="tqmenudata.html#insertItem">insertItem</a>( <a href="tqobject.html#tr">tr</a>("E&amp;xit"), tqApp, TQ_SLOT(<a href="ntqapplication.html#quit">quit</a>()),
                          <a href="tqobject.html#tr">tr</a>("Ctrl+Q", "Quit") );
</pre>
 <p>Note the use of <tt>tr()</tt> to support different keys in other languages. "Ctrl+Q" is a good choice for Quit in English, but a Dutch translator might want to use "Ctrl+A" (for Afsluiten) and a German translator "Strg+E" (for Beenden). When using <tt>tr()</tt> for Ctrl key accelerators, the two argument form should be used with the second argument describing the function that the accelerator performs.</p>
<!-- index main() --><p>Our <tt>main()</tt> function is defined in <tt>main.cpp</tt> as usual.</p>
<pre>        <a href="tqtranslator.html">TQTranslator</a> translator( 0 );
        translator.<a href="tqtranslator.html#load">load</a>( TQString("tt2_") + TQTextCodec::locale(), "." );
        app.<a href="ntqapplication.html#installTranslator">installTranslator</a>( &amp;translator );
</pre>
<!-- index TQTextCodec!locale() --><!-- index locale()!TQTextCodec --><!-- index LANG!Environment Variable --><!-- index Environment Variables!LANG --> <p>We choose which translation to use according to the current locale. <a href="tqtextcodec.html#locale">TQTextCodec::locale</a>() can be influenced by setting the <tt>LANG</tt> environment variable, for example. Notice that the use of a naming convention that incorporates the locale for <tt>.qm</tt> message files, (and <tt>.ts</tt> files), makes it easy to implement choosing the translation file according to locale.</p>
<p>If there is no <tt>.qm</tt> message file for the locale chosen the original source text will be used and no error raised.</p>
<h5><a name="2-2-2"></a>Translating to French and Dutch</h5>
<p>We'll begin by translating the example application into French. Start <em>TQt Linguist</em> with <tt>tt2_fr.ts</tt>. You should get the seven source texts ("&amp;Up", "&amp;Left", etc.) grouped in two contexts ("ArrowPad" and "MainWindow").</p>
<p>Now, enter the following translations:</p>
<ul><li><p><tt>ArrowPad</tt></p>
<ul><li><p>&amp;Up - &amp;Haut</p>
<li><p>&amp;Left - &amp;Gauche</p>
<li><p>&amp;Right - &amp;Droite</p>
<li><p>&amp;Down - &amp;Bas</p>
</ul><li><p><tt>MainWindow</tt></p>
<ul><li><p>E&amp;xit - &amp;Quitter</p>
<li><p>Ctrl+Q - Ctrl+Q</p>
<li><p>&amp;File - &amp;Fichier</p>
</ul></ul><p>It's quickest to press <b>Alt+D</b> (which clicks the <em>Done &amp; Next</em> button) after typing each translation, since this marks the translation as done and moves on to the next source text.</p>
<p>Save the file and do the same for Dutch working with <tt>tt2_nl.ts</tt>:</p>
<ul><li><p><tt>ArrowPad</tt></p>
<ul><li><p>&amp;Up - &amp;Boven</p>
<li><p>&amp;Left - &amp;Links</p>
<li><p>&amp;Right - &amp;Rechts</p>
<li><p>&amp;Down - &amp;Onder</p>
</ul><li><p><tt>MainWindow</tt></p>
<ul><li><p>E&amp;xit - &amp;Afsluiten</p>
<li><p>Ctrl+Q - Ctrl+A</p>
<li><p>File - &amp;Bestand</p>
</ul></ul><p>We have to convert the <tt>tt1_fr.ts</tt> and <tt>tt1_nl.ts</tt> translation source files into <tt>.qm</tt> files. We could use <em>TQt Linguist</em> as we've done before; however using the command line tool <a href="linguist-manual-2.html#3">lrelease</a> ensures that <em>all</em> the <tt>.qm</tt> files for the application are created without us having to remember to load and <em>File|Release</em> each one individually from <em>TQt Linguist</em>.</p>
<p>In practice we would include calls to <a href="linguist-manual-2.html#2">lupdate</a> and <a href="linguist-manual-2.html#3">lrelease</a> in the application's makefile to ensure that the latest translations are used.</p>
<p>Type</p>
<pre>
    lrelease tt2.pro
</pre>
<!-- index LANG!Environment Variable --><!-- index export!Unix Command --><!-- index setenv!Unix Command --><p>This should create both <tt>tt2_fr.qm</tt> and <tt>tt2_nl.qm</tt>. Set the <tt>LANG</tt> environment variable to <tt>fr</tt>. In Unix, one of the two following commands should work</p>
<pre>
    export LANG=fr
    setenv LANG fr
</pre>
<!-- index  --><!-- index autoexec.bat --><!-- index set!Windows Command --><p>In Windows, either modify <tt>autoexec.bat</tt> or run</p>
<pre>
    set LANG=fr
</pre>
<p>When you run the program, you should now see the French version:</p>
<p align="center"><img align="middle" src="tt2_fr.png" width="208" height="177">
</p>
<blockquote><p align="center"><em>Tutorial 2 Screenshot, French version</em></p></blockquote>
<p>Try the same with Dutch, by setting <tt>LANG=nl</tt>. Now the Dutch version should appear:</p>
<p align="center"><img align="middle" src="tt2_nl.png" width="208" height="177">
</p>
<blockquote><p align="center"><em>Tutorial 2 Screenshot, Dutch version</em></p></blockquote>
<h5><a name="2-2-3"></a>Exercises</h5>
<p>Mark one of the translations in <em>TQt Linguist</em> as not done, i.e. by unchecking the "done" checkbox; run <a href="linguist-manual-2.html#2">lupdate</a>, then <a href="linguist-manual-2.html#3">lrelease</a>, then the example. What effect did this change have?</p>
<!-- index Canada --><!-- index French Canada --><p>Set <tt>LANG=fr_CA</tt> (French Canada) and run the example program again. Explain why the result is the same as with <tt>LANG=fr</tt>.</p>
<p>Change one of the accelerators in the Dutch translation to eliminate the conflict between <em></em>&amp;Bestand and <em></em>&amp;Boven.</p>
<h4><a name="2-3"></a>Tutorial 3: Disambiguating Identical Strings</h4>
<p align="center"><img align="middle" src="tt3_10_en.png" width="208" height="177">
</p>
<blockquote><p align="center"><em>Tutorial 3 Screenshot, "Troll Print 1.0", English version</em></p></blockquote>
<pre>TEMPLATE        = app
CONFIG          += qt warn_on
HEADERS         = mainwindow.h \
                  printpanel.h
SOURCES         = main.cpp \
                  mainwindow.cpp \
                  printpanel.cpp
TRANSLATIONS    = tt3_pt.ts
</pre>
<blockquote><p align="center"><em><tt>tt3.pro</tt></em></p></blockquote>
<!-- index Portuguese Language --><!-- index Brazilian Language --><p>We've included a translation file, <tt>tt3_pt.ts</tt>, which contains some Portuguese translations for this example.</p>
<!-- index Troll Print --><p>We will consider two releases of the same application: Troll Print 1.0 and 1.1. We will learn to reuse the translations created for one release in a subsequent release. (In this tutorial, you need to edit some source files. It's probably best to copy all the files to a new temporary directory and work from there.)</p>
<p>Troll Print is a toy example application that lets the user choose printer settings. It comes in two versions: English and Portuguese.</p>
<p>Version 1.0 consists of these files:</p>
<!-- index tt3.pro --><!-- index tt3_pt.ts --><ul><li><p><tt>printpanel.h</tt> contains the definition of PrintPanel;</p>
<li><p><tt>printpanel.cpp</tt> contains the implementation of PrintPanel;</p>
<li><p><tt>mainwindow.h</tt> contains the definition of <tt>MainWindow</tt>;</p>
<li><p><tt>mainwindow.cpp</tt> contains the implementation of <tt>MainWindow</tt>;</p>
<li><p><tt>main.cpp</tt> contains main();</p>
<li><p><tt>tt3.pro</tt> is the <em>qmake</em> project file.</p>
<li><p><tt>tt3_pt.ts</tt> is the Portuguese message file.</p>
</ul><h5><a name="2-3-1"></a>Line by Line Walk-through</h5>
<p>The PrintPanel is defined in <tt>printpanel.h</tt>.</p>
<pre>    class PrintPanel : public <a href="tqvbox.html">TQVBox</a>
    {
        TQ_OBJECT
</pre>
<!-- index TQ_OBJECT --><!-- index PrintPanel!in Translation Tutorial --> <p>PrintPanel is a <a href="tqwidget.html">TQWidget</a>. It needs the <tt>TQ_OBJECT</tt> macro for <tt>tr()</tt> to work properly.</p>
<p>The implementation file is <tt>printpanel.cpp</tt>.</p>
<pre>    /*
        <a href="tqlabel.html">TQLabel</a> *lab = new <a href="tqlabel.html">TQLabel</a>( <a href="tqobject.html#tr">tr</a>("&lt;b&gt;TROLL PRINT&lt;/b&gt;"), this );
        lab-&gt;<a href="tqlabel.html#setAlignment">setAlignment</a>( <a href="ntqt.html#AlignmentFlags-enum">AlignCenter</a> );
    */
</pre>
<!-- index Troll Print --> <p>Some of the code is commented out in Troll Print 1.0; you will uncomment it later, for Troll Print 1.1.</p>
<pre>        <a href="tqhbuttongroup.html">TQHButtonGroup</a> *twoSided = new <a href="tqhbuttongroup.html">TQHButtonGroup</a>( this );
        twoSided-&gt;<a href="tqgroupbox.html#setTitle">setTitle</a>( <a href="tqobject.html#tr">tr</a>("2-sided") );
        but = new <a href="tqradiobutton.html">TQRadioButton</a>( <a href="tqobject.html#tr">tr</a>("Enabled"), twoSided );
        but = new <a href="tqradiobutton.html">TQRadioButton</a>( <a href="tqobject.html#tr">tr</a>("Disabled"), twoSided );
        but-&gt;<a href="tqbutton.html#toggle">toggle</a>();
        <a href="tqhbuttongroup.html">TQHButtonGroup</a> *colors = new <a href="tqhbuttongroup.html">TQHButtonGroup</a>( this );
        colors-&gt;<a href="tqgroupbox.html#setTitle">setTitle</a>( <a href="tqobject.html#tr">tr</a>("Colors") );
        but = new <a href="tqradiobutton.html">TQRadioButton</a>( <a href="tqobject.html#tr">tr</a>("Enabled"), colors );
        but = new <a href="tqradiobutton.html">TQRadioButton</a>( <a href="tqobject.html#tr">tr</a>("Disabled"), colors );
        but-&gt;<a href="tqbutton.html#toggle">toggle</a>();
</pre>
 <p>Notice the two occurrences of <tt>tr("Enabled")</tt> and of <tt>tr("Disabled")</tt> in PrintPanel. Since both "Enabled"s and "Disabled"s appear in the same context <em>TQt Linguist</em> will only display one occurrence of each and will use the same translations for the duplicates that it doesn't display. Whilst this is a useful timesaver, in some languages, such as Portuguese, the second occurrence requires a separate translation. We will see how <em>TQt Linguist</em> can be made to display all the occurrences for separate translation shortly.</p>
<!-- index MainWindow!in Translation Tutorial --><p>The header file for <tt>MainWindow</tt>, <tt>mainwindow.h</tt>, contains no surprises. In the implementation, <tt>mainwindow.cpp</tt>, we have some user-visible source texts that must be marked for translation.</p>
<pre>        <a href="tqwidget.html#setCaption">setCaption</a>( <a href="tqobject.html#tr">tr</a>("Troll Print 1.0") );
</pre>
 <p>We must translate the window's caption.</p>
<pre>        file-&gt;<a href="tqmenudata.html#insertItem">insertItem</a>( <a href="tqobject.html#tr">tr</a>("E&amp;xit"), tqApp, TQ_SLOT(<a href="ntqapplication.html#quit">quit</a>()),
                          <a href="tqobject.html#tr">tr</a>("Ctrl+Q", "Quit") );
        <a href="tqpopupmenu.html">TQPopupMenu</a> *help = new <a href="tqpopupmenu.html">TQPopupMenu</a>( this );
        help-&gt;<a href="tqmenudata.html#insertItem">insertItem</a>( <a href="tqobject.html#tr">tr</a>("&amp;About"), this, TQ_SLOT(about()), Key_F1 );
        help-&gt;<a href="tqmenudata.html#insertItem">insertItem</a>( <a href="tqobject.html#tr">tr</a>("About &amp;TQt"), this, TQ_SLOT(aboutTQt()) );

        <a href="tqmainwindow.html#menuBar">menuBar</a>()-&gt;insertItem( <a href="tqobject.html#tr">tr</a>("&amp;File"), file );
        <a href="tqmainwindow.html#menuBar">menuBar</a>()-&gt;insertSeparator();
        <a href="tqmainwindow.html#menuBar">menuBar</a>()-&gt;insertItem( <a href="tqobject.html#tr">tr</a>("&amp;Help"), help );
</pre>
 <p>We also need to translate the menu items. Note that the two argument form of <tt>tr()</tt> is used for the keyboard accelerator, "Ctrl+Q", since the second argument is the only clue the translator has to indicate what function that accelerator will perform.</p>
<pre>        <a href="tqtranslator.html">TQTranslator</a> translator( 0 );
        translator.<a href="tqtranslator.html#load">load</a>( TQString("tt3_") + TQTextCodec::locale(), "." );
        app.<a href="ntqapplication.html#installTranslator">installTranslator</a>( &amp;translator );
</pre>
<!-- index main() --> <p>The <tt>main()</tt> function in <tt>main.cpp</tt> is the same as the one in <a href="linguist-manual-4.html#2-2">Tutorial 2</a>. In particular it chooses a translation file based on the current locale.</p>
<h5><a name="2-3-2"></a>Running Troll Print 1.0 in English and in Portuguese</h5>
<p>We will use the translations in the <tt>tt3_pt.ts</tt> file that is provided.</p>
<p>Set the <tt>LANG</tt> environment variable to <tt>pt</tt>, and then run <tt>tt3</tt>. You should still see the English version, as shown in the <em>Tutorial 3 Screenshot, "Troll Print 1.0", English version</em>, above. Now run <a href="linguist-manual-2.html#3">lrelease</a>, e.g. <tt>lrelease tt3.pro</tt>, and then run the example again. Now you should see the Portuguese edition (Troll Imprimir 1.0):</p>
<p align="center"><img align="middle" src="tt3_10_pt_bad.png" width="208" height="177">
</p>
<blockquote><p align="center"><em>Tutorial 3 Screenshot, "Troll Imprimir 1.0", (Bad) Portuguese version</em></p></blockquote>
<p>Whilst the translation has appeared correctly, it is in fact wrong. In good Portuguese, the second occurrence of "Enabled" should be "Ativadas", not "Ativado" and the ending for the second translation of "Disabled" must change similarly too.</p>
<p>If you open <tt>tt3_pt.ts</tt> using <em>TQt Linguist</em>, you will see that there is just one occurrence of "Enabled" and of "Disabled" in the translation source file, even though there are two of each in the source code. This is because <em>TQt Linguist</em> tries to minimize the translator's work by using the same translation for duplicate source texts. In cases such as this where an identical translation is wrong, the programmer must disambiguate the duplicate occurrences. This is easily achieved by using the two argument form of <tt>tr()</tt>.</p>
<p>We can easily determine which file must be changed because the translator's "context" is in fact the class name for the class where the texts that must be changed appears. In this case the file is <tt>printpanel.cpp</tt>, where the there are four lines to change. Add the second argument "two-sided" in the appropriate <tt>tr()</tt> calls to the first pair of radio buttons:</p>
<pre>
    but = new TQRadioButton( tr("Enabled", "two-sided"), twoSided );
    but = new TQRadioButton( tr("Disabled", "two-sided"), twoSided );
</pre>
<p>and add the second argument "colors" in the appropriate <tt>tr()</tt> calls for the second pair of radio buttons:</p>
<pre>
    but = new TQRadioButton( tr("Enabled", "colors"), colors );
    but = new TQRadioButton( tr("Disabled", "colors"), colors );
</pre>
<!-- index lupdate --><!-- index tt3_pt.ts --><p>Now run <a href="linguist-manual-2.html#2">lupdate</a> and open <tt>tt3_pt.ts</tt> with <em>TQt Linguist</em>. You should now see two changes.</p>
<p>First, the translation source file now contains <em>three</em> "Enabled", "Disabled" pairs. The first pair is marked "(obs.)" signifying that they are obsolete. This is because these texts appeared in <tt>tr()</tt> calls that have been replaced by new calls with two arguments. The second pair has "two-sided" as their comment, and the third pair has "colors" as their comment. The comments are shown in the <em>Source text and comments</em> area in <em>TQt Linguist</em>.</p>
<p>Second, the translation text "Ativado" and "Desativado" have been automatically used as translations for the new "Enabled" and "Disabled" texts, again to minimize the translator's work. Of course in this case these are not correct for the second occurrence of each word, but they provide a good starting point.</p>
<p>Change the second "Ativado" into "Ativadas" and the second "Desativado" into "Desativadas", then save and quit. Run <a href="linguist-manual-2.html#3">lrelease</a> to obtain an up-to-date binary <tt>tt3_pt.qm</tt> file, and run Troll Print (or rather Troll Imprimir).</p>
<p align="center"><img align="middle" src="tt3_10_pt_good.png" width="208" height="177">
</p>
<blockquote><p align="center"><em>Tutorial 3 Screenshot, "Troll Imprimir 1.0", (Good) Portuguese version</em></p></blockquote>
<!-- index Translator Comments --><!-- index Comments!for Translators --><p>The second argument to <tt>tr()</tt> calls, called "comments" in <em>TQt Linguist</em>, distinguish between identical source texts that occur in the same context (class). They are also useful in other cases to give clues to the translator, and in the case of Ctrl key accelerators are the only means of conveying the function performed by the accelerator to the translator.</p>
<!-- index TRANSLATOR!in Comments --><!-- index Translator Comments --><!-- index Comments!for Translators --><p>An additional way of helping the translator is to provide information on how to navigate to the particular part of the application that contains the source texts they must translate. This helps them see the context in which the translation appears and also helps them to find and test the translations. This can be achieved by using a <em>TRANSLATOR</em> comment in the source code:</p>
<pre>
    /* TRANSLATOR MainWindow

       In this application the whole application is a MainWindow.
       Choose Help|About from the menu bar to see some text
       belonging to MainWindow.
    */
</pre>
<p>Try adding these comments to some source files, particularly to dialog classes, describing the navigation necessary to reach the dialogs. You could also add them to the example files, e.g. <tt>mainwindow.cpp</tt> and <tt>printpanel.cpp</tt> are appropriate files. Run <a href="linguist-manual-2.html#2">lupdate</a> and then start <em>TQt Linguist</em> and load in <tt>tt3_pt.ts</tt>. You should see the comments in the <em>Source text and comments</em> area as you browse through the list of source texts.</p>
<p>Sometimes, particularly with large programs, it can be difficult for the translator to find their translations and check that they're correct. Comments that provide good navigation information can save them time:</p>
<pre>
    /* TRANSLATOR ZClientErrorDialog

        Choose Client|Edit to reach the Client Edit dialog, then choose
        Client Specification from the drop down list at the top and pick
        client Bartel Leendert van der Waerden. Now check the Profile
        checkbox and then click the Start Processing button. You should
        now see a pop up window with the text "Error: Name too long!".
        This window is a ZClientErrorDialog.
    */
</pre>
<h5><a name="2-3-3"></a>Troll Print 1.1</h5>
<p>We'll now prepare release 1.1 of Troll Print. Start your favorite text editor and follow these steps:</p>
<ul><li><p>Uncomment the two lines that create a <a href="tqlabel.html">TQLabel</a> with the text "&lt;b&gt;TROLL PRINT&lt;/b&gt;" in <tt>printpanel.cpp</tt>.</p>
<li><p>Word-tidying: Replace "2-sided" by "Two-sided" in <tt>printpanel.cpp</tt>.</p>
<li><p>Replace "1.0" with "1.1" everywhere it occurs in <tt>mainwindow.cpp</tt>.</p>
<li><p>Update the copyright year to 1999-2000 in <tt>mainwindow.cpp</tt>.</p>
</ul><p>(Of course the version number and copyright year would be consts or #defines in a real application.)</p>
<p>Once finished, run <a href="linguist-manual-2.html#2">lupdate</a>, then open <tt>tt3_pt.ts</tt> in <em>TQt Linguist</em>. The following items are of special interest:</p>
<ul><li><p><tt>MainWindow</tt></p>
<ul><li><p>Troll Print 1.0 - marked "(obs.)", obsolete</p>
<li><p>About Troll Print 1.0 - marked "(obs.)", obsolete</p>
<li><p>Troll Print 1.0. Copyright 1999 Macroshaft, Inc. - marked "(obs.)", obsolete</p>
<li><p>Troll Print 1.1 - automatically translated as "Troll Imprimir 1.1"</p>
<li><p>About Troll Print 1.1 - automatically translated as "Troll Imprimir 1.1"</p>
<li><p>Troll Print 1.1. Copyright 1999-2000 Macroshaft, Inc. - automatically translated as "Troll Imprimir 1.1. Copyright 1999-2000 Macroshaft, Inc."</p>
</ul><li><p><tt>PrintPanel</tt></p>
<ul><li><p>2-sided - marked "(obs.)", obsolete</p>
<li><p>&lt;b&gt;TROLL PRINT&lt;/b&gt; - unmarked, i.e. untranslated</p>
<li><p>Two-sided - unmarked, i.e. untranslated.</p>
</ul></ul><p>Notice that <a href="linguist-manual-2.html#2">lupdate</a> works hard behind the scenes to make revisions easier, and it's pretty smart with numbers.</p>
<p>Go over the translations in <tt>MainWindow</tt> and mark these as "done". Translate "&lt;b&gt;TROLL PRINT&lt;/b&gt;" as "&lt;b&gt;TROLL IMPRIMIR&lt;/b&gt;". When you're translating "Two-sided", press the <em>Guess Again</em> button to translate "Two-sided", but change the "2" into "Dois".</p>
<p>Save and quit, then run <a href="linguist-manual-2.html#3">lrelease</a>. The Portuguese version should look like this:</p>
<p align="center"><img align="middle" src="tt3_11_pt.png" width="198" height="187">
</p>
<blockquote><p align="center"><em>Tutorial 3 Screenshot, "Troll Imprimir 1.1", Portuguese version</em></p></blockquote>
<p>Choose <em>Ajuda|Sobre</em>, (<em>Help|About</em>), to see the about box</p>
<p align="center"><img align="middle" src="tt3_11_about_pt.png" width="262" height="139">
</p>
<blockquote><p align="center"><em>Tutorial 3 Screenshot, About box, Portuguese version</em></p></blockquote>
<!-- index English Language --><!-- index Translating TQt --><!-- index TQt!Translating TQt --><p>If you choose <em>Ajuda|Sobre TQt</em>, (<em>Help|About TQt</em>), you'll get an English dialog. Oops! TQt itself needs to be translated. See the document <a href="i18n.html#qt-itself">Internationalization with TQt</a> for details.</p>
<p>Now set <tt>LANG=en</tt> to get the original English version:</p>
<p align="center"><img align="middle" src="tt3_11_en.png" width="208" height="189">
</p>
<blockquote><p align="center"><em>Tutorial 3 Screenshot, "Troll Print 1.1", English version</em></p></blockquote>
<h4><a name="2-4"></a>Summary</h4>
<p>These tutorials cover all that you need to know to prepare your TQt 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-manual-2.html#2">lupdate</a> and <a href="linguist-manual-2.html#3">lrelease</a> to the make file.</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 <em>TRANSLATION</em> comments to help the translator navigate the application.</p>
<!-- eof -->
<p><address><hr><div align=center>
<table width=100% cellspacing=0 border=0><tr>
<td>Copyright &copy; 2007
<a href="troll.html">Trolltech</a><td align=center><a href="trademarks.html">Trademarks</a>
<td align=right><div align=right>TQt 3.3.8</div>
</table></div></address></body>
</html>