From 0f3e3c9e3821efae35c25abbb65522955d4ede3b Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 16 May 2018 21:58:02 +0200 Subject: [PATCH] po file exporter, also for messages. --- src/bindings.c | 21 ++++++++++++++ src/util/language.c | 67 ++++++++++++++++++++++++++++++++++++++++++++ src/util/language.h | 5 ++++ src/util/nrmessage.c | 11 ++++++++ src/util/nrmessage.h | 2 ++ 5 files changed, 106 insertions(+) diff --git a/src/bindings.c b/src/bindings.c index bbea46e60..276fe1dd4 100755 --- a/src/bindings.c +++ b/src/bindings.c @@ -56,6 +56,7 @@ #include #include #include +#include #include #include #include @@ -913,6 +914,25 @@ static int lua_rng_default(lua_State *L) { return 0; } +static void export_locale(const struct locale *lang, const char *name) { + char fname[64]; + FILE * F; + + sprintf(fname, "strings.%s.po", name); + F = fopen(fname, "wt"); + if (F) { + export_strings(lang, F); + export_messages(lang, F); + fclose(F); + } +} + +static int tolua_export_locales(lua_State *L) { + UNUSED_ARG(L); + locale_foreach(export_locale); + return 0; +} + void tolua_bind_open(lua_State * L); int tolua_bindings_open(lua_State * L, const dictionary *inifile) @@ -1030,6 +1050,7 @@ int tolua_bindings_open(lua_State * L, const dictionary *inifile) tolua_function(L, TOLUA_CAST "spells", tolua_get_spells); tolua_function(L, TOLUA_CAST "read_xml", tolua_read_xml); tolua_function(L, TOLUA_CAST "equip_newunits", tolua_equip_newunits); + tolua_function(L, TOLUA_CAST "export_locales", tolua_export_locales); } tolua_endmodule(L); return 1; } diff --git a/src/util/language.c b/src/util/language.c index 52d934beb..c0e8fe55d 100644 --- a/src/util/language.c +++ b/src/util/language.c @@ -221,6 +221,66 @@ void locale_setstring(locale * lang, const char *key, const char *value) } } +static const char *escape_str(const char *in, FILE *F) { + while (*in) { + char buffer[64]; + size_t len = 0; + char *out = buffer; + while (sizeof(buffer) > len + 2) { + if (*in == '\0') break; + if (strchr("\\\"", *in) != NULL) { + *out++ = '\\'; + ++len; + } + *out++ = *in++; + ++len; + } + if (len > 0) { + fwrite(buffer, 1, len, F); + } + } + return in; +} + +void po_write_msg(FILE *F, const char *id, const char *str, const char *ctxt) { + if (ctxt) { + fputs("msgctxt \"", F); + escape_str(ctxt, F); + fputs("\"\nmsgid \"", F); + escape_str(id, F); + } + else { + fputs("msgid \"", F); + escape_str(id, F); + } + fputs("\"\nmsgstr \"", F); + escape_str(str, F); + fputs("\"\n\n", F); +} + +void export_strings(const struct locale * lang, FILE *F) { + int i; + + for (i = 0; i != SMAXHASH; ++i) { + const struct locale_str *find = lang->strings[i]; + while (find) { + const char *dcolon = strstr(find->key, "::"); + if (dcolon) { + size_t len = dcolon - find->key; + char ctxname[16]; + assert(sizeof(ctxname) > len); + memcpy(ctxname, find->key, len); + ctxname[len] = '\0'; + po_write_msg(F, dcolon + 2, find->str, ctxname); + } + else { + po_write_msg(F, find->key, find->str, NULL); + } + find = find->nexthash; + } + } +} + const char *locale_name(const locale * lang) { return lang ? lang->name : "(null)"; @@ -316,6 +376,13 @@ void *get_translation(const struct locale *lang, const char *str, int index) { return NULL; } +void locale_foreach(void(*callback)(const struct locale *, const char *)) { + const locale * lang; + for (lang = locales; lang; lang = lang->next) { + callback(lang, lang->name); + } +} + const char *localenames[] = { "de", "en", NULL diff --git a/src/util/language.h b/src/util/language.h index 36bc58378..155fea9c8 100644 --- a/src/util/language.h +++ b/src/util/language.h @@ -20,6 +20,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #define MY_LOCALE_H #include +#include #ifdef __cplusplus extern "C" { @@ -56,6 +57,10 @@ extern "C" { void make_locales(const char *str); + void locale_foreach(void(*callback)(const struct locale *lang, const char *name)); + void export_strings(const struct locale * lang, FILE *F); + void po_write_msg(FILE *F, const char *id, const char *str, const char *ctxt); + #define LOC(lang, s) (lang?locale_string(lang, s, true):s) enum { diff --git a/src/util/nrmessage.c b/src/util/nrmessage.c index 376731713..0f8dbb9d0 100644 --- a/src/util/nrmessage.c +++ b/src/util/nrmessage.c @@ -190,3 +190,14 @@ void free_nrmesssages(void) { } } } + +void export_messages(const struct locale * lang, FILE *F) { + int i; + for (i = 0; i != NRT_MAXHASH; ++i) { + nrmessage_type *nrt = nrtypes[i]; + while (nrt) { + po_write_msg(F, nrt->mtype->name, nrt->string, "message"); + nrt = nrt->next; + } + } +} diff --git a/src/util/nrmessage.h b/src/util/nrmessage.h index 6cc02bfe2..7234d5b2a 100644 --- a/src/util/nrmessage.h +++ b/src/util/nrmessage.h @@ -14,6 +14,7 @@ #define H_UTIL_NRMESSAGE #include +#include #ifdef __cplusplus extern "C" { @@ -46,6 +47,7 @@ extern "C" { int nr_level(const struct message *msg); const char *nr_section(const struct message *msg); + void export_messages(const struct locale * lang, FILE *F); /* before: * fogblock;movement:0;de;{unit} konnte von {region} nicht nach {$dir direction} ausreisen, der Nebel war zu dicht. * after: