Code

Small fix for CGI-handling of XMLRPC requests for python2.4, this worked
[roundup.git] / doc / developers.txt
1 ==================
2 Developing Roundup
3 ==================
5 .. note::
6    The intended audience of this document is the developers of the core
7    Roundup code. If you just wish to alter some behaviour of your Roundup
8    installation, see `customising roundup`_.
10 .. contents::
12 Getting Started
13 ---------------
15 Anyone wishing to help in the development of Roundup must read `Roundup's
16 Design Document`_ and the `implementation notes`_.
18 All development is coordinated through two resources:
20 - roundup-dev mailing list at
21   http://lists.sourceforge.net/mailman/listinfo/roundup-devel
22 - The issue tracker running at
23   http://issues.roundup-tracker.org/
25 Website, wiki, issue tracker
26 ----------------------------
28 1. Log into <username>,roundup@shell.sourceforge.net
29 2. cd /home/groups/r/ro/roundup
30 3. follow instructions in README.txt
33 Small Changes
34 -------------
36 Most small changes can be submitted through the issue tracker, with
37 patches attached that give context diffs of the affected source.
40 SVN Access
41 ----------
43 See http://www.roundup-tracker.org/code.html.
44 For all other questions ask on the development mailinglist.
47 Project Rules
48 -------------
50 Mostly the project follows Guido's Style (though naming tends to be a little
51 relaxed sometimes). In short:
53 - 80 column width code
54 - 4-space indentations
55 - All modules must have an Id line near the top
57 Other project rules:
59 - New functionality must be documented, even briefly (so at least we know
60   where there's missing documentation) and changes to tracker configuration
61   must be logged in the upgrading document.
62 - subscribe to roundup-checkins to receive checkin notifications from the
63   other developers with write access to the source-code repository.
64 - discuss any changes with the other developers on roundup-dev. If nothing
65   else, this makes sure there's no rude shocks
66 - write unit tests for changes you make (where possible), and ensure that
67   all unit tests run before committing changes
68 - run pychecker over changed code
70 The administrators of the project reserve the right to boot developers who
71 consistently check in code which is either broken or takes the codebase in
72 directions that have not been agreed to.
75 Debugging Aids
76 --------------
78 Try turning on logging of DEBUG level messages. This may be done a number
79 of ways, depending on what it is you're testing:
81 1. If you're testing the database unit tests, then set the environment
82    variable ``LOGGING_LEVEL=DEBUG``. This may be done like so:
84     LOGGING_LEVEL=DEBUG python run_tests.py
86    This variable replaces the older HYPERDBDEBUG environment var.
88 2. If you're testing a particular tracker, then set the logging level in
89    your tracker's ``config.ini``.
92 Internationalization Notes
93 --------------------------
95 How stuff works:
97 1. Strings that may require translation (messages in human language)
98    are marked in the source code.  This step is discussed in
99    `Marking Strings for Translation`_ section.
101 2. These strings are all extracted into Message Template File
102    ``locale/roundup.pot`` (_`POT` file).  See `Extracting Translatable
103    Messages`_ below.
105 3. Language teams use POT file to make Message Files for national
106    languages (_`PO` files).  All PO files for Roundup are kept in
107    the ``locale`` directory.  Names of these files are target
108    locale names, usually just 2-letter language codes.  `Translating
109    Messages`_ section of this chapter gives useful hints for
110    message translators.
112 4. Translated Message Files are compiled into binary form (_`MO` files)
113    and stored in ``locale`` directory (but not kept in the source code
114    repository, as they may be easily made from PO files).
115    See `Compiling Message Catalogs`_ section.
117 5. Roundup installer creates runtime locale structure on the file
118    system, putting MO files in their appropriate places.
120 6. Runtime internationalization (_`I18N`) services use these MO files
121    to translate program messages into language selected by current
122    Roundup user.  Roundup command line interface uses locale name
123    set in OS environment variable ``LANGUAGE``, ``LC_ALL``,
124    ``LC_MESSAGES``, or ``LANG`` (in that order).  Roundup Web User
125    Interface uses language selected by currently authenticated user.
127 Additional details may be found in `GNU gettext`_ and Python `gettext
128 module`_ documentation.
130 `Roundup source distribution`_ includes POT and PO files for message
131 translators, and also pre-built MO files to facilitate installations
132 from source.  Roundup binary distribution includes MO files only.
134 .. _GNU gettext:
136 GNU gettext package
137 ^^^^^^^^^^^^^^^^^^^
139 This chapter is full of references to GNU `gettext package`_.
140 GNU gettext is a "must have" for nearly all steps of internationalizing
141 any program, and it's manual is definetely a recommended reading
142 for people involved in `I18N`_.
144 There are GNU gettext ports to all major OS platforms.
145 Windows binaries are available from `GNU mirror sites`_.
147 Roundup does not use GNU gettext at runtime, but it's tools
148 are used for `extracting translatable messages`_, `compiling
149 message catalogs`_ and, optionally, for `translating messages`_.
151 Note that ``gettext`` package in some OS distributions means just
152 runtime tools and libraries.  In such cases gettext development tools
153 are usually distributed in separate package named ``gettext-devel``.
155 Marking Strings for Translation
156 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
158 Strings that need translation must be marked in the source code.
159 Following subsections explain how this is done in different cases.
161 If translatable string is used as a format string, it is recommended
162 to always use *named* format specifiers::
164   _('Index of %(classname)s') % locals()
166 This helps translators to better understand the context of the
167 message and, with Python formatting, remove format specifier altogether
168 (which is sometimes useful, especially in singular cases of `Plural Forms`_).
170 When there is more than one format specifier in the translatable
171 format string, named format specifiers **must** be used almost always,
172 because translation may require different order of items.
174 It is better to *not* mark for translation strings that are not
175 locale-dependent, as this makes it more difficult to keep track
176 of translation completeness.  For example, string ``</ol></body></html>``
177 (in ``index()`` method of the request handler in ``roundup_server``
178 script) has no human readable parts at all, and needs no translations.
179 Such strings are left untranslated in PO files, and are reported
180 as such by PO status checkers (e.g. ``msgfmt --statistics``).
182 Command Line Interfaces
183 ~~~~~~~~~~~~~~~~~~~~~~~
185 Scripts and routines run from the command line use "static" language
186 defined by environment variables recognized by ``gettext`` module
187 from Python library (``LANGUAGE``, ``LC_ALL``, ``LC_MESSAGES``, and
188 ``LANG``).  Primarilly, these are ``roundup-admin`` script and
189 ``admin.py`` module, but also help texts and startup error messages
190 in other scripts and their supporting modules.
192 For these interfaces, Python ``gettext`` engine must be initialized
193 to use Roundup message catalogs.  This is normally done by including
194 the following line in the module imports::
196   from i18n import _, ngettext
198 Simple translations are automatically marked by calls to builtin
199 message translation function ``_()``::
201   print _("This message is translated")
203 Translations for messages whose grammatical depends on a number
204 must be done by ``ngettext()`` function::
206   print ngettext("Nuked %i file", "Nuked %i files", number_of_files_nuked)
208 Deferred Translations
209 ~~~~~~~~~~~~~~~~~~~~~
211 Sometimes translatable strings appear in the source code in untranslated
212 form [#note_admin.py]_ and must be translated elsewhere.
213 Example::
215   for meal in ("spam", "egg", "beacon"):
216       print _(meal)
218 In such cases, strings must be marked for translation without actual
219 call to the translating function.  To mark these strings, we use Python
220 feature of automatic concatenation of adjacent strings and different
221 types of string quotes::
223   strings_to_translate = (
224       ''"This string will be translated",
225       ""'me too',
226       ''r"\raw string",
227       ''"""
228       multiline string"""
229   )
231 .. [#note_admin.py] In current Roundup sources, this feature is
232    extensively used in the ``admin`` module using method docstrings
233    as help messages.
235 Web User Interface
236 ~~~~~~~~~~~~~~~~~~
238 For Web User Interface, translation services are provided by Client
239 object.  Action classes have methods ``_()`` and ``gettext()``,
240 delegating translation to the Client instance.  In HTML templates,
241 translator object is available as context variable ``i18n``.
243 HTML templates have special markup for translatable strings.
244 The syntax for this markup is defined on `ZPTInternationalizationSupport`_
245 page.  Roundup translation service currently ignores values for
246 ``i18n:domain``, ``i18n:source`` and ``i18n:target``.
248 Template markup examples:
250 * simplest case::
252     <div i18n:translate="">
253      Say
254      no
255      more!
256     </div>
258   this will result in msgid ``"Say no more!"``, with all leading and
259   trailing whitespace stripped, and inner blanks replaced with single
260   space character.
262 * using variable slots::
264     <div i18n:translate="">
265      And now...<br/>
266      No.<span tal:replace="number" i18n:name="slideNo" /><br/>
267      THE LARCH
268     </div>
270   Msgid will be: ``"And now...<br /> No.${slideNo}<br /> THE LARCH"``.
271   Template rendering will use context variable ``number`` (you may use
272   any expression) to put instead of ``${slideNo}`` in translation.
274 * attribute translation::
276     <button name="btn_wink" value=" Wink " i18n:attributes="value" />
278   will translate the caption (and return value) for the "wink" button.
280 * explicit msgids.  Sometimes it may be useful to specify msgid
281   for the element translation explicitely, like this::
283     <span i18n:translate="know what i mean?">this text is ignored</span>
285   When rendered, element contents will be replaced by translation
286   of the string specified in ``i18n:translate`` attribute.
288 * ``i18n`` in `TALES`_.  You may translate strings in `TALES`_ python
289   expressions::
291     <span tal:replace="python: i18n.gettext('Oh, wicked.')" />
293 * plural forms.  There is no markup for plural forms in `TAL`_ i18n.
294   You must use python expression for that::
296     <span tal:replace="python: i18n.ngettext(
297       'Oh but it\'s only %i shilling.',
298       'Oh but it\'s only %i shillings.',
299       fine) % fine"
300     />
302 Extracting Translatable Messages
303 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
305 The most common tool for message extraction is ``xgettext`` utility
306 from `GNU gettext package`_.  Unfortunately, this utility has no means
307 of `Deferred Translations`_ in Python sources.  There is ``xpot`` tool
308 from Francois Pinard free `PO utilities`_ that allows to mark strings
309 for deferred translations, but it does not handle `plural forms`_.
311 Roundup overcomes these limitations by using both of these utilities.
312 This means that you need both `GNU gettext`_ tools and `PO utilities`_
313 to build the Message Template File yourself.
315 Latest Message Template File is kept in the source code repository 
316 and distributed with `Roundup Source`_.  
317 If you wish to rebuild the template yourself,
318 make sure that you have both ``xpot`` and ``xgettext`` installed and
319 just run ``gmake`` (or ``make``, if you are on a `GNU`_ system like
320 `linux`_ or `cygwin`_) in the ``locale`` directory.
322 For on-site i18n, Roundup provides command-line utility::
324   roundup-gettext <tracker_home>
326 extracting translatable messages from tracker's html templates.
327 This utility creates message template file ``messages.pot`` in
328 ``locale`` subdirectory of the tracker home directory.  Translated
329 messages may be put in *locale*.po files (where *locale* is selected
330 locale name) in the same directory, e.g.: ``locale/ru.po``.
331 These message catalogs are searched prior to system-wide translations
332 kept in the ``share`` directory.
334 Translating Messages
335 ^^^^^^^^^^^^^^^^^^^^
337 Gettext Message File (`PO`_ file) is a plain text file, that can be created
338 by simple copying ``roundup.pot`` to new .po file, like this::
340   $ cp roundup.pot ru.po
342 The name of PO file is target locale name, usually just 2-letter language
343 code (``ru`` for Russian in the above example).  Alternatively, PO file
344 may be initialized by ``msginit`` utility from `GNU gettext`_ tools::
346   $ msginit -i roundup.pot
348 ``msginit`` will check your current locale, and initialize the header
349 entry, setting language name, rules for `plural forms`_ and, if available,
350 translator's name and email address.  The name for PO file is also chosen
351 based on current locale.
353 Next, you will need to edit this file, filling all ``msgstr`` lines with
354 translations of the above ``msgid`` entries.  PO file is a plain text
355 file that can be edited with any text editor.  However, there are several
356 tools that may help you with this process:
358  - `poEdit`_ by Vaclav Slavik.  Very nice cross-platform GUI editor.
360  - `KBabel`_.  Being part of `KDE`_, it works in X windows only.
361     At the first glance looks pretty hairy, with all bells and whistles.
362     Haven't had much experience with it, though.
364  - ``po-mode`` for `emacs`_.  One of `GNU gettext`_ tools.  Very handy,
365    definitely recommended if you are comfortable with emacs.  Cannot
366    handle `plural forms`_ per se, but allows to edit them in simple
367    text mode.
369  - `po filetype plugin`_ for `vim`_.  Does not do as much as ``po-mode``,
370    but helps in finding untranslated and fuzzy strings, and checking
371    code references.  Please contact `alexander smishlajev`_ if you
372    prefer this, as i have patched this plugin a bit.  I have also
373    informed the original plugin author about these changes, but got
374    no reply so far.
376 Compiling Message Catalogs
377 ^^^^^^^^^^^^^^^^^^^^^^^^^^
379 Message catalogs (`PO`_ files) must be compiled into binary form
380 (`MO`_ files) before they can be used in the application.  This
381 compilation is handled by ``msgfmt`` utility from `GNU gettext`_
382 tools.  ``GNUmakefile`` in the ``locale`` directory automatically
383 compiles all existing message catalogs after updating them from
384 Roundup source files.  If you wish to rebuild an individual `MO`_
385 file without making everything else, you may, for example::
387   $ msgfmt --statistics -o ru.mo ru.po
389 This way, message translators can check their `PO`_ files without
390 extracting strings from source.  (Note: String extraction requires
391 additional utility that is not part of `GNU gettext`_.  See `Extracting
392 Translatable Messages`_.)
394 At run time, Roundup automatically compiles message catalogs whenever
395 `PO`_ file is changed.
397 .. _`Customising Roundup`: customizing.html
398 .. _`Roundup's Design Document`: spec.html
399 .. _`implementation notes`: implementation.html
402 .. _External hyperlink targets:
404 .. _alexander smishlajev:
405 .. _als: http://sourceforge.net/users/a1s/
406 .. _cygwin: http://www.cygwin.com/
407 .. _emacs: http://www.gnu.org/software/emacs/
408 .. _gettext package: http://www.gnu.org/software/gettext/
409 .. _gettext module: http://docs.python.org/lib/module-gettext.html
410 .. _GNU: http://www.gnu.org/
411 .. _GNU mirror sites: http://www.gnu.org/prep/ftp.html
412 .. _KBabel: http://i18n.kde.org/tools/kbabel/
413 .. _KDE: http://www.kde.org/
414 .. _linux: http://www.linux.org/
415 .. _Plural Forms:
416     http://www.gnu.org/software/gettext/manual/html_node/gettext_150.html
417 .. _po filetype plugin:
418     http://vim.sourceforge.net/scripts/script.php?script_id=695
419 .. _PO utilities: http://po-utils.progiciels-bpi.ca/
420 .. _poEdit: http://poedit.sourceforge.net/
421 .. _Roundup Source:
422 .. _Roundup source distribution:
423 .. _Roundup binary distribution:
424     http://sourceforge.net/project/showfiles.php?group_id=31577
425 .. _TAL:
426 .. _Template Attribute Language:
427    http://dev.zope.org/Wikis/DevSite/Projects/ZPT/TAL%20Specification%201.4
428 .. _TALES:
429 .. _Template Attribute Language Expression Syntax:
430    http://dev.zope.org/Wikis/DevSite/Projects/ZPT/TALES%20Specification%201.3
431 .. _vim: http://www.vim.org/
432 .. _ZPTInternationalizationSupport: http://dev.zope.org/Wikis/DevSite/Projects/ComponentArchitecture/ZPTInternationalizationSupport