summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaru <haru@dotalux.com>2016-05-17 01:19:35 +0200
committerHaru <haru@dotalux.com>2016-06-25 17:29:47 +0200
commit6ff6b99d6665a387d83018f39dbf88f150338711 (patch)
treed318b0089d6ed64d3841a4d1be9cb86dea594432
parentd442d4c5beca900865c5f323486818ae9ef42d89 (diff)
downloadhercules-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.c16
-rw-r--r--src/map/map.c40
-rw-r--r--src/map/npc.c6
-rw-r--r--src/map/script.c77
-rw-r--r--src/map/script.h8
-rw-r--r--src/plugins/generate-translations.c231
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);
+}