wrc: Load translations from mo files instead of po.
This commit is contained in:
parent
4215722988
commit
f4ec097c9b
|
@ -17,7 +17,7 @@ INCLUDES = -I$(srcdir) -I. -I$(top_srcdir)/include -I$(top_builddir)/include
|
||||||
ALLCFLAGS = $(INCLUDES) $(DEFS) $(DLLFLAGS) $(EXTRACFLAGS) $(CPPFLAGS) $(CFLAGS) $(MODCFLAGS)
|
ALLCFLAGS = $(INCLUDES) $(DEFS) $(DLLFLAGS) $(EXTRACFLAGS) $(CPPFLAGS) $(CFLAGS) $(MODCFLAGS)
|
||||||
ALLLINTFLAGS = $(INCLUDES) $(DEFS) $(LINTFLAGS)
|
ALLLINTFLAGS = $(INCLUDES) $(DEFS) $(LINTFLAGS)
|
||||||
IDLFLAGS = $(INCLUDES) $(DEFS) $(EXTRAIDLFLAGS)
|
IDLFLAGS = $(INCLUDES) $(DEFS) $(EXTRAIDLFLAGS)
|
||||||
RCFLAGS = --nostdinc --po-dir=$(top_srcdir)/po $(TARGETFLAGS) $(INCLUDES) $(DEFS) $(EXTRARCFLAGS)
|
RCFLAGS = --nostdinc $(PORCFLAGS) $(TARGETFLAGS) $(INCLUDES) $(DEFS) $(EXTRARCFLAGS)
|
||||||
|
|
||||||
IDL_GEN_C_SRCS = $(IDL_C_SRCS:.idl=_c.c) $(IDL_I_SRCS:.idl=_i.c) \
|
IDL_GEN_C_SRCS = $(IDL_C_SRCS:.idl=_c.c) $(IDL_I_SRCS:.idl=_i.c) \
|
||||||
$(IDL_P_SRCS:.idl=_p.c) $(IDL_S_SRCS:.idl=_s.c)
|
$(IDL_P_SRCS:.idl=_p.c) $(IDL_S_SRCS:.idl=_s.c)
|
||||||
|
@ -189,9 +189,9 @@ rsrc.pot: $(WRC)
|
||||||
msg.pot: $(WMC)
|
msg.pot: $(WMC)
|
||||||
$(LDPATH) $(WMC) -O pot -o $@ $(MC_SRCS)
|
$(LDPATH) $(WMC) -O pot -o $@ $(MC_SRCS)
|
||||||
|
|
||||||
$(MC_SRCS:.mc=.res): $(WMC) $(ALL_PO_FILES)
|
$(MC_SRCS:.mc=.res): $(WMC) $(ALL_MO_FILES)
|
||||||
$(RC_SRCS:.rc=.res): $(WRC)
|
$(RC_SRCS:.rc=.res): $(WRC)
|
||||||
$(PO_SRCS:.rc=.res): $(ALL_PO_FILES)
|
$(PO_SRCS:.rc=.res): $(ALL_MO_FILES)
|
||||||
|
|
||||||
# Misc. rules
|
# Misc. rules
|
||||||
|
|
||||||
|
|
|
@ -53,8 +53,8 @@ ICOTOOL = @ICOTOOL@
|
||||||
MSGFMT = @MSGFMT@
|
MSGFMT = @MSGFMT@
|
||||||
CROSSTARGET = @CROSSTARGET@
|
CROSSTARGET = @CROSSTARGET@
|
||||||
LINGUAS = @LINGUAS@
|
LINGUAS = @LINGUAS@
|
||||||
ALL_PO_FILES = $(LINGUAS:%=@top_srcdir@/po/%.po)
|
|
||||||
ALL_MO_FILES = $(LINGUAS:%=@top_builddir@/po/%.mo)
|
ALL_MO_FILES = $(LINGUAS:%=@top_builddir@/po/%.mo)
|
||||||
|
PORCFLAGS = @PORCFLAGS@
|
||||||
CROSSAR = $(CROSSTARGET)-ar
|
CROSSAR = $(CROSSTARGET)-ar
|
||||||
CROSSRANLIB = $(CROSSTARGET)-ranlib
|
CROSSRANLIB = $(CROSSTARGET)-ranlib
|
||||||
MKINSTALLDIRS = $(top_srcdir)/tools/mkinstalldirs -m 755
|
MKINSTALLDIRS = $(top_srcdir)/tools/mkinstalldirs -m 755
|
||||||
|
|
|
@ -604,6 +604,7 @@ ac_includes_default="\
|
||||||
|
|
||||||
ac_subst_vars='LTLIBOBJS
|
ac_subst_vars='LTLIBOBJS
|
||||||
LIBOBJS
|
LIBOBJS
|
||||||
|
PORCFLAGS
|
||||||
LINGUAS
|
LINGUAS
|
||||||
ALL_TEST_RESOURCES
|
ALL_TEST_RESOURCES
|
||||||
LDAPLIBS
|
LDAPLIBS
|
||||||
|
@ -15432,7 +15433,7 @@ then
|
||||||
@echo timestamp > \$@
|
@echo timestamp > \$@
|
||||||
|
|
||||||
ALL_POT_FILES =$ALL_POT_FILES
|
ALL_POT_FILES =$ALL_POT_FILES
|
||||||
\$(ALL_PO_FILES): \$(srcdir)/po/wine.pot
|
\$(LINGUAS:%=$srcdir/po/%.po): \$(srcdir)/po/wine.pot
|
||||||
msgmerge -q \$@ \$(srcdir)/po/wine.pot | msgattrib --no-obsolete -o \$@.new && mv \$@.new \$@
|
msgmerge -q \$@ \$(srcdir)/po/wine.pot | msgattrib --no-obsolete -o \$@.new && mv \$@.new \$@
|
||||||
\$(srcdir)/po/wine.pot: \$(ALL_POT_FILES)
|
\$(srcdir)/po/wine.pot: \$(ALL_POT_FILES)
|
||||||
msgcat -o \$@ \$(ALL_POT_FILES)"
|
msgcat -o \$@ \$(ALL_POT_FILES)"
|
||||||
|
@ -15440,7 +15441,11 @@ fi
|
||||||
|
|
||||||
if test "$MSGFMT" != false
|
if test "$MSGFMT" != false
|
||||||
then
|
then
|
||||||
|
PORCFLAGS="--po-dir=\$(top_builddir)/po"
|
||||||
|
|
||||||
wine_fn_append_rule ALL_MAKEFILE_DEPENDS "__builddeps__: \$(ALL_MO_FILES)"
|
wine_fn_append_rule ALL_MAKEFILE_DEPENDS "__builddeps__: \$(ALL_MO_FILES)"
|
||||||
|
else
|
||||||
|
LINGUAS=
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "x$enable_tools" != xno
|
if test "x$enable_tools" != xno
|
||||||
|
|
|
@ -3066,7 +3066,7 @@ then
|
||||||
@echo timestamp > \$[@]
|
@echo timestamp > \$[@]
|
||||||
|
|
||||||
ALL_POT_FILES =$ALL_POT_FILES
|
ALL_POT_FILES =$ALL_POT_FILES
|
||||||
\$(ALL_PO_FILES): \$(srcdir)/po/wine.pot
|
\$(LINGUAS:%=$srcdir/po/%.po): \$(srcdir)/po/wine.pot
|
||||||
msgmerge -q \$[@] \$(srcdir)/po/wine.pot | msgattrib --no-obsolete -o \$[@].new && mv \$[@].new \$[@]
|
msgmerge -q \$[@] \$(srcdir)/po/wine.pot | msgattrib --no-obsolete -o \$[@].new && mv \$[@].new \$[@]
|
||||||
\$(srcdir)/po/wine.pot: \$(ALL_POT_FILES)
|
\$(srcdir)/po/wine.pot: \$(ALL_POT_FILES)
|
||||||
msgcat -o \$[@] \$(ALL_POT_FILES)])
|
msgcat -o \$[@] \$(ALL_POT_FILES)])
|
||||||
|
@ -3074,7 +3074,10 @@ fi
|
||||||
|
|
||||||
if test "$MSGFMT" != false
|
if test "$MSGFMT" != false
|
||||||
then
|
then
|
||||||
|
AC_SUBST([PORCFLAGS],["--po-dir=\$(top_builddir)/po"])
|
||||||
WINE_APPEND_RULE([ALL_MAKEFILE_DEPENDS],[__builddeps__: \$(ALL_MO_FILES)])
|
WINE_APPEND_RULE([ALL_MAKEFILE_DEPENDS],[__builddeps__: \$(ALL_MO_FILES)])
|
||||||
|
else
|
||||||
|
LINGUAS=
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "x$enable_tools" != xno
|
if test "x$enable_tools" != xno
|
||||||
|
|
171
tools/wrc/po.c
171
tools/wrc/po.c
|
@ -19,6 +19,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "wine/port.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -43,6 +44,16 @@
|
||||||
|
|
||||||
static resource_t *new_top, *new_tail;
|
static resource_t *new_top, *new_tail;
|
||||||
|
|
||||||
|
struct mo_file
|
||||||
|
{
|
||||||
|
unsigned int magic;
|
||||||
|
unsigned int revision;
|
||||||
|
unsigned int count;
|
||||||
|
unsigned int msgid_off;
|
||||||
|
unsigned int msgstr_off;
|
||||||
|
/* ... rest of file data here */
|
||||||
|
};
|
||||||
|
|
||||||
static int is_english( const language_t *lan )
|
static int is_english( const language_t *lan )
|
||||||
{
|
{
|
||||||
return lan->id == LANG_ENGLISH && lan->sub == SUBLANG_DEFAULT;
|
return lan->id == LANG_ENGLISH && lan->sub == SUBLANG_DEFAULT;
|
||||||
|
@ -393,20 +404,6 @@ static const struct
|
||||||
|
|
||||||
#ifndef HAVE_LIBGETTEXTPO
|
#ifndef HAVE_LIBGETTEXTPO
|
||||||
|
|
||||||
static const char *get_msgstr( const char *msgid, const char *context, int *found )
|
|
||||||
{
|
|
||||||
if (context) (*found)++;
|
|
||||||
return msgid;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void load_po_file( const char *name )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void free_po_file(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_pot_file( const char *outname )
|
void write_pot_file( const char *outname )
|
||||||
{
|
{
|
||||||
error( "PO files not supported in this wrc build\n" );
|
error( "PO files not supported in this wrc build\n" );
|
||||||
|
@ -419,8 +416,6 @@ void write_po_files( const char *outname )
|
||||||
|
|
||||||
#else /* HAVE_LIBGETTEXTPO */
|
#else /* HAVE_LIBGETTEXTPO */
|
||||||
|
|
||||||
static po_file_t po_file;
|
|
||||||
|
|
||||||
static void po_xerror( int severity, po_message_t message,
|
static void po_xerror( int severity, po_message_t message,
|
||||||
const char *filename, size_t lineno, size_t column,
|
const char *filename, size_t lineno, size_t column,
|
||||||
int multiline_p, const char *message_text )
|
int multiline_p, const char *message_text )
|
||||||
|
@ -473,35 +468,6 @@ static po_message_t find_message( po_file_t po, const char *msgid, const char *m
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *get_msgstr( const char *msgid, const char *context, int *found )
|
|
||||||
{
|
|
||||||
const char *ret = msgid;
|
|
||||||
po_message_t msg;
|
|
||||||
po_message_iterator_t iterator;
|
|
||||||
|
|
||||||
msg = find_message( po_file, msgid, context, &iterator );
|
|
||||||
if (msg && !po_message_is_fuzzy( msg ))
|
|
||||||
{
|
|
||||||
ret = po_message_msgstr( msg );
|
|
||||||
if (!ret[0]) ret = msgid; /* ignore empty strings */
|
|
||||||
else (*found)++;
|
|
||||||
}
|
|
||||||
po_message_iterator_free( iterator );
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void load_po_file( const char *name )
|
|
||||||
{
|
|
||||||
if (!(po_file = po_file_read( name, &po_xerror_handler )))
|
|
||||||
error( "cannot load po file '%s'\n", name );
|
|
||||||
}
|
|
||||||
|
|
||||||
static void free_po_file(void)
|
|
||||||
{
|
|
||||||
po_file_free( po_file );
|
|
||||||
po_file = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void add_po_string( po_file_t po, const string_t *msgid, const string_t *msgstr,
|
static void add_po_string( po_file_t po, const string_t *msgid, const string_t *msgstr,
|
||||||
const language_t *lang )
|
const language_t *lang )
|
||||||
{
|
{
|
||||||
|
@ -820,6 +786,108 @@ void write_po_files( const char *outname )
|
||||||
|
|
||||||
#endif /* HAVE_LIBGETTEXTPO */
|
#endif /* HAVE_LIBGETTEXTPO */
|
||||||
|
|
||||||
|
static struct mo_file *mo_file;
|
||||||
|
|
||||||
|
static void byteswap( unsigned int *data, unsigned int count )
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
data[i] = data[i] >> 24 | (data[i] >> 8 & 0xff00) | (data[i] << 8 & 0xff0000) | data[i] << 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void load_mo_file( const char *name )
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
int res, fd;
|
||||||
|
|
||||||
|
fd = open( name, O_RDONLY | O_BINARY );
|
||||||
|
if (fd == -1) fatal_perror( "Failed to open %s", name );
|
||||||
|
fstat( fd, &st );
|
||||||
|
mo_file = xmalloc( st.st_size );
|
||||||
|
res = read( fd, mo_file, st.st_size );
|
||||||
|
if (res == -1) fatal_perror( "Failed to read %s", name );
|
||||||
|
else if (res != st.st_size) error( "Failed to read %s\n", name );
|
||||||
|
close( fd );
|
||||||
|
|
||||||
|
/* sanity checks */
|
||||||
|
|
||||||
|
if (st.st_size < sizeof(*mo_file))
|
||||||
|
error( "%s is not a valid .mo file\n", name );
|
||||||
|
if (mo_file->magic == 0xde120495)
|
||||||
|
byteswap( &mo_file->revision, 4 );
|
||||||
|
else if (mo_file->magic != 0x950412de)
|
||||||
|
error( "%s is not a valid .mo file\n", name );
|
||||||
|
if ((mo_file->revision >> 16) > 1)
|
||||||
|
error( "%s: unsupported file version %x\n", name, mo_file->revision );
|
||||||
|
if (mo_file->msgid_off >= st.st_size ||
|
||||||
|
mo_file->msgstr_off >= st.st_size ||
|
||||||
|
st.st_size < sizeof(*mo_file) + 2 * 8 * mo_file->count)
|
||||||
|
error( "%s: corrupted file\n", name );
|
||||||
|
|
||||||
|
if (mo_file->magic == 0xde120495)
|
||||||
|
{
|
||||||
|
byteswap( (unsigned int *)((char *)mo_file + mo_file->msgid_off), 2 * mo_file->count );
|
||||||
|
byteswap( (unsigned int *)((char *)mo_file + mo_file->msgstr_off), 2 * mo_file->count );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free_mo_file(void)
|
||||||
|
{
|
||||||
|
free( mo_file );
|
||||||
|
mo_file = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const char *get_mo_msgid( int index )
|
||||||
|
{
|
||||||
|
const char *base = (const char *)mo_file;
|
||||||
|
const unsigned int *offsets = (const unsigned int *)(base + mo_file->msgid_off);
|
||||||
|
return base + offsets[2 * index + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const char *get_mo_msgstr( int index )
|
||||||
|
{
|
||||||
|
const char *base = (const char *)mo_file;
|
||||||
|
const unsigned int *offsets = (const unsigned int *)(base + mo_file->msgstr_off);
|
||||||
|
return base + offsets[2 * index + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *get_msgstr( const char *msgid, const char *context, int *found )
|
||||||
|
{
|
||||||
|
int pos, res, min, max;
|
||||||
|
const char *ret = msgid;
|
||||||
|
char *id = NULL;
|
||||||
|
|
||||||
|
if (!mo_file) /* strings containing a context still need to be transformed */
|
||||||
|
{
|
||||||
|
if (context) (*found)++;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context) id = strmake( "%s%c%s", context, 4, msgid );
|
||||||
|
min = 0;
|
||||||
|
max = mo_file->count - 1;
|
||||||
|
while (min <= max)
|
||||||
|
{
|
||||||
|
pos = (min + max) / 2;
|
||||||
|
res = strcmp( get_mo_msgid(pos), msgid );
|
||||||
|
if (!res)
|
||||||
|
{
|
||||||
|
const char *str = get_mo_msgstr( pos );
|
||||||
|
if (str[0]) /* ignore empty strings */
|
||||||
|
{
|
||||||
|
ret = str;
|
||||||
|
(*found)++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (res > 0) max = pos - 1;
|
||||||
|
else min = pos + 1;
|
||||||
|
}
|
||||||
|
free( id );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static string_t *translate_string( string_t *str, int *found )
|
static string_t *translate_string( string_t *str, int *found )
|
||||||
{
|
{
|
||||||
string_t *new;
|
string_t *new;
|
||||||
|
@ -988,6 +1056,12 @@ void add_translations( const char *po_dir )
|
||||||
for (res = resource_top; res; res = res->next) if (is_english( res->lan )) break;
|
for (res = resource_top; res; res = res->next) if (is_english( res->lan )) break;
|
||||||
if (!res) return;
|
if (!res) return;
|
||||||
|
|
||||||
|
if (!po_dir) /* run through the translation process to remove msg contexts */
|
||||||
|
{
|
||||||
|
translate_resources( new_language( LANG_ENGLISH, SUBLANG_DEFAULT ));
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
new_top = new_tail = NULL;
|
new_top = new_tail = NULL;
|
||||||
|
|
||||||
name = strmake( "%s/LINGUAS", po_dir );
|
name = strmake( "%s/LINGUAS", po_dir );
|
||||||
|
@ -1008,15 +1082,16 @@ void add_translations( const char *po_dir )
|
||||||
if (i == sizeof(languages)/sizeof(languages[0]))
|
if (i == sizeof(languages)/sizeof(languages[0]))
|
||||||
error( "unknown language '%s'\n", tok );
|
error( "unknown language '%s'\n", tok );
|
||||||
|
|
||||||
name = strmake( "%s/%s.po", po_dir, tok );
|
name = strmake( "%s/%s.mo", po_dir, tok );
|
||||||
load_po_file( name );
|
load_mo_file( name );
|
||||||
translate_resources( new_language(languages[i].id, languages[i].sub) );
|
translate_resources( new_language(languages[i].id, languages[i].sub) );
|
||||||
free_po_file();
|
free_mo_file();
|
||||||
free( name );
|
free( name );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fclose( f );
|
fclose( f );
|
||||||
|
|
||||||
|
done:
|
||||||
/* prepend the translated resources to the global list */
|
/* prepend the translated resources to the global list */
|
||||||
if (new_tail)
|
if (new_tail)
|
||||||
{
|
{
|
||||||
|
|
|
@ -562,7 +562,7 @@ int main(int argc,char *argv[])
|
||||||
output_name = NULL;
|
output_name = NULL;
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
if (po_dir) add_translations( po_dir );
|
add_translations( po_dir );
|
||||||
|
|
||||||
/* Convert the internal lists to binary data */
|
/* Convert the internal lists to binary data */
|
||||||
resources2res(resource_top);
|
resources2res(resource_top);
|
||||||
|
|
|
@ -108,9 +108,9 @@ Enable pedantic warnings. Notably redefinition of #define statements can
|
||||||
be discovered with this option.
|
be discovered with this option.
|
||||||
.TP
|
.TP
|
||||||
.I \fB\-\-po-dir=\fIdir\fR
|
.I \fB\-\-po-dir=\fIdir\fR
|
||||||
Enable the generation of resource translations based on po files
|
Enable the generation of resource translations based on mo files
|
||||||
loaded from the specified directory. That directory must follow the
|
loaded from the specified directory. That directory must follow the
|
||||||
gettext convention, in particular in must contain one .po file for
|
gettext convention, in particular in must contain one .mo file for
|
||||||
each language, and a LINGUAS file listing the available languages.
|
each language, and a LINGUAS file listing the available languages.
|
||||||
.TP
|
.TP
|
||||||
.I \fB\-r\fR
|
.I \fB\-r\fR
|
||||||
|
|
Loading…
Reference in New Issue