"Fossies" - the Fresh Open Source Software Archive

Member "klavaro-3.13/src/translation.c" (18 Apr 2021, 19802 Bytes) of package /linux/privat/klavaro-3.13.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "translation.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.12_vs_3.13.

    1 /**************************************************************************/
    2 /*  Klavaro - a flexible touch typing tutor                               */
    3 /*  Copyright (C) 2005-2021 Felipe Emmanuel Ferreira de Castro            */
    4 /*                                                                        */
    5 /*  This file is part of Klavaro, which is a free software: you can       */
    6 /*  redistribute it and/or modify it under the terms of the GNU General   */
    7 /*  Public License as published by the Free Software Foundation, either   */
    8 /*  version 3 of the License, or (at your option) any later version.      */
    9 /*                                                                        */
   10 /*  Klavaro is distributed in the hope that it will be useful,            */
   11 /*  but WITHOUT ANY WARRANTY; without even the implied warranty of        */
   12 /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         */
   13 /*  GNU General Public License for more details (in the file COPYING).    */
   14 /*  You should have received a copy of the GNU General Public License     */
   15 /*  along with Klavaro.  If not, see <https://www.gnu.org/licenses/>      */
   16 /**************************************************************************/
   17 
   18 /*
   19  * Set of functions to deal with internationalization (translation).
   20  */
   21 #include <stdio.h>
   22 #include <string.h>
   23 #include <locale.h>
   24 #include <glib.h>
   25 #include <glib/gstdio.h>
   26 #include <gtk/gtk.h>
   27 
   28 #include "auxiliar.h"
   29 #include "main.h"
   30 #include "callbacks.h"
   31 #include "keyboard.h"
   32 #include "velocity.h"
   33 #include "fluidness.h"
   34 #include "translation.h"
   35 
   36 /**********************************************************************
   37  * Variables
   38  */
   39 static Lang_Name_Code *lang;
   40 static gint lang_num = 0;
   41 
   42 /**********************************************************************
   43  * Get country name from its "ISO code" (eo and xx are just languages...)
   44  */
   45 const gchar *
   46 trans_code_to_country (gchar *code)
   47 {
   48 #define COUNTRY_N 50
   49     gsize i;
   50     gchar *dummy = NULL;
   51     static gchar map[COUNTRY_N][3][64] = {
   52         {"xx","Esperantio"},
   53         {"ad","Andorra"},
   54         {"ar","العالم العربي"},
   55         {"be","België"},
   56         {"bg","България"},
   57         {"bo","ཧི་མ་ལ་ཡ།"},
   58         {"br","Brasil"},
   59         {"ca","Canada"},
   60         {"ch","Schweiz / Suisse"},
   61         /* 10 */
   62         {"cn","中华人民共和国"},
   63         {"cz","Česká republika"},
   64         {"dk","Danmark"},
   65         {"de","Deutschland"},
   66         {"eo","Esperantujo"},
   67         {"es","España"},
   68         {"eu","Euskal Herria"},
   69         {"fi","Suomi"},
   70         {"fr","France"},
   71         {"gr","Ελλάδα"},
   72         /* 20 */
   73         {"il","ישראל"},
   74         {"hr","Hrvatska"},
   75         {"hu","Magyarország"},
   76         {"id","Indonesia"},
   77         {"in","India"},
   78         {"it","Italia"},
   79         {"jp","日本 (Nippon)"},
   80         {"kk","Қазақстан"},
   81         {"kr","대한민국"}, /* Korea */
   82         {"no","Norge"},
   83         /* 30 */
   84         {"pl","Polska"},
   85         {"pk","پاکستان"},
   86         {"pt","Portugal"},
   87         {"rs","Србија"}, /* Serbia */
   88         {"ru","Россия"},
   89         {"se","Sverige"},
   90         {"si","Slovenija"},
   91         {"sk","Slovensko"},
   92         {"tr","Türkiye"},
   93         {"ua","Україна"},
   94         /* 40 */
   95         {"uk","United Kingdom"},
   96         {"us","USA"},
   97         {"",""},
   98         {"",""},
   99         {"",""},
  100         {"",""},
  101         {"",""},
  102         {"",""},
  103         {"",""},
  104         {"",""},
  105         /* 50 */
  106         {"",""}
  107     };
  108 
  109     for (i = 0; i < COUNTRY_N; i++)
  110         if (g_str_equal (code, map[i][0]))
  111             return (map[i][1]);
  112     dummy = g_strdup_printf ("(%s)", code);
  113     return (dummy);
  114 }
  115 
  116 /**********************************************************************
  117  * Get a 'reazonable' value for keyboard, that is, QWERTY... :-(
  118  */
  119 gchar *
  120 trans_get_default_keyboard ()
  121 {
  122     gint i;
  123     gchar *tmp;
  124 
  125     if (lang_num == 0)
  126     {
  127         g_warning ("Internal error: trying to use language data not initialized!");
  128         return (NULL);
  129     }
  130 
  131     tmp = main_preferences_get_string ("interface", "language");
  132     for (i = 0; i < lang_num; i++)
  133         if (g_str_equal (lang[i].code, tmp))
  134         {
  135             g_free (tmp);
  136             return (lang[i].kbd);
  137         }
  138 
  139     g_free (tmp);
  140     return (NULL);
  141 }
  142 
  143 /**********************************************************************
  144  * Initialize 'lang', 'code' and 'kbd' accordingly to 'language_set',
  145  * which was defined in "languages.h".
  146  */
  147 void
  148 trans_init_lang_name_code ()
  149 {
  150     static gboolean init = FALSE;
  151     gint i;
  152     gchar *tmp;
  153     gchar **temp_lang = NULL;
  154     const gchar languages_set[] = LANG_SET;
  155 
  156     if (init)
  157     {
  158         g_warning ("Not initializing again the language data");
  159         return;
  160     }
  161     init = TRUE;
  162 
  163     /* Number of configured languages
  164      */
  165     temp_lang = g_strsplit (languages_set, "\n", -1);
  166     i = 0;
  167     while (temp_lang[i] != NULL)
  168         i++;
  169     g_assert (i > 0);
  170     lang = g_new (Lang_Name_Code, i);
  171     lang_num = i;
  172 
  173     for (i = 0; i < lang_num; i++)
  174     {
  175         gchar *end;
  176         gchar *begin;
  177 
  178         tmp = g_strdup (temp_lang[i]);
  179         /* Initialize 'lang'
  180          */
  181         end = strchr (tmp, '(');
  182         if (end)
  183                 end -= ( ((end - tmp) > 1) ? 1 : 0 );
  184         else
  185             g_error ("Internal lang error: found nothing like '(LL...'");
  186         lang[i].name = g_strndup (tmp, end - tmp);
  187 
  188         /* Initialize 'code'
  189          */
  190         begin = strchr (end, '(') + 1;
  191         end = strchr (begin, ')');
  192         if (end == NULL)
  193             g_error ("Internal lang error: found nothing like '(LL)'");
  194         lang[i].code = g_strndup (begin, end - begin);
  195 
  196         /* Initialize 'cd'
  197          */
  198         if (lang[i].code[0] == 'C')
  199             strcpy (lang[i].cd, "en");
  200         else
  201             strncpy (lang[i].cd, lang[i].code, 2);
  202         lang[i].cd[2] = '\0';
  203 
  204         /* Initialize 'kbd'
  205          */
  206         begin = strchr (end, '[') + 1;
  207         end = strchr (begin, ']');
  208         if (end == NULL)
  209             g_error ("Internal lang error: found nothing like '[yy_zz]'");
  210         lang[i].kbd = g_strndup (begin, end - begin);
  211 
  212         //g_printf ("%s : %s : %s : %s\n", lang[i].name, lang[i].code, lang[i].cd, lang[i].kbd);
  213     }
  214     g_strfreev (temp_lang);
  215 }
  216 
  217 gchar *
  218 trans_get_code (gint i)
  219 {
  220     if (i >= lang_num || i < 0)
  221         return (NULL);
  222     return (lang[i].cd);
  223 }
  224 
  225 gboolean
  226 trans_lang_is_available (gchar * langcode)
  227 {
  228     gint i;
  229 
  230     for (i = 0; i < lang_num; i++)
  231         if (g_str_equal (lang[i].code, langcode))
  232             break;
  233     return (i == lang_num ? FALSE : TRUE);
  234 }
  235 
  236 /**********************************************************************
  237  * Define if we may put a stop mark at the end of "phrases".
  238  */
  239 gboolean
  240 trans_lang_has_stopmark ()
  241 {
  242     gboolean stopmark;
  243     gchar *hlp;
  244 
  245     hlp = main_preferences_get_string ("interface", "language");
  246     stopmark = g_str_has_prefix (hlp, "ur") ||
  247            g_str_has_prefix (hlp, "ar") ||
  248            g_str_has_prefix (hlp, "bn") ||
  249            g_str_has_prefix (hlp, "bo") ||
  250            g_str_has_prefix (hlp, "pa");
  251     g_free (hlp);
  252 
  253     return (!stopmark);
  254 }
  255 
  256 /**********************************************************************
  257  * Private auxiliar function
  258  */
  259 static gboolean
  260 trans_lang_get_similar (gchar * test)
  261 {
  262     gint i;
  263     gchar aux_code_2[3];
  264 
  265     /* Prefer C over en_GB for English variants other than en_GB. (Debian patch 02) */
  266     if (g_str_has_prefix (test, "en"))
  267     {
  268         g_free (test);
  269         test = g_strdup ("C");
  270         return (TRUE);
  271     }
  272 
  273     if (g_str_equal (test, "C"))
  274         return TRUE;
  275 
  276     strncpy (aux_code_2, test, 2);
  277     aux_code_2[2] = '\0';
  278 
  279     for (i = 0; i < lang_num; i++)
  280     {
  281         if (strstr (lang[i].code, aux_code_2))
  282         {
  283             g_free (test);
  284             test = g_strdup (lang[i].code);
  285             break;
  286         }
  287     }
  288     if (i == lang_num && g_str_has_prefix (test, "en"))
  289     {
  290         g_free (test);
  291         test = g_strdup ("C");
  292         return (TRUE);
  293     }
  294     return (i == lang_num ? FALSE : TRUE);
  295 }
  296 
  297 /**********************************************************************
  298  * Get the current locale and change it if necessary
  299  */
  300 void
  301 trans_init_language_env ()
  302 {
  303     gchar *tmp_code;
  304     gboolean lang_ok;
  305     gint i;
  306 
  307     /*
  308      * If the language is already set in preferences, just use it
  309      */
  310     lang_ok = FALSE;
  311     if (main_preferences_exist ("interface", "language"))
  312     {
  313         lang_ok = TRUE;
  314         tmp_code = main_preferences_get_string ("interface", "language");
  315         if (trans_lang_is_available (tmp_code) == FALSE)
  316         {
  317             tmp_code[2] = '\0';
  318             if (trans_lang_is_available (tmp_code) == FALSE)
  319             {
  320                 lang_ok = FALSE;
  321                 main_preferences_remove ("interface", "language");
  322             }
  323             else
  324                 main_preferences_set_string ("interface", "language", tmp_code);
  325         }
  326     }
  327 
  328     if (lang_ok == FALSE)
  329     {
  330         /* 
  331          * Read the current locale
  332          */
  333 #ifdef G_OS_UNIX
  334         i = 0;
  335         while ((tmp_code = g_strdup (g_get_language_names ()[i])))
  336         {
  337             if (tmp_code[0] == 'C')
  338             {
  339                 lang_ok = (i == 0 ? TRUE : FALSE);
  340                 break;
  341             }
  342             lang_ok = trans_lang_is_available (tmp_code);
  343             if (lang_ok == TRUE)
  344                 break;
  345             g_free (tmp_code);
  346             lang_ok = FALSE;
  347             i++;
  348         }
  349         if (lang_ok == FALSE)
  350         {
  351             i = 0;
  352             while ((tmp_code = g_strdup (g_get_language_names ()[i])))
  353             {
  354                 if (tmp_code[0] == 'C')
  355                 {
  356                     lang_ok = (i == 0 ? TRUE : FALSE);
  357                     break;
  358                 }
  359                 lang_ok = trans_lang_get_similar (tmp_code);
  360                 if (lang_ok == TRUE)
  361                     break;
  362                 g_free (tmp_code);
  363                 lang_ok = FALSE;
  364                 i++;
  365             }
  366         }
  367 #else
  368         tmp_code = g_win32_getlocale ();
  369         lang_ok = trans_lang_is_available (tmp_code);
  370         if (lang_ok == FALSE)
  371             lang_ok = trans_lang_get_similar (tmp_code);
  372 #endif
  373     }
  374     if (tmp_code == NULL)
  375         tmp_code = g_strdup ("xx");
  376 
  377     /* If even a similar is not available...
  378      */
  379     if (lang_ok == FALSE)
  380     {
  381         g_message ("as your locale (%s) isn't available, "
  382                    "we are using \"C\"", tmp_code);
  383         g_free (tmp_code);
  384         tmp_code = g_strdup ("C");
  385     }
  386 
  387 #ifdef G_OS_WIN32
  388     g_setenv ("LANGUAGE", tmp_code, TRUE);
  389 #endif
  390     main_preferences_set_string ("interface", "language", tmp_code);
  391     g_free (tmp_code);
  392 }
  393 
  394 /**********************************************************************
  395  * Inserts the list of available languages in the 'combo_language'.
  396  */
  397 void
  398 trans_set_combo_language ()
  399 {
  400     static gboolean recur = FALSE;
  401     gint i;
  402     gint i_env;
  403     gchar *tmp_code;
  404     gchar *langcode;
  405     GtkComboBox *cmb;
  406 
  407     callbacks_shield_set (TRUE);
  408 
  409     if (recur)
  410         cmb = GTK_COMBO_BOX (get_wg ("combobox_top10_language"));
  411     else
  412         cmb = GTK_COMBO_BOX (get_wg ("combobox_language"));
  413 
  414     tmp_code = main_preferences_get_string ("interface", "language");
  415     if (tmp_code == NULL || g_str_equal ("en_US", tmp_code))
  416     {
  417         g_message ("Using \"C\" as language code.");
  418         main_preferences_set_string ("interface", "language", "C");
  419         if (tmp_code)
  420             g_free (tmp_code);
  421         tmp_code = g_strdup ("C");
  422     }
  423     gtk_combo_box_text_remove (GTK_COMBO_BOX_TEXT (cmb), 0);
  424     for (i = 0, i_env = -1; i < lang_num; i++)
  425     {
  426         langcode = g_strdup_printf ("%s (%s)", lang[i].name, lang[i].code);
  427         gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (cmb), langcode);
  428         if (g_str_equal (lang[i].code, tmp_code))
  429             i_env = i;
  430         else if (g_str_has_prefix (tmp_code, lang[i].code))
  431         {
  432             i_env = i;
  433             main_preferences_set_string ("interface", "language", lang[i].code);
  434         }
  435         g_free (langcode);
  436     }
  437     if (i_env == -1)
  438     {
  439         g_warning ("set_combo_language() ==> the locale \"%s\" is not available!", tmp_code);
  440         g_message ("Using \"C\" as language code.");
  441         g_free (tmp_code);
  442         tmp_code = g_strdup ("C");
  443         main_preferences_set_string ("interface", "language", "C");
  444         gtk_combo_box_set_active (cmb, 8);
  445     }
  446     else
  447         gtk_combo_box_set_active (cmb, i_env);
  448 
  449     callbacks_shield_set (FALSE);
  450 
  451     if (! recur)
  452     {
  453         recur = TRUE;
  454         trans_set_combo_language ();
  455         return;
  456     }
  457     recur = FALSE;
  458 
  459     if (g_str_has_prefix (tmp_code, "en") || g_str_equal (tmp_code, "C"))
  460         gtk_widget_show (get_wg ("checkbutton_speech"));
  461     else
  462         gtk_widget_hide (get_wg ("checkbutton_speech"));
  463 
  464     g_free (tmp_code);
  465 }
  466 
  467 /**********************************************************************
  468  * Get the current language name, mapped from the preference's key code
  469  */
  470 gchar *
  471 trans_get_current_language ()
  472 {
  473     gchar *tmp_code;
  474     gint i;
  475 
  476     if (lang_num == 0)
  477     {
  478         g_warning ("Internal error: trying to use language data not initialized!");
  479         return (NULL);
  480     }
  481 
  482     tmp_code = main_preferences_get_string ("interface", "language");
  483     for (i = 0; i < lang_num; i++)
  484         if (g_str_equal (lang[i].code, tmp_code))
  485         {
  486             g_free (tmp_code);
  487             return (lang[i].name);
  488         }
  489     g_free (tmp_code);
  490     return ("??");
  491 }
  492 
  493 /**********************************************************************
  494  * Update the current language used accordingly to that selected in the
  495  * 'combo_language'
  496  */
  497 void
  498 trans_change_language (gchar *language)
  499 {
  500     gint i;
  501     gchar *tmp_code;
  502 
  503     /* Keep decreasing order of scanning, for not missing "English UK", for instance. */
  504     for (i = lang_num-1; i >= 0; i--)
  505         if (g_str_has_prefix (language, lang[i].name))
  506             break;
  507 
  508     if (i == lang_num)
  509     {
  510         g_warning ("change_language() --> couldn't find the language: %s", language);
  511         return;
  512     }
  513 
  514     main_preferences_set_string ("interface", "language", lang[i].code);
  515 
  516     velo_reset_dict ();
  517     fluid_reset_paragraph ();
  518 
  519     /* Check if the interface language is the same of the selected in the combo,
  520      * so that it may be spoken
  521      */
  522     if (lang[i].code[0] == 'C')
  523         tmp_code = g_strdup ("en");
  524     else
  525         tmp_code = g_strdup (lang[i].code);
  526     if (tmp_code[0] == _("en")[0] && tmp_code[1] == _("en")[1])
  527         gtk_widget_show (get_wg ("checkbutton_speech"));
  528     else
  529         gtk_widget_hide (get_wg ("checkbutton_speech"));
  530     g_free (tmp_code);
  531 }
  532 
  533 /**********************************************************************
  534  * Find a file whose language prefix is similar to the current one
  535  */
  536 FILE *
  537 trans_lang_get_similar_file (const gchar * file_end)
  538 {
  539     gint i;
  540     gchar *tmp_code;
  541     gchar *tmp_path = NULL;
  542     FILE *fh = NULL;
  543 
  544     tmp_code = main_preferences_get_string ("interface", "language");
  545     for (i = 0; i < lang_num && fh == NULL; i++)
  546     {
  547         if (g_str_equal (lang[i].code, tmp_code))
  548             continue;
  549         if (lang[i].code[0] == tmp_code[0] && lang[i].code[1] == tmp_code[1])
  550         {
  551             g_free (tmp_path);
  552             tmp_path =
  553                 g_strconcat (main_path_data (), G_DIR_SEPARATOR_S, lang[i].code, file_end, NULL);
  554             fh = (FILE *) g_fopen (tmp_path, "r");
  555         }
  556     }
  557     g_free (tmp_code);
  558     g_free (tmp_path);
  559     i--;
  560     if (fh)
  561         g_message ("applying similar file: %s%s", lang[i].code, file_end);
  562     return (fh);
  563 }
  564 
  565 /**********************************************************************
  566  * Find a file whose language prefix is similar to the current one, returnig
  567  * its name
  568  */
  569 gchar *
  570 trans_lang_get_similar_file_name (const gchar * file_end)
  571 {
  572     gint i;
  573     gchar *tmp_code;
  574     gchar *tmp_path = NULL;
  575 
  576     tmp_code = main_preferences_get_string ("interface", "language");
  577     for (i = 0; i < lang_num; i++)
  578     {
  579         if (g_str_equal (lang[i].code, tmp_code))
  580             continue;
  581         if (lang[i].code[0] == tmp_code[0] && lang[i].code[1] == tmp_code[1])
  582         {
  583             g_free (tmp_path);
  584             tmp_path =
  585                 g_strconcat (main_path_data (), G_DIR_SEPARATOR_S, lang[i].code, file_end, NULL);
  586             if (g_file_test (tmp_path, G_FILE_TEST_IS_REGULAR))
  587                 break;
  588         }
  589     }
  590     if (tmp_path == NULL)
  591         tmp_path = g_strconcat (main_path_data (), G_DIR_SEPARATOR_S, "C", file_end, NULL);
  592     g_free (tmp_code);
  593     return (tmp_path);
  594 }
  595 
  596 /**********************************************************************
  597  * Reads the text of a file to be presented at some dialog,
  598  * accordingly to the environment language.
  599  * 'text': new buffer where the text is copied into.
  600  * 'file_end': how the file name ends
  601  */
  602 
  603 gchar *
  604 trans_read_text (const gchar * file_end)
  605 {
  606     gchar *buf;
  607     gchar *tmp_name = NULL;
  608     gchar *tmp_path = NULL;
  609     gchar *tmp_code;
  610     FILE *fh;
  611 
  612     gchar *basic1 = _(
  613 "The basic course focuses on having you read the characters presented to you on screen "
  614 "and typing the corresponding keys. Remember to keep your hands correctly oriented "
  615 "on the home row of the keyboard at all times (see introduction on main menu).");
  616     gchar *basic2 = _(
  617 "The key set used in each series will be shown in the above message line. "
  618 "The [Space], [Shift] and [Enter] keys may not show up there but are used very often.");
  619     gchar *basic3 = _(
  620 "The message line below follows and echoes your key presses. "
  621 "If required, it changes and displays instructions for actions required from you.");
  622 
  623     gchar *adapt1 = _(
  624 "Here you may practice and improve your memorization of all keys. "
  625 "There will be sentences presented with nonsense words which mix some numbers and symbols.");
  626     gchar *adapt2 = _(
  627 "In order to keep the lesson contents language and keyboard independent, "
  628 "accented letter combinations will probably not appear. For real word sentences, "
  629 "please use the fourth option of the main menu (about fluidness).");
  630     gchar *adapt3 = _(
  631 "After each exercise there will be a brief statistics panel "
  632 "reviewing your performance along with some relevant comments.");
  633 
  634     gchar *velo1 = _(
  635 "This exercise is very similar to the second one, for adaptability. "
  636 "The difference is that here you'll type real words.");
  637     gchar *velo2 = _(
  638 "The default language is the actual one of the interface. "
  639 "But you may select any other texts with words you would like to use. "
  640 "Press the 'Other' option above and add files containing those texts.");
  641     gchar *velo3 = _(
  642 "With this exercise the focus is on speed. "
  643 "So, you are supposed to type really fast and I will only flatter you when you deserve it!");
  644 
  645     gchar *fluid1 = _(
  646 "We will now use complete sentences and paragraphs which make logical sense. "
  647 "This may distract you while you type if you try to understand what you are entering. "
  648 "The previous exercises were aimed at getting you to type without interpreting and analyzing the content.");
  649     gchar *fluid2 = _(
  650 "We do not mean to imply that the typists must behave like a robot, without understanding what they type. "
  651 "We do aim to develop the skill of typing, making it an automatic reflex akin to the acts of walking, talking, etc. "
  652 "After reaching this goal, the act of typing will become automatic and require little concentration. "
  653 "Then you will be able to pay attention to the real meaning of the text.");
  654     gchar *fluid3 = _("These exercises are longer. Each exercise consists of three paragraphs and "
  655 "the emphasis is placed on correctness and rhythm, with a minimum speed requirement. "
  656 "Here you will be required to use the backspace key to correct any mistakes. "
  657 "In other words, only input without error will be accepted.");
  658 
  659     if (g_str_equal (file_end, "_basic_intro.txt"))
  660         return (g_strdup_printf ("%s\n%s\n%s", basic1, basic2, basic3));
  661 
  662     if (g_str_equal (file_end, "_adapt_intro.txt"))
  663         return (g_strdup_printf ("%s\n%s\n%s", adapt1, adapt2, adapt3));
  664 
  665     if (g_str_equal (file_end, "_velo_intro.txt"))
  666         return (g_strdup_printf ("%s\n%s\n%s", velo1, velo2, velo3));
  667 
  668     if (g_str_equal (file_end, "_fluid_intro.txt"))
  669         return (g_strdup_printf ("%s\n%s\n%s", fluid1, fluid2, fluid3));
  670 
  671     /* Use text files
  672      */
  673     tmp_code = main_preferences_get_string ("interface", "language");
  674     tmp_name = g_strconcat (tmp_code, file_end, NULL);
  675 
  676     /* Try at HOME
  677      */
  678     tmp_path = g_build_filename (main_path_user (), tmp_name, NULL);
  679     fh = (FILE *) g_fopen (tmp_path, "r");
  680 
  681     /* Try at PACKAGE_DATA
  682      */
  683     if (fh == NULL)
  684     {
  685         g_free (tmp_path);
  686         tmp_path = g_build_filename (main_path_data (), tmp_name, NULL);
  687         fh = (FILE *) g_fopen (tmp_path, "r");
  688     }
  689 
  690     /*
  691      * Try other "flavors" of the same language
  692      */
  693     if (fh == NULL && strlen (tmp_code) > 1)
  694         fh = trans_lang_get_similar_file (file_end);
  695 
  696     /*
  697      * Default to C
  698      */
  699     if (fh == NULL && ! g_str_equal (tmp_code, "C"))
  700     {
  701         g_message ("trans_read_text() --> couldn't open the data file: %s\n"
  702              " So, we have to apply the default one: C%s", tmp_name, file_end);
  703         main_preferences_set_string ("interface", "language", "C");
  704         buf = trans_read_text (file_end);
  705         main_preferences_set_string ("interface", "language", tmp_code);
  706         g_free (tmp_code);
  707         g_free (tmp_path);
  708         g_free (tmp_name);
  709         return buf;
  710     }
  711 
  712     if (fh == NULL)
  713         g_error ("trans_read_text() --> couldn't open the data file:\n %s", tmp_name);
  714 
  715     g_free (tmp_code);
  716     g_free (tmp_path);
  717     g_free (tmp_name);
  718 
  719     /*
  720      * Process the file
  721      */
  722     gsize bufsize = 16;
  723     gsize pos = 0;
  724     buf = g_malloc (bufsize);
  725     while (1)
  726     {
  727         gsize max = bufsize - pos - 1; // -1 for terminating zero
  728         gsize ct = fread (buf + pos, 1, max, fh);
  729         if (ct == 0)
  730             break;
  731         pos += ct;
  732         if (ct == max)
  733         {
  734             bufsize *= 2;
  735             buf = g_realloc (buf, bufsize);
  736         }
  737     }
  738     buf[pos] = 0;
  739     fclose (fh);
  740     return buf;
  741 }