diff options
author | Haru <haru@dotalux.com> | 2016-05-17 01:19:35 +0200 |
---|---|---|
committer | Haru <haru@dotalux.com> | 2016-06-25 17:29:47 +0200 |
commit | 6ff6b99d6665a387d83018f39dbf88f150338711 (patch) | |
tree | d318b0089d6ed64d3841a4d1be9cb86dea594432 | |
parent | d442d4c5beca900865c5f323486818ae9ef42d89 (diff) | |
download | hercules-6ff6b99d6665a387d83018f39dbf88f150338711.tar.gz hercules-6ff6b99d6665a387d83018f39dbf88f150338711.tar.bz2 hercules-6ff6b99d6665a387d83018f39dbf88f150338711.tar.xz hercules-6ff6b99d6665a387d83018f39dbf88f150338711.zip |
Moved translations template generator to a plugin
Signed-off-by: Haru <haru@dotalux.com>
-rw-r--r-- | src/map/atcommand.c | 16 | ||||
-rw-r--r-- | src/map/map.c | 40 | ||||
-rw-r--r-- | src/map/npc.c | 6 | ||||
-rw-r--r-- | src/map/script.c | 77 | ||||
-rw-r--r-- | src/map/script.h | 8 | ||||
-rw-r--r-- | src/plugins/generate-translations.c | 231 |
6 files changed, 232 insertions, 146 deletions
diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 841cf855d..094e64e2a 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -132,7 +132,6 @@ bool msg_config_read(const char *cfg_name, bool allow_override) { int msg_number; char line[1024], w1[1024], w2[1024]; FILE *fp; - static int called = 1; nullpo_retr(false, cfg_name); if ((fp = fopen(cfg_name, "r")) == NULL) { @@ -170,21 +169,6 @@ bool msg_config_read(const char *cfg_name, bool allow_override) { } fclose(fp); - if( ++called == 1 ) { //Original - if( script->lang_export_fp ) { - int i; - for(i = 0; i < MAX_MSG;i++) { - if( atcommand->msg_table[0][i] != NULL ) { - fprintf(script->lang_export_fp, "msgctxt \"messages.conf\"\n" - "msgid \"%s\"\n" - "msgstr \"\"\n", - atcommand->msg_table[0][i] - ); - } - } - } - } - return true; } diff --git a/src/map/map.c b/src/map/map.c index 22486b8f4..779f8d601 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -6002,45 +6002,6 @@ static CMDLINEARG(loadscript) } /** - * --generate-translations - * - * Creates "./generated_translations.pot" - * @see cmdline->exec - **/ -static CMDLINEARG(generatetranslations) { - script->lang_export_file = aStrdup("./generated_translations.pot"); - - if (!(script->lang_export_fp = fopen(script->lang_export_file,"wb"))) { - ShowError("export-dialog: failed to open '%s' for writing\n",script->lang_export_file); - } else { - time_t t = time(NULL); - struct tm *lt = localtime(&t); - int year = lt->tm_year+1900; - fprintf(script->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); - } - core->runflag = CORE_ST_STOP; - return true; -} - -/** * Defines the local command line arguments */ void cmdline_args_init_local(void) @@ -6056,7 +6017,6 @@ void cmdline_args_init_local(void) CMDLINEARG_DEF2(log-config, logconfig, "Alternative logging configuration.", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM); CMDLINEARG_DEF2(script-check, scriptcheck, "Doesn't run the server, only tests the scripts passed through --load-script.", CMDLINE_OPT_SILENT); CMDLINEARG_DEF2(load-script, loadscript, "Loads an additional script (can be repeated).", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM); - CMDLINEARG_DEF2(generate-translations, generatetranslations, "Creates './generated_translations.pot' file with all translateable strings from scripts, server terminates afterwards.", CMDLINE_OPT_NORMAL); } int do_init(int argc, char *argv[]) diff --git a/src/map/npc.c b/src/map/npc.c index b49e56d20..945a84957 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -5002,12 +5002,6 @@ int do_init_npc(bool minimal) { timer->add_func_list(npc->timerevent,"npc_timerevent"); } - if( script->lang_export_fp ) { - ShowInfo("Lang exported to '%s'\n",script->lang_export_file); - fclose(script->lang_export_fp); - script->lang_export_fp = NULL; - } - // Init dummy NPC CREATE(npc->fake_nd, struct npc_data, 1); npc->fake_nd->bl.m = -1; diff --git a/src/map/script.c b/src/map/script.c index 1f2f51d13..e4c973045 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -1331,7 +1331,6 @@ const char *parse_simpleexpr_name(const char *p) void script_add_translatable_string(const struct script_string_buf *string, const char *start_point) { struct string_translation *st = NULL; - bool duplicate = true; if (script->syntax.translation_db == NULL || (st = strdb_get(script->syntax.translation_db, VECTOR_DATA(*string))) == NULL) { @@ -1363,67 +1362,6 @@ void script_add_translatable_string(const struct script_string_buf *string, cons st_cursor += sizeof(uint8); // FIXME: What are we skipping here? } } - - /* When exporting we don't know what is a translation and what isn't */ - if (script->lang_export_fp != NULL && VECTOR_LENGTH(*string) > 1) { - // The length of script->parse_simpleexpr_strbuf will always be at least 1 because of the '\0' - if (script->syntax.strings == NULL) { - script->syntax.strings = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_ALLOW_NULL_DATA, 0); - } - - if (!strdb_exists(script->syntax.strings, VECTOR_DATA(*string))) { - strdb_put(script->syntax.strings, VECTOR_DATA(*string), NULL); - duplicate = false; - } - } - - if (script->lang_export_fp != NULL && !duplicate && - ( ( ( script->syntax.last_func == script->buildin_mes_offset || - script->syntax.last_func == script->buildin_select_offset ) - ) || script->syntax.lang_macro_active ) ) { - const char *line_start = start_point; - const char *line_end = start_point; - int line_length; - - while( line_start > script->parser_current_src ) { - if( *line_start != '\n' ) - line_start--; - else - break; - } - - while( *line_end != '\n' && *line_end != '\0' ) - line_end++; - - line_length = (int)(line_end - line_start); - if( line_length > 0 ) { - VECTOR_ENSURE(script->lang_export_line_buf, line_length + 1, 512); - VECTOR_PUSHARRAY(script->lang_export_line_buf, line_start, line_length); - VECTOR_PUSH(script->lang_export_line_buf, '\0'); - - normalize_name(VECTOR_DATA(script->lang_export_line_buf), "\r\n\t "); // [!] Note: VECTOR_LENGTH() will lie. - } - - VECTOR_ENSURE(script->lang_export_escaped_buf, 4*VECTOR_LENGTH(*string)+1, 1); - VECTOR_LENGTH(script->lang_export_escaped_buf) = (int)sv->escape_c(VECTOR_DATA(script->lang_export_escaped_buf), - VECTOR_DATA(*string), - VECTOR_LENGTH(*string)-1, /* exclude null terminator */ - "\""); - VECTOR_PUSH(script->lang_export_escaped_buf, '\0'); - - fprintf(script->lang_export_fp, "\n#: %s\n" - "# %s\n" - "msgctxt \"%s\"\n" - "msgid \"%s\"\n" - "msgstr \"\"\n", - script->parser_current_file ? script->parser_current_file : "Unknown File", - VECTOR_DATA(script->lang_export_line_buf), - script->parser_current_npc_name ? script->parser_current_npc_name : "Unknown NPC", - VECTOR_DATA(script->lang_export_escaped_buf) - ); - VECTOR_TRUNCATE(script->lang_export_line_buf); - VECTOR_TRUNCATE(script->lang_export_escaped_buf); - } } /*========================================== @@ -2564,9 +2502,6 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o script->parse_cleanup_timer_id = timer->add(timer->gettick() + 10, script->parse_cleanup_timer, 0, 0); } - if( script->syntax.strings ) /* used only when generating translation file */ - db_destroy(script->syntax.strings); - memset(&script->syntax,0,sizeof(script->syntax)); script->syntax.last_func = -1;/* as valid values are >= 0 */ if( script->parser_current_npc_name ) { @@ -4875,9 +4810,6 @@ void do_final_script(void) script->clear_translations(false); script->parser_clean_leftovers(); - - if( script->lang_export_file ) - aFree(script->lang_export_file); } /** @@ -5195,14 +5127,7 @@ void script_parser_clean_leftovers(void) script->translation_db = NULL; } - if( script->syntax.strings ) { /* used only when generating translation file */ - db_destroy(script->syntax.strings); - script->syntax.strings = NULL; - } - VECTOR_CLEAR(script->parse_simpleexpr_strbuf); - VECTOR_CLEAR(script->lang_export_line_buf); - VECTOR_CLEAR(script->lang_export_escaped_buf); } /** @@ -5221,8 +5146,6 @@ int script_parse_cleanup_timer(int tid, int64 tick, int id, intptr_t data) { *------------------------------------------*/ void do_init_script(bool minimal) { script->parse_cleanup_timer_id = INVALID_TIMER; - VECTOR_INIT(script->lang_export_line_buf); - VECTOR_INIT(script->lang_export_escaped_buf); VECTOR_INIT(script->parse_simpleexpr_strbuf); script->st_db = idb_alloc(DB_OPT_BASE); diff --git a/src/map/script.h b/src/map/script.h index 30737e950..133c205a7 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -502,8 +502,7 @@ struct script_syntax_data { int index; // Number of the syntax used in the script int last_func; // buildin index of the last parsed function unsigned int nested_call; //Dont really know what to call this - bool lang_macro_active; - struct DBMap *strings; // string map parsed (used when exporting strings only) + bool lang_macro_active; // Used to generate translation strings struct DBMap *translation_db; //non-null if this npc has any translated strings to be linked }; @@ -619,9 +618,6 @@ struct script_interface { /* */ unsigned int *generic_ui_array; unsigned int generic_ui_array_size; - /* 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 */ /* set and unset on npc_parse_script */ const char *parser_current_npc_name; /* */ @@ -636,8 +632,6 @@ struct script_interface { uint8 max_lang_id; /* */ struct script_string_buf parse_simpleexpr_strbuf; - struct script_string_buf lang_export_line_buf; - struct script_string_buf lang_export_escaped_buf; /* */ int parse_cleanup_timer_id; /* */ diff --git a/src/plugins/generate-translations.c b/src/plugins/generate-translations.c new file mode 100644 index 000000000..daa3349fa --- /dev/null +++ b/src/plugins/generate-translations.c @@ -0,0 +1,231 @@ +/** + * 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"))) { + 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; + + /* When exporting we don't know what is a translation and what isn't */ + if (lang_export_fp != NULL && 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 (lang_export_fp != NULL && !duplicate && + ( ( ( script->syntax.last_func == script->buildin_mes_offset || + script->syntax.last_func == script->buildin_select_offset ) + ) || script->syntax.lang_macro_active ) ) { + const char *line_start = start_point; + const char *line_end = start_point; + int line_length; + + while( line_start > script->parser_current_src ) { + if( *line_start != '\n' ) + line_start--; + else + break; + } + + 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" + "msgctxt \"%s\"\n" + "msgid \"%s\"\n" + "msgstr \"\"\n", + script->parser_current_file ? script->parser_current_file : "Unknown File", + VECTOR_DATA(lang_export_line_buf), + 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) /* used only when generating translation file */ + db_destroy(translatable_strings); + translatable_strings = NULL; + return NULL; +} + +void script_parser_clean_leftovers_posthook(void) +{ + if (translatable_strings != NULL) { /* used only when generating translation file */ + 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 (retVal && ++called == 1) { //Original + if (lang_export_fp != NULL) { + int i; + for (i = 0; i < MAX_MSG; i++) { + if (atcommand->msg_table[0][i] != NULL) { + 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 (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); +} |