Table of Contents
gtkmm applications can easily support multiple languages, including non-European languages such as Chinese and right-to-left languages such as Arabic. An appropriately-written and translated gtkmm application will use the appropriate language at runtime based on the user's environment.
You might not anticipate the need to support additional languages, but you can never rule it out. And it's easier to develop the application properly in the first place rather than retrofitting later.
The process of writing source code that allows for translation is called
internationalization
, often abbreviated to
i18n
. The Localization
process,
sometimes abbreviated as l10n
, provides translated text
for other languages, based on that source code.
The main activity in the internationalization process is finding strings seen by users and marking them for translation. You do not need to do it all at once - if you set up the necessary project infrastructure correctly then your application will work normally regardless of how many strings you've covered.
String literals should be typed in the source code in English, but surrounded by a macro. The gettext (or intltool) utility can then extract the marked strings for translation, and substitute the translated text at runtime.
Note | |
---|---|
In the instructions below we will assume that you will not be using
gettext directly, but
intltool, which was written specifically for
We also assume that you are using autotools (automake
and autoconf) to build your project (although
autotools is not recommended for new applications), and
that you are using
|
Note | |
---|---|
If you are using meson (recommended), see the Localisation chapter in Meson's manual. You can then skip this section. |
An alternative to gnome-common's
autogen.sh
may look like this:
#! /bin/sh -e test -n "$srcdir" || srcdir=`dirname "$0"` test -n "$srcdir" || srcdir=. autoreconf --force --install --verbose --warnings=all "$srcdir" echo "Running intltoolize --copy --force --automake" intltoolize --copy --force --automake test -n "$NOCONFIGURE" || "$srcdir/configure" "$@"
Create a sub-directory named po
in your project's root
directory. This directory will eventually contain all of your
translations. Within it, create a file named LINGUAS
and a file named POTFILES.in
. It is common practice to
also create a ChangeLog
file in the
po
directory so that translators can keep track of
translation changes.
LINGUAS
contains an alphabetically sorted list of codes
identifying the languages for which your program is translated (comment
lines starting with a #
are ignored). Each language
code listed in the LINGUAS
file must have a
corresponding .po
file. So, if your program has German
and Japanese translations, your LINGUAS
file would
look like this:
# keep this file sorted alphabetically, one language code per line de ja
(In addition, you'd have the files de.po
and
ja.po
in your
po
directory which contain the German and Japanese
translations, respectively.)
POTFILES.in
is a list of paths to all files which
contain strings marked up for translation, starting from the project root
directory. So for example, if your project sources were located in a
subdirectory named src
, and you had two files that
contained strings that should be translated, your
POTFILES.in
file might look like this:
src/main.cc src/other.cc
If you are using gettext directly, you can only
mark strings for translation if they are in source code file. However, if
you use intltool, you can mark strings for
translation in a variety of other file formats, including
.ui
files, xml,
.desktop files
and several more. So, if you have designed some of the
application UI in xml files then also add your
.ui
files to the list in
POTFILES.in
.
Now that there is a place to put your translations, you need to initialize
intltool and gettext.
Add the following code to your configure.ac
,
substituting 'programname' with the name of your program:
IT_PROG_INTLTOOL([0.35.0]) GETTEXT_PACKAGE=programname AC_SUBST(GETTEXT_PACKAGE) AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE], ["$GETTEXT_PACKAGE"], [The domain to use with gettext]) AM_GNU_GETTEXT([external]) AM_GNU_GETTEXT_VERSION([0.17]) PROGRAMNAME_LOCALEDIR=[${datadir}/locale] AC_SUBST(PROGRAMNAME_LOCALEDIR)
This PROGRAMNAME_LOCALEDIR
variable will be used later
in the Makefile.am
file, to define a macro that will be
used when you initialize gettext in your source
code.
AM_GLIB_GNU_GETTEXT
has been an alternative to
AM_GNU_GETTEXT
and AM_GNU_GETTEXT_VERSION
,
but AM_GLIB_GNU_GETTEXT
is now deprecated, and shall
not be used in new code.
In the top-level Makefile.am:
Add po
to the SUBDIRS
variable. Without this, your translations won't get built and
installed when you build the program
Define INTLTOOL_FILES
as:
INTLTOOL_FILES = intltool-extract.in \ intltool-merge.in \ intltool-update.in
Add INTLTOOL_FILES
to the
EXTRA_DIST
list of files. This ensures that when
you do a make dist, these files will be
included in the source tarball.
Update your DISTCLEANFILES
:
DISTCLEANFILES = ... intltool-extract \ intltool-merge \ intltool-update \ po/.intltool-merge-cache
Depending on the types of files that contain translatable strings, add code such as
desktopdir = $(datadir)/applications desktop_in_files = programname.desktop.in desktop_DATA = $(desktop_in_files:.desktop.in=.desktop) @INTLTOOL_DESKTOP_RULE@
In your src/Makefile.am
, update your
AM_CPPFLAGS
to add the following preprocessor macro
definition:
AM_CPPFLAGS = ... -DPROGRAMNAME_LOCALEDIR=\"${PROGRAMNAME_LOCALEDIR}\"
This macro will be used when you initialize gettext
in
your source code.