[gcompris] core: now the configuration window's locale combo display the real language name instead of the loca



commit 89b2285f2b9f1edc5af75aed6cb95f0857497667
Author: Bruno Coudoin <bruno coudoin free fr>
Date:   Sun Aug 28 04:19:50 2011 +0200

    core: now the configuration window's locale combo display the real language name instead of the locale code.

 src/gcompris/board_config_combo.c    |  158 ++++++++++++++++++++++------------
 src/gcompris/board_config_wordlist.c |   82 ++++++++++++------
 src/gcompris/config.c                |  100 +++++++++++++++++++--
 src/gcompris/gcompris.h              |    5 +-
 4 files changed, 251 insertions(+), 94 deletions(-)
---
diff --git a/src/gcompris/board_config_combo.c b/src/gcompris/board_config_combo.c
index 96722d4..c84a739 100644
--- a/src/gcompris/board_config_combo.c
+++ b/src/gcompris/board_config_combo.c
@@ -26,16 +26,19 @@
 /***********************************************/
 
 /** \brief return the list of locales in which GCompris has been translated
- *         even partialy.
+ *         even partialy. A locale is returned only if the GCompris translation
+ *         has been installed.
+ *
  *
  * \note The list is calculated at the first call and must not be freed.
  *       Uppon next call, the same list is returned.
  *
- * \return a list containing the locales we suport
+ * \return a list containing the locales we suport: "fr_FR.UTF-8",
  */
 GList*
 gc_locale_gets_list(){
 
+  // Maintains the locale list "fr_FR.UTF-8", ...
   static GList *gcompris_locales_list = NULL;
 
   GcomprisProperties *properties = gc_prop_get();
@@ -47,7 +50,7 @@ gc_locale_gets_list(){
     return(gcompris_locales_list);
 
   /* There is no english locale but it exists anyway */
-  locales = g_list_append(locales, g_strdup("en"));
+  locales = g_list_append(locales,  g_strdup( "en_US") );
 
   textdomain_dir = g_dir_open (properties->package_locale_dir, 0, error);
   const gchar *fname;
@@ -62,51 +65,68 @@ gc_locale_gets_list(){
 
       catalog = g_strdup_printf("%s/LC_MESSAGES/gcompris.mo", fname_abs);
 
-      if (g_file_test(catalog, G_FILE_TEST_EXISTS)){
-      locales = g_list_append(locales, g_strdup(fname));
-      }
+      if ( g_file_test(catalog, G_FILE_TEST_EXISTS) && gc_locale_get_name(fname) )
+	{
+	  locales = g_list_append( locales, g_strdup( fname ) );
+	}
       g_free (fname_abs);
       g_free(catalog);
     }
   g_dir_close (textdomain_dir);
   }
 
-#if DEBUG	/* to find locales list when run from src directory */
-  if(g_file_test("po", G_FILE_TEST_IS_DIR))
-  {
-  	textdomain_dir= g_dir_open("po",0, error);
-	while((fname = g_dir_read_name(textdomain_dir)))
-	{
-		if(g_str_has_suffix(fname,".po"))
-			locales = g_list_append(locales, g_strndup(fname,2));
-	}
-	g_dir_close(textdomain_dir);
-
-  }
-#endif
   /* Save it for next call */
   gcompris_locales_list = locales;
 
   return locales;
 }
 
+/** \brief return the list of locales name in which GCompris has been translated
+ *         even partialy. A locale is returned only if the GCompris translation
+ *         has been installed.
+ *
+ *
+ * \note The list is calculated at each call because it depends on the locale
+ *       You must not free the list, it is freed internaly on next call.
+ *
+ * \return a list containing the locales we suport: "French", ...
+ */
+GList*
+gc_locale_gets_list_name(){
+
+  static GList *gcompris_locales_list_name = NULL;
+  GList *list;
+
+  if(gcompris_locales_list_name) {
+    g_list_free(gcompris_locales_list_name);
+    gcompris_locales_list_name = NULL;
+  }
+
+  for (list = gc_locale_gets_list(); list != NULL; list = list->next)
+    {
+      gcompris_locales_list_name =			\
+	g_list_insert_sorted(gcompris_locales_list_name,
+			     g_strdup( gc_locale_get_name( list->data) ),
+			     (GCompareFunc) g_strcmp0  );
+    }
+  return gcompris_locales_list_name;
+}
 
 void
 gc_board_config_combo_locales_changed(GtkComboBox *combobox,
-			       gpointer data)
+				      gpointer data)
 {
   _gc_boardconf_key *u = (_gc_boardconf_key*)data;
   gchar *the_key = g_strdup((gchar *)u->key);
-  gchar *value;
-  gint index = gtk_combo_box_get_active (combobox);
+  const gchar *value;
 
-  if (index == 0)
-    /* Default value of gcompris selected */
-    value = g_strdup ("NULL");
-  else
-    value = _get_active_text (combobox);
+  // Get back the locale from the locale name (French becomes fr_FR.UTF8)
+  value = gc_locale_get_locale( _get_active_text (combobox) );
+  if ( value == NULL || value[0] == '\0' )
+    value = "NULL";
 
-  g_hash_table_replace(u->config->hash_conf, (gpointer) the_key, (gpointer) value);
+  g_hash_table_replace(u->config->hash_conf,
+		       (gpointer) the_key, (gpointer) g_strdup( value ) );
 }
 
 /* key = "locale" */
