Back to Index

Maemo for mobile developers

Resources and localization

Table of contents

  1. Adding internationalization support to an application
  2. Internationalization support in source code

Adding internationalization support to an application

The Hello World application still does not support internationalization (i18n). To add internationalization support to the application, the build system created in the previous section must be modified as explained in the following instructions:

  1. Add the lines in red to the configure.ac file:

    AC_INIT(helloworld-i18n, 0.1)
    AC_PREREQ(2.59)
    
    AM_INIT_AUTOMAKE([1.7.9])
    AC_CONFIG_HEADERS([config.h])
    
    AC_GNU_SOURCE
    AC_CANONICAL_HOST
    AM_MAINTAINER_MODE
    
    AC_PROG_INSTALL
    AC_PROG_MAKE_SET
    AC_PROG_CXX
    
    hildondesktopentrydir=`pkg-config --variable=desktopentrydir osso-af-settings`
    AC_SUBST(hildondesktopentrydir)
    
    IT_PROG_INTLTOOL([0.35.0])
    GETTEXT_PACKAGE="$PACKAGE_NAME"
    AC_SUBST(GETTEXT_PACKAGE)
    AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE], ["$GETTEXT_PACKAGE"],
    		[The domain to use with gettext])
    AM_GLIB_GNU_GETTEXT
    HELLOWORLD_I18N_LOCALEDIR=[${datadir}/locale]
    AC_SUBST(HELLOWORLD_I18N_LOCALEDIR)
    AC_CONFIG_FILES([Makefile
    		src/Makefile
    		src/helloworld_i18n.desktop
    		po/Makefile.in])
    
    PKG_CHECK_MODULES(LIBHILDONMM, hildonmm >= 0.9.6)
    AC_SUBST(LIBHILDONMM_CFLAGS)
    AC_SUBST(LIBHILDONMM_LIBS)
    
    AC_OUTPUT
    
  2. Modify the makefile.am file:

    AUTOMAKE_OPTIONS = foreign
    
    SUBDIRS = src po
    
    INTLTOOL_FILES = intltool-extract.in \
                     intltool-merge.in \
                     intltool-update.in
    
    DISTCLEANFILES = intltool-extract \
                     intltool-merge \
                     intltool-update
    
    EXTRA_DIST = $(INTLTOOL_FILES) \
                 data/helloworld_i18n.png \
                 data/helloworld_i18n.26.png \
                 data/helloworld_i18n.40.png \
                 data/helloworld_i18n.links
    
    # Icon installation
    icondir = $(datadir)/icons/hicolor
    
    install-data-local:
    	$(mkinstalldirs) $(DESTDIR)$(icondir)/scalable/hildon; \
    	$(mkinstalldirs) $(DESTDIR)$(icondir)/26x26/hildon; \
    	$(mkinstalldirs) $(DESTDIR)$(icondir)/40x40/hildon; \
    	$(INSTALL_DATA) $(srcdir)/data/helloworld_i18n.png $(DESTDIR)$(icondir)/scalable/hildon/helloworld_i18n.png; \
    	$(INSTALL_DATA) $(srcdir)/data/helloworld_i18n.26.png $(DESTDIR)$(icondir)/26x26/hildon/helloworld_i18n.png; \
    	$(INSTALL_DATA) $(srcdir)/data/helloworld_i18n.40.png $(DESTDIR)$(icondir)/40x40/hildon/helloworld_i18n.png;
    
    uninstall-local:
    	rm $(DESTDIR)$(icondir)/scalable/hildon/helloworld_i18n.png; \
    	rm $(DESTDIR)$(icondir)/26x26/hildon/helloworld_i18n.png; \
    	rm $(DESTDIR)$(icondir)/40x40/hildon/helloworld_i18n.png;
    
  3. Now create the po directory. This is the standard name of the directory for storing the localized resource files:

    [sbox-SDK_ARMEL: ~] > mkdir po
    
  4. Create the following files in the po directory:
    1. ChangeLog, an empty file created only for compatibility reasons.

      [sbox-SDK_ARMEL: ~/po] > touch ChangeLog
      
    2. POTFILES.in, with the path of files with literal strings (one per line).

      [sbox-SDK_ARMEL: ~/po] > cat POTFILES.in
      src/main.cpp
      src/mywindow.cpp
      
    3. LINGUAS, with an entry per line for each supported language.

      [sbox-SDK_ARMEL: ~/po] > cat LINGUAS
      en_GB
      pt_BR
      
  5. Create a translation file (.po) for each language inside LINGUAS. In the root of your project, type the command:

    [sbox-SDK_ARMEL: ~] > xgettext -f po/POTFILES.in -C -a -o po/pt_BR.po
    

    This command will extract the translatable strings from source files in POTIFILES.in and create the pt_BR.po translation template. Fill the msgstr fields with the proper translation. Example:

    #: ../src/main.cpp:25
    msgid "osso_initialize() failed."
    msgstr "osso_initialize() falhou"
    

    Repeat this step for each language supported by your application.

  6. Now, run the following commands to create the internationalization scripts necessary to build your application with internationalization support.

    [sbox-SDK_ARMEL: ~] > intltoolize
    [sbox-SDK_ARMEL: ~] > autoreconf -i
    

    After this point, the process to compile your application remains the same as explained before, using the make command. The debian package creation method works normally with the upgraded build system.

