Code

6698616dd14d5994e5335e0fd91ae089c74adb36
[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 - Sourceforge's issue trackers at
23   https://sourceforge.net/tracker/?group_id=31577
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 `feature tracker`_, with
37 patches attached that give context diffs of the affected source.
40 SVN Access
41 ----------
43 To get SVN access, contact richard@users.sourceforge.net.
46 Project Rules
47 -------------
49 Mostly the project follows Guido's Style (though naming tends to be a little
50 relaxed sometimes). In short:
52 - 80 column width code
53 - 4-space indentations
54 - All modules must have a CVS Id line near the top
56 Other project rules:
58 - New functionality must be documented, even briefly (so at least we know
59   where there's missing documentation) and changes to tracker configuration
60   must be logged in the upgrading document.
61 - subscribe to roundup-checkins to receive checkin notifications from the
62   other developers with CVS access
63 - discuss any changes with the other developers on roundup-dev. If nothing
64   else, this makes sure there's no rude shocks
65 - write unit tests for changes you make (where possible), and ensure that
66   all unit tests run before committing changes
67 - run pychecker over changed code
69 The administrators of the project reserve the right to boot developers who
70 consistently check in code which is either broken or takes the codebase in
71 directions that have not been agreed to.
74 Debugging Aids
75 --------------
77 Try turning on logging of DEBUG level messages. This may be done a number
78 of ways, depending on what it is you're testing:
80 1. If you're testing the database unit tests, then set the environment
81    variable ``LOGGING_LEVEL=DEBUG``. This may be done like so:
83     LOGGING_LEVEL=DEBUG python run_tests.py
85    This variable replaces the older HYPERDBDEBUG environment var.
87 2. If you're testing a particular tracker, then set the logging level in
88    your tracker's ``config.ini``.
91 Internationalization Notes
92 --------------------------
94 How stuff works:
96 1. Strings that may require translation (messages in human language)
97    are marked in the source code.  This step is discussed in
98    `Marking Strings for Translation`_ section.
100 2. These strings are all extracted into Message Template File
101    ``locale/roundup.pot`` (_`POT` file).  See `Extracting Translatable
102    Messages`_ below.
104 3. Language teams use POT file to make Message Files for national
105    languages (_`PO` files).  All PO files for Roundup are kept in
106    the ``locale`` directory.  Names of these files are target
107    locale names, usually just 2-letter language codes.  `Translating
108    Messages`_ section of this chapter gives useful hints for
109    message translators.
111 4. Translated Message Files are compiled into binary form (_`MO` files)
112    and stored in ``locale`` directory (but not kept in the `Roundup
113    CVS`_ repository, as they may be easily made from PO files).
114    See `Compiling Message Catalogs`_ section.
116 5. Roundup installer creates runtime locale structure on the file
117    system, putting MO files in their appropriate places.
119 6. Runtime internationalization (_`I18N`) services use these MO files
120    to translate program messages into language selected by current
121    Roundup user.  Roundup command line interface uses locale name
122    set in OS environment variable ``LANGUAGE``, ``LC_ALL``,
123    ``LC_MESSAGES``, or ``LANG`` (in that order).  Roundup Web User
124    Interface uses language selected by currently authenticated user.
126 Additional details may be found in `GNU gettext`_ and Python `gettext
127 module`_ documentation.
129 `Roundup source distribution`_ includes POT and PO files for message
130 translators, and also pre-built MO files to facilitate installations
131 from source.  Roundup binary distribution includes MO files only.
133 .. _GNU gettext:
135 GNU gettext package
136 ^^^^^^^^^^^^^^^^^^^
138 This chapter is full of references to GNU `gettext package`_.
139 GNU gettext is a "must have" for nearly all steps of internationalizing
140 any program, and it's manual is definetely a recommended reading
141 for people involved in `I18N`_.
143 There are GNU gettext ports to all major OS platforms.
144 Windows binaries are available from `GNU mirror sites`_.
146 Roundup does not use GNU gettext at runtime, but it's tools
147 are used for `extracting translatable messages`_, `compiling
148 message catalogs`_ and, optionally, for `translating messages`_.
150 Note that ``gettext`` package in some OS distributions means just
151 runtime tools and libraries.  In such cases gettext development tools
152 are usually distributed in separate package named ``gettext-devel``.
154 Marking Strings for Translation
155 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
157 Strings that need translation must be marked in the source code.
158 Following subsections explain how this is done in different cases.
160 If translatable string is used as a format string, it is recommended
161 to always use *named* format specifiers::
163   _('Index of %(classname)s') % locals()
165 This helps translators to better understand the context of the
166 message and, with Python formatting, remove format specifier altogether
167 (which is sometimes useful, especially in singular cases of `Plural Forms`_).
169 When there is more than one format specifier in the translatable
170 format string, named format specifiers **must** be used almost always,
171 because translation may require different order of items.
173 It is better to *not* mark for translation strings that are not
174 locale-dependent, as this makes it more difficult to keep track
175 of translation completeness.  For example, string ``</ol></body></html>``
176 (in ``index()`` method of the request handler in ``roundup_server``
177 script) has no human readable parts at all, and needs no translations.
178 Such strings are left untranslated in PO files, and are reported
179 as such by PO status checkers (e.g. ``msgfmt --statistics``).
181 Command Line Interfaces
182 ~~~~~~~~~~~~~~~~~~~~~~~
184 Scripts and routines run from the command line use "static" language
185 defined by environment variables recognized by ``gettext`` module
186 from Python library (``LANGUAGE``, ``LC_ALL``, ``LC_MESSAGES``, and
187 ``LANG``).  Primarilly, these are ``roundup-admin`` script and
188 ``admin.py`` module, but also help texts and startup error messages
189 in other scripts and their supporting modules.
191 For these interfaces, Python ``gettext`` engine must be initialized
192 to use Roundup message catalogs.  This is normally done by including
193 the following line in the module imports::
195   from i18n import _, ngettext
197 Simple translations are automatically marked by calls to builtin
198 message translation function ``_()``::
200   print _("This message is translated")
202 Translations for messages whose grammatical depends on a number
203 must be done by ``ngettext()`` function::
205   print ngettext("Nuked %i file", "Nuked %i files", number_of_files_nuked)
207 Deferred Translations
208 ~~~~~~~~~~~~~~~~~~~~~
210 Sometimes translatable strings appear in the source code in untranslated
211 form [#note_admin.py]_ and must be translated elsewhere.
212 Example::
214   for meal in ("spam", "egg", "beacon"):
215       print _(meal)
217 In such cases, strings must be marked for translation without actual
218 call to the translating function.  To mark these strings, we use Python
219 feature of automatic concatenation of adjacent strings and different
220 types of string quotes::
222   strings_to_translate = (
223       ''"This string will be translated",
224       ""'me too',
225       ''r"\raw string",
226       ''"""
227       multiline string"""
228   )
230 .. [#note_admin.py] In current Roundup sources, this feature is
231    extensively used in the ``admin`` module using method docstrings
232    as help messages.
234 Web User Interface
235 ~~~~~~~~~~~~~~~~~~
237 For Web User Interface, translation services are provided by Client
238 object.  Action classes have methods ``_()`` and ``gettext()``,
239 delegating translation to the Client instance.  In HTML templates,
240 translator object is available as context variable ``i18n``.
242 HTML templates have special markup for translatable strings.
243 The syntax for this markup is defined on `ZPTInternationalizationSupport`_
244 page.  Roundup translation service currently ignores values for
245 ``i18n:domain``, ``i18n:source`` and ``i18n:target``.
247 Template markup examples:
249 * simplest case::
251     <div i18n:translate="">
252      Say
253      no
254      more!
255     </div>
257   this will result in msgid ``"Say no more!"``, with all leading and
258   trailing whitespace stripped, and inner blanks replaced with single
259   space character.
261 * using variable slots::
263     <div i18n:translate="">
264      And now...<br/>
265      No.<span tal:replace="number" i18n:name="slideNo" /><br/>
266      THE LARCH
267     </div>
269   Msgid will be: ``"And now...<br /> No.${slideNo}<br /> THE LARCH"``.
270   Template rendering will use context variable ``number`` (you may use
271   any expression) to put instead of ``${slideNo}`` in translation.
273 * attribute translation::
275     <button name="btn_wink" value=" Wink " i18n:attributes="value" />
277   will translate the caption (and return value) for the "wink" button.
279 * explicit msgids.  Sometimes it may be useful to specify msgid
280   for the element translation explicitely, like this::
282     <span i18n:translate="know what i mean?">this text is ignored</span>
284   When rendered, element contents will be replaced by translation
285   of the string specified in ``i18n:translate`` attribute.
287 * ``i18n`` in `TALES`_.  You may translate strings in `TALES`_ python
288   expressions::
290     <span tal:replace="python: i18n.gettext('Oh, wicked.')" />
292 * plural forms.  There is no markup for plural forms in `TAL`_ i18n.
293   You must use python expression for that::
295     <span tal:replace="python: i18n.ngettext(
296       'Oh but it\'s only %i shilling.',
297       'Oh but it\'s only %i shillings.',
298       fine) % fine"
299     />
301 Extracting Translatable Messages
302 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
304 The most common tool for message extraction is ``xgettext`` utility
305 from `GNU gettext package`_.  Unfortunately, this utility has no means
306 of `Deferred Translations`_ in Python sources.  There is ``xpot`` tool
307 from Francois Pinard free `PO utilities`_ that allows to mark strings
308 for deferred translations, but it does not handle `plural forms`_.
310 Roundup overcomes these limitations by using both of these utilities.
311 This means that you need both `GNU gettext`_ tools and `PO utilities`_
312 to build the Message Template File yourself.
314 Latest Message Template File is kept in `Roundup CVS`_ and distributed
315 with `Roundup Source`_.  If you wish to rebuild the template yourself,
316 make sure that you have both ``xpot`` and ``xgettext`` installed and
317 just run ``gmake`` (or ``make``, if you are on a `GNU`_ system like
318 `linux`_ or `cygwin`_) in the ``locale`` directory.
320 For on-site i18n, Roundup provides command-line utility::
322   roundup-gettext <tracker_home>
324 extracting translatable messages from tracker's html templates.
325 This utility creates message template file ``messages.pot`` in
326 ``locale`` subdirectory of the tracker home directory.  Translated
327 messages may be put in *locale*.po files (where *locale* is selected
328 locale name) in the same directory, e.g.: ``locale/ru.po``.
329 These message catalogs are searched prior to system-wide translations
330 kept in the ``share`` directory.
332 Translating Messages
333 ^^^^^^^^^^^^^^^^^^^^
335 Gettext Message File (`PO`_ file) is a plain text file, that can be created
336 by simple copying ``roundup.pot`` to new .po file, like this::
338   $ cp roundup.pot ru.po
340 The name of PO file is target locale name, usually just 2-letter language
341 code (``ru`` for Russian in the above example).  Alternatively, PO file
342 may be initialized by ``msginit`` utility from `GNU gettext`_ tools::
344   $ msginit -i roundup.pot
346 ``msginit`` will check your current locale, and initialize the header
347 entry, setting language name, rules for `plural forms`_ and, if available,
348 translator's name and email address.  The name for PO file is also chosen
349 based on current locale.
351 Next, you will need to edit this file, filling all ``msgstr`` lines with
352 translations of the above ``msgid`` entries.  PO file is a plain text
353 file that can be edited with any text editor.  However, there are several
354 tools that may help you with this process:
356  - `poEdit`_ by Vaclav Slavik.  Very nice cross-platform GUI editor.
358  - `KBabel`_.  Being part of `KDE`_, it works in X windows only.
359     At the first glance looks pretty hairy, with all bells and whistles.
360     Haven't had much experience with it, though.
362  - ``po-mode`` for `emacs`_.  One of `GNU gettext`_ tools.  Very handy,
363    definitely recommended if you are comfortable with emacs.  Cannot
364    handle `plural forms`_ per se, but allows to edit them in simple
365    text mode.
367  - `po filetype plugin`_ for `vim`_.  Does not do as much as ``po-mode``,
368    but helps in finding untranslated and fuzzy strings, and checking
369    code references.  Please contact `alexander smishlajev`_ if you
370    prefer this, as i have patched this plugin a bit.  I have also
371    informed the original plugin author about these changes, but got
372    no reply so far.
374 Compiling Message Catalogs
375 ^^^^^^^^^^^^^^^^^^^^^^^^^^
377 Message catalogs (`PO`_ files) must be compiled into binary form
378 (`MO`_ files) before they can be used in the application.  This
379 compilation is handled by ``msgfmt`` utility from `GNU gettext`_
380 tools.  ``GNUmakefile`` in the ``locale`` directory automatically
381 compiles all existing message catalogs after updating them from
382 Roundup source files.  If you wish to rebuild an individual `MO`_
383 file without making everything else, you may, for example::
385   $ msgfmt --statistics -o ru.mo ru.po
387 This way, message translators can check their `PO`_ files without
388 extracting strings from source.  (Note: String extraction requires
389 additional utility that is not part of `GNU gettext`_.  See `Extracting
390 Translatable Messages`_.)
392 At run time, Roundup automatically compiles message catalogs whenever
393 `PO`_ file is changed.
395 .. _`Customising Roundup`: customizing.html
396 .. _`Roundup's Design Document`: spec.html
397 .. _`implementation notes`: implementation.html
400 .. _External hyperlink targets:
402 .. _alexander smishlajev:
403 .. _als: http://sourceforge.net/users/a1s/
404 .. _cygwin: http://www.cygwin.com/
405 .. _emacs: http://www.gnu.org/software/emacs/
406 .. _gettext package: http://www.gnu.org/software/gettext/
407 .. _gettext module: http://docs.python.org/lib/module-gettext.html
408 .. _GNU: http://www.gnu.org/
409 .. _GNU mirror sites: http://www.gnu.org/prep/ftp.html
410 .. _KBabel: http://i18n.kde.org/tools/kbabel/
411 .. _KDE: http://www.kde.org/
412 .. _linux: http://www.linux.org/
413 .. _Plural Forms:
414     http://www.gnu.org/software/gettext/manual/html_node/gettext_150.html
415 .. _po filetype plugin:
416     http://vim.sourceforge.net/scripts/script.php?script_id=695
417 .. _PO utilities: http://po-utils.progiciels-bpi.ca/
418 .. _poEdit: http://poedit.sourceforge.net/
419 .. _Roundup CVS: http://sourceforge.net/cvs/?group_id=31577
420 .. _Roundup Source:
421 .. _Roundup source distribution:
422 .. _Roundup binary distribution:
423     http://sourceforge.net/project/showfiles.php?group_id=31577
424 .. _TAL:
425 .. _Template Attribute Language:
426    http://dev.zope.org/Wikis/DevSite/Projects/ZPT/TAL%20Specification%201.4
427 .. _TALES:
428 .. _Template Attribute Language Expression Syntax:
429    http://dev.zope.org/Wikis/DevSite/Projects/ZPT/TALES%20Specification%201.3
430 .. _vim: http://www.vim.org/
431 .. _ZPTInternationalizationSupport: http://dev.zope.org/Wikis/DevSite/Projects/ComponentArchitecture/ZPTInternationalizationSupport
432 .. _feature tracker: http://sourceforge.net/tracker/?group_id=31577&atid=402791