Autoconf/I18n-ify HelloWorld HOW-TO
-----------------------------------

Authors:
	Kenneth Christiansen <kenneth at gnu dot org>
	Thomas Vander Stichele <thomas at apestaart dot org>

Disclaimer:
	Kenneth last used autoconf 2.52 and automake 1.4p5 to test this guide.
	Thomas last used autoconf 2.52 and automake 1.5 to test this guide.
	We would like you to let us know if you have different versions of
	these tools and things don't work out the same way.
	No authors of any autotools were harmed during the making of this guide.

In this article we are going to explain how to turn a simple
Hello World application with a standard Makefile into an autotools-
and I18N-enabled tree up to the point where it can be distributed.

Our existing helloworld.c file looks like the following:

#include <stdio.h>

int main (void) {
  printf ("Hello, world!\n");
} 

1. First we create a source tree :
    
   /                        - This is the top level directory
   /src/                    - Here the source will end up.

   and place the helloworld.c file in the src/ dir

2. If your program has not been autoconf-enabled yet, you can
   create configure.scan (which is a good starting point for configure.in)
   and rename it to configure.in

        autoscan   # creates configure.scan
        mv configure.scan configure.in

   Now edit configure.in and make some changes.
   You can remove everything after AC_INIT, we'll be using AM_INIT_AUTOMAKE
   to pass on variables.

   Add the lines
     PACKAGE=helloworld
     VERSION=0.0.1
     AM_INIT_AUTOMAKE($PACKAGE, $VERSION) 
   to configure.in, just after AC_INIT

   Change AC_CONFIG_HEADER to AM_CONFIG_HEADER as well.

   If you have an empty AC_CONFIG_FILES macro, then comment that, or automake
   will fail in the next step.

   Finally, add Makefile to the AC_OUTPUT macro by changing that
   line to read
     AC_OUTPUT(Makefile)

4. We add some files that automake does not make but are necessary
   to adhere to GNU standards.

   touch NEWS README AUTHORS ChangeLog

   These two files need to be created to satisfy automake

   touch config.h.in Makefile.am

   We will create Makefile.am later on.

4. To add some basic files (like COPYING, INSTALL, etc..) 
   we run automake in the toplevel directory.

   automake --add-missing --gnu

5. After that we do the big i18n trick :-), also in the toplevel
   directory.

   gettextize --force --copy    # created po/ intl/ dir with some files
   intltoolize 		        # bring in the perl helper scripts

7. Add support for libtool to our package (which provides a platform
   independent way of creating static and shared libraries)

	libtoolize --force

   FIXME: is there good reason to do so ? If not, let's leave it out


9. Run autoheader which will create config.h.in

	autoheader # create config.h.in

10. Now, open up configure.in and make some modifications.

    The gettext macros need to be added after the initial checks.  
    Putting them after the checks for library functions is a good idea.

    AC_PROG_INTLTOOL(0.18)
    AM_WITH_NLS
    ALL_LINGUAS="da nl"                 # Internationalization, means there is 
					# a .po file for danish and dutch.
    AM_GLIB_GNU_GETTEXT

    AC_OUTPUT(
	Makefile
	src/Makefile
	intl/Makefile
	po/Makefile.in
    )

    AC_PROG_INTLTOOL checks if a good enough intltool is available.
    Please require the latest intltool that exists. Intltool releases
    are pretty stable and often only contains bugfixes.

    AM_WITH_NLS adds native language support to automake, together
    with a compile option.

    AM_GLIB_GNU_GETTEXT will check for additional required functions and
    programs and will finally create po/POTFILES during configure.

    Instead of using AM_GLIB_GNU_GETTEXT you can do the following:

    [sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile] 

    The text domain is identified by PACKAGE.  We will need to add a few
    functions later on to helloworld.c that will use this #define'd variable.

    Also, this will be the base filename for all your translation files, 
    so make sure you choose a unique one.

13.  Run 
       aclocal 
     to make sure that the necessary autoconf and automake macros
     are inserted in aclocal.m4

     Run 
       autoconf 
     to create the configure script.

