Code

- refactor: move import_journal to hyperdb -- it was reimplemented in
[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
26 -------------
28 1. ssh -t <username>,roundup@shell.sourceforge.net create
29 2. cd /home/groups/r/ro/roundup
30 3. follow instructions in README.txt
33 Issue Tracker
34 -------------
36 The tracker resides on psf.upfronthosting.co.za. The roundup installation
37 belongs to the user roundup. In ~roundup, all trackers are stored and
38 the roundup code itself. roundup is started through /etc/init.d/roundup;
39 other parts of the installation are started through
40 /etc/init.d/{postgresql-8-1,spambayes,postfix}.
42 The machine is operated by Upfronthosting in South Africa. The meta
43 tracker is http://psf.upfronthosting.co.za/roundup/meta/
44 In this tracker, Upfronthosting people are the users izak and roche.
46 The Roundup tracker http://issues.roundup-tracker.org/ is in
47 ~roundup/trackers/roundup
49 The configuration is in the "web/trunk/issues" section of Roundup's
50 Subversion repository and copied manually to the live tracker.
52 A checkout of the roundup sources is in ~roundup/src/roundup-src.
55 Small Changes
56 -------------
58 Most small changes can be submitted through the issue tracker, with
59 patches attached that give context diffs of the affected source.
62 SVN Access
63 ----------
65 See http://www.roundup-tracker.org/code.html.
66 For all other questions ask on the development mailinglist.
69 Project Rules
70 -------------
72 Mostly the project follows Guido's Style (though naming tends to be a little
73 relaxed sometimes). In short:
75 - 80 column width code
76 - 4-space indentations
77 - All modules must have an Id line near the top
79 Other project rules:
81 - New functionality must be documented, even briefly (so at least we know
82   where there's missing documentation) and changes to tracker configuration
83   must be logged in the upgrading document.
84 - subscribe to roundup-checkins to receive checkin notifications from the
85   other developers with write access to the source-code repository.
86 - discuss any changes with the other developers on roundup-dev. If nothing
87   else, this makes sure there's no rude shocks
88 - write unit tests for changes you make (where possible), and ensure that
89   all unit tests run before committing changes
90 - run pychecker over changed code
92 The administrators of the project reserve the right to boot developers who
93 consistently check in code which is either broken or takes the codebase in
94 directions that have not been agreed to.
97 Debugging Aids
98 --------------
100 See `debugging.txt`_.
102 Internationalization Notes
103 --------------------------
105 How stuff works:
107 1. Strings that may require translation (messages in human language)
108    are marked in the source code.  This step is discussed in
109    `Marking Strings for Translation`_ section.
111 2. These strings are all extracted into Message Template File
112    ``locale/roundup.pot`` (_`POT` file).  See `Extracting Translatable
113    Messages`_ below.
115 3. Language teams use POT file to make Message Files for national
116    languages (_`PO` files).  All PO files for Roundup are kept in
117    the ``locale`` directory.  Names of these files are target
118    locale names, usually just 2-letter language codes.  `Translating
119    Messages`_ section of this chapter gives useful hints for
120    message translators.
122 4. Translated Message Files are compiled into binary form (_`MO` files)
123    and stored in ``locale`` directory (but not kept in the source code
124    repository, as they may be easily made from PO files).
125    See `Compiling Message Catalogs`_ section.
127 5. Roundup installer creates runtime locale structure on the file
128    system, putting MO files in their appropriate places.
130 6. Runtime internationalization (_`I18N`) services use these MO files
131    to translate program messages into language selected by current
132    Roundup user.  Roundup command line interface uses locale name
133    set in OS environment variable ``LANGUAGE``, ``LC_ALL``,
134    ``LC_MESSAGES``, or ``LANG`` (in that order).  Roundup Web User
135    Interface uses language selected by currently authenticated user.
137 Additional details may be found in `GNU gettext`_ and Python `gettext
138 module`_ documentation.
140 `Roundup source distribution`_ includes POT and PO files for message
141 translators, and also pre-built MO files to facilitate installations
142 from source.  Roundup binary distribution includes MO files only.
144 .. _GNU gettext:
146 GNU gettext package
147 ^^^^^^^^^^^^^^^^^^^
149 This chapter is full of references to GNU `gettext package`_.
150 GNU gettext is a "must have" for nearly all steps of internationalizing
151 any program, and it's manual is definetely a recommended reading
152 for people involved in `I18N`_.
154 There are GNU gettext ports to all major OS platforms.
155 Windows binaries are available from `GNU mirror sites`_.
157 Roundup does not use GNU gettext at runtime, but it's tools
158 are used for `extracting translatable messages`_, `compiling
159 message catalogs`_ and, optionally, for `translating messages`_.
161 Note that ``gettext`` package in some OS distributions means just
162 runtime tools and libraries.  In such cases gettext development tools
163 are usually distributed in separate package named ``gettext-devel``.
165 Marking Strings for Translation
166 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
168 Strings that need translation must be marked in the source code.
169 Following subsections explain how this is done in different cases.
171 If translatable string is used as a format string, it is recommended
172 to always use *named* format specifiers::
174   _('Index of %(classname)s') % locals()
176 This helps translators to better understand the context of the
177 message and, with Python formatting, remove format specifier altogether
178 (which is sometimes useful, especially in singular cases of `Plural Forms`_).
180 When there is more than one format specifier in the translatable
181 format string, named format specifiers **must** be used almost always,
182 because translation may require different order of items.
184 It is better to *not* mark for translation strings that are not
185 locale-dependent, as this makes it more difficult to keep track
186 of translation completeness.  For example, string ``</ol></body></html>``
187 (in ``index()`` method of the request handler in ``roundup_server``
188 script) has no human readable parts at all, and needs no translations.
189 Such strings are left untranslated in PO files, and are reported
190 as such by PO status checkers (e.g. ``msgfmt --statistics``).
192 Command Line Interfaces
193 ~~~~~~~~~~~~~~~~~~~~~~~
195 Scripts and routines run from the command line use "static" language
196 defined by environment variables recognized by ``gettext`` module
197 from Python library (``LANGUAGE``, ``LC_ALL``, ``LC_MESSAGES``, and
198 ``LANG``).  Primarilly, these are ``roundup-admin`` script and
199 ``admin.py`` module, but also help texts and startup error messages
200 in other scripts and their supporting modules.
202 For these interfaces, Python ``gettext`` engine must be initialized
203 to use Roundup message catalogs.  This is normally done by including
204 the following line in the module imports::
206   from i18n import _, ngettext
208 Simple translations are automatically marked by calls to builtin
209 message translation function ``_()``::
211   print _("This message is translated")
213 Translations for messages whose grammatical depends on a number
214 must be done by ``ngettext()`` function::
216   print ngettext("Nuked %i file", "Nuked %i files", number_of_files_nuked)
218 Deferred Translations
219 ~~~~~~~~~~~~~~~~~~~~~
221 Sometimes translatable strings appear in the source code in untranslated
222 form [#note_admin.py]_ and must be translated elsewhere.
223 Example::
225   for meal in ("spam", "egg", "beacon"):
226       print _(meal)
228 In such cases, strings must be marked for translation without actual
229 call to the translating function.  To mark these strings, we use Python
230 feature of automatic concatenation of adjacent strings and different
231 types of string quotes::
233   strings_to_translate = (
234       ''"This string will be translated",
235       ""'me too',
236       ''r"\raw string",
237       ''"""
238       multiline string"""
239   )
241 .. [#note_admin.py] In current Roundup sources, this feature is
242    extensively used in the ``admin`` module using method docstrings
243    as help messages.
245 Web User Interface
246 ~~~~~~~~~~~~~~~~~~
248 For Web User Interface, translation services are provided by Client
249 object.  Action classes have methods ``_()`` and ``gettext()``,
250 delegating translation to the Client instance.  In HTML templates,
251 translator object is available as context variable ``i18n``.
253 HTML templates have special markup for translatable strings.
254 The syntax for this markup is defined on `ZPTInternationalizationSupport`_
255 page.  Roundup translation service currently ignores values for
256 ``i18n:domain``, ``i18n:source`` and ``i18n:target``.
258 Template markup examples:
260 * simplest case::
262     <div i18n:translate="">
263      Say
264      no
265      more!
266     </div>
268   this will result in msgid ``"Say no more!"``, with all leading and
269   trailing whitespace stripped, and inner blanks replaced with single
270   space character.
272 * using variable slots::
274     <div i18n:translate="">
275      And now...<br/>
276      No.<span tal:replace="number" i18n:name="slideNo" /><br/>
277      THE LARCH
278     </div>
280   Msgid will be: ``"And now...<br /> No.${slideNo}<br /> THE LARCH"``.
281   Template rendering will use context variable ``number`` (you may use
282   any expression) to put instead of ``${slideNo}`` in translation.
284 * attribute translation::
286     <button name="btn_wink" value=" Wink " i18n:attributes="value" />
288   will translate the caption (and return value) for the "wink" button.
290 * explicit msgids.  Sometimes it may be useful to specify msgid
291   for the element translation explicitely, like this::
293     <span i18n:translate="know what i mean?">this text is ignored</span>
295   When rendered, element contents will be replaced by translation
296   of the string specified in ``i18n:translate`` attribute.
298 * ``i18n`` in `TALES`_.  You may translate strings in `TALES`_ python
299   expressions::
301     <span tal:replace="python: i18n.gettext('Oh, wicked.')" />
303 * plural forms.  There is no markup for plural forms in `TAL`_ i18n.
304   You must use python expression for that::
306     <span tal:replace="python: i18n.ngettext(
307       'Oh but it\'s only %i shilling.',
308       'Oh but it\'s only %i shillings.',
309       fine) % fine"
310     />
312 Extracting Translatable Messages
313 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
315 The most common tool for message extraction is ``xgettext`` utility
316 from `GNU gettext package`_.  Unfortunately, this utility has no means
317 of `Deferred Translations`_ in Python sources.  There is ``xpot`` tool
318 from Francois Pinard free `PO utilities`_ that allows to mark strings
319 for deferred translations, but it does not handle `plural forms`_.
321 Roundup overcomes these limitations by using both of these utilities.
322 This means that you need both `GNU gettext`_ tools and `PO utilities`_
323 to build the Message Template File yourself.
325 Latest Message Template File is kept in the source code repository 
326 and distributed with `Roundup Source`_.  
327 If you wish to rebuild the template yourself,
328 make sure that you have both ``xpot`` and ``xgettext`` installed and
329 just run ``gmake`` (or ``make``, if you are on a `GNU`_ system like
330 `linux`_ or `cygwin`_) in the ``locale`` directory.
332 For on-site i18n, Roundup provides command-line utility::
334   roundup-gettext <tracker_home>
336 extracting translatable messages from tracker's html templates.
337 This utility creates message template file ``messages.pot`` in
338 ``locale`` subdirectory of the tracker home directory.  Translated
339 messages may be put in *locale*.po files (where *locale* is selected
340 locale name) in the same directory, e.g.: ``locale/ru.po``.
341 These message catalogs are searched prior to system-wide translations
342 kept in the ``share`` directory.
344 Translating Messages
345 ^^^^^^^^^^^^^^^^^^^^
347 Gettext Message File (`PO`_ file) is a plain text file, that can be created
348 by simple copying ``roundup.pot`` to new .po file, like this::
350   $ cp roundup.pot ru.po
352 The name of PO file is target locale name, usually just 2-letter language
353 code (``ru`` for Russian in the above example).  Alternatively, PO file
354 may be initialized by ``msginit`` utility from `GNU gettext`_ tools::
356   $ msginit -i roundup.pot
358 ``msginit`` will check your current locale, and initialize the header
359 entry, setting language name, rules for `plural forms`_ and, if available,
360 translator's name and email address.  The name for PO file is also chosen
361 based on current locale.
363 Next, you will need to edit this file, filling all ``msgstr`` lines with
364 translations of the above ``msgid`` entries.  PO file is a plain text
365 file that can be edited with any text editor.  However, there are several
366 tools that may help you with this process:
368  - `poEdit`_ by Vaclav Slavik.  Very nice cross-platform GUI editor.
370  - `KBabel`_.  Being part of `KDE`_, it works in X windows only.
371     At the first glance looks pretty hairy, with all bells and whistles.
372     Haven't had much experience with it, though.
374  - ``po-mode`` for `emacs`_.  One of `GNU gettext`_ tools.  Very handy,
375    definitely recommended if you are comfortable with emacs.  Cannot
376    handle `plural forms`_ per se, but allows to edit them in simple
377    text mode.
379  - `po filetype plugin`_ for `vim`_.  Does not do as much as ``po-mode``,
380    but helps in finding untranslated and fuzzy strings, and checking
381    code references.  Please contact `alexander smishlajev`_ if you
382    prefer this, as i have patched this plugin a bit.  I have also
383    informed the original plugin author about these changes, but got
384    no reply so far.
386 Compiling Message Catalogs
387 ^^^^^^^^^^^^^^^^^^^^^^^^^^
389 Message catalogs (`PO`_ files) must be compiled into binary form
390 (`MO`_ files) before they can be used in the application.  This
391 compilation is handled by ``msgfmt`` utility from `GNU gettext`_
392 tools.  ``GNUmakefile`` in the ``locale`` directory automatically
393 compiles all existing message catalogs after updating them from
394 Roundup source files.  If you wish to rebuild an individual `MO`_
395 file without making everything else, you may, for example::
397   $ msgfmt --statistics -o ru.mo ru.po
399 This way, message translators can check their `PO`_ files without
400 extracting strings from source.  (Note: String extraction requires
401 additional utility that is not part of `GNU gettext`_.  See `Extracting
402 Translatable Messages`_.)
404 At run time, Roundup automatically compiles message catalogs whenever
405 `PO`_ file is changed.
407 .. _`Customising Roundup`: customizing.html
408 .. _`Roundup's Design Document`: spec.html
409 .. _`implementation notes`: implementation.html
412 .. _External hyperlink targets:
414 .. _alexander smishlajev:
415 .. _als: http://sourceforge.net/users/a1s/
416 .. _cygwin: http://www.cygwin.com/
417 .. _emacs: http://www.gnu.org/software/emacs/
418 .. _gettext package: http://www.gnu.org/software/gettext/
419 .. _gettext module: http://docs.python.org/lib/module-gettext.html
420 .. _GNU: http://www.gnu.org/
421 .. _GNU mirror sites: http://www.gnu.org/prep/ftp.html
422 .. _KBabel: http://i18n.kde.org/tools/kbabel/
423 .. _KDE: http://www.kde.org/
424 .. _linux: http://www.linux.org/
425 .. _Plural Forms:
426     http://www.gnu.org/software/gettext/manual/html_node/gettext_150.html
427 .. _po filetype plugin:
428     http://vim.sourceforge.net/scripts/script.php?script_id=695
429 .. _PO utilities: http://po-utils.progiciels-bpi.ca/
430 .. _poEdit: http://poedit.sourceforge.net/
431 .. _Roundup Source:
432 .. _Roundup source distribution:
433 .. _Roundup binary distribution:
434     http://sourceforge.net/project/showfiles.php?group_id=31577
435 .. _TAL:
436 .. _Template Attribute Language:
437    http://dev.zope.org/Wikis/DevSite/Projects/ZPT/TAL%20Specification%201.4
438 .. _TALES:
439 .. _Template Attribute Language Expression Syntax:
440    http://dev.zope.org/Wikis/DevSite/Projects/ZPT/TALES%20Specification%201.3
441 .. _vim: http://www.vim.org/
442 .. _ZPTInternationalizationSupport: http://dev.zope.org/Wikis/DevSite/Projects/ComponentArchitecture/ZPTInternationalizationSupport