HOWTO translate GRASS messages
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

This file contains following sections:
1. Instructions for programmers;
2. A translation workflow overview;
3. A detailed explanation of translation workflow, testing;
4. Some notes and links

[ Web page: https://grass.osgeo.org/devel/i18n.php ]

Updating the message catalogs currently only works on 
unix-like systems and requires xgettext.

------------------------------------------------------

REQUIRED SOURCE CODE CHANGES (programming required)

Generally, to support i18N multiple languages,
message strings in GRASS must be modified from

 fprintf ( ..., "...\n", ...);
to either
 fprintf ( ..., _("...\n"), ...);
or (omit \n)
 G_message ( _("..."), ...);

Careful:
  G_message should be used for messages - information about
  the process for user while fprintf(stdout...) for data output.
  G_message output is not expected to be send to pipe or file.
  fprintf(stdout...) output is usually send to pipe or file.


Three steps:
1) check if fprintf is to be replaced (see above)

2) to add (see example above):
     the macro _( ) which encapulates the message

3) to be added to file.c header:
     #include "glocale.h"

   This line has to be added to each C file which contains
   user messages, preferably as last #include statement.
   Only, if missing, also add
     #include "gis.h"

NOTE: Also G_warning() and G_fatal_error() need the message
      encapsulation with macro _() but no further changes.

NOTE2: Also the parameters/flags of each module needs the
       macro _().

NOTE3: Notices to translators can be added by placing
       a comment line starting with GTC tag just above
       message to be translated:
        /* GTC A comma separated keyword list. 
           Should not contain spaces! */
        keywords = _("first,second,third");