15. in the source directory add a i18n-support.h file

    touch src/i18n-support.h

16. And fill it up with contents :

/*
 * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation
 * All rights reserved.
 *
 * The program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this program; see the file COPYING.LIB.  If not,
 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */
/*
  @NOTATION@
 */

/*
 * Handles all of the internationalization configuration options.
 * Author: Tom Tromey <tromey@creche.cygnus.com>
 */

#ifndef __I18N_SUPPORT_H__
#define __I18N_SUPPORT_H__

#include <config.h>

#ifdef ENABLE_NLS
#    include <libintl.h>
#    ifdef EXPLICIT_TRANSLATION_DOMAIN
#        undef _
#        define _(String) dgettext (EXPLICIT_TRANSLATION_DOMAIN, String)
#    else 
#        define _(String) gettext (String)
#    endif
#    ifdef gettext_noop
#        define N_(String) gettext_noop (String)
#    else
#        define N_(String) (String)
#    endif
#else
/* Stubs that do something close enough.  */
#    define textdomain(String) (String)
#    define gettext(String) (String)
#    define dgettext(Domain,Message) (Message)
#    define dcgettext(Domain,Message,Type) (Message)
#    define bindtextdomain(Domain,Directory) (Domain)
#    define _(String) (String)
#    define N_(String) (String)
#endif

#endif /* __I18N_SUPPORT_H__ */

17. Now add the following to helloworld.c

    #include <i18n-support.h>
/* includes used by original program here */    

    int main(void) {

	    setlocale (LC_ALL, "");
            bindtextdomain (PACKAGE, LOCALEDIR);
            textdomain (PACKAGE);

            /* 
             * Original Helloworld code here
             */
    }

    If you use GNOME og GTK+ the setlocale sentence shouldn't be needed

    We also substitute all strings we want to be translated with 
    _("original string") to make sure that gettext is run on the strings.
    So the printf now looks like

      printf (_("Hello, world!\n"));

18. We create src/Makefile.am (from which Makefile.in and Makefile will be
    generated)

    INCLUDES = -I$(top_srcdir) -I$(includedir) -I$(top_srcdir)/intl \
               -DLOCALEDIR=\""$(datadir)/locale"\"

    bin_PROGRAMS = helloworld

    helloworld_SOURCES = helloworld.c
    noinst_HEADERS = i18n-support.h

19. Now we create the following toplevel Makefile.am

     SUBDIRS = src po intl

     EXTRA_DIST = intltool-extract.in intltool-merge.in intltool-update.in

14. Go into the directory po/ and create POTFILES.in
    This file should contain a list of all the files in your distribution
    (starting from the top, one level above the po dir) that contain
    strings to be internationalized.

    For the helloworld sample, it would contain
    src/helloworld.c

    Run 
      intltool-update --pot

    Run
      intltool-update --maintain 
    to see if you are missing files that contain marked strings.  
    You should consider adding these to POTFILES.in

    FIXME: I get the following error on my system :
    mismatched quotes at line 353 in ../intl/plural.c


21. Now we start making a Danish and Dutch translation

    cp helloworld.pot da.po
    cp helloworld.pot nl.po

    intltool-update da
    intltool-update nl

    edit and update da.po and nl.po
    (The respective translations are "Hej verden" and "Hallo wereld")
    
20. Now we can compile.  We will test it later, so we will install it in
    a temporary location.
    Close your eyes and type 
      ./configure --prefix=/tmp/helloworld && make 
    in the toplevel directory. :-)

22. To test if it works, you have to install the package.
    Run
      make install
    in the toplevel directory.

23. Now set the environment variable LC_ALL to your preferred language :
      export LC_ALL=nl_NL
      /tmp/helloworld/bin/helloworld
      export LC_ALL=nl_DK
      /tmp/helloworld/bin/helloworld

    And if all goes well, the string should be translated in the two languages.

24. To finish it all up, run
      make dist
    to create a distributable tarball containing your internationalized
    program.

25. Exercises :
    - add another language