@@ -120,15 +140,19 @@ gc_board_config_combo_locales(GcomprisBoardConf *config, gchar *init)
   GtkWidget *label_combo;
   gint init_index = 0;
 
-  strings = gc_locale_gets_list();
+  strings = gc_locale_gets_list_name();
 
-  strings = g_list_prepend( strings, _("Default"));
+  /* System default */
+  strings = g_list_prepend( strings, g_strdup( gc_locale_get_name("") ) );
 
   if (init)
-    init_index = g_list_position(strings,
-				 g_list_find_custom(strings,
-						    (gconstpointer) init,
-						    (GCompareFunc) strcmp));
+    {
+      const gchar *init_name = gc_locale_get_name( init );
+      init_index = g_list_position(strings,
+				   g_list_find_custom(strings,
+						      (gconstpointer) init_name,
+						      (GCompareFunc) g_strcmp0));
+    }
 
   if (init_index < 0)
     init_index=0;
@@ -168,8 +192,8 @@ gc_board_config_combo_locales(GcomprisBoardConf *config, gchar *init)
 
 
   for (list = strings; list != NULL; list = list->next)
-    gtk_combo_box_append_text       (GTK_COMBO_BOX(combobox),
-				     list->data);
+    gtk_combo_box_append_text (GTK_COMBO_BOX(combobox),
+			       list->data);
 
   if (g_list_length(strings) > COMBOBOX_COL_MAX)
     gtk_combo_box_set_wrap_width    (GTK_COMBO_BOX(combobox),
@@ -301,7 +325,7 @@ gc_locale_change(gchar *locale)
   if (!locale)
     return;
 
-  if (strcmp(locale, "NULL") == 0){
+  if (g_strcmp0(locale, "NULL") == 0){
     gc_locale_reset();
     return;
   }
@@ -330,7 +354,7 @@ gc_locale_reset()
  *              filename that includes a $LOCALE in it like:
  *              voices/$LOCALE/colors/blue.ogg
  *
- * \return a list of locale
+ * \return a list of locale name (French, English, ...)
  */
 GList*
 gc_locale_gets_asset_list(const gchar *filename)
@@ -353,10 +377,22 @@ gc_locale_gets_asset_list(const gchar *filename)
 	  /* try with the locale */
 	  g_strlcpy(locale, list->data, sizeof(locale));
 	  filename2 = g_strjoinv(locale, tmp);
-	  g_warning("trying locale file '%s'\n", filename2);
 	  abs_filename = gc_file_find_absolute(filename2);
 	  g_free(filename2);
 
+	  // Try the short locale
+	  if ( ! abs_filename )
+	    {
+	      gchar **locale_short = g_strsplit_set(locale, "_", 2);
+	      if(g_strv_length(locale_short) >= 1)
+		{
+		  filename2 = g_strjoinv(locale_short[0], tmp);
+		  abs_filename = gc_file_find_absolute(filename2);
+		  g_free(filename2);
+		  g_strfreev(locale_short);
+		}
+	    }
+
 	  g_strfreev(tmp);
 	}
       else
@@ -366,15 +402,12 @@ gc_locale_gets_asset_list(const gchar *filename)
 
       if(abs_filename)
       {
-	/* It would be cleaner to provide the real locale name but then we need a way
-	 * to get back the locale code from it's name and from the boards
-	 *
-	 * locales_asset = g_list_append(locales_asset, gc_locale_get_name(list->data));
-	 *
-	 */
-	locales_asset = g_list_append(locales_asset, list->data);
+	locales_asset = \
+	  g_list_insert_sorted(locales_asset,
+			       g_strdup( gc_locale_get_name( list->data) ),
+			       (GCompareFunc) g_strcmp0  );
 	g_free(abs_filename);
-	}
+      }
     }
 
 
