10.5.8 Localization (LilyPond Contributor’s Guide)

#### 10.5.8 Localization

This document provides some guidelines to help programmers write proper user messages. To help translations, user messages must follow uniform conventions. Follow these rules when coding for LilyPond. Hopefully, this can be replaced by general GNU guidelines in the future. Even better would be to have an English (en_GB, en_US) guide helping programmers writing consistent messages for all GNU programs.

Non-preferred messages are marked with ‘`+`’. By convention, ungrammatical examples are marked with ‘`*`’. However, such ungrammatical examples may still be preferred.

- Every message to the user should be localized (and thus be marked for localization). This includes warning and error messages.
- Do not localize/gettextify:
  - − `programming_error`
  - − `programming_warning`
  - − debug strings
  - − output strings (PostScript, TeX, etc.)
- Messages to be localized must be encapsulated in `_ (string)` or `_f (format, ...)`, for example

      warning (_ ("need music in a score"));
      error (_f ("cannot open file: `%s'", file_name));

  In some rare cases you may need to call `gettext` by hand. This happens when you pre-define (a list of) string constants for later use. In that case, you’ll probably also need to mark these string constants for translation, using `_i (string)`. The ‘_i’ macro is a no-op, it only serves as a marker for `xgettext`.

      char const* messages[] = {
        _i ("enable debugging output"),
        _i ("ignore lilypond version"),
        0
      };

      void
      foo (int i)
      {
        puts (gettext (messages i));
      }

  See also `flower/getopt-long.cc` and `lily/main.cc`.

- Do not use leading or trailing whitespace in messages. If you need whitespace to be printed, prepend or append it to the translated message

      message ("Calculating line breaks..." + " ");

- Error or warning messages displayed with a file name and line number never start with a capital, eg,

      foo.ly: 12: not a duration: 3

  Messages containing a final verb, or a gerund (‘-ing’-form) always start with a capital. Other (simpler) messages start with a lowercase letter

      Processing foo.ly...
      `foo': not declared.
      Not declaring: `foo'.

- Avoid abbreviations or short forms, use ‘cannot’ and ‘do not’ rather than ‘can’t’ or ‘don’t’ To avoid having a number of different messages for the same situation, we will use quoting like this `"message: `%s'"` for all strings. Numbers are not quoted:

      _f ("cannot open file: `%s'", name_str)
      _f ("cannot find character number: %d", i)

- Think about translation issues. In a lot of cases, it is better to translate a whole message. English grammar must not be imposed on the translator. So, instead of

      stem at  + moment.str () +  does not fit in beam

  have

      _f ("stem at %s does not fit in beam", moment.str ())