Internationalization support in source code

The build system is ready for internationalization. Now you must add some lines to the source code. Every translatable string in the source file must be surrounded by the _("string") macro. This is necessary for the Application Framework to get the correct localized files. Note: GTK signals must not be translated. This sample shows the modifications (in red) needed to main.cpp.

#include "config.h"

#include <hildonmm.h>
#include <iostream>
#include <glibmm/i18n.h> /* Must be after <iostream> */

#include "mywindow.h"

int main(int argc, char *argv[])
{
        /* i18n initialization */
        bindtextdomain(GETTEXT_PACKAGE, HELLOWORLD_I18N_LOCALEDIR);
        bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
        textdomain(GETTEXT_PACKAGE);

        /* Initialize gtkmm and checks the arguments passed to your application */
        Gtk::Main main_loop(&argc, &argv);

        /* Initialize the hildomm libraries */
        Hildon::init();

        /* Initialize libosso environment */
        osso_context_t* osso_context = osso_initialize(PACKAGE_NAME, PACKAGE_VERSION, TRUE, 0);
        if(!osso_context)
                std::cerr << _("osso_initialize() failed.") << std::endl;

        /* Set the application name */
        Glib::set_application_name(PACKAGE_STRING);

        /* Create an object for the main Window and attach it to the program */
        MyWindow window;
	Hildon::Program::get_instance()->add_window(window);

        /* Begin the main application */
        main_loop.run(window);

        /* Clean the libosso environment */
        osso_deinitialize(osso_context);

        return 0;
}

Open mywindow.cpp and surround all translatables strings with _("string") macro. Remember to include the i18n.h header in each file using this macro.

#include <glibmm/i18n.h>
#include <gtkmm.h>
#include <hildonmm.h>

#include "mywindow.h"

/* Class constructor */
MyWindow::MyWindow() :
        m_item_exit(_("Exit")),
        m_item_helloworld(_("Say Hello"))
{
        /* Add items to the menu */
        m_main.append(m_item_helloworld);
        m_main.append(m_item_exit);
        m_main.show_all();

        /* Attach the menu object to the application */
        set_main_menu(m_main);

        /* Attach the callback function to signal handler */
        m_item_exit.signal_activate().connect(sigc::mem_fun(*this, &MyWindow::on_menu_quit));
        m_item_helloworld.signal_activate().connect(sigc::mem_fun(*this, &MyWindow::on_menu_helloworld));

        /* Make all menu widgets visible */
        show_all();
}

/* Class destructor */
MyWindow::~MyWindow()
{
}

/* Callback function for menu exit */
void MyWindow::on_menu_quit()
{
        /* Close the window */
        hide();
}

void MyWindow::on_menu_helloworld()
{
        /* Create and show a "Hello World" dialog */
        Hildon::Note helloworld_note(Hildon::NOTE_TYPE_INFORMATION, _("Hello World!"));
        helloworld_note.run();
}

The maemo "Hello World" source code with resources and localization is available here.

The application is now enabled for internationalization.

Adding more widgets