diff options
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/HPMHooking/HPMHooking.Defs.inc | 22 | ||||
-rw-r--r-- | src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc | 20 | ||||
-rw-r--r-- | src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc | 5 | ||||
-rw-r--r-- | src/plugins/HPMHooking/HPMHooking_map.Hooks.inc | 163 | ||||
-rw-r--r-- | src/plugins/generate-translations.c | 256 |
5 files changed, 446 insertions, 20 deletions
diff --git a/src/plugins/HPMHooking/HPMHooking.Defs.inc b/src/plugins/HPMHooking/HPMHooking.Defs.inc index 65bc2bd82..8a6f34e2e 100644 --- a/src/plugins/HPMHooking/HPMHooking.Defs.inc +++ b/src/plugins/HPMHooking/HPMHooking.Defs.inc @@ -5796,10 +5796,10 @@ typedef const char* (*HPMHOOK_pre_script_parse_syntax_close_sub) (const char **p typedef const char* (*HPMHOOK_post_script_parse_syntax_close_sub) (const char* retVal___, const char *p, int *flag); typedef const char* (*HPMHOOK_pre_script_parse_syntax) (const char **p); typedef const char* (*HPMHOOK_post_script_parse_syntax) (const char* retVal___, const char *p); -typedef c_op (*HPMHOOK_pre_script_get_com) (unsigned char **scriptbuf, int **pos); -typedef c_op (*HPMHOOK_post_script_get_com) (c_op retVal___, unsigned char *scriptbuf, int *pos); -typedef int (*HPMHOOK_pre_script_get_num) (unsigned char **scriptbuf, int **pos); -typedef int (*HPMHOOK_post_script_get_num) (int retVal___, unsigned char *scriptbuf, int *pos); +typedef c_op (*HPMHOOK_pre_script_get_com) (const struct script_buf **scriptbuf, int **pos); +typedef c_op (*HPMHOOK_post_script_get_com) (c_op retVal___, const struct script_buf *scriptbuf, int *pos); +typedef int (*HPMHOOK_pre_script_get_num) (const struct script_buf **scriptbuf, int **pos); +typedef int (*HPMHOOK_post_script_get_num) (int retVal___, const struct script_buf *scriptbuf, int *pos); typedef const char* (*HPMHOOK_pre_script_op2name) (int *op); typedef const char* (*HPMHOOK_post_script_op2name) (const char* retVal___, int op); typedef void (*HPMHOOK_pre_script_reportsrc) (struct script_state **st); @@ -5836,6 +5836,16 @@ typedef const char* (*HPMHOOK_pre_script_parse_variable) (const char **p); typedef const char* (*HPMHOOK_post_script_parse_variable) (const char* retVal___, const char *p); typedef const char* (*HPMHOOK_pre_script_parse_simpleexpr) (const char **p); typedef const char* (*HPMHOOK_post_script_parse_simpleexpr) (const char* retVal___, const char *p); +typedef const char* (*HPMHOOK_pre_script_parse_simpleexpr_paren) (const char **p); +typedef const char* (*HPMHOOK_post_script_parse_simpleexpr_paren) (const char* retVal___, const char *p); +typedef const char* (*HPMHOOK_pre_script_parse_simpleexpr_number) (const char **p); +typedef const char* (*HPMHOOK_post_script_parse_simpleexpr_number) (const char* retVal___, const char *p); +typedef const char* (*HPMHOOK_pre_script_parse_simpleexpr_string) (const char **p); +typedef const char* (*HPMHOOK_post_script_parse_simpleexpr_string) (const char* retVal___, const char *p); +typedef const char* (*HPMHOOK_pre_script_parse_simpleexpr_name) (const char **p); +typedef const char* (*HPMHOOK_post_script_parse_simpleexpr_name) (const char* retVal___, const char *p); +typedef void (*HPMHOOK_pre_script_add_translatable_string) (const struct script_string_buf **string, const char **start_point); +typedef void (*HPMHOOK_post_script_add_translatable_string) (const struct script_string_buf *string, const char *start_point); typedef const char* (*HPMHOOK_pre_script_parse_expr) (const char **p); typedef const char* (*HPMHOOK_post_script_parse_expr) (const char* retVal___, const char *p); typedef const char* (*HPMHOOK_pre_script_parse_line) (const char **p); @@ -5978,8 +5988,8 @@ typedef int (*HPMHOOK_pre_script_string_dup) (char **str); typedef int (*HPMHOOK_post_script_string_dup) (int retVal___, char *str); typedef void (*HPMHOOK_pre_script_load_translations) (void); typedef void (*HPMHOOK_post_script_load_translations) (void); -typedef void (*HPMHOOK_pre_script_load_translation) (const char **file, uint8 *lang_id, uint32 **total); -typedef void (*HPMHOOK_post_script_load_translation) (const char *file, uint8 lang_id, uint32 *total); +typedef int (*HPMHOOK_pre_script_load_translation) (const char **file, uint8 *lang_id); +typedef int (*HPMHOOK_post_script_load_translation) (int retVal___, const char *file, uint8 lang_id); typedef int (*HPMHOOK_pre_script_translation_db_destroyer) (union DBKey *key, struct DBData **data, va_list ap); typedef int (*HPMHOOK_post_script_translation_db_destroyer) (int retVal___, union DBKey key, struct DBData *data, va_list ap); typedef void (*HPMHOOK_pre_script_clear_translations) (bool *reload); diff --git a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc index 5c2ead5ef..776099871 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc @@ -4672,6 +4672,16 @@ struct { struct HPMHookPoint *HP_script_parse_variable_post; struct HPMHookPoint *HP_script_parse_simpleexpr_pre; struct HPMHookPoint *HP_script_parse_simpleexpr_post; + struct HPMHookPoint *HP_script_parse_simpleexpr_paren_pre; + struct HPMHookPoint *HP_script_parse_simpleexpr_paren_post; + struct HPMHookPoint *HP_script_parse_simpleexpr_number_pre; + struct HPMHookPoint *HP_script_parse_simpleexpr_number_post; + struct HPMHookPoint *HP_script_parse_simpleexpr_string_pre; + struct HPMHookPoint *HP_script_parse_simpleexpr_string_post; + struct HPMHookPoint *HP_script_parse_simpleexpr_name_pre; + struct HPMHookPoint *HP_script_parse_simpleexpr_name_post; + struct HPMHookPoint *HP_script_add_translatable_string_pre; + struct HPMHookPoint *HP_script_add_translatable_string_post; struct HPMHookPoint *HP_script_parse_expr_pre; struct HPMHookPoint *HP_script_parse_expr_post; struct HPMHookPoint *HP_script_parse_line_pre; @@ -10575,6 +10585,16 @@ struct { int HP_script_parse_variable_post; int HP_script_parse_simpleexpr_pre; int HP_script_parse_simpleexpr_post; + int HP_script_parse_simpleexpr_paren_pre; + int HP_script_parse_simpleexpr_paren_post; + int HP_script_parse_simpleexpr_number_pre; + int HP_script_parse_simpleexpr_number_post; + int HP_script_parse_simpleexpr_string_pre; + int HP_script_parse_simpleexpr_string_post; + int HP_script_parse_simpleexpr_name_pre; + int HP_script_parse_simpleexpr_name_post; + int HP_script_add_translatable_string_pre; + int HP_script_add_translatable_string_post; int HP_script_parse_expr_pre; int HP_script_parse_expr_post; int HP_script_parse_line_pre; diff --git a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc index 77ee32f2f..573ef06c5 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc @@ -2391,6 +2391,11 @@ struct HookingPointData HookingPoints[] = { { HP_POP(script->parse_nextline, HP_script_parse_nextline) }, { HP_POP(script->parse_variable, HP_script_parse_variable) }, { HP_POP(script->parse_simpleexpr, HP_script_parse_simpleexpr) }, + { HP_POP(script->parse_simpleexpr_paren, HP_script_parse_simpleexpr_paren) }, + { HP_POP(script->parse_simpleexpr_number, HP_script_parse_simpleexpr_number) }, + { HP_POP(script->parse_simpleexpr_string, HP_script_parse_simpleexpr_string) }, + { HP_POP(script->parse_simpleexpr_name, HP_script_parse_simpleexpr_name) }, + { HP_POP(script->add_translatable_string, HP_script_add_translatable_string) }, { HP_POP(script->parse_expr, HP_script_parse_expr) }, { HP_POP(script->parse_line, HP_script_parse_line) }, { HP_POP(script->read_constdb, HP_script_read_constdb) }, diff --git a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc index 48fae567f..dc4df803c 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc @@ -61773,11 +61773,11 @@ const char* HP_script_parse_syntax(const char *p) { } return retVal___; } -c_op HP_script_get_com(unsigned char *scriptbuf, int *pos) { +c_op HP_script_get_com(const struct script_buf *scriptbuf, int *pos) { int hIndex = 0; c_op retVal___ = C_NOP; if( HPMHooks.count.HP_script_get_com_pre ) { - c_op (*preHookFunc) (unsigned char **scriptbuf, int **pos); + c_op (*preHookFunc) (const struct script_buf **scriptbuf, int **pos); *HPMforce_return = false; for(hIndex = 0; hIndex < HPMHooks.count.HP_script_get_com_pre; hIndex++ ) { preHookFunc = HPMHooks.list.HP_script_get_com_pre[hIndex].func; @@ -61792,7 +61792,7 @@ c_op HP_script_get_com(unsigned char *scriptbuf, int *pos) { retVal___ = HPMHooks.source.script.get_com(scriptbuf, pos); } if( HPMHooks.count.HP_script_get_com_post ) { - c_op (*postHookFunc) (c_op retVal___, unsigned char *scriptbuf, int *pos); + c_op (*postHookFunc) (c_op retVal___, const struct script_buf *scriptbuf, int *pos); for(hIndex = 0; hIndex < HPMHooks.count.HP_script_get_com_post; hIndex++ ) { postHookFunc = HPMHooks.list.HP_script_get_com_post[hIndex].func; retVal___ = postHookFunc(retVal___, scriptbuf, pos); @@ -61800,11 +61800,11 @@ c_op HP_script_get_com(unsigned char *scriptbuf, int *pos) { } return retVal___; } -int HP_script_get_num(unsigned char *scriptbuf, int *pos) { +int HP_script_get_num(const struct script_buf *scriptbuf, int *pos) { int hIndex = 0; int retVal___ = 0; if( HPMHooks.count.HP_script_get_num_pre ) { - int (*preHookFunc) (unsigned char **scriptbuf, int **pos); + int (*preHookFunc) (const struct script_buf **scriptbuf, int **pos); *HPMforce_return = false; for(hIndex = 0; hIndex < HPMHooks.count.HP_script_get_num_pre; hIndex++ ) { preHookFunc = HPMHooks.list.HP_script_get_num_pre[hIndex].func; @@ -61819,7 +61819,7 @@ int HP_script_get_num(unsigned char *scriptbuf, int *pos) { retVal___ = HPMHooks.source.script.get_num(scriptbuf, pos); } if( HPMHooks.count.HP_script_get_num_post ) { - int (*postHookFunc) (int retVal___, unsigned char *scriptbuf, int *pos); + int (*postHookFunc) (int retVal___, const struct script_buf *scriptbuf, int *pos); for(hIndex = 0; hIndex < HPMHooks.count.HP_script_get_num_post; hIndex++ ) { postHookFunc = HPMHooks.list.HP_script_get_num_post[hIndex].func; retVal___ = postHookFunc(retVal___, scriptbuf, pos); @@ -62302,6 +62302,140 @@ const char* HP_script_parse_simpleexpr(const char *p) { } return retVal___; } +const char* HP_script_parse_simpleexpr_paren(const char *p) { + int hIndex = 0; + const char* retVal___ = NULL; + if( HPMHooks.count.HP_script_parse_simpleexpr_paren_pre ) { + const char* (*preHookFunc) (const char **p); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_parse_simpleexpr_paren_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_script_parse_simpleexpr_paren_pre[hIndex].func; + retVal___ = preHookFunc(&p); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.script.parse_simpleexpr_paren(p); + } + if( HPMHooks.count.HP_script_parse_simpleexpr_paren_post ) { + const char* (*postHookFunc) (const char* retVal___, const char *p); + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_parse_simpleexpr_paren_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_script_parse_simpleexpr_paren_post[hIndex].func; + retVal___ = postHookFunc(retVal___, p); + } + } + return retVal___; +} +const char* HP_script_parse_simpleexpr_number(const char *p) { + int hIndex = 0; + const char* retVal___ = NULL; + if( HPMHooks.count.HP_script_parse_simpleexpr_number_pre ) { + const char* (*preHookFunc) (const char **p); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_parse_simpleexpr_number_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_script_parse_simpleexpr_number_pre[hIndex].func; + retVal___ = preHookFunc(&p); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.script.parse_simpleexpr_number(p); + } + if( HPMHooks.count.HP_script_parse_simpleexpr_number_post ) { + const char* (*postHookFunc) (const char* retVal___, const char *p); + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_parse_simpleexpr_number_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_script_parse_simpleexpr_number_post[hIndex].func; + retVal___ = postHookFunc(retVal___, p); + } + } + return retVal___; +} +const char* HP_script_parse_simpleexpr_string(const char *p) { + int hIndex = 0; + const char* retVal___ = NULL; + if( HPMHooks.count.HP_script_parse_simpleexpr_string_pre ) { + const char* (*preHookFunc) (const char **p); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_parse_simpleexpr_string_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_script_parse_simpleexpr_string_pre[hIndex].func; + retVal___ = preHookFunc(&p); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.script.parse_simpleexpr_string(p); + } + if( HPMHooks.count.HP_script_parse_simpleexpr_string_post ) { + const char* (*postHookFunc) (const char* retVal___, const char *p); + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_parse_simpleexpr_string_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_script_parse_simpleexpr_string_post[hIndex].func; + retVal___ = postHookFunc(retVal___, p); + } + } + return retVal___; +} +const char* HP_script_parse_simpleexpr_name(const char *p) { + int hIndex = 0; + const char* retVal___ = NULL; + if( HPMHooks.count.HP_script_parse_simpleexpr_name_pre ) { + const char* (*preHookFunc) (const char **p); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_parse_simpleexpr_name_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_script_parse_simpleexpr_name_pre[hIndex].func; + retVal___ = preHookFunc(&p); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.script.parse_simpleexpr_name(p); + } + if( HPMHooks.count.HP_script_parse_simpleexpr_name_post ) { + const char* (*postHookFunc) (const char* retVal___, const char *p); + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_parse_simpleexpr_name_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_script_parse_simpleexpr_name_post[hIndex].func; + retVal___ = postHookFunc(retVal___, p); + } + } + return retVal___; +} +void HP_script_add_translatable_string(const struct script_string_buf *string, const char *start_point) { + int hIndex = 0; + if( HPMHooks.count.HP_script_add_translatable_string_pre ) { + void (*preHookFunc) (const struct script_string_buf **string, const char **start_point); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_add_translatable_string_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_script_add_translatable_string_pre[hIndex].func; + preHookFunc(&string, &start_point); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return; + } + } + { + HPMHooks.source.script.add_translatable_string(string, start_point); + } + if( HPMHooks.count.HP_script_add_translatable_string_post ) { + void (*postHookFunc) (const struct script_string_buf *string, const char *start_point); + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_add_translatable_string_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_script_add_translatable_string_post[hIndex].func; + postHookFunc(string, start_point); + } + } + return; +} const char* HP_script_parse_expr(const char *p) { int hIndex = 0; const char* retVal___ = NULL; @@ -64326,31 +64460,32 @@ void HP_script_load_translations(void) { } return; } -void HP_script_load_translation(const char *file, uint8 lang_id, uint32 *total) { +int HP_script_load_translation(const char *file, uint8 lang_id) { int hIndex = 0; + int retVal___ = 0; if( HPMHooks.count.HP_script_load_translation_pre ) { - void (*preHookFunc) (const char **file, uint8 *lang_id, uint32 **total); + int (*preHookFunc) (const char **file, uint8 *lang_id); *HPMforce_return = false; for(hIndex = 0; hIndex < HPMHooks.count.HP_script_load_translation_pre; hIndex++ ) { preHookFunc = HPMHooks.list.HP_script_load_translation_pre[hIndex].func; - preHookFunc(&file, &lang_id, &total); + retVal___ = preHookFunc(&file, &lang_id); } if( *HPMforce_return ) { *HPMforce_return = false; - return; + return retVal___; } } { - HPMHooks.source.script.load_translation(file, lang_id, total); + retVal___ = HPMHooks.source.script.load_translation(file, lang_id); } if( HPMHooks.count.HP_script_load_translation_post ) { - void (*postHookFunc) (const char *file, uint8 lang_id, uint32 *total); + int (*postHookFunc) (int retVal___, const char *file, uint8 lang_id); for(hIndex = 0; hIndex < HPMHooks.count.HP_script_load_translation_post; hIndex++ ) { postHookFunc = HPMHooks.list.HP_script_load_translation_post[hIndex].func; - postHookFunc(file, lang_id, total); + retVal___ = postHookFunc(retVal___, file, lang_id); } } - return; + return retVal___; } int HP_script_translation_db_destroyer(union DBKey key, struct DBData *data, va_list ap) { int hIndex = 0; diff --git a/src/plugins/generate-translations.c b/src/plugins/generate-translations.c new file mode 100644 index 000000000..50a0f162c --- /dev/null +++ b/src/plugins/generate-translations.c @@ -0,0 +1,256 @@ +/** + * This file is part of Hercules. + * http://herc.ws - http://github.com/HerculesWS/Hercules + * + * Copyright (C) 2016 Hercules Dev Team + * + * Hercules 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 3 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include "config/core.h" + +#include "common/hercules.h" +#include "common/cbasetypes.h" +#include "common/memmgr.h" +#include "common/showmsg.h" +#include "common/strlib.h" +#include "map/atcommand.h" +#include "map/map.h" +#include "map/script.h" + +#include "plugins/HPMHooking.h" +#include "common/HPMDataCheck.h" + +#include <stdio.h> +#include <stdlib.h> + +HPExport struct hplugin_info pinfo = { + "generate-translations", // Plugin name + SERVER_TYPE_MAP, // Which server types this plugin works with? + "0.1", // Plugin version + HPM_VERSION, // HPM Version (don't change, macro is automatically updated) +}; + +struct DBMap *translatable_strings; // string map parsed (used when exporting strings only) +/* Set during startup when attempting to export the lang, unset after server initialization is over */ +FILE *lang_export_fp; +char *lang_export_file;/* for lang_export_fp */ +struct script_string_buf lang_export_line_buf; +struct script_string_buf lang_export_escaped_buf; + +/// Whether the translations template generator will automatically run. +bool generating_translations = false; + +/** + * --generate-translations + * + * Creates "./generated_translations.pot" + * @see cmdline->exec + */ +CMDLINEARG(generatetranslations) +{ + lang_export_file = aStrdup("./generated_translations.pot"); + + if ((lang_export_fp = fopen(lang_export_file, "wb")) == NULL) { + ShowError("export-dialog: failed to open '%s' for writing\n", lang_export_file); + } else { + time_t t = time(NULL); + struct tm *lt = localtime(&t); + int year = lt->tm_year+1900; + fprintf(lang_export_fp, + "# This file is part of Hercules.\n" + "# http://herc.ws - http://github.com/HerculesWS/Hercules\n" + "#\n" + "# Copyright (C) 2013-%d Hercules Dev Team\n" + "#\n" + "# Hercules is free software: you can redistribute it and/or modify\n" + "# it under the terms of the GNU General Public License as published by\n" + "# the Free Software Foundation, either version 3 of the License, or\n" + "# (at your option) any later version.\n" + "#\n" + "# This program is distributed in the hope that it will be useful,\n" + "# but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "# GNU General Public License for more details.\n" + "#\n" + "# You should have received a copy of the GNU General Public License\n" + "# along with this program. If not, see <http://www.gnu.org/licenses/>.\n", + year); + } + generating_translations = true; + return true; +} + +void script_add_translatable_string_posthook(const struct script_string_buf *string, const char *start_point) +{ + bool duplicate = true; + bool is_translatable_string = false; + bool is_translatable_fmtstring = false; + + if (!generating_translations || lang_export_fp == NULL) + return; + + /* When exporting we don't know what is a translation and what isn't */ + if (VECTOR_LENGTH(*string) > 1) { + // The length of *string will always be at least 1 because of the '\0' + if (translatable_strings == NULL) { + translatable_strings = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_ALLOW_NULL_DATA, 0); + } + + if (!strdb_exists(translatable_strings, VECTOR_DATA(*string))) { + strdb_put(translatable_strings, VECTOR_DATA(*string), NULL); + duplicate = false; + } + } + + if (!duplicate) { + if (script->syntax.last_func == script->buildin_mes_offset + || script->syntax.last_func == script->buildin_select_offset + || script->syntax.lang_macro_active + ) { + is_translatable_string = true; + } else if (script->syntax.last_func == script->buildin_mesf_offset + || script->syntax.lang_macro_fmtstring_active + ) { + is_translatable_fmtstring = true; + } + } + + if (is_translatable_string || is_translatable_fmtstring) { + const char *line_start = start_point; + const char *line_end = start_point; + int line_length; + bool has_percent_sign = false; + + if (!is_translatable_fmtstring && strchr(VECTOR_DATA(*string), '%') != NULL) { + has_percent_sign = true; + } + + while (line_start > script->parser_current_src && *line_start != '\n') + line_start--; + + while (*line_end != '\n' && *line_end != '\0') + line_end++; + + line_length = (int)(line_end - line_start); + if (line_length > 0) { + VECTOR_ENSURE(lang_export_line_buf, line_length + 1, 512); + VECTOR_PUSHARRAY(lang_export_line_buf, line_start, line_length); + VECTOR_PUSH(lang_export_line_buf, '\0'); + + normalize_name(VECTOR_DATA(lang_export_line_buf), "\r\n\t "); // [!] Note: VECTOR_LENGTH() will lie. + } + + VECTOR_ENSURE(lang_export_escaped_buf, 4*VECTOR_LENGTH(*string)+1, 1); + VECTOR_LENGTH(lang_export_escaped_buf) = (int)sv->escape_c(VECTOR_DATA(lang_export_escaped_buf), + VECTOR_DATA(*string), + VECTOR_LENGTH(*string)-1, /* exclude null terminator */ + "\""); + VECTOR_PUSH(lang_export_escaped_buf, '\0'); + + fprintf(lang_export_fp, "\n#: %s\n" + "# %s\n" + "%s" + "msgctxt \"%s\"\n" + "msgid \"%s\"\n" + "msgstr \"\"\n", + script->parser_current_file ? script->parser_current_file : "Unknown File", + VECTOR_DATA(lang_export_line_buf), + is_translatable_fmtstring ? "#, c-format\n" : (has_percent_sign ? "#, no-c-format\n" : ""), + script->parser_current_npc_name ? script->parser_current_npc_name : "Unknown NPC", + VECTOR_DATA(lang_export_escaped_buf) + ); + VECTOR_TRUNCATE(lang_export_line_buf); + VECTOR_TRUNCATE(lang_export_escaped_buf); + } +} + +struct script_code *parse_script_prehook(const char **src, const char **file, int *line, int *options, int **retval) +{ + if (translatable_strings != NULL) { + db_destroy(translatable_strings); + translatable_strings = NULL; + } + return NULL; +} + +void script_parser_clean_leftovers_posthook(void) +{ + if (translatable_strings != NULL) { + db_destroy(translatable_strings); + translatable_strings = NULL; + } + + VECTOR_CLEAR(lang_export_line_buf); + VECTOR_CLEAR(lang_export_escaped_buf); +} + +bool msg_config_read_posthook(bool retVal, const char *cfg_name, bool allow_override) +{ + static int called = 1; + + if (!generating_translations || lang_export_fp == NULL) + return retVal; + + if (!retVal) + return retVal; + + if (++called == 1) { // Original + int i; + for (i = 0; i < MAX_MSG; i++) { + if (atcommand->msg_table[0][i] == NULL) + continue; + fprintf(lang_export_fp, "msgctxt \"messages.conf\"\n" + "msgid \"%s\"\n" + "msgstr \"\"\n", + atcommand->msg_table[0][i] + ); + } + } + + return retVal; +} + +HPExport void server_preinit(void) +{ + addArg("--generate-translations", false, generatetranslations, + "Creates './generated_translations.pot' file with all translateable strings from scripts, server terminates afterwards."); + VECTOR_INIT(lang_export_line_buf); + VECTOR_INIT(lang_export_escaped_buf); + addHookPost(script, add_translatable_string, script_add_translatable_string_posthook); + addHookPre(script, parse, parse_script_prehook); + addHookPost(script, parser_clean_leftovers, script_parser_clean_leftovers_posthook); + addHookPost(atcommand, msg_read, msg_config_read_posthook); +} + +HPExport void plugin_init(void) +{ +} + +HPExport void server_online(void) +{ + if (generating_translations && lang_export_fp != NULL) { + ShowInfo("Lang exported to '%s'\n", lang_export_file); + fclose(lang_export_fp); + lang_export_fp = NULL; + } + core->runflag = CORE_ST_STOP; +} + +HPExport void plugin_final(void) +{ + if (lang_export_file != NULL) { + aFree(lang_export_file); + lang_export_file = NULL; + } +} |