Internacionalização (I18n) com Autotools
Explicarei como internacionalizar, ou seja, tornar um programa traduzível.
Tomarei como exemplo o projeto hello-world do post anterior.
Você pode baixar o pacote final do projeto do post anterior em http://dl.getdropbox.com/u/1671797/Blog/hello-world-0.2.0.tar.gz.
Será necessário as seguintes ferramentas: intltool e gettext.
Adicione o seguinte código no arquivo configure.ac:
# Checks for libraries.
PKG_CHECK_MODULES([DEPS],[glib-2.0]) (1)
AC_SUBST(DEPS_CFLAGS) (2)
AC_SUBST(DEPS_LIBS) (3)
# -------------------------------------------------
# Internationalization
# -------------------------------------------------
GETTEXT_PACKAGE=hello-world (4)
AC_SUBST(GETTEXT_PACKAGE) (5)
AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE], ["$GETTEXT_PACKAGE"],
[the gettext translation domain]) (6)
AM_GLIB_GNU_GETTEXT (7)
GLIB_DEFINE_LOCALEDIR(HELLO_WORLD_LOCALEDIR) (8)
IT_PROG_INTLTOOL([0.35.1]) (9)
# -------------------------------------------------
# Check OS-specific platform
1 | Procura pela biblioteca glib-2.0 e define as variáveis DEPS_CFLAGS e DEPS_LIBS (detalhes abaixo). Caso a biblioteca não seja encontrada é retornado um erro. |
2 | Faz com que @DEPS_CFLAGS@ ou $(DEPS_CFLAGS), nos arquivos de saída do autoconf, seja substituído pelo valor da variável. |
3 | O mesmo que o comando acima, mas com a variável DEPS_LIBS. |
4 | Está sendo definida uma variável local. |
5 | O mesmo que as macros AC_SUBST acima, mas com a variável GETTEXT_PACKAGE. |
6 | Igual a macro AC_DEFINE com o diferencial de expandir expressões de shell (ver "Definindo símbolos"). Define, no arquivo config.h, o símbolo GETTEXT_PACKAGE com o valor da variável GETTEXT_PACKAGE. |
7 | Faz verificações se o gettext pode ser usado, define o símbolo HAVE_GETTEXT no arquivo config.h entre outros. |
8 | Define o nome do símbolo que conterá o caminho do diretório de localização. É o caminho do diretório de onde os catálogos de mensagens de cada língua será instalado. |
9 | Faz verificações se o intltool pode ser usado e define a versão mínima necessária. |
Ainda no arquivo configure.ac adicione o arquivo "po/Makefile.in" em AC_CONFIG_FILES. Desta maneira o arquivo Makefile que será criado no diretório po fará parte da compilação.
AC_CONFIG_FILES([Makefile
src/Makefile
po/Makefile.in])
Para que se possa fazer o uso da biblioteca glib-2.0 é necessário indicar ao compilador onde achar os arquivos de cabeçalho e os objetos de ligação. Para isso é necessário modificar o arquivo Makefile.am como abaixo:
bin_PROGRAMS = hello-world
hello_world_SOURCES = main.cpp
if OS_WIN32
hello_world_SOURCES += windowsdef.h
endif
hello_world_LDADD = $(DEPS_LIBS) (1)
hello_world_CXXFLAGS = $(DEPS_CFLAGS) (2)
1 | DEPS_LIBS é a variável com os caminhos para os objetos de ligação. Esses objetos têm a listagem e endereçamento de cada função. |
2 | DEPS_CFLAGS é a variável com os caminhos para os arquivos de cabeçalho. |
Crie o diretório po no diretório raíz do projeto, este diretório conterá os catálogos de cada língua.
Crie um arquivo vazio com o nome LINGUAS, neste arquivo será listado os códigos de cada idioma com suporte.
Crie um arquivo vazio com o nome POTFILES.in, neste arquivo será listado todos os arquivos com mensagens traduzíveis.
No arquivo Makefile.am do diretório raíz do projeto adicione o diretório po em SUBDIRS.
SUBDIRS = src po
É necessário adicionar os scripts de internacionalização ao pacote de distribuição, para isso adicione o código abaixo ao arquivo Makefile.am do diretório raíz.
SUBDIRS = src po
INTLTOOL_FILES = \ (1)
intltool-extract.in \
intltool-merge.in \
intltool-update.in
EXTRA_DIST = \ (2)
$(INTLTOOL_FILES)
DISTCLEANFILES = \ (3)
intltool-extract \
intltool-merge \
intltool-update \
po/.intltool-merge-cache
1 | INTLTOOL_FILES é uma variável com a lista de scripts usados pelo intltool. |
2 | EXTRA_DIST define arquivos adicionais que serão adicionados ao pacote de distribuição. |
3 | DISTCLEANFILES define os arquivos adicionais que serão removidos pelo comando "make distclean". |
Para atualizar os scripts com as mudanças execute o comando "autoreconf".
Para preparar o projeto para o intltool, execute o comando "intltoolize" no diretório raíz do projeto.
Agora é necessário inicializar o libintl e marcar as strings como traduzíveis. Para isso modifique o arquivo main.cpp como a seguir:
#ifdef HAVE_CONFIG_H
#include <config.h> (1)
#endif
#ifdef WINNT
#include "windowsdef.h"
#endif
#include <iostream>
#include <glib/gi18n.h> (2)
int main()
{
// Gettext initialization
setlocale(LC_ALL, ""); (3)
bindtextdomain(GETTEXT_PACKAGE, HELLO_WORLD_LOCALEDIR); (4)
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); (5)
textdomain(GETTEXT_PACKAGE); (6)
std::cout << _("Hello World!") << std::endl; (7)
return 0;
}
1 | Para usar os símbolos GETTEXT_PACKAGE e HELLO_WORLD_LOCALEDIR é necessário incluir o cabeçalho config.h. |
2 | O cabeçalho gi18n.h inclui o cabeçalho libintl.h, que contém as funções de internacionalização, e define símbolos comumente usados na internacionalização. |
3 | A função setlocale() define a localização atual que será usada pelo gettext. |
4 | A função bindtextdomain() define o caminho do catálogo de GETTEXT_PACKAGE para HELLO_WORLD_LOCALEDIR. |
5 | A função bind_textdomain_codeset() define a codificação das mensagens do catálogo de GETTEXT_PACKAGE para UTF-8. |
6 | A função textdomain() define o catálogo de mensagens padrão para GETTEXT_PACKAGE. |
7 | A função _() é um símbolo que foi definido pelo gi18n.h que é um apelido para a função gettext() do cabeçalho libintl.h. |
Agora o projeto está pronto para ser traduzido (localizado).
O pacote final pode ser acessado neste link: http://dl.getdropbox.com/u/1671797/Blog/hello-world-0.3.0.tar.gz.
Referências
Definindo símbolos: http://www.gnu.org/software/hello/manual/autoconf/Defining-Symbols.html
Internacionalização: http://www.gtkmm.org/docs/gtkmm-2.4/docs/tutorial/html/chapter-internationalization.html
pkg-config: http://pkg-config.freedesktop.org/