@@ -382,9 +415,10 @@ gc_locale_gets_asset_list(const gchar *filename)
 }
 
 /* key = "locale_sound" */
-GtkComboBox *gc_board_config_combo_locales_asset(GcomprisBoardConf *config, const gchar *label,
-					  gchar *init,
-					  const gchar *file)
+GtkComboBox *gc_board_config_combo_locales_asset(GcomprisBoardConf *config,
+						 const gchar *label,
+						 gchar *init,
+						 const gchar *file)
 {
   g_return_val_if_fail(config, NULL);
   GtkWidget *combobox;
@@ -395,14 +429,15 @@ GtkComboBox *gc_board_config_combo_locales_asset(GcomprisBoardConf *config, cons
 
   strings = gc_locale_gets_asset_list(file);
 
-  strings = g_list_prepend( strings, _("Default"));
+  strings = g_list_prepend( strings, g_strdup ( gc_locale_get_name("") ) );
 
   if (init)
     {
+      const gchar *init_name = gc_locale_get_name( init );
       init_index =  g_list_position(strings,
 				    g_list_find_custom(strings,
-						       (gconstpointer)init,
-						       (GCompareFunc) strcmp));
+						       (gconstpointer)init_name,
+						       (GCompareFunc) g_strcmp0));
     }
 
   if (init_index < 0)
@@ -476,13 +511,19 @@ _combo_box_changed(GtkComboBox *combobox,
   _gc_boardconf_key *u = (_gc_boardconf_key*)data;
   gchar *the_key = g_strdup(u->key);
 
-  gchar *value = g_strdup_printf("%s", _get_active_text (combobox));
+  // Get back the locale from the locale name (French becomes fr_FR.UTF8)
+  const gchar *value = gc_locale_get_locale( _get_active_text(combobox) );
 
-  g_hash_table_replace(u->config->hash_conf, (gpointer) the_key, (gpointer) value);
+  if ( value == NULL || value[0] == '\0' )
+    value = "NULL";
+
+  g_hash_table_replace(u->config->hash_conf,
+		       (gpointer) the_key, (gpointer) g_strdup ( value ) );
 }
 
 
