wmc: Add support for generating message translations based on po files.
This commit is contained in:
parent
196ffdf671
commit
72921af40b
141
tools/wmc/po.c
141
tools/wmc/po.c
|
@ -435,6 +435,143 @@ void write_pot_file( const char *outname )
|
|||
po_file_free( po );
|
||||
}
|
||||
|
||||
static lan_blk_t *new_top, *new_tail;
|
||||
|
||||
static lanmsg_t *translate_string( po_file_t po, lanmsg_t *str, int lang, int *found )
|
||||
{
|
||||
po_message_t msg;
|
||||
po_message_iterator_t iterator;
|
||||
lanmsg_t *new;
|
||||
const char *transl;
|
||||
int res;
|
||||
char *buffer, *msgid, *context;
|
||||
|
||||
if (str->len <= 1 || !(buffer = convert_msgid_ascii( str, 0 ))) return str;
|
||||
|
||||
msgid = buffer;
|
||||
context = get_message_context( &msgid );
|
||||
msg = find_message( po, msgid, context, &iterator );
|
||||
po_message_iterator_free( iterator );
|
||||
|
||||
if (msg && !po_message_is_fuzzy( msg ))
|
||||
{
|
||||
transl = po_message_msgstr( msg );
|
||||
if (!transl[0]) transl = msgid; /* ignore empty strings */
|
||||
else (*found)++;
|
||||
}
|
||||
else transl = msgid;
|
||||
|
||||
new = xmalloc( sizeof(*new) );
|
||||
new->lan = lang;
|
||||
new->cp = 0; /* FIXME */
|
||||
new->file = str->file;
|
||||
new->line = str->line;
|
||||
new->len = wine_utf8_mbstowcs( 0, transl, strlen(transl) + 1, NULL, 0 );
|
||||
new->msg = xmalloc( new->len * sizeof(WCHAR) );
|
||||
res = wine_utf8_mbstowcs( MB_ERR_INVALID_CHARS, transl, strlen(transl) + 1, new->msg, new->len );
|
||||
if (res == -2)
|
||||
error( "Invalid utf-8 character in string '%s'\n", transl );
|
||||
free( buffer );
|
||||
return new;
|
||||
}
|
||||
|
||||
static void translate_block( po_file_t po, block_t *blk, block_t *new, int lang, int *found )
|
||||
{
|
||||
int i;
|
||||
|
||||
new->idlo = blk->idlo;
|
||||
new->idhi = blk->idhi;
|
||||
new->size = 0;
|
||||
new->msgs = xmalloc( blk->nmsg * sizeof(*new->msgs) );
|
||||
new->nmsg = blk->nmsg;
|
||||
for (i = 0; i < blk->nmsg; i++)
|
||||
{
|
||||
new->msgs[i] = translate_string( po, blk->msgs[i], lang, found );
|
||||
new->size += ((2 * new->msgs[i]->len + 3) & ~3) + 4;
|
||||
}
|
||||
}
|
||||
|
||||
static void translate_messages( po_file_t po, int lang )
|
||||
{
|
||||
int i, found;
|
||||
lan_blk_t *lbp, *new;
|
||||
|
||||
for (lbp = lanblockhead; lbp; lbp = lbp->next)
|
||||
{
|
||||
if (!is_english( lbp->lan )) continue;
|
||||
found = 0;
|
||||
new = xmalloc( sizeof(*new) );
|
||||
/* English "translations" take precedence over the original contents */
|
||||
new->version = is_english( lang ) ? 1 : -1;
|
||||
new->lan = lang;
|
||||
new->blks = xmalloc( lbp->nblk * sizeof(*new->blks) );
|
||||
new->nblk = lbp->nblk;
|
||||
|
||||
for (i = 0; i < lbp->nblk; i++)
|
||||
translate_block( po, &lbp->blks[i], &new->blks[i], lang, &found );
|
||||
if (found)
|
||||
{
|
||||
if (new_tail) new_tail->next = new;
|
||||
else new_top = new;
|
||||
new->prev = new_tail;
|
||||
new_tail = new;
|
||||
}
|
||||
else
|
||||
{
|
||||
free( new->blks );
|
||||
free( new );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void add_translations( const char *po_dir )
|
||||
{
|
||||
lan_blk_t *lbp;
|
||||
po_file_t po;
|
||||
char buffer[256];
|
||||
char *p, *tok, *name;
|
||||
unsigned int i;
|
||||
FILE *f;
|
||||
|
||||
/* first check if we have English resources to translate */
|
||||
for (lbp = lanblockhead; lbp; lbp = lbp->next) if (is_english( lbp->lan )) break;
|
||||
if (!lbp) return;
|
||||
|
||||
new_top = new_tail = NULL;
|
||||
|
||||
name = strmake( "%s/LINGUAS", po_dir );
|
||||
if (!(f = fopen( name, "r" ))) return;
|
||||
free( name );
|
||||
while (fgets( buffer, sizeof(buffer), f ))
|
||||
{
|
||||
if ((p = strchr( buffer, '#' ))) *p = 0;
|
||||
for (tok = strtok( buffer, " \t\r\n" ); tok; tok = strtok( NULL, " \t\r\n" ))
|
||||
{
|
||||
for (i = 0; i < sizeof(languages)/sizeof(languages[0]); i++)
|
||||
if (!strcmp( tok, languages[i].name )) break;
|
||||
|
||||
if (i == sizeof(languages)/sizeof(languages[0]))
|
||||
error( "unknown language '%s'\n", tok );
|
||||
|
||||
name = strmake( "%s/%s.po", po_dir, tok );
|
||||
if (!(po = po_file_read( name, &po_xerror_handler )))
|
||||
error( "cannot load po file for language '%s'\n", tok );
|
||||
translate_messages( po, MAKELANGID(languages[i].id, languages[i].sub) );
|
||||
po_file_free( po );
|
||||
free( name );
|
||||
}
|
||||
}
|
||||
fclose( f );
|
||||
|
||||
/* prepend the translated messages to the global list */
|
||||
if (new_tail)
|
||||
{
|
||||
new_tail->next = lanblockhead;
|
||||
lanblockhead->prev = new_tail;
|
||||
lanblockhead = new_top;
|
||||
}
|
||||
}
|
||||
|
||||
#else /* HAVE_LIBGETTEXTPO */
|
||||
|
||||
void write_pot_file( const char *outname )
|
||||
|
@ -442,4 +579,8 @@ void write_pot_file( const char *outname )
|
|||
error( "PO files not supported in this wmc build\n" );
|
||||
}
|
||||
|
||||
void add_translations( const char *po_dir )
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -49,6 +49,7 @@ static const char usage[] =
|
|||
" -i Inline messagetable(s)\n"
|
||||
" -o file Output to file (default is inputfile.rc)\n"
|
||||
" -O fmt Set output format (rc, res, pot)\n"
|
||||
" -P dir Directory where to find po files\n"
|
||||
" -u Inputfile is in unicode\n"
|
||||
" -U Output unicode messagetable(s)\n"
|
||||
" -v Show supported codepages and languages\n"
|
||||
|
@ -104,6 +105,8 @@ int rcinline = 0;
|
|||
*/
|
||||
static int dodebug = 0;
|
||||
|
||||
static char *po_dir;
|
||||
|
||||
char *output_name = NULL; /* The name given by the -o option */
|
||||
char *input_name = NULL; /* The name given on the command-line */
|
||||
char *header_name = NULL; /* The name given by the -H option */
|
||||
|
@ -173,7 +176,7 @@ int main(int argc,char *argv[])
|
|||
strcat(cmdline, " ");
|
||||
}
|
||||
|
||||
while((optc = getopt(argc, argv, "B:cdDhH:io:O:p:uUvVW")) != EOF)
|
||||
while((optc = getopt(argc, argv, "B:cdDhH:io:O:P:uUvVW")) != EOF)
|
||||
{
|
||||
switch(optc)
|
||||
{
|
||||
|
@ -229,6 +232,9 @@ int main(int argc,char *argv[])
|
|||
lose++;
|
||||
}
|
||||
break;
|
||||
case 'P':
|
||||
po_dir = xstrdup( optarg );
|
||||
break;
|
||||
case 'u':
|
||||
unicodein = 1;
|
||||
break;
|
||||
|
@ -319,6 +325,7 @@ int main(int argc,char *argv[])
|
|||
write_bin_files();
|
||||
break;
|
||||
case FORMAT_RES:
|
||||
if (po_dir) add_translations( po_dir );
|
||||
write_res_file( output_name );
|
||||
break;
|
||||
case FORMAT_POT:
|
||||
|
|
|
@ -52,6 +52,12 @@ Output to \fIfile\fR. Default is \fIinputfile.rc\fR.
|
|||
Set the output format. Supported formats are \fBrc\fR (the default),
|
||||
\fBres\fR, and \fBpot\fR.
|
||||
.TP
|
||||
.BI \-P\ directory
|
||||
Enable the generation of resource translations based on po files
|
||||
loaded from the specified directory. That directory must follow the
|
||||
gettext convention, in particular in must contain one .po file for
|
||||
each language, and a LINGUAS file listing the available languages.
|
||||
.TP
|
||||
.B \-u
|
||||
Assume that the inputfile is in unicode.
|
||||
.TP
|
||||
|
|
|
@ -117,6 +117,7 @@ typedef struct lan_blk {
|
|||
struct lan_blk *next; /* Linkage for languages */
|
||||
struct lan_blk *prev;
|
||||
int lan; /* The language of this block */
|
||||
int version; /* The resource version for auto-translated resources */
|
||||
block_t *blks; /* Array of blocks for this language */
|
||||
int nblk; /* Nr of blocks in array */
|
||||
} lan_blk_t;
|
||||
|
|
|
@ -620,7 +620,7 @@ void write_res_file( const char *name )
|
|||
put_dword( 0 ); /* DataVersion */
|
||||
put_word( 0x30 ); /* Memory options */
|
||||
put_word( lbp->lan ); /* Language */
|
||||
put_dword( 0 ); /* Version */
|
||||
put_dword( lbp->version ); /* Version */
|
||||
put_dword( 0 ); /* Characteristics */
|
||||
|
||||
output_bin_data( lbp );
|
||||
|
|
|
@ -25,5 +25,6 @@ void write_rc_file(const char *fname);
|
|||
void write_bin_files(void);
|
||||
void write_res_file( const char *name );
|
||||
void write_pot_file( const char *outname );
|
||||
void add_translations( const char *po_dir );
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue