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 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745
|
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
<title>Developing Roundup</title>
<style type="text/css">
/*
:Author: David Goodger
:Contact: goodger@users.sourceforge.net
:Date: $Date$
:Revision: $Revision$
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin-left: 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left {
clear: left }
img.align-right {
clear: right }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font-family: serif ;
font-size: 100% }
pre.literal-block, pre.doctest-block {
margin-left: 2em ;
margin-right: 2em ;
background-color: #eeeeee }
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
tt.docutils {
background-color: #eeeeee }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="developing-roundup">
<h1 class="title">Developing Roundup</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr><th class="docinfo-name">Version:</th>
<td>$Revision$</td></tr>
</tbody>
</table>
<div class="note">
<p class="first admonition-title">Note</p>
<p class="last">The intended audience of this document is the developers of the core
Roundup code. If you just wish to alter some behaviour of your Roundup
installation, see <a class="reference" href="customizing.html">customising roundup</a>.</p>
</div>
<div class="contents topic">
<p class="topic-title first"><a id="contents" name="contents">Contents</a></p>
<ul class="simple">
<li><a class="reference" href="#getting-started" id="id2" name="id2">Getting Started</a></li>
<li><a class="reference" href="#small-changes" id="id3" name="id3">Small Changes</a></li>
<li><a class="reference" href="#cvs-access" id="id4" name="id4">CVS Access</a></li>
<li><a class="reference" href="#project-rules" id="id5" name="id5">Project Rules</a></li>
<li><a class="reference" href="#debugging-aids" id="id6" name="id6">Debugging Aids</a></li>
<li><a class="reference" href="#internationalization-notes" id="id7" name="id7">Internationalization Notes</a><ul>
<li><a class="reference" href="#gnu-gettext-package" id="id8" name="id8">GNU gettext package</a></li>
<li><a class="reference" href="#marking-strings-for-translation" id="id9" name="id9">Marking Strings for Translation</a><ul>
<li><a class="reference" href="#command-line-interfaces" id="id10" name="id10">Command Line Interfaces</a></li>
<li><a class="reference" href="#deferred-translations" id="id11" name="id11">Deferred Translations</a></li>
<li><a class="reference" href="#web-user-interface" id="id12" name="id12">Web User Interface</a></li>
</ul>
</li>
<li><a class="reference" href="#extracting-translatable-messages" id="id13" name="id13">Extracting Translatable Messages</a></li>
<li><a class="reference" href="#translating-messages" id="id14" name="id14">Translating Messages</a></li>
<li><a class="reference" href="#compiling-message-catalogs" id="id15" name="id15">Compiling Message Catalogs</a></li>
</ul>
</li>
</ul>
</div>
<div class="section">
<h1><a class="toc-backref" href="#id2" id="getting-started" name="getting-started">Getting Started</a></h1>
<p>Anyone wishing to help in the development of Roundup must read <a class="reference" href="spec.html">Roundup's
Design Document</a> and the <a class="reference" href="implementation.html">implementation notes</a>.</p>
<p>All development is coordinated through two resources:</p>
<ul class="simple">
<li>roundup-dev mailing list at
<a class="reference" href="http://lists.sourceforge.net/mailman/listinfo/roundup-devel">http://lists.sourceforge.net/mailman/listinfo/roundup-devel</a></li>
<li>Sourceforge's issue trackers at
<a class="reference" href="https://sourceforge.net/tracker/?group_id=31577">https://sourceforge.net/tracker/?group_id=31577</a></li>
</ul>
</div>
<div class="section">
<h1><a class="toc-backref" href="#id3" id="small-changes" name="small-changes">Small Changes</a></h1>
<p>Most small changes can be submitted through the <a class="reference" href="http://sourceforge.net/tracker/?group_id=31577&atid=402791">feature tracker</a>, with
patches attached that give context diffs of the affected source.</p>
</div>
<div class="section">
<h1><a class="toc-backref" href="#id4" id="cvs-access" name="cvs-access">CVS Access</a></h1>
<p>To get CVS access, contact <a class="reference" href="mailto:richard@users.sourceforge.net">richard@users.sourceforge.net</a>.</p>
<p>CVS stuff:</p>
<ol class="arabic">
<li><p class="first">to tag a release (eg. the pre-release of 0.5.0):</p>
<pre class="literal-block">
cvs tag release-0-5-0-pr1
</pre>
</li>
</ol>
<ol class="arabic">
<li><p class="first">to make a branch (eg. branching for code freeze/release):</p>
<pre class="literal-block">
cvs co -d maint-0-5 -r release-0-5-0-pr1 roundup
cd maint-0-5
cvs tag -b maint-0-5
</pre>
</li>
<li><p class="first">to check out a branch (eg. the maintenance branch for 0.5.x):</p>
<pre class="literal-block">
cvs co -d maint-0-5 -r maint-0-5
</pre>
</li>
<li><p class="first">to merge changes from the maintenance branch to the trunk, in the
directory containing the HEAD checkout:</p>
<pre class="literal-block">
cvs up -j maint-0-5
</pre>
<p>though this is highly discouraged, as it generally creates a whole swag
of conflicts :(</p>
</li>
</ol>
<p>Standard tag names:</p>
<dl class="docutils">
<dt><em>release-maj-min-patch[-sub]</em></dt>
<dd>Release of the major.minor.patch release, possibly a beta or pre-release,
in which case <em>sub</em> will be one of "b*N*" or "pr*N*".</dd>
<dt><em>maint-maj-min</em></dt>
<dd>Maintenance branch for the major.minor release. Patch releases are tagged in
this branch.</dd>
</dl>
<p>Typically, release happen like this:</p>
<ol class="arabic simple">
<li>work progresses in the HEAD branch until milestones are met,</li>
<li>a series of beta releases are tagged in the HEAD until the code is
stable enough to freeze,</li>
<li>the pre-release is tagged in the HEAD, with the resultant code branched
to the maintenance branch for that release,</li>
<li>bugs in the release are patched in the maintenance branch, and the final
and patch releases are tagged there, and</li>
<li>further major work happens in the HEAD.</li>
</ol>
</div>
<div class="section">
<h1><a class="toc-backref" href="#id5" id="project-rules" name="project-rules">Project Rules</a></h1>
<p>Mostly the project follows Guido's Style (though naming tends to be a little
relaxed sometimes). In short:</p>
<ul class="simple">
<li>80 column width code</li>
<li>4-space indentations</li>
<li>All modules must have a CVS Id line near the top</li>
</ul>
<p>Other project rules:</p>
<ul class="simple">
<li>New functionality must be documented, even briefly (so at least we know
where there's missing documentation) and changes to tracker configuration
must be logged in the upgrading document.</li>
<li>subscribe to roundup-checkins to receive checkin notifications from the
other developers with CVS access</li>
<li>discuss any changes with the other developers on roundup-dev. If nothing
else, this makes sure there's no rude shocks</li>
<li>write unit tests for changes you make (where possible), and ensure that
all unit tests run before committing changes</li>
<li>run pychecker over changed code</li>
</ul>
<p>The administrators of the project reserve the right to boot developers who
consistently check in code which is either broken or takes the codebase in
directions that have not been agreed to.</p>
</div>
<div class="section">
<h1><a class="toc-backref" href="#id6" id="debugging-aids" name="debugging-aids">Debugging Aids</a></h1>
<p>Try turning on logging of DEBUG level messages. This may be done a number
of ways, depending on what it is you're testing:</p>
<ol class="arabic">
<li><p class="first">If you're testing the database unit tests, then set the environment
variable <tt class="docutils literal"><span class="pre">LOGGING_LEVEL=DEBUG</span></tt>. This may be done like so:</p>
<blockquote>
<p>LOGGING_LEVEL=DEBUG python run_tests.py</p>
</blockquote>
<p>This variable replaces the older HYPERDBDEBUG environment var.</p>
</li>
<li><p class="first">If you're testing a particular tracker, then set the logging level in
your tracker's <tt class="docutils literal"><span class="pre">config.ini</span></tt>.</p>
</li>
</ol>
</div>
<div class="section">
<h1><a class="toc-backref" href="#id7" id="internationalization-notes" name="internationalization-notes">Internationalization Notes</a></h1>
<p>How stuff works:</p>
<ol class="arabic simple">
<li>Strings that may require translation (messages in human language)
are marked in the source code. This step is discussed in
<a class="reference" href="#marking-strings-for-translation">Marking Strings for Translation</a> section.</li>
<li>These strings are all extracted into Message Template File
<tt class="docutils literal"><span class="pre">locale/roundup.pot</span></tt> (<span class="target" id="pot">POT</span> file). See <a class="reference" href="#extracting-translatable-messages">Extracting Translatable
Messages</a> below.</li>
<li>Language teams use POT file to make Message Files for national
languages (<span class="target" id="po">PO</span> files). All PO files for Roundup are kept in
the <tt class="docutils literal"><span class="pre">locale</span></tt> directory. Names of these files are target
locale names, usually just 2-letter language codes. <a class="reference" href="#translating-messages">Translating
Messages</a> section of this chapter gives useful hints for
message translators.</li>
<li>Translated Message Files are compiled into binary form (<span class="target" id="mo">MO</span> files)
and stored in <tt class="docutils literal"><span class="pre">locale</span></tt> directory (but not kept in the <a class="reference" href="http://sourceforge.net/cvs/?group_id=31577">Roundup
CVS</a> repository, as they may be easily made from PO files).
See <a class="reference" href="#compiling-message-catalogs">Compiling Message Catalogs</a> section.</li>
<li>Roundup installer creates runtime locale structure on the file
system, putting MO files in their appropriate places.</li>
<li>Runtime internationalization (<span class="target" id="i18n">I18N</span>) services use these MO files
to translate program messages into language selected by current
Roundup user. Roundup command line interface uses locale name
set in OS environment variable <tt class="docutils literal"><span class="pre">LANGUAGE</span></tt>, <tt class="docutils literal"><span class="pre">LC_ALL</span></tt>,
<tt class="docutils literal"><span class="pre">LC_MESSAGES</span></tt>, or <tt class="docutils literal"><span class="pre">LANG</span></tt> (in that order). Roundup Web User
Interface uses language selected by currently authenticated user.</li>
</ol>
<p>Additional details may be found in <a class="reference" href="#gnu-gettext">GNU gettext</a> and Python <a class="reference" href="http://docs.python.org/lib/module-gettext.html">gettext
module</a> documentation.</p>
<p><a class="reference" href="http://sourceforge.net/project/showfiles.php?group_id=31577">Roundup source distribution</a> includes POT and PO files for message
translators, and also pre-built MO files to facilitate installations
from source. Roundup binary distribution includes MO files only.</p>
<div class="section">
<h2><a class="toc-backref" href="#id8" id="gnu-gettext-package" name="gnu-gettext-package"><span id="gnu-gettext"></span>GNU gettext package</a></h2>
<p>This chapter is full of references to GNU <a class="reference" href="http://www.gnu.org/software/gettext/">gettext package</a>.
GNU gettext is a "must have" for nearly all steps of internationalizing
any program, and it's manual is definetely a recommended reading
for people involved in <a class="reference" href="#i18n">I18N</a>.</p>
<p>There are GNU gettext ports to all major OS platforms.
Windows binaries are available from <a class="reference" href="http://www.gnu.org/prep/ftp.html">GNU mirror sites</a>.</p>
<p>Roundup does not use GNU gettext at runtime, but it's tools
are used for <a class="reference" href="#extracting-translatable-messages">extracting translatable messages</a>, <a class="reference" href="#compiling-message-catalogs">compiling
message catalogs</a> and, optionally, for <a class="reference" href="#translating-messages">translating messages</a>.</p>
<p>Note that <tt class="docutils literal"><span class="pre">gettext</span></tt> package in some OS distributions means just
runtime tools and libraries. In such cases gettext development tools
are usually distributed in separate package named <tt class="docutils literal"><span class="pre">gettext-devel</span></tt>.</p>
</div>
<div class="section">
<h2><a class="toc-backref" href="#id9" id="marking-strings-for-translation" name="marking-strings-for-translation">Marking Strings for Translation</a></h2>
<p>Strings that need translation must be marked in the source code.
Following subsections explain how this is done in different cases.</p>
<p>If translatable string is used as a format string, it is recommended
to always use <em>named</em> format specifiers:</p>
<pre class="literal-block">
_('Index of %(classname)s') % locals()
</pre>
<p>This helps translators to better understand the context of the
message and, with Python formatting, remove format specifier altogether
(which is sometimes useful, especially in singular cases of <a class="reference" href="http://www.gnu.org/software/gettext/manual/html_node/gettext_150.html">Plural Forms</a>).</p>
<p>When there is more than one format specifier in the translatable
format string, named format specifiers <strong>must</strong> be used almost always,
because translation may require different order of items.</p>
<p>It is better to <em>not</em> mark for translation strings that are not
locale-dependent, as this makes it more difficult to keep track
of translation completeness. For example, string <tt class="docutils literal"><span class="pre"></ol></body></html></span></tt>
(in <tt class="docutils literal"><span class="pre">index()</span></tt> method of the request handler in <tt class="docutils literal"><span class="pre">roundup_server</span></tt>
script) has no human readable parts at all, and needs no translations.
Such strings are left untranslated in PO files, and are reported
as such by PO status checkers (e.g. <tt class="docutils literal"><span class="pre">msgfmt</span> <span class="pre">--statistics</span></tt>).</p>
<div class="section">
<h3><a class="toc-backref" href="#id10" id="command-line-interfaces" name="command-line-interfaces">Command Line Interfaces</a></h3>
<p>Scripts and routines run from the command line use "static" language
defined by environment variables recognized by <tt class="docutils literal"><span class="pre">gettext</span></tt> module
from Python library (<tt class="docutils literal"><span class="pre">LANGUAGE</span></tt>, <tt class="docutils literal"><span class="pre">LC_ALL</span></tt>, <tt class="docutils literal"><span class="pre">LC_MESSAGES</span></tt>, and
<tt class="docutils literal"><span class="pre">LANG</span></tt>). Primarilly, these are <tt class="docutils literal"><span class="pre">roundup-admin</span></tt> script and
<tt class="docutils literal"><span class="pre">admin.py</span></tt> module, but also help texts and startup error messages
in other scripts and their supporting modules.</p>
<p>For these interfaces, Python <tt class="docutils literal"><span class="pre">gettext</span></tt> engine must be initialized
to use Roundup message catalogs. This is normally done by including
the following line in the module imports:</p>
<pre class="literal-block">
from i18n import _, ngettext
</pre>
<p>Simple translations are automatically marked by calls to builtin
message translation function <tt class="docutils literal"><span class="pre">_()</span></tt>:</p>
<pre class="literal-block">
print _("This message is translated")
</pre>
<p>Translations for messages whose grammatical depends on a number
must be done by <tt class="docutils literal"><span class="pre">ngettext()</span></tt> function:</p>
<pre class="literal-block">
print ngettext("Nuked %i file", "Nuked %i files", number_of_files_nuked)
</pre>
</div>
<div class="section">
<h3><a class="toc-backref" href="#id11" id="deferred-translations" name="deferred-translations">Deferred Translations</a></h3>
<p>Sometimes translatable strings appear in the source code in untranslated
form <a class="footnote-reference" href="#note-admin-py" id="id1" name="id1">[1]</a> and must be translated elsewhere.
Example:</p>
<pre class="literal-block">
for meal in ("spam", "egg", "beacon"):
print _(meal)
</pre>
<p>In such cases, strings must be marked for translation without actual
call to the translating function. To mark these strings, we use Python
feature of automatic concatenation of adjacent strings and different
types of string quotes:</p>
<pre class="literal-block">
strings_to_translate = (
''"This string will be translated",
""'me too',
''r"\raw string",
''"""
multiline string"""
)
</pre>
<table class="docutils footnote" frame="void" id="note-admin-py" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id1" name="note-admin-py">[1]</a></td><td>In current Roundup sources, this feature is
extensively used in the <tt class="docutils literal"><span class="pre">admin</span></tt> module using method docstrings
as help messages.</td></tr>
</tbody>
</table>
</div>
<div class="section">
<h3><a class="toc-backref" href="#id12" id="web-user-interface" name="web-user-interface">Web User Interface</a></h3>
<p>For Web User Interface, translation services are provided by Client
object. Action classes have methods <tt class="docutils literal"><span class="pre">_()</span></tt> and <tt class="docutils literal"><span class="pre">gettext()</span></tt>,
delegating translation to the Client instance. In HTML templates,
translator object is available as context variable <tt class="docutils literal"><span class="pre">i18n</span></tt>.</p>
<p>HTML templates have special markup for translatable strings.
The syntax for this markup is defined on <a class="reference" href="http://dev.zope.org/Wikis/DevSite/Projects/ComponentArchitecture/ZPTInternationalizationSupport">ZPTInternationalizationSupport</a>
page. Roundup translation service currently ignores values for
<tt class="docutils literal"><span class="pre">i18n:domain</span></tt>, <tt class="docutils literal"><span class="pre">i18n:source</span></tt> and <tt class="docutils literal"><span class="pre">i18n:target</span></tt>.</p>
<p>Template markup examples:</p>
<ul>
<li><p class="first">simplest case:</p>
<pre class="literal-block">
<div i18n:translate="">
Say
no
more!
</div>
</pre>
<p>this will result in msgid <tt class="docutils literal"><span class="pre">"Say</span> <span class="pre">no</span> <span class="pre">more!"</span></tt>, with all leading and
trailing whitespace stripped, and inner blanks replaced with single
space character.</p>
</li>
<li><p class="first">using variable slots:</p>
<pre class="literal-block">
<div i18n:translate="">
And now...<br/>
No.<span tal:replace="number" i18n:name="slideNo" /><br/>
THE LARCH
</div>
</pre>
<p>Msgid will be: <tt class="docutils literal"><span class="pre">"And</span> <span class="pre">now...<br</span> <span class="pre">/></span> <span class="pre">No.${slideNo}<br</span> <span class="pre">/></span> <span class="pre">THE</span> <span class="pre">LARCH"</span></tt>.
Template rendering will use context variable <tt class="docutils literal"><span class="pre">number</span></tt> (you may use
any expression) to put instead of <tt class="docutils literal"><span class="pre">${slideNo}</span></tt> in translation.</p>
</li>
<li><p class="first">attribute translation:</p>
<pre class="literal-block">
<button name="btn_wink" value=" Wink " i18n:attributes="value" />
</pre>
<p>will translate the caption (and return value) for the "wink" button.</p>
</li>
<li><p class="first">explicit msgids. Sometimes it may be useful to specify msgid
for the element translation explicitely, like this:</p>
<pre class="literal-block">
<span i18n:translate="know what i mean?">this text is ignored</span>
</pre>
<p>When rendered, element contents will be replaced by translation
of the string specified in <tt class="docutils literal"><span class="pre">i18n:translate</span></tt> attribute.</p>
</li>
<li><p class="first"><tt class="docutils literal"><span class="pre">i18n</span></tt> in <a class="reference" href="http://dev.zope.org/Wikis/DevSite/Projects/ZPT/TALES%20Specification%201.3">TALES</a>. You may translate strings in <a class="reference" href="http://dev.zope.org/Wikis/DevSite/Projects/ZPT/TALES%20Specification%201.3">TALES</a> python
expressions:</p>
<pre class="literal-block">
<span tal:replace="python: i18n.gettext('Oh, wicked.')" />
</pre>
</li>
<li><p class="first">plural forms. There is no markup for plural forms in <a class="reference" href="http://dev.zope.org/Wikis/DevSite/Projects/ZPT/TAL%20Specification%201.4">TAL</a> i18n.
You must use python expression for that:</p>
<pre class="literal-block">
<span tal:replace="python: i18n.ngettext(
'Oh but it\'s only %i shilling.',
'Oh but it\'s only %i shillings.',
fine) % fine"
/>
</pre>
</li>
</ul>
</div>
</div>
<div class="section">
<h2><a class="toc-backref" href="#id13" id="extracting-translatable-messages" name="extracting-translatable-messages">Extracting Translatable Messages</a></h2>
<p>The most common tool for message extraction is <tt class="docutils literal"><span class="pre">xgettext</span></tt> utility
from <a class="reference" href="#gnu-gettext-package">GNU gettext package</a>. Unfortunately, this utility has no means
of <a class="reference" href="#deferred-translations">Deferred Translations</a> in Python sources. There is <tt class="docutils literal"><span class="pre">xpot</span></tt> tool
from Francois Pinard free <a class="reference" href="http://po-utils.progiciels-bpi.ca/">PO utilities</a> that allows to mark strings
for deferred translations, but it does not handle <a class="reference" href="http://www.gnu.org/software/gettext/manual/html_node/gettext_150.html">plural forms</a>.</p>
<p>Roundup overcomes these limitations by using both of these utilities.
This means that you need both <a class="reference" href="#gnu-gettext">GNU gettext</a> tools and <a class="reference" href="http://po-utils.progiciels-bpi.ca/">PO utilities</a>
to build the Message Template File yourself.</p>
<p>Latest Message Template File is kept in <a class="reference" href="http://sourceforge.net/cvs/?group_id=31577">Roundup CVS</a> and distributed
with <a class="reference" href="http://sourceforge.net/project/showfiles.php?group_id=31577">Roundup Source</a>. If you wish to rebuild the template yourself,
make sure that you have both <tt class="docutils literal"><span class="pre">xpot</span></tt> and <tt class="docutils literal"><span class="pre">xgettext</span></tt> installed and
just run <tt class="docutils literal"><span class="pre">gmake</span></tt> (or <tt class="docutils literal"><span class="pre">make</span></tt>, if you are on a <a class="reference" href="http://www.gnu.org/">GNU</a> system like
<a class="reference" href="http://www.linux.org/">linux</a> or <a class="reference" href="http://www.cygwin.com/">cygwin</a>) in the <tt class="docutils literal"><span class="pre">locale</span></tt> directory.</p>
<p>For on-site i18n, Roundup provides command-line utility:</p>
<pre class="literal-block">
roundup-gettext <tracker_home>
</pre>
<p>extracting translatable messages from tracker's html templates.
This utility creates message template file <tt class="docutils literal"><span class="pre">messages.pot</span></tt> in
<tt class="docutils literal"><span class="pre">locale</span></tt> subdirectory of the tracker home directory. Translated
messages may be put in <em>locale</em>.po files (where <em>locale</em> is selected
locale name) in the same directory, e.g.: <tt class="docutils literal"><span class="pre">locale/ru.po</span></tt>.
These message catalogs are searched prior to system-wide translations
kept in the <tt class="docutils literal"><span class="pre">share</span></tt> directory.</p>
</div>
<div class="section">
<h2><a class="toc-backref" href="#id14" id="translating-messages" name="translating-messages">Translating Messages</a></h2>
<p>Gettext Message File (<a class="reference" href="#po">PO</a> file) is a plain text file, that can be created
by simple copying <tt class="docutils literal"><span class="pre">roundup.pot</span></tt> to new .po file, like this:</p>
<pre class="literal-block">
$ cp roundup.pot ru.po
</pre>
<p>The name of PO file is target locale name, usually just 2-letter language
code (<tt class="docutils literal"><span class="pre">ru</span></tt> for Russian in the above example). Alternatively, PO file
may be initialized by <tt class="docutils literal"><span class="pre">msginit</span></tt> utility from <a class="reference" href="#gnu-gettext">GNU gettext</a> tools:</p>
<pre class="literal-block">
$ msginit -i roundup.pot
</pre>
<p><tt class="docutils literal"><span class="pre">msginit</span></tt> will check your current locale, and initialize the header
entry, setting language name, rules for <a class="reference" href="http://www.gnu.org/software/gettext/manual/html_node/gettext_150.html">plural forms</a> and, if available,
translator's name and email address. The name for PO file is also chosen
based on current locale.</p>
<p>Next, you will need to edit this file, filling all <tt class="docutils literal"><span class="pre">msgstr</span></tt> lines with
translations of the above <tt class="docutils literal"><span class="pre">msgid</span></tt> entries. PO file is a plain text
file that can be edited with any text editor. However, there are several
tools that may help you with this process:</p>
<blockquote>
<ul>
<li><p class="first"><a class="reference" href="http://poedit.sourceforge.net/">poEdit</a> by Vaclav Slavik. Very nice cross-platform GUI editor.</p>
</li>
<li><dl class="first docutils">
<dt><a class="reference" href="http://i18n.kde.org/tools/kbabel/">KBabel</a>. Being part of <a class="reference" href="http://www.kde.org/">KDE</a>, it works in X windows only.</dt>
<dd><p class="first last">At the first glance looks pretty hairy, with all bells and whistles.
Haven't had much experience with it, though.</p>
</dd>
</dl>
</li>
<li><p class="first"><tt class="docutils literal"><span class="pre">po-mode</span></tt> for <a class="reference" href="http://www.gnu.org/software/emacs/">emacs</a>. One of <a class="reference" href="#gnu-gettext">GNU gettext</a> tools. Very handy,
definitely recommended if you are comfortable with emacs. Cannot
handle <a class="reference" href="http://www.gnu.org/software/gettext/manual/html_node/gettext_150.html">plural forms</a> per se, but allows to edit them in simple
text mode.</p>
</li>
<li><p class="first"><a class="reference" href="http://vim.sourceforge.net/scripts/script.php?script_id=695">po filetype plugin</a> for <a class="reference" href="http://www.vim.org/">vim</a>. Does not do as much as <tt class="docutils literal"><span class="pre">po-mode</span></tt>,
but helps in finding untranslated and fuzzy strings, and checking
code references. Please contact <a class="reference" href="http://sourceforge.net/users/a1s/">alexander smishlajev</a> if you
prefer this, as i have patched this plugin a bit. I have also
informed the original plugin author about these changes, but got
no reply so far.</p>
</li>
</ul>
</blockquote>
</div>
<div class="section">
<h2><a class="toc-backref" href="#id15" id="compiling-message-catalogs" name="compiling-message-catalogs">Compiling Message Catalogs</a></h2>
<p>Message catalogs (<a class="reference" href="#po">PO</a> files) must be compiled into binary form
(<a class="reference" href="#mo">MO</a> files) before they can be used in the application. This
compilation is handled by <tt class="docutils literal"><span class="pre">msgfmt</span></tt> utility from <a class="reference" href="#gnu-gettext">GNU gettext</a>
tools. <tt class="docutils literal"><span class="pre">GNUmakefile</span></tt> in the <tt class="docutils literal"><span class="pre">locale</span></tt> directory automatically
compiles all existing message catalogs after updating them from
Roundup source files. If you wish to rebuild an individual <a class="reference" href="#mo">MO</a>
file without making everything else, you may, for example:</p>
<pre class="literal-block">
$ msgfmt --statistics -o ru.mo ru.po
</pre>
<p>This way, message translators can check their <a class="reference" href="#po">PO</a> files without
extracting strings from source. (Note: String extraction requires
additional utility that is not part of <a class="reference" href="#gnu-gettext">GNU gettext</a>. See <a class="reference" href="#extracting-translatable-messages">Extracting
Translatable Messages</a>.)</p>
<p>At run time, Roundup automatically compiles message catalogs whenever
<a class="reference" href="#po">PO</a> file is changed.</p>
<hr class="docutils" />
<p>Back to <a class="reference" href="index.html">Table of Contents</a></p>
</div>
</div>
</div>
<div class="footer">
<hr class="footer" />
Generated on: 2006-08-09.
</div>
</body>
</html>
|