-GtkComboBox *gc_board_config_combo_box(GcomprisBoardConf *config, const gchar *label, GList *strings, gchar *key, gchar *init)
+GtkComboBox *gc_board_config_combo_box(GcomprisBoardConf *config,
+				       const gchar *label, GList *strings, gchar *key, gchar *init)
 {
   g_return_val_if_fail(config, NULL);
   check_key(key);
@@ -493,7 +534,10 @@ GtkComboBox *gc_board_config_combo_box(GcomprisBoardConf *config, const gchar *l
   gint init_index = 0;
 
   if (init)
-    init_index =  g_list_position ( strings, g_list_find_custom ( strings,(gconstpointer)  init, (GCompareFunc) strcmp));
+    init_index = \
+      g_list_position ( strings,
+			g_list_find_custom ( strings,(gconstpointer) init,
+					     (GCompareFunc) g_strcmp0));
 
   if (init_index < 0)
     init_index=0;
diff --git a/src/gcompris/board_config_wordlist.c b/src/gcompris/board_config_wordlist.c
index a6364b2..39351f2 100644
--- a/src/gcompris/board_config_wordlist.c
+++ b/src/gcompris/board_config_wordlist.c
@@ -63,24 +63,38 @@ static void _combo_level_changed(GtkComboBox *combo_level, gpointer user_data)
 	gtk_widget_set_sensitive(GTK_WIDGET(w->button), FALSE);
 }
 
-static void _combo_lang_changed(GtkComboBox *combo_lang, gpointer user_data)
+static void
+_combo_lang_changed(GtkComboBox *combo_lang, gpointer user_data)
 {
 	user_param_type_wordlist *w = (user_param_type_wordlist*)user_data;
-	gchar * lang, *filename, *temp, **tmp;
+	const gchar *locale;
+	gchar *filename, *temp, **tmp;
 	int i;
 
 	if(gtk_combo_box_get_active(combo_lang)<0)
 		return;
 	/* get the filename of the xml */
-	lang =_get_active_text(combo_lang);
+	locale = gc_locale_get_locale( _get_active_text(combo_lang) );
 	if((tmp = g_strsplit(w->files, "$LOCALE", -1)))
 	{
-		filename = g_strjoinv(lang, tmp);
-		g_strfreev(tmp);
+	  // Try the short locale
+	  gchar *lang_short = gc_locale_short(locale);
+	  filename = g_strjoinv(lang_short, tmp);
+	  gchar *f_short = gc_file_find_absolute(filename);
+	  if ( ! f_short )
+	    {
+	      // Try the long locale
+	      g_free(filename);
+	      gchar *lang_long = gc_locale_long(locale);
+	      filename = g_strjoinv(lang_long, tmp);
+	      f_short = gc_file_find_absolute(filename);
+	    }
+	  g_free(f_short);
+
+	  g_strfreev(tmp);
 	}
 	else
 		filename = g_strdup(w->files);
-	g_free(lang);
 
 	/* clear combo level entry */
 	if(w->wordlist)
@@ -92,6 +106,9 @@ static void _combo_lang_changed(GtkComboBox *combo_lang, gpointer user_data)
 	w->wordlist = gc_wordlist_get_from_file(filename);
 	g_free(filename);
 
+	if ( ! w->wordlist )
+	  g_error("Failed to find the wordlist file '%s'", filename);
+
 	/* combo level */
 	for(i=1; i <= w->wordlist->number_of_level; i++)
 	{
@@ -164,6 +181,37 @@ static void _destroy(GtkWidget *w, gpointer data)
 	g_free(u);
 }
 
+/**
+ * Create a combo that let the user select the language
+ */
+static GtkWidget*
+_create_lang_combo(const gchar *files) {
+  GtkWidget *combo_lang = gtk_combo_box_new_text();
+  GList *file_list;
+  GList *list;
+  const gchar *locale_name = gc_locale_get_name(  gc_locale_get() );
+
+  file_list = gc_locale_gets_asset_list(files);
+  for(list = file_list; list; list = list->next)
+    {
+      gtk_combo_box_append_text(GTK_COMBO_BOX(combo_lang), list->data);
+      if(g_strcmp0( list->data, locale_name)==0)
+	{
+	  gtk_combo_box_set_active(GTK_COMBO_BOX(combo_lang),
+				   g_list_position(file_list, list));
+	}
+    }
+  if (g_list_length(file_list) > COMBOBOX_COL_MAX)
+    gtk_combo_box_set_wrap_width    (GTK_COMBO_BOX(combo_lang),
+				     g_list_length(file_list) / COMBOBOX_COL_MAX +1 );
+
+  g_list_free(file_list);
+
+  gtk_widget_show(combo_lang);
+
+  return combo_lang;
+}
+
 /* wordlist edit */
 GtkWidget *gc_board_config_wordlist(GcomprisBoardConf *config, const gchar *files)
 {
@@ -172,9 +220,7 @@ GtkWidget *gc_board_config_wordlist(GcomprisBoardConf *config, const gchar *file
 	GtkWidget *hbox, *vbox, *frame;
 	GtkWidget *textview;
 	GtkWidget *button;
-	GList *file_list, *list;
 	user_param_type_wordlist *user_data;
-	const gchar *locale;
 
 	/* frame */
 	frame = gtk_frame_new(_("Configure the list of words"));
@@ -186,25 +232,7 @@ GtkWidget *gc_board_config_wordlist(GcomprisBoardConf *config, const gchar *file
 
 	gtk_container_add(GTK_CONTAINER(frame), vbox);
 	/* Combo_box lang */
-	combo_lang = gtk_combo_box_new_text();
-
-	locale = gc_locale_get();
-	file_list = gc_locale_gets_asset_list(files);
-	for(list = file_list; list; list = list->next)
-	{
-		gtk_combo_box_append_text(GTK_COMBO_BOX(combo_lang), list->data);
-		if(strncmp((char*)list->data, locale,2)==0)
-		{
-			gtk_combo_box_set_active(GTK_COMBO_BOX(combo_lang), g_list_position(file_list, list));
-		}
-	}
-	if (g_list_length(file_list) > COMBOBOX_COL_MAX)
-		gtk_combo_box_set_wrap_width    (GTK_COMBO_BOX(combo_lang),
-				g_list_length(file_list) / COMBOBOX_COL_MAX +1 );
-
-	g_list_free(file_list);
-
-	gtk_widget_show(combo_lang);
+	combo_lang = _create_lang_combo(files);
 	hbox = gtk_hbox_new(FALSE, 8);
 	label = gtk_label_new(_("Choice of the language"));
 	gtk_widget_show(label);
diff --git a/src/gcompris/config.c b/src/gcompris/config.c
index 87a7414..ada0d85 100644
--- a/src/gcompris/config.c
+++ b/src/gcompris/config.c
@@ -484,27 +484,109 @@ void gc_config_stop ()
 
 /**
  * Given the locale name, return the full translated name
- * If not found, simply return the name
+ * e.g In the French locale, gc_locale_get_name("fr_FR.UTF8") returns "FranÃais"
+ * If not found, return NULL
+ * The result must not be freed.
  */
-gchar*
-gc_locale_get_name(gchar *locale)
+const gchar*
+gc_locale_get_name(const gchar *locale)
 {
   guint i = 0;
 
-  /* en (US) is not in the Linguas table */
-  if(locale[0] != '\0' && !strncmp(locale, "en", strlen(locale)))
-    return(_("English (United State)"));
+  if ( !locale )
+    return NULL;
+
+  /*
+   * On some systems, locales are returned as fr_FR.utf8
+   * but in GCompris we use fr_FR.UTF-8
+   * Do our best to support both
+   */
+  const gchar *dot_char = g_strrstr ( locale, ".");
 
   while(linguas[i] != NULL)
     {
 
-      if(!strncmp(locale, linguas[i], strlen(locale)))
+      if( !g_ascii_strncasecmp(locale, linguas[i],
+			       (dot_char ? dot_char - locale : strlen(locale)) ) )
 	return(gettext(linguas[i+1]));
 
       i=i+2;
     }
-  // Oups this locale is not in the table. Return the first one (system default)
-  return(linguas[1]);
+  // Oups this locale is not in the table.
+  return( NULL );
+}
+
+/**
+ * Given the locale code, return the short version
+ * e.g In the French locale, gc_locale_short("fr_FR.UTF8") returns "fr"
+ * The result must be freed.
+ */
+gchar*
+gc_locale_short(const gchar *locale)
+{
+  if ( ! locale )
+    return NULL;
+
+  gchar **locale_short = g_strsplit_set(locale, "_", 2);
+  if(g_strv_length(locale_short) >= 1)
+    {
+      gchar *result = g_strdup(locale_short[0]);
+      g_strfreev(locale_short);
+      return result;
+    }
+  g_strfreev(locale_short);
+
+  // We found no '_', this is already a short version
+  return ( g_strdup(locale) );
+}
+
+/**
+ * Given the locale code, return the long version
+ * e.g In the French locale, gc_locale_long("fr_FR.UTF8") returns "fr_FR"
+ * The result must be freed.
+ */
+gchar*
+gc_locale_long(const gchar *locale)
+{
+  if ( ! locale )
+    return NULL;
+
+  gchar **locale_long = g_strsplit_set(locale, ".", 2);
+  if(g_strv_length(locale_long) >= 1)
+    {
+      gchar *result = g_strdup(locale_long[0]);
+      g_strfreev(locale_long);
+      return result;
+    }
+  g_strfreev(locale_long);
+
+  // We found no '.', this is already a short version
+  return ( g_strdup(locale) );
+}
+
+/**
+ * Given the locale translated name, return the locale name
+ * e.g In the French local, gc_locale_get_locale("FranÃais") returns "fr_FR.UTF8"
+ * If not found, return NULL
+ * The result must not be freed.
+ */
+const gchar*
+gc_locale_get_locale(const gchar *name)
+{
+  guint i = 0;
+
+  if ( !name )
+    return NULL;
+
+  while(linguas[i] != NULL)
+    {
+      if( !strncmp(name, gettext(linguas[i+1]), strlen(name)) )
+	 return( linguas[i] );
+
+      i=i+2;
+    }
+  // Oups this locale is not in the table.
+  return( NULL );
 }
 
 /*-------------------------------------------------------------------------------*/
diff --git a/src/gcompris/gcompris.h b/src/gcompris/gcompris.h
index 8f4b914..e914ff7 100644
--- a/src/gcompris/gcompris.h
+++ b/src/gcompris/gcompris.h
@@ -170,7 +170,10 @@ GtkWidget	*gc_get_window(void);
 const gchar	*gc_locale_get(void);
 void		 gc_locale_set(gchar *locale);
 char		*gc_locale_get_user_default(void);
-gchar		*gc_locale_get_name(gchar *locale);
+const gchar	*gc_locale_get_name(const gchar *locale);
+const gchar	*gc_locale_get_locale(const gchar *name);
+gchar		*gc_locale_short(const gchar *locale);
+gchar		*gc_locale_long(const gchar *locale);
 
 guint		 gc_cursor_get();
 void		 gc_cursor_set(guint gdk_cursor_type);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]