diff options
author | Haru <haru@dotalux.com> | 2019-10-18 13:29:03 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-10-18 13:29:03 +0200 |
commit | ef60d6c53db89a6a932618895acf4ee194b3f2e3 (patch) | |
tree | 5683ad48dd74af701b463a5aeaad7b7f58f95705 | |
parent | 1e6580e56850adb241261c33bffca60f934294fb (diff) | |
parent | ae22cb6f20091e290cf6c30c049400535d6f1aca (diff) | |
download | hercules-ef60d6c53db89a6a932618895acf4ee194b3f2e3.tar.gz hercules-ef60d6c53db89a6a932618895acf4ee194b3f2e3.tar.bz2 hercules-ef60d6c53db89a6a932618895acf4ee194b3f2e3.tar.xz hercules-ef60d6c53db89a6a932618895acf4ee194b3f2e3.zip |
Merge pull request #2492 from dastgirp/huld/split
Split HULD translations to per NPC file instead of one large file
-rw-r--r-- | db/translations.conf | 10 | ||||
-rw-r--r-- | src/common/utils.c | 15 | ||||
-rw-r--r-- | src/common/utils.h | 2 | ||||
-rw-r--r-- | src/map/script.c | 123 | ||||
-rw-r--r-- | src/map/script.h | 5 | ||||
-rw-r--r-- | src/plugins/HPMHooking/HPMHooking.Defs.inc | 10 | ||||
-rw-r--r-- | src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc | 12 | ||||
-rw-r--r-- | src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc | 3 | ||||
-rw-r--r-- | src/plugins/HPMHooking/HPMHooking_map.Hooks.inc | 63 | ||||
-rw-r--r-- | src/plugins/generate-translations.c | 242 |
10 files changed, 343 insertions, 142 deletions
diff --git a/db/translations.conf b/db/translations.conf index e786a72ac..72288ea63 100644 --- a/db/translations.conf +++ b/db/translations.conf @@ -31,6 +31,12 @@ //========================================================================= translations: ( - //"path/to/my/Language.po", - //"db/Spanish.po", //(Example) + //"db/translations/Foo", + // "db/Spanish", // (Example) + // The .po files in the language folder should have the same directory + // structure as the generating scripts: + // - db/Spanish/conf/messages_conf.po + // - db/Spanish/npc/MOTD_txt.po + // - db/Spanish/npc/airports/airship_txt.po + // - ... ) diff --git a/src/common/utils.c b/src/common/utils.c index d4c838b56..238ebe65d 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -128,7 +128,7 @@ static char *checkpath(char *path, const char *srcpath) return path; } -void findfile(const char *p, const char *pat, void (func)(const char *)) +void findfile(const char *p, const char *pat, void (func)(const char *, void *context), void *context) { WIN32_FIND_DATAA FindFileData; HANDLE hFind; @@ -155,12 +155,11 @@ void findfile(const char *p, const char *pat, void (func)(const char *)) sprintf(tmppath,"%s%c%s",path,PATHSEP,FindFileData.cFileName); if (strstr(FindFileData.cFileName, pattern)) { - func( tmppath ); + func(tmppath, context); } - if( FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) - { - findfile(tmppath, pat, func); + if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { + findfile(tmppath, pat, func, context); } }while (FindNextFileA(hFind, &FindFileData) != 0); FindClose(hFind); @@ -190,7 +189,7 @@ static char *checkpath(char *path, const char *srcpath) return path; } -void findfile(const char *p, const char *pat, void (func)(const char *)) +void findfile(const char *p, const char *pat, void (func)(const char *, void *context), void *context) { DIR* dir; ///< pointer to the scanned directory. struct dirent* entry; ///< pointer to one directory entry. @@ -220,7 +219,7 @@ void findfile(const char *p, const char *pat, void (func)(const char *)) // check if the pattern matches. if (strstr(entry->d_name, pattern)) { - func( tmppath ); + func(tmppath, context); } // check if it is a directory. if (stat(tmppath, &dir_stat) == -1) { @@ -230,7 +229,7 @@ void findfile(const char *p, const char *pat, void (func)(const char *)) // is this a directory? if (S_ISDIR(dir_stat.st_mode)) { // decent recursively - findfile(tmppath, pat, func); + findfile(tmppath, pat, func, context); } }//end while diff --git a/src/common/utils.h b/src/common/utils.h index f564dcf29..81234c843 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -39,7 +39,7 @@ void WriteDump(FILE* fp, const void* buffer, size_t length); void ShowDump(const void* buffer, size_t length); -void findfile(const char *p, const char *pat, void (func)(const char*)); +void findfile(const char *p, const char *pat, void (func)(const char *, void *), void *context); bool exists(const char* filename); /// calculates the value of A / B, in percent (rounded down) diff --git a/src/map/script.c b/src/map/script.c index fffe57c34..ab7513ede 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -5189,8 +5189,8 @@ static void script_load_translations(void) size = libconfig->setting_length(translations); for(i = 0; i < size; i++) { - const char *translation_file = libconfig->setting_get_string_elem(translations, i); - total += script->load_translation(translation_file, ++lang_id); + const char *translation_dir = libconfig->setting_get_string_elem(translations, i); + total += script->load_translation(translation_dir, ++lang_id); } libconfig->destroy(&translations_conf); @@ -5227,39 +5227,39 @@ static void script_load_translations(void) } /** - * Generates a language name from a translation filename. + * Generates a language name from a translation directory name. * - * @param file The filename. + * @param directory The directory name. * @return The corresponding translation name. */ -static const char *script_get_translation_file_name(const char *file) +static const char *script_get_translation_dir_name(const char *directory) { const char *basename = NULL, *last_dot = NULL; - nullpo_retr("Unknown", file); + nullpo_retr("Unknown", directory); - basename = strrchr(file, '/');; + basename = strrchr(directory, '/'); #ifdef WIN32 { - const char *basename_windows = strrchr(file, '\\'); + const char *basename_windows = strrchr(directory, '\\'); if (basename_windows > basename) basename = basename_windows; } #endif // WIN32 if (basename == NULL) - basename = file; + basename = directory; else basename++; // Skip slash Assert_retr("Unknown", *basename != '\0'); last_dot = strrchr(basename, '.'); if (last_dot != NULL) { - static char file_name[200]; + static char dir_name[200]; if (last_dot == basename) return basename + 1; - safestrncpy(file_name, basename, last_dot - basename + 1); - return file_name; + safestrncpy(dir_name, basename, last_dot - basename + 1); + return dir_name; } return basename; @@ -5340,18 +5340,19 @@ static bool script_load_translation_addstring(const char *file, uint8 lang_id, c /** * Parses an individual translation file. * - * @param file The filename to parse. + * @param directory The directory structure to read. * @param lang_id The language identifier. * @return The amount of strings loaded. */ -static int script_load_translation(const char *file, uint8 lang_id) +static int script_load_translation_file(const char *file, uint8 lang_id) { - int translations = 0; char line[1024]; - char msgctxt[NAME_LENGTH*2+1] = { 0 }; - FILE *fp; - int lineno = 0; + char msgctxt[NAME_LENGTH*2+1] = ""; struct script_string_buf msgid, msgstr; + struct script_string_buf *msg_ptr; + int translations = 0; + int lineno = 0; + FILE *fp; nullpo_ret(file); @@ -5363,46 +5364,50 @@ static int script_load_translation(const char *file, uint8 lang_id) VECTOR_INIT(msgid); VECTOR_INIT(msgstr); - script->add_language(script->get_translation_file_name(file)); - if (lang_id >= atcommand->max_message_table) - atcommand->expand_message_table(); - while (fgets(line, sizeof(line), fp) != NULL) { int len = (int)strlen(line); int i; lineno++; - if(len <= 1) + if (len <= 1) { + if (VECTOR_LENGTH(msgid) > 0 && VECTOR_LENGTH(msgstr) > 0) { + // Add string + if (script->load_translation_addstring(file, lang_id, msgctxt, &msgid, &msgstr)) + translations++; + + msgctxt[0] = '\0'; + VECTOR_TRUNCATE(msgid); + VECTOR_TRUNCATE(msgstr); + } continue; + } if (line[0] == '#') continue; - if (VECTOR_LENGTH(msgid) > 0 && VECTOR_LENGTH(msgstr) > 0) { + if (VECTOR_LENGTH(msgid) > 0) { + if (VECTOR_LENGTH(msgstr) > 0) { + msg_ptr = &msgstr; + } else { + msg_ptr = &msgid; + } if (line[0] == '"') { // Continuation line - (void)VECTOR_POP(msgstr); // Pop final '\0' - for (i = 8; i < len - 2; i++) { - VECTOR_ENSURE(msgstr, 1, 512); + (void)VECTOR_POP(*msg_ptr); // Pop final '\0' + for (i = 1; i < len - 2; i++) { + VECTOR_ENSURE(*msg_ptr, 1, 512); if (line[i] == '\\' && line[i+1] == '"') { - VECTOR_PUSH(msgstr, '"'); + VECTOR_PUSH(*msg_ptr, '"'); i++; } else { - VECTOR_PUSH(msgstr, line[i]); + VECTOR_PUSH(*msg_ptr, line[i]); } } - VECTOR_ENSURE(msgstr, 1, 512); - VECTOR_PUSH(msgstr, '\0'); + VECTOR_ENSURE(*msg_ptr, 1, 512); + VECTOR_PUSH(*msg_ptr, '\0'); continue; } - // Add string - if (script->load_translation_addstring(file, lang_id, msgctxt, &msgid, &msgstr)) - translations++; - - msgctxt[0] = '\0'; - VECTOR_TRUNCATE(msgid); - VECTOR_TRUNCATE(msgstr); } if (strncasecmp(line,"msgctxt \"", 9) == 0) { @@ -5477,10 +5482,47 @@ static int script_load_translation(const char *file, uint8 lang_id) VECTOR_CLEAR(msgid); VECTOR_CLEAR(msgstr); - ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' translations in '"CL_WHITE"%s"CL_RESET"'.\n", translations, file); return translations; } +struct load_translation_data { + uint8 lang_id; + int translation_count; +}; + +static void script_load_translation_sub(const char *filename, void *context) +{ + nullpo_retv(context); + + struct load_translation_data *data = context; + + data->translation_count += script->load_translation_file(filename, data->lang_id); +} + +/** + * Loads a translations directory + * + * @param directory The directory structure to read. + * @param lang_id The language identifier. + * @return The amount of strings loaded. + */ +static int script_load_translation(const char *directory, uint8 lang_id) +{ + struct load_translation_data data = { 0 }; + data.lang_id = lang_id; + + nullpo_ret(directory); + + script->add_language(script->get_translation_dir_name(directory)); + if (lang_id >= atcommand->max_message_table) + atcommand->expand_message_table(); + + findfile(directory, ".po", script_load_translation_sub, &data); + + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' translations in '"CL_WHITE"%s"CL_RESET"'.\n", data.translation_count, directory); + return data.translation_count; +} + /** * **/ @@ -27514,12 +27556,13 @@ void script_defaults(void) script->string_dup = script_string_dup; script->load_translations = script_load_translations; script->load_translation_addstring = script_load_translation_addstring; + script->load_translation_file = script_load_translation_file; script->load_translation = script_load_translation; script->translation_db_destroyer = script_translation_db_destroyer; script->clear_translations = script_clear_translations; script->parse_cleanup_timer = script_parse_cleanup_timer; script->add_language = script_add_language; - script->get_translation_file_name = script_get_translation_file_name; + script->get_translation_dir_name = script_get_translation_dir_name; script->parser_clean_leftovers = script_parser_clean_leftovers; script->run_use_script = script_run_use_script; diff --git a/src/map/script.h b/src/map/script.h index 57652e77a..1cec02b97 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -1039,12 +1039,13 @@ struct script_interface { int (*string_dup) (char *str); void (*load_translations) (void); bool (*load_translation_addstring) (const char *file, uint8 lang_id, const char *msgctxt, const struct script_string_buf *msgid, const struct script_string_buf *msgstr); - int (*load_translation) (const char *file, uint8 lang_id); + int (*load_translation_file) (const char *file, uint8 lang_id); + int (*load_translation) (const char *directory, uint8 lang_id); int (*translation_db_destroyer) (union DBKey key, struct DBData *data, va_list ap); void (*clear_translations) (bool reload); int (*parse_cleanup_timer) (int tid, int64 tick, int id, intptr_t data); uint8 (*add_language) (const char *name); - const char *(*get_translation_file_name) (const char *file); + const char *(*get_translation_dir_name) (const char *directory); void (*parser_clean_leftovers) (void); void (*run_use_script) (struct map_session_data *sd, struct item_data *data, int oid); void (*run_item_equip_script) (struct map_session_data *sd, struct item_data *data, int oid); diff --git a/src/plugins/HPMHooking/HPMHooking.Defs.inc b/src/plugins/HPMHooking/HPMHooking.Defs.inc index 61de7bbc6..b207e52ba 100644 --- a/src/plugins/HPMHooking/HPMHooking.Defs.inc +++ b/src/plugins/HPMHooking/HPMHooking.Defs.inc @@ -7056,8 +7056,10 @@ typedef void (*HPMHOOK_pre_script_load_translations) (void); typedef void (*HPMHOOK_post_script_load_translations) (void); typedef bool (*HPMHOOK_pre_script_load_translation_addstring) (const char **file, uint8 *lang_id, const char **msgctxt, const struct script_string_buf **msgid, const struct script_string_buf **msgstr); typedef bool (*HPMHOOK_post_script_load_translation_addstring) (bool retVal___, const char *file, uint8 lang_id, const char *msgctxt, const struct script_string_buf *msgid, const struct script_string_buf *msgstr); -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_load_translation_file) (const char **file, uint8 *lang_id); +typedef int (*HPMHOOK_post_script_load_translation_file) (int retVal___, const char *file, uint8 lang_id); +typedef int (*HPMHOOK_pre_script_load_translation) (const char **directory, uint8 *lang_id); +typedef int (*HPMHOOK_post_script_load_translation) (int retVal___, const char *directory, 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); @@ -7066,8 +7068,8 @@ typedef int (*HPMHOOK_pre_script_parse_cleanup_timer) (int *tid, int64 *tick, in typedef int (*HPMHOOK_post_script_parse_cleanup_timer) (int retVal___, int tid, int64 tick, int id, intptr_t data); typedef uint8 (*HPMHOOK_pre_script_add_language) (const char **name); typedef uint8 (*HPMHOOK_post_script_add_language) (uint8 retVal___, const char *name); -typedef const char* (*HPMHOOK_pre_script_get_translation_file_name) (const char **file); -typedef const char* (*HPMHOOK_post_script_get_translation_file_name) (const char* retVal___, const char *file); +typedef const char* (*HPMHOOK_pre_script_get_translation_dir_name) (const char **directory); +typedef const char* (*HPMHOOK_post_script_get_translation_dir_name) (const char* retVal___, const char *directory); typedef void (*HPMHOOK_pre_script_parser_clean_leftovers) (void); typedef void (*HPMHOOK_post_script_parser_clean_leftovers) (void); typedef void (*HPMHOOK_pre_script_run_use_script) (struct map_session_data **sd, struct item_data **data, int *oid); diff --git a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc index 0b3e9b923..6b3cee6b5 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc @@ -5590,6 +5590,8 @@ struct { struct HPMHookPoint *HP_script_load_translations_post; struct HPMHookPoint *HP_script_load_translation_addstring_pre; struct HPMHookPoint *HP_script_load_translation_addstring_post; + struct HPMHookPoint *HP_script_load_translation_file_pre; + struct HPMHookPoint *HP_script_load_translation_file_post; struct HPMHookPoint *HP_script_load_translation_pre; struct HPMHookPoint *HP_script_load_translation_post; struct HPMHookPoint *HP_script_translation_db_destroyer_pre; @@ -5600,8 +5602,8 @@ struct { struct HPMHookPoint *HP_script_parse_cleanup_timer_post; struct HPMHookPoint *HP_script_add_language_pre; struct HPMHookPoint *HP_script_add_language_post; - struct HPMHookPoint *HP_script_get_translation_file_name_pre; - struct HPMHookPoint *HP_script_get_translation_file_name_post; + struct HPMHookPoint *HP_script_get_translation_dir_name_pre; + struct HPMHookPoint *HP_script_get_translation_dir_name_post; struct HPMHookPoint *HP_script_parser_clean_leftovers_pre; struct HPMHookPoint *HP_script_parser_clean_leftovers_post; struct HPMHookPoint *HP_script_run_use_script_pre; @@ -12403,6 +12405,8 @@ struct { int HP_script_load_translations_post; int HP_script_load_translation_addstring_pre; int HP_script_load_translation_addstring_post; + int HP_script_load_translation_file_pre; + int HP_script_load_translation_file_post; int HP_script_load_translation_pre; int HP_script_load_translation_post; int HP_script_translation_db_destroyer_pre; @@ -12413,8 +12417,8 @@ struct { int HP_script_parse_cleanup_timer_post; int HP_script_add_language_pre; int HP_script_add_language_post; - int HP_script_get_translation_file_name_pre; - int HP_script_get_translation_file_name_post; + int HP_script_get_translation_dir_name_pre; + int HP_script_get_translation_dir_name_post; int HP_script_parser_clean_leftovers_pre; int HP_script_parser_clean_leftovers_post; int HP_script_run_use_script_pre; diff --git a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc index c6e887d08..ad9e7e123 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc @@ -2861,12 +2861,13 @@ struct HookingPointData HookingPoints[] = { { HP_POP(script->string_dup, HP_script_string_dup) }, { HP_POP(script->load_translations, HP_script_load_translations) }, { HP_POP(script->load_translation_addstring, HP_script_load_translation_addstring) }, + { HP_POP(script->load_translation_file, HP_script_load_translation_file) }, { HP_POP(script->load_translation, HP_script_load_translation) }, { HP_POP(script->translation_db_destroyer, HP_script_translation_db_destroyer) }, { HP_POP(script->clear_translations, HP_script_clear_translations) }, { HP_POP(script->parse_cleanup_timer, HP_script_parse_cleanup_timer) }, { HP_POP(script->add_language, HP_script_add_language) }, - { HP_POP(script->get_translation_file_name, HP_script_get_translation_file_name) }, + { HP_POP(script->get_translation_dir_name, HP_script_get_translation_dir_name) }, { HP_POP(script->parser_clean_leftovers, HP_script_parser_clean_leftovers) }, { HP_POP(script->run_use_script, HP_script_run_use_script) }, { HP_POP(script->run_item_equip_script, HP_script_run_item_equip_script) }, diff --git a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc index daa1b9d7a..6dd6cb34f 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc @@ -74589,15 +74589,42 @@ bool HP_script_load_translation_addstring(const char *file, uint8 lang_id, const } return retVal___; } -int HP_script_load_translation(const char *file, uint8 lang_id) { +int HP_script_load_translation_file(const char *file, uint8 lang_id) { int hIndex = 0; int retVal___ = 0; - if (HPMHooks.count.HP_script_load_translation_pre > 0) { + if (HPMHooks.count.HP_script_load_translation_file_pre > 0) { int (*preHookFunc) (const char **file, uint8 *lang_id); *HPMforce_return = false; + for (hIndex = 0; hIndex < HPMHooks.count.HP_script_load_translation_file_pre; hIndex++) { + preHookFunc = HPMHooks.list.HP_script_load_translation_file_pre[hIndex].func; + retVal___ = preHookFunc(&file, &lang_id); + } + if (*HPMforce_return) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.script.load_translation_file(file, lang_id); + } + if (HPMHooks.count.HP_script_load_translation_file_post > 0) { + int (*postHookFunc) (int retVal___, const char *file, uint8 lang_id); + for (hIndex = 0; hIndex < HPMHooks.count.HP_script_load_translation_file_post; hIndex++) { + postHookFunc = HPMHooks.list.HP_script_load_translation_file_post[hIndex].func; + retVal___ = postHookFunc(retVal___, file, lang_id); + } + } + return retVal___; +} +int HP_script_load_translation(const char *directory, uint8 lang_id) { + int hIndex = 0; + int retVal___ = 0; + if (HPMHooks.count.HP_script_load_translation_pre > 0) { + int (*preHookFunc) (const char **directory, 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; - retVal___ = preHookFunc(&file, &lang_id); + retVal___ = preHookFunc(&directory, &lang_id); } if (*HPMforce_return) { *HPMforce_return = false; @@ -74605,13 +74632,13 @@ int HP_script_load_translation(const char *file, uint8 lang_id) { } } { - retVal___ = HPMHooks.source.script.load_translation(file, lang_id); + retVal___ = HPMHooks.source.script.load_translation(directory, lang_id); } if (HPMHooks.count.HP_script_load_translation_post > 0) { - int (*postHookFunc) (int retVal___, const char *file, uint8 lang_id); + int (*postHookFunc) (int retVal___, const char *directory, 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; - retVal___ = postHookFunc(retVal___, file, lang_id); + retVal___ = postHookFunc(retVal___, directory, lang_id); } } return retVal___; @@ -74729,15 +74756,15 @@ uint8 HP_script_add_language(const char *name) { } return retVal___; } -const char* HP_script_get_translation_file_name(const char *file) { +const char* HP_script_get_translation_dir_name(const char *directory) { int hIndex = 0; const char* retVal___ = NULL; - if (HPMHooks.count.HP_script_get_translation_file_name_pre > 0) { - const char* (*preHookFunc) (const char **file); + if (HPMHooks.count.HP_script_get_translation_dir_name_pre > 0) { + const char* (*preHookFunc) (const char **directory); *HPMforce_return = false; - for (hIndex = 0; hIndex < HPMHooks.count.HP_script_get_translation_file_name_pre; hIndex++) { - preHookFunc = HPMHooks.list.HP_script_get_translation_file_name_pre[hIndex].func; - retVal___ = preHookFunc(&file); + for (hIndex = 0; hIndex < HPMHooks.count.HP_script_get_translation_dir_name_pre; hIndex++) { + preHookFunc = HPMHooks.list.HP_script_get_translation_dir_name_pre[hIndex].func; + retVal___ = preHookFunc(&directory); } if (*HPMforce_return) { *HPMforce_return = false; @@ -74745,13 +74772,13 @@ const char* HP_script_get_translation_file_name(const char *file) { } } { - retVal___ = HPMHooks.source.script.get_translation_file_name(file); + retVal___ = HPMHooks.source.script.get_translation_dir_name(directory); } - if (HPMHooks.count.HP_script_get_translation_file_name_post > 0) { - const char* (*postHookFunc) (const char* retVal___, const char *file); - for (hIndex = 0; hIndex < HPMHooks.count.HP_script_get_translation_file_name_post; hIndex++) { - postHookFunc = HPMHooks.list.HP_script_get_translation_file_name_post[hIndex].func; - retVal___ = postHookFunc(retVal___, file); + if (HPMHooks.count.HP_script_get_translation_dir_name_post > 0) { + const char* (*postHookFunc) (const char* retVal___, const char *directory); + for (hIndex = 0; hIndex < HPMHooks.count.HP_script_get_translation_dir_name_post; hIndex++) { + postHookFunc = HPMHooks.list.HP_script_get_translation_dir_name_post[hIndex].func; + retVal___ = postHookFunc(retVal___, directory); } } return retVal___; diff --git a/src/plugins/generate-translations.c b/src/plugins/generate-translations.c index 759e788a2..14a3c0a4d 100644 --- a/src/plugins/generate-translations.c +++ b/src/plugins/generate-translations.c @@ -22,11 +22,13 @@ #include "common/hercules.h" #include "common/cbasetypes.h" #include "common/memmgr.h" +#include "common/nullpo.h" #include "common/showmsg.h" #include "common/strlib.h" #include "common/sysinfo.h" #include "map/atcommand.h" #include "map/map.h" +#include "map/npc.h" #include "map/script.h" #include "plugins/HPMHooking.h" @@ -34,6 +36,8 @@ #include <stdio.h> #include <stdlib.h> +#include <sys/stat.h> +#include <time.h> HPExport struct hplugin_info pinfo = { "generate-translations", // Plugin name @@ -45,14 +49,33 @@ HPExport struct hplugin_info pinfo = { 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 */ +char *lang_export_filepath; +#define DIRECTORYNAME "generated_translations" struct script_string_buf lang_export_line_buf; struct script_string_buf lang_export_escaped_buf; -int lang_export_stringcount; +int lang_export_stringcount_total; +int lang_export_stringcount_current; /// Whether the translations template generator will automatically run. bool generating_translations = false; +bool createdirectory(const char *dirname) +{ +#ifdef WIN32 + if (!CreateDirectory(dirname, NULL)) { + if (ERROR_ALREADY_EXISTS != GetLastError()) + return false; + } +#else /* Not WIN32 */ + struct stat st = { 0 }; + if (stat(dirname, &st) == -1 ) { + if (mkdir(dirname, 0755) != 0) + return false; + } +#endif // WIN32 check + return true; +} + /** * --generate-translations * @@ -61,49 +84,9 @@ bool generating_translations = false; */ 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; - char timestring[128] = ""; - strftime(timestring, sizeof(timestring), "%Y-%m-%d %H:%M:%S%z", lt); - 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\n" - - "#,fuzzy\n" - "msgid \"\"\n" - "msgstr \"\"\n" - "\"Project-Id-Version: %s\\n\"\n" - "\"Report-Msgid-Bugs-To: dev@herc.ws\\n\"\n" - "\"POT-Creation-Date: %s\\n\"\n" - "\"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n\"\n" - "\"Last-Translator: FULL NAME <EMAIL@ADDRESS>\\n\"\n" - "\"Language-Team: LANGUAGE <LL@li.org>\\n\"\n" - "\"Language: \\n\"\n" - "\"MIME-Version: 1.0\\n\"\n" - "\"Content-Type: text/plain; charset=ISO-8859-1\\n\"\n" - "\"Content-Transfer-Encoding: 8bit\\n\"\n\n", - year, sysinfo->vcsrevision_scripts(), timestring); + if (!createdirectory(DIRECTORYNAME)) { + ShowError("generatetranslations: Unable to create output directory '%s'.\n", DIRECTORYNAME); + return false; } generating_translations = true; return true; @@ -188,7 +171,8 @@ void script_add_translatable_string_posthook(const struct script_string_buf *str script->parser_current_npc_name ? script->parser_current_npc_name : "Unknown NPC", VECTOR_DATA(lang_export_escaped_buf) ); - lang_export_stringcount++; + lang_export_stringcount_total++; + lang_export_stringcount_current++; VECTOR_TRUNCATE(lang_export_line_buf); VECTOR_TRUNCATE(lang_export_escaped_buf); } @@ -214,44 +198,184 @@ void script_parser_clean_leftovers_posthook(void) VECTOR_CLEAR(lang_export_escaped_buf); } +bool translations_enter_file(const char *filepath) +{ + const char *p = NULL; + int len, i; + + if (!generating_translations) + return false; + + p = filepath; + len = (int)strlen(filepath) + (int)strlen(DIRECTORYNAME) + (int)strlen(PATHSEP_STR); + lang_export_filepath = aCalloc(len + 4 + 1, sizeof(char)); // + ".pot" + strncat(lang_export_filepath, DIRECTORYNAME PATHSEP_STR, len); + lang_export_stringcount_current = 0; + + i = (int)strlen(lang_export_filepath); + while (*p != '\0') { + if (Assert_chk(i < len)) { + aFree(lang_export_filepath); + lang_export_filepath = NULL; + return false; + } + if (*p == '.') { + lang_export_filepath[i] = '_'; + } else if (*p == PATHSEP) { + if (!createdirectory(lang_export_filepath)) { + ShowError("generatetranslations: Unable to create output directory '%s'.\n", lang_export_filepath); + aFree(lang_export_filepath); + lang_export_filepath = NULL; + return false; + } + lang_export_filepath[i] = PATHSEP; + } else { + lang_export_filepath[i] = *p; + } + i++; + p++; + } + strncat(lang_export_filepath, ".pot", len + 4); + + if ((lang_export_fp = fopen(lang_export_filepath, "wb")) == NULL) { + ShowError("export-dialog: failed to open '%s' for writing\n", lang_export_filepath); + aFree(lang_export_filepath); + lang_export_filepath = NULL; + return false; + } + + { + time_t t = time(NULL); + struct tm *lt = localtime(&t); + int year = lt->tm_year+1900; + char timestring[128] = ""; + strftime(timestring, sizeof(timestring), "%Y-%m-%d %H:%M:%S%z", lt); + 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\n" + + "#,fuzzy\n" + "msgid \"\"\n" + "msgstr \"\"\n" + "\"Project-Id-Version: %s\\n\"\n" + "\"Report-Msgid-Bugs-To: dev@herc.ws\\n\"\n" + "\"POT-Creation-Date: %s\\n\"\n" + "\"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n\"\n" + "\"Last-Translator: FULL NAME <EMAIL@ADDRESS>\\n\"\n" + "\"Language-Team: LANGUAGE <LL@li.org>\\n\"\n" + "\"Language: \\n\"\n" + "\"MIME-Version: 1.0\\n\"\n" + "\"Content-Type: text/plain; charset=ISO-8859-1\\n\"\n" + "\"Content-Transfer-Encoding: 8bit\\n\"\n\n", + year, sysinfo->vcsrevision_scripts(), timestring); + } + return true; +} + +bool translations_leave_file(const char *filepath) +{ + if (lang_export_fp != NULL) { + fclose(lang_export_fp); + lang_export_fp = NULL; + } + if (lang_export_filepath != NULL) { + if (lang_export_stringcount_current == 0) { + remove(lang_export_filepath); + } else { + ShowMessage("\r"); + ShowInfo("%s => %s (%d strings)\n", filepath, lang_export_filepath, lang_export_stringcount_current); + } + aFree(lang_export_filepath); + lang_export_filepath = NULL; + } + lang_export_stringcount_current = 0; + return true; +} + +bool msg_config_read_prehook(const char **cfg_name, bool *allow_override) +{ + if (*allow_override) // allow_override is true in nested calls + return false; + + translations_enter_file(*cfg_name); + return true; +} + bool msg_config_read_posthook(bool retVal, const char *cfg_name, bool allow_override) { - static int called = 1; + int i; if (!generating_translations || lang_export_fp == NULL) return retVal; - if (!retVal) + if (allow_override) // allow_override is true in nested calls return retVal; - if (++called == 1) { // Original - int i; + if (retVal) { for (i = 0; i < MAX_MSG; i++) { if (atcommand->msg_table[0][i] == NULL) continue; - fprintf(lang_export_fp, "msgctxt \"messages.conf\"\n" + fprintf(lang_export_fp, "\n#: conf/messages.conf\n" + "# %d: %s\n" + "#, c-format\n" + "msgctxt \"messages.conf\"\n" "msgid \"%s\"\n" "msgstr \"\"\n", + i, atcommand->msg_table[0][i], atcommand->msg_table[0][i] ); - lang_export_stringcount++; + lang_export_stringcount_total++; + lang_export_stringcount_current++; } } + translations_leave_file(cfg_name); + + return retVal; +} + +int npc_parsesrcfile_prehook(const char **filepath, bool *runOnInit) +{ + translations_enter_file(*filepath); + return 0; +} + +int npc_parsesrcfile_posthook(int retVal, const char *filepath, bool runOnInit) +{ + translations_leave_file(filepath); 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."); + "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); + addHookPre(atcommand, msg_read, msg_config_read_prehook); addHookPost(atcommand, msg_read, msg_config_read_posthook); - lang_export_stringcount = 0; + addHookPre(npc, parsesrcfile, npc_parsesrcfile_prehook); + addHookPost(npc, parsesrcfile, npc_parsesrcfile_posthook); + lang_export_stringcount_total = 0; + lang_export_stringcount_current = 0; } HPExport void plugin_init(void) @@ -260,18 +384,12 @@ HPExport void plugin_init(void) HPExport void server_online(void) { - if (generating_translations && lang_export_fp != NULL) { - ShowInfo("Translations template exported to '%s' with %d strings.\n", lang_export_file, lang_export_stringcount); - fclose(lang_export_fp); - lang_export_fp = NULL; + if (generating_translations) { + ShowInfo("Translations template exported to '%s' with %d strings.\n", DIRECTORYNAME, lang_export_stringcount_total); } core->runflag = CORE_ST_STOP; } HPExport void plugin_final(void) { - if (lang_export_file != NULL) { - aFree(lang_export_file); - lang_export_file = NULL; - } } |