1 \input texinfo @c -*-texinfo-*-
2 @setfilename internals.info
3 @settitle LilyPond internals
6 @node Top, LilyPond internals, (dir), (dir)
11 * LilyPond internals::
20 @node LilyPond internals, , Top, Top
24 * Request_engraver:: Request_engraver
28 @chapter Getting involved
30 Please help us make LilyPond a better program. You can help LilyPond in
31 several ways. Not all tasks requiring programming or understanding the
32 full source code. You can write to the mailing list
33 (@email{gnu-music-discuss@@gnu.org} for more information)
35 @unnumberedsubsec Users
37 Mutopia needs your help. The mutopia project is a collection of public
38 domain sheet music. You can help the project by entering music (either
39 by hand, or by converting from scans or MIDI) and submitting it. Point
40 your browser to the @uref{http://sca.uwaterloo.ca/Mutopia, Mutopia
43 @unnumberedsubsec Font designers
45 Our set of glyphs (the Feta font) is far from complete. We need the
46 following glyphs: segno, coda. The fonts have been coded in MetaFont,
47 so you will need to know MetaFont if you want to contribute a glyph.
49 @unnumberedsubsec Writers
51 The documentation of LilyPond and related utilities needs a lot of
52 work. The documentation is written in
53 @uref{http://www.gnu.org/software/texinfo,texinfo}. The documentation of
54 LilyPond is sorely lacking in terms of completeness, depth and
57 Write if you know how to write english documentation in texinfo, and
58 know about music and music notation. You must also know how to use
59 LilyPond (or be prepared to learn using it). The task is not especially
60 hard, but it is a lot of work, and you must be familiar with LilyPond.
62 @unnumberedsubsec Translators
64 LilyPond is completely ready for internationalized messages, but there
65 are only a few translations so far (dutch, italian, german, japanese,
66 french, russian). Translation involves writing a .po file, which is
67 relatively easy, and does not even require running LilyPond.
69 @unnumberedsubsec Hackers
71 There are lots of possibilities of improving the program itself. There
72 are both small projects and big ones. Most of them are listed in our
73 TODO file, listed on the homepage of Jan and
74 @uref{http://www.cs.uu.nl/~hanwen/lily-devel,Han-Wen}. Modifying
75 LilyPond almost always requires patches to the C++ part.
77 There are also numerous other interesting projects that are more or less
81 @item Writing convertors, eg. from NIFF and MIDI (we tried writing one with
82 limited success: midi2ly, included with lilypond.)
84 We found that writing them in Python is the easiest.
86 @item Writing a GUI frontend to
87 LilyPond. At the moment @uref{denemo,denemo.sourceforge.net} is the most
90 @item Helping write @uref{ http://solfege.sourceforge.net/,solfege
93 @item Helping @uref{primrose.sourceforge.net,primrose}, a tool for
98 @chapter LilyPond internals
101 @node Overview, , , Top
104 GNU LilyPond is a "multi-pass" system.
110 No difficult algorithms. The .ly file is read, and converted to a list
111 of @code{Scores}, which each contain @code{Music} and paper/midi-definitions.
113 @item Interpreting music
115 The music is walked through in time-order. The iterators which do the
116 walking report Music to Translators which use this information to
117 create elements, either MIDI or "visual" elements. The translators
118 form a hierarchy; the ones for paper output are Engravers, for MIDI
121 The translators swallow Music (mostly atomic gobs called Requests),
122 create elements, broadcast them to other translators on higher or same
123 level in the hierarchy:
125 The stem of a voice A is broadcast to the staff which contains A, but
126 not to the stems, beams and noteheads of a different voice (say B) or
127 a different staff. The stem and noteheads of A are coupled, because
128 the the Note_heads_engraver broadcasts its heads, and the Stem_engraver catches
131 The engraver which agrees to handle a request decides whether to to
132 honor the request, ignore it, or merge it with other requests. Merging
133 of requests is preferably done with other requests done by members of
134 the same voicegroups (beams, brackets, stems). In this way you can put
135 the voices of 2 instruments in a conductor's score so they make chords
136 (the Beam requests of both instruments will be merged).
140 Breakable stuff (eg. clefs and bars) are copied into pre and
145 Some dependencies are resolved, such as the direction of stems, beams,
146 and "horizontal" placement issues (the order of clefs, keys etc,
147 placement of chords in multi-voice music),
149 @item Break calculation:
151 The lines and horizontal positions of the columns are determined.
155 Through some magical interactions with Line_of_score and Super_elem
156 (check out the source) the "lines" are produced.
158 All other spanners can figure across which lines they are spread. If
159 applicable, they break themselves into pieces. After this, each piece
160 (or, if there are no pieces, the original spanner itself) throws out
161 any dependencies which are in the wrong line.
165 Some items and all spanners need computation after the Paper_column
166 positions are determined. Examples: slurs, vertical positions of
174 @node Request_engraver, , , Top
175 @section Request_engraver
177 In the previous section the idea of Request has been explained, but
178 this only solves one half of the problem. The other half is deciding
179 which requests should be honored, which should merged with other
180 requests, and which should be ignored. Consider this input
184 \type Staff < % chord
185 @{ \meter 2/4; [c8 c8] @}
186 @{\meter 2/4; [e8 e8] @}
191 Both the cs and es are part of a staff (they are in the same
192 Voice_group), so they should share meters, but the two [ ] pairs
195 The judge in this "allocation" problem a set of brokers: the requests
196 are transmitted to so-called engravers which respond if they want to
197 accept a request eg, the @code{Notehead_engraver} will accept
198 @code{Note_req}s, and turn down @code{Slur_req}s. If the Music_iterator
199 cannot find a engraver that wants the request, it is junked (with a
202 After all requests have been either assigned, or junked, the Engraver
203 will process the requests (which usually means creating an @code{Item}
204 or @code{Spanner}). If a @code{Request_engraver} creates something, it
205 tells the enclosing context. If all items/spanners have been created,
206 then each Engraver is notified of any created Score_element, via a
209 @unnumberedsubsec example:
221 Note_request (duration 1/4)
222 Stem_request (duration 1/4)
226 Note_request will be taken by a @code{Notehead_engraver}, stem_request
227 will be taken by a @code{Stem_beam_engraver}. @code{Notehead_engraver}
228 creates a @code{Notehead}, @code{Stem_beam_engraver} creates a
229 @code{Stem}. Both announce this to the Staff_engraver. Staff_engraver
230 will tell @code{Stem_beam_engraver} about the @code{Notehead}, which
231 will add the @code{Notehead} to the @code{Stem} it just created.
233 To decide on merging, several engravers have been grouped. Please
234 check @file{init/engraver.ly}.
236 @node Backend, , , Top
240 @section The backend of LilyPond
247 * Graphic elements:: blah
248 * Position and width Callbacks:: blah
249 * Score_element properties:: blah
250 * Score elements:: blah
257 @node Graphic elements, , , Backend
260 Music notation is composed of a sets of interrelated glyphs. In
261 Lilypond every glyph usually is represented by one object, a so-called
262 Graphic Object. The primary relations between graphic objects involve
266 @item consecutive notes are printed left to right, grouped in a staff
267 @item simultaneous notes are horizontally aligned (internally grouped in
269 @item the staccato mark is horizontally centered on the note it applies
273 The abstract encoding of such relations is done with the concept
274 @dfn{reference point}. The reference point (in X direction) of the
275 staccato mark is the note it applies to. The (X) position of the
276 staccato mark is stored relative to the position of the note head. This
277 means that the staccato will always maintain a fixed offset wrt to the
278 note head, whereever the head is moved to.
280 In the same vein, all notes on a staff have their Y positions stored
281 relative to an object that groups the staff. If that object is moved,
282 the absolute Y positions of all objects in that spanner change along, in
283 effect causing the staff and all its contents to move as a whole.
285 Each graphic object stores a pointer and an relative offset for each
286 direction: one for the X-axis, one for the Y-axis. For example, the X
287 parent of a Note_head usually is a Note_column. The X parent of a
288 Note_column usually is either a Collision or a Paper_column. The X
289 parent of a Collision usually is a Paper_column. If the Collision
290 moves, all Note_heads that have that Collision as parent also move, but
291 the absolute position of the Paper_column does not change.
293 To build a graphical score with Graphic_elements, conceptually, one
294 needs to have one Root object (in Lilypond: Line_of_score), and
295 recursively attach objects to the Root. However, due to the nature
296 of the context selection mechanisms, it turns out to be more
297 advantageous to construct the tree the other way around: first small
298 trees (note heads, barlines etc.) are created, and these are
299 subsequently composed into larger trees, which are finally hung on a
300 Paper_column (in X direction) or Line_of_score (in Y direction).
302 The structure of the X,Y parent relations are determined by the
303 engravers and notation contexts:
305 The most important X-axis parent relation depends on the timing: notes
306 that come earlier are attached to Paper_column that will be positioned
309 The most important Y-axis relation depends on containment of contexts:
310 notes (created in a Thread or Voice context) are put in the staff where
311 the originating context lives in.
313 Graphical_axis_groups are special graphic objects, that are designed to
314 function as a parent. The size of a Graphical_axis_groups group is the
315 union of its children.
317 @node Position and width Callbacks, , , Backend
320 The positions are, as explained relative to a parent reference
321 point. Most positions are not known when an object is created, so these
322 are calculated as needed. This is done by adding a callback for a
323 specific direction, eg
327 my_translate (Score_element * ptr, Axis a)
333 my_element->add_offset_callback (my_translate, Y_AXIS)
336 When a call is made to @code{my_element->relative_position (obj,
337 Y_AXIS)}, @code{my_translate} will be called. The result is that
338 my_element will be translated up by 5 pt. There are numerous callbacks,
341 @item to offset element by staff-spaces (See class
342 @code{Staff_symbol_referencer}).
343 @item to align elements next to other groups of elements (See class
344 @code{Side_position_interface})
348 Offset callbacks can be stacked. The callbacks will be executed in the
349 order that they were added.
351 Width and height are similarly implemted using extent callbacks. There
352 can be only one callback for each axis. No callback (the 0 ptr) means:
353 "empty in this direction".
355 @node Score_element properties, , , Backend
358 Score elements can have other properties besides positioning, for
359 example, text strings (for text objects) style settings, glyphs, padding
360 settings (for scripts). These settings are stored in element properties.
362 Properties are stored as GUILE association lists, with symbols as keys.
363 Element properties can be accessed using the C++ functions
366 SCM get_elt_property (SCM) const;
367 void set_elt_property (const char * , SCM val);
368 void set_immutable_elt_property (const char * , SCM val);
369 void set_immutable_elt_property (SCM key, SCM val);
370 void set_elt_property (SCM , SCM val);
371 void set_elt_pointer (const char*, SCM val);
372 SCM remove_elt_property (const char* nm);
375 All lookup functions identify undefined properties with GUILE
376 end-of-list (ie. @code{'()} in Scheme or @code{SCM_EOL} in C)
378 Implementation wise, there are two kinds of properties:
381 @item mutable properties:
382 element properties that change from object to object. The storage of
383 these are private to a Score element. Typically this is used to store
384 lists of pointers to other objects
386 @item immutable properties:
387 element properties that are shared across objects. The storage is
388 shared, and hence is read-only. Typically, this is used to store
389 function callbacks, and values for shared element properties are read
390 from @file{ly/engraver.ly}.
394 The following is from lily 1.3.80, and it shows the settings for the bar
395 numbers: Bar numbers are breakable, and visible at the beginning of the
396 line. The setting for @code{molecule-callback} indicates that Bar_number
397 is implemented as a text.
399 basicBarNumberProperties = #`(
400 (molecule-callback . ,Text_item::brew_molecule)
402 (visibility-lambda . ,begin-of-line-visible)
408 In 1.3.81 an music expression was added to add to the immutable property
412 \pushproperty #'(basicBarNumberProperties)
413 #'visibility-lambda #end-of-line-visible
416 This will add the entry @code{`(visibility-lambda .
417 ,end-of-line-visible)} to the immutable property list for bar numbers,
418 in effect overriding the setting from @file{ly/engraver.ly}. This can be
422 \popproperty #'(basicBarNumberProperties)
426 Note that you must accompany these statements with a proper context
427 selection in most cases.
434 @node Score elements, , , Backend
437 [FIXME: we want to get rid of dependencies in the implementation.]
439 Besides relative positions there are lots of other relations between
440 elements. Lilypond does not contain other specialized relation
441 management (Like the relative positioning code). Instead, objects can
442 be connected through dependencies, which sets the order in which objects
445 Example: the direction of a beamed stem should equal the direction of
446 the beam. When the stem is a added to the beam, a dependency on the
447 beam is set in the stem: this means that @code{Beam::do_pre_processing
448 ()} (which does various direction related things) will be called before
449 @code{Stem::do_pre_processing ()}.
451 The code that manages dependencies resides in the class
452 @code{Score_element}, a derived class of @code{Graphical_element}. The
453 bulk of the code handles line breaking related issues.
455 To sketch the problems with line breaking: suppose a slur spans a line
459 c4( c'''' c | \break d d )d
462 In this case, the slur will appear as two parts, the first part spanning
463 the first three notes (the @code{c}s), the second spanning the last
464 three (the @code{d}s). Within Lilypond this is modeled as breaking the
465 slur in parts: from the Original slur, two new clones of the old slur
466 are made. Initially both clones depend on the six notes. After the
467 hairy code in Score_element, Spanner and Item which does substitutions
468 in sets of dependencies, the first clone depends on the first three
469 notes, the second on the last three.
471 The major derived classes of Score_element are Item and Spanner.
472 An item has one horizontal position. A spanner hangs on two items.
474 @node Items, , , Backend
479 An item is a score element that is associated with only one
480 Paper_column. Examples are note heads, clefs, super and superscripts, etc.
481 Item is a derived class of Score_element.
483 The shape of an item is known before the break calculations, and line
484 spacing depends on the size of items: very wide items need more space
485 than very small ones.
487 An additional complication is the behavior of items at linebreaks. For
488 example, when you do a time signature change, you get only one symbol.
489 If it occurs at a linebreak, the new time signature must be printed both
490 before and after the linebreak. Other `breakable symbols' such as
491 clefs, and bar lines also exhibit this behavior.
493 if a line of music is broken, the next line usually gets a clef. So in
494 TeX terms, the clef is a postbreak. The same thing happens with meter
495 signs: Normally the meter follows the bar. If a line is broken at that
496 bar, the bar along with the meter stays on the "last" line, but the next
497 line also gets a meter sign after the clef. To support this,
498 breakable items are generated in the three versions: original
499 (unbroken), left (before line break) and right (after line break).
500 During the line spacing, these versions are used to try how the spacing
503 Once the definitive spacing is determined, dependencies (and various
504 other pointers) are substituted such that all dependencies point at the
505 active items: either they point at the original, or they point at left
508 @node Spanners, , , Backend
511 Spanners are symbols that are of variable shape, eg. Slurs, beams, etc.
512 Spanners is a derived class of Score_element.
514 The final shape can only be determined after the line breaking process.
515 All spanners are spanned on two items, called the left and right
516 boundary item. The X reference point is the left boundary item.
519 @node Future work, , , Backend
522 There are plans to unify Spanner and Item, so there will no longer be
523 such a clear distinction between the two. Right now, Score_elements are
524 always either Item or either Spanner.
526 @node Coding standards, , , Top
528 @chapter CodingStyle - standards while programming for GNU LilyPond
530 Functions and methods do not return errorcodes: they never crash, but
531 report a programming_error and try to carry on.q
534 @unnumberedsubsec Languages
536 C++ and Python are preferred. Perl is forbidden. Python code should
537 use an indent of 8, using TAB characters.
539 @unnumberedsubsec Filenames
541 Definitions of classes that are only accessed via pointers
542 (*) or references (&) shall not be included as include files.
548 ".cc" Implementation files
549 ".icc" Inline definition files
550 ".tcc" non inline Template defs
556 (setq auto-mode-alist
557 (append '(("\\.make$" . makefile-mode)
558 ("\\.cc$" . c++-mode)
559 ("\\.icc$" . c++-mode)
560 ("\\.tcc$" . c++-mode)
561 ("\\.hh$" . c++-mode)
562 ("\\.pod$" . text-mode)
568 The class Class_name_abbreviation is coded in @file{class-name-abbr.*}
570 @unnumberedsubsec Indentation
572 Standard GNU coding style is used. In emacs:
575 (add-hook 'c++-mode-hook
576 '(lambda() (c-set-style "gnu")
581 If you like using font-lock, you can also add this to your @file{.emacs}:
584 (setq font-lock-maximum-decoration t)
585 (setq c++-font-lock-keywords-3
587 c++-font-lock-keywords-3
588 '(("\\b\\([a-zA-Z_]+_\\)\\b" 1 font-lock-variable-name-face)
589 ("\\b\\([A-Z]+[a-z_]+\\)\\b" 1 font-lock-type-face))
593 @unnumberedsubsec Classes and Types
599 @unnumberedsubsec Members
603 Type Class::member_type_
604 Type Class::member_type ()
607 the @code{type} is a Hungarian notation postfix for @code{Type}. See below
609 @unnumberedsubsec Macros
611 Macros should be written completely in uppercase
613 The code should not be compilable if proper macro declarations are not
616 Don't laugh. It took us a whole evening/night to figure out one of
617 these bugs, because we had a macro that looked like
618 @code{DECLARE_VIRTUAL_FUNCTIONS ()}.
620 @unnumberedsubsec Broken code
622 Broken code (hardwired dependencies, hardwired constants, slow
623 algorithms and obvious limitations) should be marked as such: either
624 with a verbose TODO, or with a short "ugh" comment.
626 @unnumberedsubsec Comments
628 The source is commented in the DOC++ style. Check out doc++ at
629 @uref{http://www.zib.de/Visual/software/doc++/index.html}
634 C style comments for multiline comments.
635 They come before the thing to document.
641 Long class documentation.
644 TODO Fix boring_member ()
655 short memo. long doco of member ()
656 @@param description of arguments
659 Rettype member (Argtype);
663 data_member_ = 121; // ugh
670 Unfortunately most of the code isn't really documented that good.
672 @unnumberedsec Hungarian notation naming convention
674 Proposed is a naming convention derived from the so-called
675 @emph{Hungarian Notation}. Macros, @code{enum}s and @code{const}s are all
676 uppercase, with the parts of the names separated by underscores.
678 The hungarian notation is to be used when variables are not declared
679 near usage (mostly in member variables and functions).
681 @unnumberedsubsec Types
685 unsigned char. (The postfix _by is ambiguous)
699 Zero terminated c string
704 @unnumberedsubsec User defined types
712 Slur* slur_p = new Slur;
716 @unnumberedsubsec Modifiers
718 The following types modify the meaning of the prefix.
719 These are preceded by the prefixes:
727 const. Note that the proper order is @code{Type const}
728 i.s.o. @code{const Type}
730 A const pointer. This would be equivalent to @code{_c_l}, but since any
731 "const" pointer has to be a link (you can't delete a const pointer),
734 temporary pointer to object (link)
736 pointer to newed object
741 @unnumberedsubsec Adjective
743 Adjectives such as global and static should be spelled out in full.
744 They come before the noun that they refer to, just as in normal english.
748 foo_global_i: a global variable of type int commonly called "foo".
752 static class members do not need the static_ prefix in the name (the
753 Class::var notation usually makes it clear that it is static)
757 Variable loop: an integer
759 Temporary variable: an unsigned integer
761 Variable test: a character
762 @item @code{first_name_str}
763 Variable first_name: a String class object
764 @item @code{last_name_ch_a}
765 Variable last_name: a @code{char} array
767 Variable foo: an @code{Int*} that you must delete
769 Variable bar: an @code{Int*} that you must not delete
772 Generally default arguments are taboo, except for nil pointers.
774 The naming convention can be quite conveniently memorised, by
775 expressing the type in english, and abbreviating it
779 static Array<int*> foo
783 @code{foo} can be described as "the static int-pointer user-array", so you get
792 @unnumberedsec Miscellaneous
794 For some tasks, some scripts are supplied, notably creating patches, a
795 mirror of the website, generating the header to put over cc and hh
796 files, doing a release.
800 @node Making patches, , , Top
803 @unnumberedsec Track and distribute your code changes
805 This page documents how to distribute your changes to GNU lilypond
807 We would like to have unified context diffs with full pathnames. A
808 script automating supplied with Lily.
810 Distributing a change normally goes like this:
813 @item make your fix/add your code
814 @item Add changes to CHANGES, and add yourself to Documentation/topdocs/AUTHORS.texi
815 @item generate a patch,
816 @item e-mail your patch to one of the mailing lists
817 gnu-music-discuss@@gnu.org or bug-gnu-music@@gnu.org
820 Please do not send entire files, even if the patch is bigger than the
821 original. A patch makes it clear what is changed, and it won't
822 overwrite previous (not yet released) changes.
824 @unnumberedsec Generating a patch
829 make -C lilypond-x.y.z/ distclean
830 make -C lilypond-x.y.z.NEW/ distclean
831 diff -urN lilypond-x.y.z/ lilypond-x.y.z.NEW/
834 Complicated (but automated) version:
836 In @file{VERSION}, set MY_PATCH_LEVEL:
846 In @file{CHANGES}, enter a summary of changes:
853 Then, from the top of Lily's source tree, type
859 These handy python scripts assume a directory structure which looks
864 lilypond -> lilypond-x.y.z # symlink to development directory
865 lilypond-x.y.z/ # current development
866 patches/ # patches between different releases
867 releases/ # .tar.gz releases
871 (Some scripts also assume this lives in @file{$HOME/usr/src}).
874 @unnumberedsec Applying patches
877 If you're following LilyPond development regularly, you probably want to
878 download just the patch for each subsequent release.
879 After downloading the patch (into the patches directory, of course), simply
884 gzip -dc ../patches/lilypond-0.1.74.diff.gz | patch -p1 -E
888 and don't forget to make automatically generated files:
892 autoconf footnote(patches don't include automatically generated files,
893 i.e. file(configure) and files generated by file(configure).)
899 @node Localisation, , , Top
901 @chapter Localisation - User messages in LilyPond
903 @section Introduction
905 This document provides some guidelines for uniformising user messages.
906 In the absence of other standards, we'll be using these rules when coding
907 for for LilyPond@footnote{
908 In addition to the C++ coding standards that come with Lily
909 }. Hopefully, this can be replaced by general GNU
910 guidelines in the future.
912 Not-preferred messages are marked with @code{+}.
913 By convention, agrammatical examples are marked with @code{*}.
921 Every message to the user should be localised (and thus be marked
922 for localisation). This includes warning and error messages.
925 Don't localise/gettextify:
928 @item @code{programming_error ()}s
929 @item @code{programming_warning ()}s
931 @item output strings (PostScript, TeX)@footnote{
932 This may seem ridiculously obvious, however, makeinfo-3.12s localises
933 output strings. Sending bug report now ---jcn
940 Messages to be localised must be encapsulated in @code{_ (STRING)}
941 or @code{_f (FORMAT, ...)}. Eg:
944 warning (_ ("Need music in a score"));
945 error (_f ("Can't open file: `%s'", file_name));
948 In some rare cases you may need to call @code{gettext ()} by hand.
949 This happens when you pre-define (a list of) string constants for later
950 use. In that case, you'll probably also need to mark these string
951 constants for translation, using @code{_i (STRING)}. The @code{_i}
952 macro is a no-op, it only serves as a marker for @file{xgettext}.
955 char const* messages[] = @{
956 _i ("enable debugging output"),
957 _i ("ignore lilypond version"),
964 puts (gettext (messages [i]));
969 @file{flower/getopt-long.cc} and @file{lily/main.cc}.
972 Don't use leading or trailing whitespace in messages.
975 Messages containing a final verb, or a gerund (@code{-ing}-form)
976 always start with a capital. Other (simpler) messages start with
980 The word `foo' is not declared.
982 Not declaring: `foo'.
986 To avoid having a number of different messages for the same situation,
987 we'll use quoting like this @code{"message: `%s'"} for all strings.
988 Numbers are not quoted:
991 _f ("Can't open file: `%s'", name_str)
992 _f ("Can't find charater number: %d", i)
996 Think about translation issues.
997 In a lot of cases,it's better to translate a whole message.
998 The english grammar mustn't be imposed on the translator.
1002 _ ("Stem at ") + moment.str () + _(" doen't fit in beam")
1009 _f ("Stem at %s doen't fit in beam", moment.str ())
1013 Split up multi-sentence messages, whenever possible. Instead of
1016 warning (_f ("out of tune! Can't find: `%s', "Key_engraver"));
1018 warning (_f ("Can't find font `%s', loading default",
1026 warning (_ ("out of tune:");
1027 warning (_f ("Can't find: `%s', "Key_engraver"));
1029 warning (_f ("Can't find font: `%s', font_name));
1030 warning (_f ("Loading default font"));
1034 If you must have multiple-sentence messages, use full punctuation.
1035 Use two spaces after end of sentence punctuation.
1036 No punctuation (esp. period) is used at the end of simple messages.
1039 _f ("Non-matching braces in text `%s', adding braces", text)
1040 _ ("Debug output disabled. Compiled with NPRINT.")
1041 _f ("Huh? Not a Request: `%s'. Ignoring.", request)
1045 Don't modularise too much; a lot of words cannot be translated
1047 It's probably safe to treat most occurences of words like
1048 stem, beam, crescendo as separately translatable words.
1051 When translating, it is preferrable to put interesting information
1052 at the end of the message, rather than embedded in the middle.
1053 This especially applies to frequently used messages, even if this
1054 would mean sacrificing a bit of eloquency. This holds for original
1055 messages too, of course.
1058 en: can't open: `foo.ly'
1059 + nl: kan `foo.ly' niet openen (1)
1060 kan niet openen: `foo.ly'* (2)
1061 niet te openen: `foo.ly'* (3)
1064 The first nl message, although gramatically and stylishly correct,
1065 is not friendly for parsing by humans (even if they speak dutch).
1066 I guess we'd prefer something like (2) or (3).
1069 Please don't run make po/po-update with GNU gettext < 0.10.35