/** * getxml-merge: * @title: getxml-merge * @subtitle: getxml-merge * @project: getxml * @lang: fr,en * @authors: Philippe Roy * @copyright: Copyright (c) 2001 Philippe Roy * @license: GNU GPL * * fr: Fusion * * en: Merge **/ /* * Ce programme est un logiciel libre ; vous pouvez le redistribuer et/ou le modifier * sous les termes de la licence publique générale GNU telle qu'elle est publiée par * la Free Software Foundation ; soit la version 2 de la licence, ou * (comme vous voulez) toute version ultérieure. * * Ce programme est distribué dans l'espoir qu'il sera utile, * mais SANS AUCUNE GARANTIE ; même sans la garantie de * COMMERCIALITÉ ou d'ADÉQUATION A UN BUT PARTICULIER. Voir la * licence publique générale GNU pour plus de détails. * * Vous devriez avoir reçu une copie de la licence publique générale GNU * avec ce programme ; si ce n'est pas le cas, écrivez à la Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * This program 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 2 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include /* #include */ /* #include */ #include "getxml-merge.h" /*****************************************************************************/ /*** Standardisation du vocabulaire - Vocabulary standardization */ /*****************************************************************************/ #define XmlDoc xmlDoc #define XmlNs xmlNs #define XmlNode xmlNode #define XmlAttribute xmlAttribute #define XmlAttr xmlAttr #define XmlChar xmlChar /*****************************************************************************/ /*** Variables globales - Global variables */ /*****************************************************************************/ #define BUFFER_SIZE 256 #define MAX_RING 100 gchar *PACKAGE_COMMAND; TdPopt popts[6]; /*****************************************************************************/ /*** Communs - Commons /*****************************************************************************/ /** * string_file: * @file: file * * fr: Retourne le contenu du fichier * * en: Returns the file content * * Return value: string **/ GString* string_file (gchar *file) { gint i; gint fd; GString *ret; GIOChannel *iochannel; char *buff; guint readden; buff = g_malloc0 (BUFFER_SIZE); ret = g_string_new (""); /* Go ! */ fd = open (file, O_RDONLY); if (fd < 0) g_error ("getxml-extract: loading file '%s' unreadable", file); iochannel = g_io_channel_unix_new (fd); g_io_channel_read (iochannel, buff, BUFFER_SIZE, &readden); if (readden == 0) return NULL; i=0; while (readden != 0) { g_string_append (ret, g_strdup (buff)); g_free (buff); buff = g_malloc0 (BUFFER_SIZE); g_io_channel_read (iochannel, buff, BUFFER_SIZE, &readden); } close (fd); g_free (buff); return ret; } /*****************************************************************************/ /*** Arguments de la ligne de commande - Command line arguments */ /*****************************************************************************/ /** * popt_def: * @key: char key * @long key: string key * @argument: argument * @description: description * * fr: Créé une option de ligne de commande * * en: Creates an option of command line * * Return value: popt structure **/ TdPopt popt_def (gchar *key, gchar *longkey, gchar *argument, gchar *description) { TdPopt ret = NULL; ret = g_malloc0 (sizeof (TdPopt_tmp)); ret->key = g_strdup (key); ret->longkey = g_strdup (longkey); ret->argument = g_strdup (argument); ret->description = description; ret->flag = FALSE; ret->value = NULL; ret->nbpredef = 0; return ret; } /** * popts_help: * @nbpopts: counter of options of commande line * @popts[]: arraw of options of commande line options * * fr: Affiche l'usage * * en: Displays the usage **/ void popts_help (gint nbpopts, TdPopt popts[]) { gint i, j, k, key, longkey, argument; gint length = 0; /*** Alignement - Aligment */ g_print ("%s [option ...]\n", PACKAGE_COMMAND); for (i=0; ikey) key = 3; if (popts[i]->longkey) longkey = strlen (popts[i]->longkey); if (popts[i]->argument) argument = strlen (popts[i]->argument); if (length < (9+key+longkey+argument)) length = 9+key+longkey+argument; } /*** Texte - Text */ for (i=0; ikey) { g_print ("-%s, ", popts[i]->key); key = 4; } if (popts[i]->longkey) { g_print ("--%s ", popts[i]->longkey); longkey = strlen (popts[i]->longkey); } if (popts[i]->argument) { g_print ("%s", popts[i]->argument); argument = strlen (popts[i]->argument); } for (j=7+key+longkey+argument; jdescription); for (j=0; jnbpredef; j++) { for (k=0; kpredef[j]); } } exit (0); } /** * popts_parse: * @argc: counter of options used of command line * @argv[]: arraw of options used of command line * @nbpopts: counter of options of command line * @popts[]: arraw of options of command line * * fr: Analyse de la ligne de commande * * en: Parses the command line **/ void popts_parse (gint argc, char *argv[], gint nbpopts, TdPopt popts[]) { gint i, j; GList *option = NULL; GList *argument = NULL; gchar *txt_tmp = NULL; gchar *txt_tmp1 = NULL; gchar *txt_tmp2 = NULL; gboolean bool_tmp; /*** Découpage - Cutting */ for (i=1; ikey) && (!strcmp (popts[j]->key, g_list_nth_data (option, i)))) || ((popts[j]->longkey) && (!strcmp (popts[j]->longkey, g_list_nth_data (option, i))))) { popts[j]->flag = TRUE; bool_tmp = TRUE; if (g_list_nth_data (argument, i)) popts[j]->value = g_strdup (g_list_nth_data (argument, i)); else if (popts[j]->argument) g_error ("getxml-extract: option '%s' needs argument '%s'", (gchar*) g_list_nth_data (option, i), popts[j]->argument); } if (!bool_tmp) g_error ("getxml-extract: option '%s' unknow", (gchar*) g_list_nth_data (option, i)); } } /** * popts_version: * * fr: Affiche la version du programme * * en: Display the version of the program **/ void popts_version (void) { g_print ("%s %s\n", PACKAGE_COMMAND, GETXML_VERSION); exit (0); } /*****************************************************************************/ /*** Dictionnaire - Dictionnary */ /*****************************************************************************/ /** * dictionnary: * @file: po file location * @statistics_flag: display statistics * * fr: Créé le dictionnaire * * en: Creates the dictionnary * * Return value: hash table **/ GHashTable *dictionnary (gchar *file, gboolean statistics_flag) { GHashTable *ret; gint i, j; GString *string; gchar **string2; gchar **string3; gchar **string4; gchar **string5; gchar **string6; gchar *msgid; gchar *msgstr; gchar **fuzzy_string; gchar **untranslated_string; gchar **obsoleted_string; gint fuzzy_count = 0; gint untranslated_count = 0; gint obsoleted_count = 0; gint word_count = 0; gchar *txt_tmp; /*** Découpage - Cutting */ string = string_file (file); ret = g_hash_table_new (g_str_hash, g_str_equal); string2 = g_strsplit (string->str, "\nmsgid \"", string->len); i=0; while (string2[i]) { if (strstr (string2[i], "\nmsgstr \"")) { msgid = NULL; msgstr = NULL; string3 = g_strsplit (string2[i], "\nmsgstr \"", 2); string4 = g_strsplit (string3[1], "\"\n\n#", 2); /*** msgid */ if (*string3[0] == '"') { string5 = g_strsplit (g_strndup (string3[0], strlen (string3[0])-1), "\"\n\"", MAX_RING); j=0; while (string5[j]) { if (msgid) msgid = g_strdup_printf ("%s%s", msgid, string5[j]); else msgid = g_strdup (string5[j]); j++; } } else msgid = g_strndup (string3[0], strlen (string3[0])-1); /*** msgstr */ if (*string4[0] == '"') { string5 = g_strsplit (g_strndup (string4[0], strlen (string4[0])), "\"\n\"", MAX_RING); j=0; while (string5[j]) { if (msgstr) msgstr = g_strdup_printf ("%s%s", msgstr, string5[j]); else msgstr = g_strdup (string5[j]); j++; } } else msgstr = g_strdup (string4[0]); /*** Dernier mot - Lastest word */ if (strstr (msgstr+strlen (msgstr)-2, "\"")) msgstr = g_strndup (msgstr, strlen (msgstr)-2); /*** Ajout - Add */ if (!strcmp (msgstr, "\"")) msgstr = ""; if (msgid && msgstr) g_hash_table_insert (ret, msgid, msgstr); } i++; } /*** Compteurs - Counters */ if (statistics_flag) { i--; untranslated_string = g_strsplit (string->str, "\nmsgstr \"\"\n\n#", string->len); untranslated_count=0; while (untranslated_string[untranslated_count]) untranslated_count++; untranslated_count--; fuzzy_string = g_strsplit (string->str, "\n#, fuzzy\n", string->len); fuzzy_count=0; while (fuzzy_string[fuzzy_count]) fuzzy_count++; fuzzy_count--; obsoleted_string = g_strsplit (string->str, "\"\n\n#~", string->len); obsoleted_count=0; while (obsoleted_string[obsoleted_count]) obsoleted_count++; obsoleted_count--; g_print ("%d translated messages, %d fuzzy translations, %d untranslated messages, %d obsolted translations\n", i-fuzzy_count-untranslated_count, fuzzy_count, untranslated_count, obsoleted_count); } return ret; } /*****************************************************************************/ /*** Traduction - Translation */ /*****************************************************************************/ /** * translation: * @file_in: input file location * @file_out: output file location * @dico: dictionnary * * fr: Traduit le fichier * * en: Translates the file **/ void translation (gchar *file_in, gchar *file_out, GHashTable *dico) { XmlDoc *doc; XmlNs *ns; XmlNode *cur; XmlNode *cur_parent = NULL; gboolean stop_doc; gboolean stop_node; gchar *carac; gchar *txt_tmp; XmlAttr *property; /*** En-tête - Head */ xmlKeepBlanksDefault (0); doc = xmlParseFile (file_in); if (!doc) g_error ("getxml-extract: parsing XML file : doc == NULL"); cur = xmlDocGetRootElement (doc); if (!cur) { xmlFreeDoc (doc); g_error ("getxml-extract: parsing XML file : cur == NULL"); } /*** Valeurs - Values */ stop_doc = FALSE; while (!stop_doc) { /*** Attributs - Attributes */ property = (XmlAttr*) (cur->properties); if (property) { stop_node = FALSE; if ((!property->name) || (!strlen (g_strstrip ((gchar*) property->name)))) stop_node = TRUE; while (!stop_node) { carac = (guchar*) property->name; if (*carac == '_') { txt_tmp = g_hash_table_lookup (dico, xmlGetProp (cur, property->name)); if (txt_tmp && (strlen (g_strstrip (g_strdup (txt_tmp))))) xmlSetProp (cur, property->name, txt_tmp); property->name = g_strndup (property->name+1, strlen (property->name)-1); } if (!property->next) stop_node = TRUE; else property = property->next; } } /*** Suivant - Next */ if (cur->xmlChildrenNode) { cur = cur->xmlChildrenNode; continue; } else { if (cur->next) { cur = cur->next; continue; } else { do { if (cur == xmlDocGetRootElement (doc)) stop_doc = TRUE; else { cur_parent = cur->parent; if (cur_parent->next == NULL) cur = cur_parent; else cur = cur_parent->next; } } while ((cur == cur_parent) && (!stop_doc)); } } } /* FIXME: libxml2 : attente d'une version plus mature - libxml2 : wait a more mature version */ /* if (base->encoding) */ /* { */ /* if (xmlSaveFileEnc (file, doc, base->encoding)<0) */ /* { */ /* td_app_message (g_strdup_printf (_("Saving geometry '%s'"), file), TD_MSG_FAILED); */ /* xmlFreeDoc (doc); */ /* return FALSE; */ /* } */ /* } */ /* else */ if (xmlSaveFile (file_out, doc)<0) g_error ("getxml-extract: saving XML file failed"); xmlFreeDoc (doc); } /*****************************************************************************/ /*** Principale - Main */ /*****************************************************************************/ /** * popts_about: * * fr: Affiche le à propos du programme * * en: Display the about of the program **/ void popts_about (void) { g_print ("%s %s : Traducteur XML - XML translator\n", PACKAGE_COMMAND, GETXML_VERSION); g_print ("Copyright (c) 2001 Philippe Roy\n"); g_print ("Author : Philippe Roy \n"); g_print ("getxml-merge is a free software, covered by the GNU General Public License. (http://www.gnu.org)\n"); g_print ("getxml-merge is a tool developped for the ToutDoux project. (http://www.toutdoux.org)\n"); exit (0); } /** * popts_def: * * fr: Definition des options de la ligne de commande * * en: Definition of the options of command line **/ void popts_def (void) { PACKAGE_COMMAND = "getxml-merge"; popts[0] = popt_def (NULL, "about", NULL, "About"); popts[1] = popt_def ("v", "version", NULL, "Version"); popts[2] = popt_def ("i", "input", "", "Specify the XML input file (obligatory)"); popts[3] = popt_def ("p", "po", "", "Specify the po file (obligatory)"); popts[4] = popt_def ("o", "output", "", "Specify the XML output file (obligatory)"); popts[5] = popt_def (NULL, "stat", NULL, "Enable statistics of po file (optional)"); }; /** * main: * @argc: counter of command line options used * @argv[]: arraw of command line options used * * fr: Procédure principale du programme * * en: Main procedure of the program * * Return value: -1 on error **/ int main (gint argc, char *argv[]) { FILE *file_in; FILE *file_out; void *ctx; GHashTable *dico; /*** Popts */ popts_def(); popts_parse (argc, argv, 6, popts); /*** Vérification des fichiers - Files checking */ file_in = fopen (popts[2]->value, "r"); if (file_in == NULL) g_error ("getxml-extract: reading XML input file : error in opening"); fclose (file_in); file_out = fopen (popts[4]->value, "w"); if (file_out == NULL) g_error ("getxml-extract: reading XML output file : error in opening"); fclose (file_out); /*** Dictionnaire - Dictionnary */ dico = dictionnary (popts[3]->value, popts[5]->flag); if (!dico) g_error ("getxml-extract: dictionnary incomplete"); /*** Traduction - Translation */ translation (popts[2]->value, popts[4]->value, dico); return 0; }