NOTE4:  Any string containing a number that requires a correct plural form of
        a noun, has to pass trough ngettext function implemented in GRASS
        as a n_() macro.
        n_("Message in English for singular case", "Message in English for
        plural case", number) 

Examples of messages with plural forms.
Wrong:
    G_message( _("%d map(s) from mapset <%s> removed"), n, ms);
    G_message( n == 1 ? _("One file removed") : _("%d files removed"), n);
    G_warning( _("%d %s without geometry skipped"), n, 
        n == 1 ? "feature" : "features"); 
    G_message( _("%d maps selected"), n);
    G_message( n == 1 ? _("Remove map") : _("Remove maps"));

Correct:
    G_message( n_("%d map from mapset <%s> removed", 
        "%d maps from mapset <%s> removed", n), n, ms);
    /* Notice double use of number "n" - as an argument for 
    both functions - n_() and G_message() */
    G_message( n_("One file removed", "%d files removed", n) n);
    /* Both of forms of singular case "%d file" or "One file" are correct. 
    The choice between them is purely stylistic one. */
    G_warning( n_("One feature without geometry skipped", 
        "%d features without geometry skipped", n), n);
    G_message( n_("%d map selected", "%d maps selected", n), n);
    /* Although in English it is not necessary to provide a separate
    text if "n" always is >1, in other languages is a difference if "n"
    is i.e. 2-4, or n==10 etc. */
    G_message( n_("Remove map", "Remove maps", n));
    /* Number it self doesn't have to be used in the output text */
        
        
All these messages strings will be then automatically 
extracted into the message files.

See for example ./vector/v.what.rast/main.c

NOTE4: Such lines
        fprintf (stdout,"\n");
  do not need a change as no translation is needed.

A detailed example of adapting code for use in multiple languages
can be found in gettext manual.
How to prepare program source: 
https://www.gnu.org/software/gettext/manual/gettext.html#Sources

More advanced tricks like resolving ambiguties and handling of plural forms:
https://www.gnu.org/software/gettext/manual/gettext.html#Programmers


TODO: ADD PYTHON code snippets here

------------------------------------------------------

GENERAL TRANSLATION PROCEDURE (no programming required)

 POT files [1] ---->  PO files [2] ----> update PO files [3] ----> PO merge + MO files [4]
 (original           (translated            (updating of msgs      (final binary message file,
  messages)           messages)              in Transifex)          used by GRASS GIS modules)

 see also: https://grasswiki.osgeo.org/wiki/GRASS_messages_translation#Get_the_translated_po_files

[1] .pot files are auto-generated on grass.osgeo.org and
    stored in https://grass.osgeo.org/grass-devel/binary/linux/snapshot/transifex/
     --> cronjob (on grasslxd container): /home/neteler/cronjobs/cron_grass8_main_src_snapshot.sh

[2] Transifex job copies daily from [1] to here: 
	https://www.transifex.com/grass-gis/grass7/dashboard/

[3] Translators work in Transifex,

[4] Updated po files are taken from Transifex and merged into GRASS GIS source repo 
    (MO files are generated when compiling GRASS GIS)
    Script: https://github.com/OSGeo/grass-addons/blob/grass8/utils/transifex_merge.sh

    # trim disconnected=obsolete translations
    POFILE=grassYXZ_LANG.po
    msgattrib --output-file=$POFILE --no-obsolete $POFILE


Semi-automated procedure:

  1. In the main GRASS source code directory, run:
     
        ./configured --with-nls [...further options...]
        make

  2. In the locale/ directory, run:

TODO OLD    make pot        creates grass.pot (containing original messages)

TODO OLD    make update-po  merges new messages into existing *.po files

  3. Now translate the messages in the po/*.po files (using kbabel or 
     other editor). Just open the .po file(s) in your preferred translation
     software.

  4. In the locale/ directory, run:
      
        make mo         creates the mo files (containing translated messages as
                        binary file)

If you have any difficulty with these instructions please ask for help
on the GRASS development mailing list <grass-dev lists.osgeo.org>
(subscribe at https://lists.osgeo.org/mailman/listinfo/grass-dev). Your
willingness, time, and effort translating are valuable. If necessary,
all of these steps except for the actual translation can be done by
someone else on a different computer.

A convenient software package to translate messages is 'kbabel'.
It permits to enhance it's message database by loading existing
.po files to semi-automate the translation.

Note that GRASS must be configured with '--with-nls' and (re)compiled
to make use of the translated messages.

There is a file for all library messages and another for all
module messages (this might be split in future).

------------------------------------------------------
DETAILED PROCEDURE :

1. Define/check language settings

   echo $LANG
   echo $LANGUAGE
   echo $LC_ALL

   Maybe you have to change it (example for Japanese):
   - for bash shell:
       export LANG=ja_JP
       export LANGUAGE=ja_JP
       export LC_ALL=ja_JP

   - for (t)csh shell:
       setenv LANG ja_JP
       setenv LANGUAGE ja_JP
       setenv LC_ALL ja_JP


2. CREATE POT FILES
   run
    make pot
    
   This will create
    ./templates/grasslibs.pot
    ./templates/grassmods.pot
    ./templates/grasswxpy.pot


3. CREATE LANGUAGE FILES

   Two cases have to be distinguished:
    a) Messages have not yet been translated to your language.
    b) Some messages have already been translated to your language,
       so you want to merge your efforts into the existing translation.
       
  3.a) First CASE: Messages have not yet been translated to your language.
       No .po file is present for your language in the ./po/ directory.
      
       Run:
        make pot
        make update-po
 
       Move the generated file from the ./template/ directory
       to the ./po/ directory (for example German language):
        mv ./template/grasslibs.pot ./po/grasslibs_de.po
        mv ./template/grassmods.pot ./po/grassmods_de.po
        mv ./template/grasswxpy.pot ./po/grasswxpy_de.po

       Get the two characters indicating the language from this
       code list: https://www.loc.gov/standards/iso639-2/php/English_list.php
       The code to use is ISO 639-1 (two characters).

       Then continue with 4. below.

  3.b) Second CASE: Some messages have already been translated to 
       your language (files present in ./po/ directory), and
       you want to continue with translating new and still
       untranslated messages.

       First we have to merge new messages into existing .po files 
       (which contain already translated messages) as new messages
       might have been added into the GRASS system. 
       To do so, run:
    
       make pot
       make update-po
    
       This will update the messages in all existing files in 
       the .po/ directory.
    

4. TRANSLATE MESSAGES

   In the links section at bottom of this page you find references to the
   'kbabel' and 'poEdit' software to easily translate the message files.
   
   Run 'kbabel' or equivalent program
    kbabel ./po/grasslibs_<LANGUAGE>.po
    kbabel ./po/grassmods_<LANGUAGE>.po
    kbabel ./po/grasswxpy_<LANGUAGE>.po

   For example (German):
    kbabel ./po/grasslibs_de.po
    kbabel ./po/grassmods_de.po
    kbabel ./po/grasswxpy_de.po

   KBABEL: You may load .po files from other projects [see footnote 1].
           Then use TOOLS -> ROUGH TRANSLATION to auto-translate messages.
           For Asian, Indian and other keymaps, see [footnote 3].

   NOTES:
   * Pay attention to keep '%s', '\n' and other stuff also 
     in the translated messages!
   
   * Please use 'ISO-8859-1' or 'ISO-8859-15' for western languages.
     See https://en.wikipedia.org/wiki/ISO_8859 for details.
   
   After finishing the translation, save the files.

     
5. CREATE MO FILES

   run
    make mo

   READY.


6. Now recompile, install and run GRASS.
   It should work :-)

   If you don't have this possibility, just skip this step.


7. Send the updated .po files to a GRASS Development Team member.
   If possible, please send diffs against CVS:
   git diff grasslibs_LANG.po > grasslibs_LANG_po.diff
   git diff grassmods_LANG.po > grassmods_LANG_po.diff
   git diff grasswxpy_LANG.po > grasswxpy_LANG_po.diff

   If you updated .c files with _() macros as explained
   above, please send C file diffs against git:
   
   git diff file.c > file.diff
   
   Thanks for submitting.

   
PLEASE HELP TO TRANSLATE GRASS MESSAGES!

----------------------------------------------

LINKS

- Localize: https://userbase.kde.org/Lokalize
- poEdit: https://poedit.net/
- *.po files for many languages: KDE translator center, https://l10n.kde.org/teams-list.php

NOTES

[1] To load existing .po files (eg from older GRASS versions or
    KDE translator center, https://l10n.kde.org/teams-list.php) into
    Kbabel, use
    KBABEL -> SETTINGS -> CONFIGURE DIRECTORY -> PO AUXILIARY

[2] To change/add the keymap under KDE, you have to:
    1. Open "(KDE) Control Center = kcontrol"
    2. Go to Regional & Accessibility -> Keyboard Layout
    3. Check "Enable Keyboard Layout".
    4. Select Layout (e.g. Hindi) from the Additional Layouts list
    5. Press "Add >>"
    6. Press "Apply".

    Note!: You can change between the new and the original layouts by
    pressing Alt+Ctrl+k or by clicking the keyboard icon in the system
    tray.

    Command line alternative:
      # hindi layout (Devanagari)
      setxkbmap -model  -layout dev -variant basic
      # back to US layout:
      setxkbmap -model  -layout us -variant basic