- Split up multi-sentence messages, whenever possible. Instead of

      warning (_f ("out of tune!  Can't find: `%s'", "Key_engraver"));
      warning (_f ("cannot find font `%s', loading default", font_name));

  rather say:

      warning (_ ("out of tune:"));
      warning (_f ("cannot find: `%s', "Key_engraver"));
      warning (_f ("cannot find font: `%s', font_name));
      warning (_f ("Loading default font"));

- If you must have multiple-sentence messages, use full punctuation. Use two spaces after end of sentence punctuation. No punctuation (esp. period) is used at the end of simple messages.

      _f ("Non-matching braces in text `%s', adding braces", text)
      _ ("Debug output disabled.  Compiled with NPRINT.")
      _f ("Huh?  Not a Request: `%s'.  Ignoring.", request)

- Do not modularize too much; words frequently cannot be translated without context. It is probably safe to treat most occurrences of words like stem, beam, crescendo as separately translatable words.
- When translating, it is preferable to put interesting information at the end of the message, rather than embedded in the middle. This especially applies to frequently used messages, even if this would mean sacrificing a bit of eloquence. This holds for original messages too, of course.

      en: cannot open: `foo.ly'
      +   nl: kan `foo.ly' niet openen (1)
      kan niet openen: `foo.ly'*   (2)
      niet te openen: `foo.ly'*    (3)

  The first nl message, although grammatically and stylistically correct, is not friendly for parsing by humans (even if they speak dutch). I guess we would prefer something like (2) or (3).

- Do not run make po/po-update with GNU gettext < 0.10.35

#### LilyPond Contributor’s Guide v2.26.0 (stable-branch).

- 1 Introduction to contributing
  - 1.1 Help us
  - 1.2 Overview of work flow
  - 1.3 Summary for experienced developers
  - 1.4 Mentors
- 2 Quick start
  - 2.1 LilyDev
    - Installing LilyDev in VirtualBox
    - Configuring LilyDev in VirtualBox
  - 2.2 Compiling with LilyDev
  - 2.3 Now start work!
- 3 Working with source code
  - 3.1 Setting up
    - 3.1.1 Installing Git
    - 3.1.2 Creating a GitLab account and setting up SSH
    - 3.1.3 Cloning and forking the repository
    - 3.1.4 Configuring Git
  - 3.2 Git cheat sheet
  - 3.3 Lifecycle of a merge request
    - 3.3.1 Uploading a patch for review
    - 3.3.2 Automated testing
    - 3.3.3 Patch countdown
    - 3.3.4 Merging to master
    - 3.3.5 Abandoned patches
  - 3.4 Writing good commit messages
  - 3.5 Commit access
  - 3.6 Further Git documentation resources
  - 3.7 Repository directory structure
- 4 Compiling
  - 4.1 Overview of compiling
  - 4.2 Requirements
    - 4.2.1 Requirements for running LilyPond
    - 4.2.2 Requirements for compiling LilyPond
      - Fedora
      - Linux Mint
      - OpenSUSE
      - Ubuntu
      - Other
    - 4.2.3 Requirements for building documentation
  - 4.3 Getting the source code
  - 4.4 Configuring `make`
    - 4.4.1 Build modes
    - 4.4.2 Running `autogen.sh`
    - 4.4.3 Running `configure`
      - Configuration options
      - Checking build dependencies
      - Configuring target directories
  - 4.5 Compiling LilyPond
    - 4.5.1 Using `make`
    - 4.5.2 Saving time with the `-j` option
    - 4.5.3 Useful `make` variables
  - 4.6 Post-compilation options
    - 4.6.1 Installing LilyPond from a local build
    - 4.6.2 Generating documentation
      - Documentation editor’s edit/compile cycle
      - Building documentation
      - Building a single document
      - Saving time with `CPU_COUNT`
      - Installing documentation
      - Building documentation without compiling
    - 4.6.3 Testing LilyPond binary
  - 4.7 Problems
  - 4.8 Concurrent stable and development versions
    - 4.8.1 Replacing the notation fonts in development versions
  - 4.9 Build system
- 5 Documentation work
  - 5.1 Introduction to documentation work
  - 5.2 `\version` in documentation files
  - 5.3 Documentation suggestions
  - 5.4 Texinfo introduction and usage policy
    - 5.4.1 Texinfo introduction
    - 5.4.2 Documentation files
    - 5.4.3 Sectioning commands
    - 5.4.4 Menus
    - 5.4.5 LilyPond formatting
    - 5.4.6 Text formatting
    - 5.4.7 Syntax survey
      - Comments
      - Cross-references
      - External links
      - Fixed-width font
      - Indexing
      - Lists
      - Special characters
      - Miscellany
    - 5.4.8 Other text concerns
  - 5.5 Documentation policy
    - 5.5.1 Books
    - 5.5.2 Section organization
    - 5.5.3 Checking cross-references
    - 5.5.4 General writing
    - 5.5.5 Technical writing style
  - 5.6 Tips for writing documentation
    - 5.6.1 Working on subsections
    - 5.6.2 Searching
  - 5.7 Scripts to ease documentation work
    - 5.7.1 Building only one section of the documentation
    - 5.7.2 Updating documentation with `convert-ly`
  - 5.8 Documentation strings in the Internals Reference
  - 5.9 Translating the documentation
    - 5.9.1 Getting started with documentation translation
      - Translation requirements
      - Which documentation can be translated
      - Starting translation in a new language
    - 5.9.2 Documentation translation details
      - Files to be translated
      - Translating the website and other Texinfo documentation
      - Adding a Texinfo manual
    - 5.9.3 Documentation translation maintenance
      - Check state of translation
      - Updating documentation translation
      - Updating translation committishes
      - Maintaining without updating translations
    - 5.9.4 Technical background
- 6 Website work
  - 6.1 Introduction to website work
  - 6.2 Uploading website
  - 6.3 Debugging website and docs locally
  - 6.4 Translating the website
- 7 LilyPond Wiki work
  - 7.1 Introduction to the LilyPond Wiki
  - 7.2 Adding and editing snippets
  - 7.3 Snippet administration
  - 7.4 The `makelsr.pl` script
  - 7.5 LilyPond Wiki to Git
- 8 Issues
  - 8.1 Introduction to issues
  - 8.2 Triaging bugs
  - 8.3 Issue classification
  - 8.4 Adding issues to the tracker
- 9 Regression tests
  - 9.1 Introduction to regression tests
  - 9.2 Precompiled regression tests
  - 9.3 Compiling regression tests
  - 9.4 Regtest comparison
  - 9.5 Pixel-based regtest comparison
  - 9.6 Finding the cause of a regression
  - 9.7 MusicXML tests
- 10 Programming work
  - 10.1 Overview of LilyPond architecture
  - 10.2 LilyPond programming languages
  - 10.3 Programming without compiling
  - 10.4 Finding functions
  - 10.5 Code style
    - 10.5.1 Languages
    - 10.5.2 Filenames
    - 10.5.3 Code formatting
    - 10.5.4 Naming Conventions
    - 10.5.5 Broken code
    - 10.5.6 Code comments
    - 10.5.7 Handling errors
    - 10.5.8 Localization
  - 10.6 Warnings, Errors, Progress and Debug Output
  - 10.7 Debugging LilyPond
    - 10.7.1 Debugging overview
    - 10.7.2 Debugging C++ code
    - 10.7.3 Debugging Scheme code
    - 10.7.4 Debugging scoring algorithms
    - 10.7.5 Debugging skylines
  - 10.8 Tracing object relationships
  - 10.9 Tracing processing time
  - 10.10 Adding or modifying features
    - 10.10.1 Write the code
    - 10.10.2 Write regression tests
    - 10.10.3 Write convert-ly rule
    - 10.10.4 Automatically update documentation
    - 10.10.5 Manually update documentation
    - 10.10.6 Edit changes.tely
    - 10.10.7 Verify successful build
    - 10.10.8 Verify regression tests
    - 10.10.9 Post patch for comments
    - 10.10.10 Push patch
    - 10.10.11 Closing the issues
  - 10.11 Iterator tutorial
  - 10.12 Engraver tutorial
    - 10.12.1 Useful methods for information processing
    - 10.12.2 Translation process
    - 10.12.3 Listening to music events
    - 10.12.4 Acknowledging grobs
    - 10.12.5 Engraver declaration/documentation
  - 10.13 Callback tutorial
  - 10.14 Understanding pure properties
    - 10.14.1 Purity in LilyPond
    - 10.14.2 Writing a pure function
    - 10.14.3 How purity is defined and stored
    - 10.14.4 Where purity is used
    - 10.14.5 Case studies
    - 10.14.6 Debugging tips
  - 10.15 LilyPond scoping
  - 10.16 Regular expressions
  - 10.17 Scheme->C interface
    - 10.17.1 Comparison
    - 10.17.2 Conversion
  - 10.18 Garbage collection for dummies
  - 10.19 LilyPond miscellany
    - 10.19.1 Spacing algorithms
    - 10.19.2 Info from Han-Wen email
    - 10.19.3 Music functions and Guile debugging
    - 10.19.4 Articulations on EventChord
- 11 Release work
  - 11.1 Development phases
  - 11.2 Release checklist
  - 11.3 Major release checklist
- 12 Modifying the Emmentaler font
  - 12.1 Overview of the Emmentaler font
  - 12.2 Font creation tools
  - 12.3 Adding a new font section
  - 12.4 Adding a new glyph
  - 12.5 Building the changed font
  - 12.6 METAFONT formatting rules
- 13 Administrative policies
  - 13.1 LilyPond is GNU Software
  - 13.2 Environment variables
  - 13.3 Performing yearly copyright update (“grand-replace”)
- Appendix A GNU Free Documentation License