po2c - Gettext language files to C source code converter
po2c {.po files} > source.c
po2c is a Perl script that takes a bunch of gettext (.po) language translation files from its command line arguments and dumps a C source code file containing all those messages and the necessary functions to use them without any other dependency. This is useful when you want to deploy .po translated strings to systems where no easy gettext support exist (for example, win32) or when a unique, self-contained binary without external file dependencies is convenient (for example, embedded or small systems).
The resulting C source code file include the original and translated messages as a group of static, NULL terminated pointer-to-string arrays and the following two C functions:
void po2c_setlang(char * lang); char * po2c_gettext(char * msgid);
The first one, po2c_setlang(), is used to set the user favourite language,
probably got from him or read from any of the LANG, LC_ALL or LC_MESSAGES
environment variables. the processed .po files' names must match those
language strings.
The second one, po2c_gettext(), is exactly orthogonal to the original
gettext() function; the msgid is the character string to translate. It
returns the translated string if found, or the same msgid otherwise.
Suppose you have a directory named po and the following two files, po/es.po:
#spanish translations msgid "Good morning!" msgstr "?Buenos d?as!"
and po/fr.po:
#french translations msgid "Good morning!" msgstr "Bon jour!"
Then running the following command:
po2c po/*.po > lang.c
Will result in the following lang.c C source file:
/* generated by po2c 1.0.2 - Do not modify */
#include <stdio.h>
#include <string.h>
static char * _po2c_msgids[] = {
/* 0 */ "Good morning!",
NULL
};
struct _po2c_msg {
int msgid;
char * msgstr;
};
static struct _po2c_msg _po2c_lang_fr[] = {
{ 0, "Bon jour!" },
{ -1, NULL }
};
static struct _po2c_msg _po2c_lang_es[] = {
{ 0, "?Buenos d?as!" },
{ -1, NULL }
};
static struct {
char * lang;
struct _po2c_msg * msgs;
} _po2c_langs[] = {
{ "fr", _po2c_lang_fr },
{ "es", _po2c_lang_es },
{ NULL, NULL }
};
/* code */
static struct _po2c_msg * _po2c_lang=NULL;
static int _po2c_lang_size=0;
void po2c_setlang(char * lang)
{
int n;
_po2c_lang=NULL;
_po2c_lang_size=0;
/* if lang is NULL or "", deactivate it */
if(lang == NULL || *lang == '\0')
return;
/* searches for a valid language array */
for(n=0;_po2c_lang == NULL && _po2c_langs[n].lang != NULL;n++)
{
if(strcmp(lang, _po2c_langs[n].lang) == 0)
_po2c_lang=_po2c_langs[n].msgs;
}
/* try partial searches */
for(n=0;_po2c_lang == NULL && _po2c_langs[n].lang != NULL;n++)
{
if(strncmp(lang, _po2c_langs[n].lang, 2) == 0)
_po2c_lang=_po2c_langs[n].msgs;
}
/* if found, count entries */
if(_po2c_lang != NULL)
{
struct _po2c_msg * m;
for(m=_po2c_lang;m->msgid != -1;m++)
_po2c_lang_size++;
}
}
char * po2c_gettext(char * msgid)
{
struct _po2c_msg * m;
int b, t, n, c;
/* if no language is set or msgid is empty, return msgid as is */
if(_po2c_lang == NULL || *msgid == '\0')
return(msgid);
/* binary-search for the msgid */
b=0; t=_po2c_lang_size - 1;
while(t >= b)
{
n=(b + t) / 2;
m=&_po2c_lang[n];
c=strcmp(msgid, _po2c_msgids[m->msgid]);
if(c == 0)
return(m->msgstr);
else
if(c < 0)
t=n - 1;
else
b=n + 1;
}
return(msgid);
}
You can compile and link it against your code. There, you'll add the function prototypes and use them.
Note that po2c is an incomplete solution; though it works, there is no support for specifying each language translation's character encoding, so you're on your own on this issue. It has proven well with western language .po files in ISO-8859-1, but will catastrophically fail if you have greek, chinese or russian .po files unless you provide some kind of character set detection outside this code.
po2c has been written by Angel Ortega <angel@triptico.com>.
See http://www.triptico.com/software/po2c.html for updates.
This program is free software; you can redistribute it and/or modify it under the terms of the GNU 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 General Public License for more details.