From 7ee1915ef8101e1cac5b9a2d5c858aac371d6367 Mon Sep 17 00:00:00 2001 From: Christian Persch Date: Thu, 25 Nov 2004 13:51:57 +0000 Subject: Check for iso-codes package. 2004-11-25 Christian Persch * configure.ac: Check for iso-codes package. * data/glade/prefs-dialog.glade: * lib/ephy-langs.c: (ephy_langs_bind_iso_domains), (read_iso_639_entry), (read_iso_3166_entry), (load_iso_entries), (ephy_langs_iso_639_table), (ephy_langs_iso_3166_table): * lib/ephy-langs.h: Load language and locales list from iso-codes package, if available. * src/prefs-dialog.c: (prefs_dialog_finalize), (add_lang_dialog_selection_changed), (add_lang_dialog_response_cb), (get_name_for_lang_code), (add_system_language_entry), (setup_add_language_dialog), (create_language_section): If the iso-codes package is available, use that to translate language names and offer a wider variety of languages. Fixes bug #155498. --- ChangeLog | 23 +++ configure.ac | 29 +++- data/glade/prefs-dialog.glade | 8 +- lib/ephy-langs.c | 204 +++++++++++++++++++++++++++ lib/ephy-langs.h | 7 + src/prefs-dialog.c | 318 ++++++++++++++++++++++++++++++++++++++++-- 6 files changed, 575 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 887037b04..fc108e412 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2004-11-25 Christian Persch + + * configure.ac: + + Check for iso-codes package. + + * data/glade/prefs-dialog.glade: + * lib/ephy-langs.c: (ephy_langs_bind_iso_domains), + (read_iso_639_entry), (read_iso_3166_entry), (load_iso_entries), + (ephy_langs_iso_639_table), (ephy_langs_iso_3166_table): + * lib/ephy-langs.h: + + Load language and locales list from iso-codes package, if available. + + * src/prefs-dialog.c: (prefs_dialog_finalize), + (add_lang_dialog_selection_changed), (add_lang_dialog_response_cb), + (get_name_for_lang_code), (add_system_language_entry), + (setup_add_language_dialog), (create_language_section): + + If the iso-codes package is available, use that to translate + language names and offer a wider variety of languages. + Fixes bug #155498. + 2004-11-24 Christian Persch * configure.ac: diff --git a/configure.ac b/configure.ac index fb186d61e..b2c876a76 100644 --- a/configure.ac +++ b/configure.ac @@ -364,7 +364,7 @@ AC_MSG_RESULT([$result]) dnl Added in 1.8a6 on trunk dnl https://bugzilla.mozilla.org/show_bug.cgi?id=223310 -AC_MSG_CHECKING([whether nsIKeygenThread takes an nsIObserver]) +AC_MSG_CHECKING([whether nsIKeygenThread::StartKeyGeneration takes an nsIObserver]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM( @@ -429,9 +429,34 @@ fi dnl ******************************* dnl Internationalization dnl ******************************* -dnl Add the languages which your application supports here. +AC_MSG_CHECKING([for iso-codes package]) +have_iso_codes=no +if $PKG_CONFIG --exists iso-codes --atleast-version=0.35; then + have_iso_codes=yes +fi +AC_MSG_RESULT([$have_iso_codes]) + +if test "x$have_iso_codes" = "xyes"; then + AC_MSG_CHECKING([whether iso-codes has iso-639 and iso-3166 domains]) + if $PKG_CONFIG --variable=domains iso-codes | grep -q 639 && \ + $PKG_CONFIG --variable=domains iso-codes | grep -q 3166 ; then + result=yes + else + result=no + have_iso_codes=no + fi + AC_MSG_RESULT([$result]) +fi + +if test "x$have_iso_codes" = "xyes"; then + AC_DEFINE_UNQUOTED([ISO_CODES_PREFIX],["`$PKG_CONFIG --variable=prefix iso-codes`"],[ISO codes prefix]) + AC_DEFINE([HAVE_ISO_CODES],[1],[Define if you have the iso-codes package]) +fi + +dnl Add the languages which your application supports here. ALL_LINGUAS="am ar az be bg bn bs ca cs cy da de el en_CA en_GB es et eu fa fi fr ga gu he hi hr hu id is it ja ko li lt mi mk ml mn ms nb ne nl nn no pa pl pt pt_BR ro ru sk sl sq sr sr@Latn sv ta th tk tr uk vi wa zh_CN zh_TW" + GETTEXT_PACKAGE=epiphany AC_SUBST([GETTEXT_PACKAGE]) AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE], ["$GETTEXT_PACKAGE"], [Gettext package]) diff --git a/data/glade/prefs-dialog.glade b/data/glade/prefs-dialog.glade index 8980fb16f..3e3cdebd6 100644 --- a/data/glade/prefs-dialog.glade +++ b/data/glade/prefs-dialog.glade @@ -2099,7 +2099,7 @@ GTK_WIN_POS_NONE False True - False + True True False False @@ -2132,15 +2132,15 @@ - + True True True - gtk-ok + gtk-add True GTK_RELIEF_NORMAL True - -5 + -3 diff --git a/lib/ephy-langs.c b/lib/ephy-langs.c index 129ab525d..793f179ce 100644 --- a/lib/ephy-langs.c +++ b/lib/ephy-langs.c @@ -22,10 +22,16 @@ #include "ephy-langs.h" +#include "ephy-debug.h" + #include #include +#ifdef HAVE_ISO_CODES +#include +#endif + static const EphyFontsLanguageInfo font_languages [] = { { N_("Arabic"), "ar" }, @@ -195,3 +201,201 @@ ephy_langs_get_languages (void) return (char **) g_array_free (array, FALSE); } + +#ifdef HAVE_ISO_CODES + +#define ISOCODESLOCALEDIR ISO_CODES_PREFIX "/share/locale" + +static void +ephy_langs_bind_iso_domains (void) +{ +#ifdef ENABLE_NLS + static gboolean bound = FALSE; + + if (bound == FALSE) + { + bindtextdomain (ISO_639_DOMAIN, ISOCODESLOCALEDIR); + bind_textdomain_codeset (ISO_639_DOMAIN, "UTF-8"); + + bindtextdomain(ISO_3166_DOMAIN, ISOCODESLOCALEDIR); + bind_textdomain_codeset (ISO_3166_DOMAIN, "UTF-8"); + + bound = TRUE; + } +#endif +} + +static void +read_iso_639_entry (xmlTextReaderPtr reader, + GHashTable *table) +{ + xmlChar *code, *name; + + code = xmlTextReaderGetAttribute (reader, (const xmlChar *) "iso_639_1_code"); + name = xmlTextReaderGetAttribute (reader, (const xmlChar *) "name"); + + /* Get iso-639-2 code */ + if (code == NULL || code[0] == '\0') + { + xmlFree (code); + /* FIXME: use the 2T or 2B code? */ + code = xmlTextReaderGetAttribute (reader, (const xmlChar *) "iso_639_2T_code"); + } + + if (code != NULL && code[0] != '\0' && name != NULL && name[0] != '\0') + { + g_hash_table_insert (table, code, name); + } + else + { + xmlFree (code); + xmlFree (name); + } +} + +static void +read_iso_3166_entry (xmlTextReaderPtr reader, + GHashTable *table) +{ + xmlChar *code, *name; + + code = xmlTextReaderGetAttribute (reader, (const xmlChar *) "alpha_2_code"); + name = xmlTextReaderGetAttribute (reader, (const xmlChar *) "name"); + + if (code != NULL && code[0] != '\0' && name != NULL && name[0] != '\0') + { + char *lcode; + + lcode = g_ascii_strdown ((char *) code, -1); + xmlFree (code); + + g_hash_table_insert (table, lcode, name); + } + else + { + xmlFree (code); + xmlFree (name); + } + +} + +typedef enum +{ + STATE_START, + STATE_STOP, + STATE_ENTRIES, +} ParserState; + +static gboolean +load_iso_entries (int iso, + GFunc read_entry_func, + gpointer user_data) +{ + xmlTextReaderPtr reader; + ParserState state = STATE_START; + xmlChar iso_entries[32], iso_entry[32]; + char *filename; + int ret = -1; + + LOG ("Loading ISO-%d codes", iso) + + START_PROFILER ("Loading ISO codes") + + filename = g_strdup_printf (ISO_CODES_PREFIX "/share/xml/iso-codes/iso_%d.xml", iso); + reader = xmlNewTextReaderFilename (filename); + if (reader == NULL) goto out; + + xmlStrPrintf (iso_entries, sizeof (iso_entries), "iso_%d_entries", iso); + xmlStrPrintf (iso_entry, sizeof (iso_entry), "iso_%d_entry", iso); + + ret = xmlTextReaderRead (reader); + + while (ret == 1) + { + const xmlChar *tag; + xmlReaderTypes type; + + tag = xmlTextReaderConstName (reader); + type = xmlTextReaderNodeType (reader); + + if (state == STATE_ENTRIES && + type == XML_READER_TYPE_ELEMENT && + xmlStrEqual (tag, iso_entry)) + { + read_entry_func (reader, user_data); + } + else if (state == STATE_START && + type == XML_READER_TYPE_ELEMENT && + xmlStrEqual (tag, iso_entries)) + { + state = STATE_ENTRIES; + } + else if (state == STATE_ENTRIES && + type == XML_READER_TYPE_END_ELEMENT && + xmlStrEqual (tag, iso_entries)) + { + state = STATE_STOP; + } + else if (type == XML_READER_TYPE_SIGNIFICANT_WHITESPACE || + type == XML_READER_TYPE_WHITESPACE || + type == XML_READER_TYPE_TEXT || + type == XML_READER_TYPE_COMMENT) + { + /* eat it */ + } + else + { + /* ignore it */ + } + + ret = xmlTextReaderRead (reader); + } + + xmlFreeTextReader (reader); + +out: + if (ret < 0 || state != STATE_STOP) + { + g_warning ("Failed to load ISO-%d codes from %s!\n", + iso, filename); + return FALSE; + } + + g_free (filename); + + STOP_PROFILER ("Loading ISO codes") + + return TRUE; +} + +GHashTable * +ephy_langs_iso_639_table (void) +{ + GHashTable *table; + + ephy_langs_bind_iso_domains (); + table = g_hash_table_new_full (g_str_hash, g_str_equal, + (GDestroyNotify) xmlFree, + (GDestroyNotify) xmlFree); + + load_iso_entries (639, (GFunc) read_iso_639_entry, table); + + return table; +} + +GHashTable * +ephy_langs_iso_3166_table (void) +{ + GHashTable *table; + + ephy_langs_bind_iso_domains (); + table = g_hash_table_new_full (g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) xmlFree); + + load_iso_entries (3166, (GFunc) read_iso_3166_entry, table); + + return table; +} + +#endif /* HAVE_ISO_CODES */ diff --git a/lib/ephy-langs.h b/lib/ephy-langs.h index baefdd78d..758501509 100644 --- a/lib/ephy-langs.h +++ b/lib/ephy-langs.h @@ -26,6 +26,9 @@ G_BEGIN_DECLS +#define ISO_639_DOMAIN "iso_639" +#define ISO_3166_DOMAIN "iso_3166" + typedef struct { char *title; @@ -42,6 +45,10 @@ void ephy_langs_sanitise (GArray *array); char **ephy_langs_get_languages (void); +GHashTable *ephy_langs_iso_639_table (void); + +GHashTable *ephy_langs_iso_3166_table (void); + G_END_DECLS #endif diff --git a/src/prefs-dialog.c b/src/prefs-dialog.c index a2ea03acf..f8a863d1a 100644 --- a/src/prefs-dialog.c +++ b/src/prefs-dialog.c @@ -86,6 +86,190 @@ void language_editor_up_button_clicked_cb (GtkWidget *button, void language_editor_down_button_clicked_cb (GtkWidget *button, PrefsDialog *pd); +#ifdef HAVE_ISO_CODES +static const char *languages[] = +{ + /* If you're missing your language/locale combination, file a bug at + * http://bugzilla.gnome.org/enter_bug.cgi?product=epiphany + */ + "af", + "am", + "an", + "ar", + "ar-ae", + "ar-bh", + "ar-dz", + "ar-eg", + "ar-iq", + "ar-jo", + "ar-kw", + "ar-lb", + "ar-ly", + "ar-ma", + "ar-om", + "ar-qa", + "ar-sa", + "ar-sy", + "ar-tn", + "ar-ye", + "ast", + "az", + "be", + "bg", + "bn", + "bs", + "br", + "bs", + "ca", + "ce", + "ch", + "co", + "cs", + "cv", + "cy", + "da", + "de", + "de-at", + "de-ch", + "de-de", + "de-li", + "de-lu", + "el", + "en", + "en-au", + "en-bz", + "en-ca", + "en-gb", + "en-ie", + "en-jm", + "en-nz", + "en-ph", + "en-tt", + "en-us", + "en-za", + "en-zw", + "eo", + "es", + "es-ar", + "es-bo", + "es-cl", + "es-co", + "es-cr", + "es-do", + "es-ec", + "es-es", + "es-gt", + "es-hn", + "es-mx", + "es-ni", + "es-pa", + "es-pe", + "es-pr", + "es-py", + "es-sv", + "es-uy", + "es-ve", + "et", + "eu", + "fa", + "fi", + "fj", + "fo", + "fr", + "fr-be", + "fr-ca", + "fr-ch", + "fr-fr", + "fr-lu", + "fr-mc", + "fy", + "ga", + "gd", + "gl", + "gu", + "he", + "hsb", + "hi", + "hr", + "ht", + "hu", + "hy", + "ia", + "id", + "ie", + "is", + "it", + "it-ch", + "it-it", + "iu", + "ja", + "ka", + "kk", + "ko", + "ko-kp", + "ko-kr", + "ky", + "la", + "lb", + "li", + "lt", + "lv", + "mi", + "mk-mk", + "ml", + "mn", + "mo", + "mr", + "ms", + "nb", + "ne", + "ng", + "nl", + "nl-be", + "nn", + "no", + "nv", + "oc", + "om", + "pa", + "pl", + "pt", + "pt-br", + "qu", + "rm", + "ro", + "ru", + "sa", + "sc", + "sd", + "sg", + "sk", + "sl", + "so", + "sq", + "sr", + "sv", + "sv-fi", + "sw", + "ta", + "th", + "tk", + "tr", + "uk", + "ve", + "vi", + "vo", + "wa", + "xh", + "yi", + "zh", + "zh-cn", + "zh-hk", + "zh-sg", + "zh-tw", + "zu" +}; +#else static const struct { @@ -151,7 +335,7 @@ languages [] = { "zh-cn", N_("Simplified Chinese") }, { "zh-tw", N_("Traditional Chinese") } }; -static guint n_languages = G_N_ELEMENTS (languages); +#endif /* HAVE_ISO_CODES */ static const char *cookies_accept_enum [] = @@ -284,7 +468,8 @@ EphyDialogProperty properties [] = enum { LANGUAGE_DIALOG, - LANGUAGE_PROP + LANGUAGE_PROP, + LANGUAGE_ACCEPT_BUTTON_PROP }; static const @@ -292,6 +477,7 @@ EphyDialogProperty add_lang_props [] = { { "add_language_dialog", NULL, PT_NORMAL, 0 }, { "languages_treeview", NULL, PT_NORMAL, G_TYPE_STRING }, + { "add_button", NULL, PT_NORMAL, 0 }, { NULL } }; @@ -326,6 +512,10 @@ struct PrefsDialogPrivate GtkWidget *lang_remove_button; GtkWidget *lang_up_button; GtkWidget *lang_down_button; +#ifdef HAVE_ISO_CODES + GHashTable *iso_639_table; + GHashTable *iso_3166_table; +#endif }; static GObjectClass *parent_class = NULL; @@ -378,6 +568,11 @@ prefs_dialog_finalize (GObject *object) (gpointer *) &dialog->priv->download_dir_chooser); } +#ifdef HAVE_ISO_CODES + g_hash_table_destroy (dialog->priv->iso_639_table); + g_hash_table_destroy (dialog->priv->iso_3166_table); +#endif + G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -718,6 +913,19 @@ language_editor_update_buttons (PrefsDialog *dialog) gtk_widget_set_sensitive (dialog->priv->lang_down_button, can_move_down); } +static void +add_lang_dialog_selection_changed (GtkTreeSelection *selection, + EphyDialog *dialog) +{ + GtkWidget *button; + int n_selected; + + button = ephy_dialog_get_control (dialog, add_lang_props[LANGUAGE_ACCEPT_BUTTON_PROP].id); + + n_selected = gtk_tree_selection_count_selected_rows (selection); + gtk_widget_set_sensitive (button, n_selected > 0); +} + static void add_lang_dialog_response_cb (GtkWidget *widget, int response, @@ -732,7 +940,7 @@ add_lang_dialog_response_cb (GtkWidget *widget, g_return_if_fail (dialog != NULL); - if (response == GTK_RESPONSE_OK) + if (response == GTK_RESPONSE_ACCEPT) { treeview = GTK_TREE_VIEW (ephy_dialog_get_control (dialog, add_lang_props[LANGUAGE_PROP].id)); @@ -770,6 +978,60 @@ add_lang_dialog_response_cb (GtkWidget *widget, g_object_unref (dialog); } +#ifdef HAVE_ISO_CODES +static char * +get_name_for_lang_code (PrefsDialog *pd, + const char *code) +{ + char **str; + char *name; + const char *langname, *localename; + int len; + + str = g_strsplit (code, "-", -1); + len = g_strv_length (str); + g_return_val_if_fail (len != 0, NULL); + + langname = (const char *) g_hash_table_lookup (pd->priv->iso_639_table, str[0]); + + if (len == 1 && langname != NULL) + { + name = g_strdup (dgettext (ISO_639_DOMAIN, langname)); + } + else if (len == 2 && langname != NULL) + { + localename = (const char *) g_hash_table_lookup (pd->priv->iso_3166_table, str[1]); + + if (localename != NULL) + { + /* translators: the first %s is the language name, and the + * second %s is the locale name. Example: + * "French (France)" + */ + name = g_strdup_printf (Q_("language|%s (%s)"), + dgettext (ISO_639_DOMAIN, langname), + dgettext (ISO_3166_DOMAIN, localename)); + } + else + { + name = g_strdup_printf (Q_("language|%s (%s)"), + dgettext (ISO_639_DOMAIN, langname), str[1]); + } + } + else + { + /* translators: this refers to a user-define language code + * (one which isn't in our built-in list). + */ + name = g_strdup_printf (Q_("language|User defined (%s)"), code); + } + + g_strfreev (str); + + return name; +} +#endif /* HAVE_ISO_CODES */ + static void add_system_language_entry (GtkListStore *store) { @@ -784,8 +1046,8 @@ add_system_language_entry (GtkListStore *store) system = g_strjoinv (", ", sys_langs); text = g_strdup_printf - (ngettext ("System language [%s]", - "System languages [%s]", n_sys_langs), system); + (ngettext ("System language (%s)", + "System languages (%s)", n_sys_langs), system); gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, @@ -828,14 +1090,27 @@ setup_add_language_dialog (PrefsDialog *pd) store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING); - for (i = 0; i < n_languages; i++) + for (i = 0; i < G_N_ELEMENTS (languages); i++) { - gtk_list_store_append (store, &iter); +#ifdef HAVE_ISO_CODES + const char *code = languages[i]; + char *name; + name = get_name_for_lang_code (pd, code); + + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + COL_LANG_NAME, name, + COL_LANG_CODE, code, + -1); + g_free (name); +#else + gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, COL_LANG_NAME, _(languages[i].name), COL_LANG_CODE, languages[i].code, -1); +#endif /* HAVE_ISO_CODES */ } add_system_language_entry (store); @@ -868,6 +1143,10 @@ setup_add_language_dialog (PrefsDialog *pd) selection = gtk_tree_view_get_selection (treeview); gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE); + + add_lang_dialog_selection_changed (GTK_TREE_SELECTION (selection), dialog); + g_signal_connect (selection, "changed", + G_CALLBACK (add_lang_dialog_selection_changed), dialog); g_signal_connect (window, "response", G_CALLBACK (add_lang_dialog_response_cb), pd); @@ -1001,6 +1280,11 @@ create_language_section (EphyDialog *dialog) GtkTreeSelection *selection; GSList *list, *l, *ulist = NULL; +#ifdef HAVE_ISO_CODES + pd->priv->iso_639_table = ephy_langs_iso_639_table (); + pd->priv->iso_3166_table = ephy_langs_iso_3166_table (); +#endif + ephy_dialog_get_controls (dialog, properties[LANGUAGE_TREEVIEW_PROP].id, &treeview, @@ -1066,6 +1350,23 @@ create_language_section (EphyDialog *dialog) for (l = ulist; l != NULL; l = l->next) { const char *code = (const char *) l->data; + +#ifdef HAVE_ISO_CODES + if (strcmp (code, "system") == 0) + { + add_system_language_entry (store); + } + else if (code[0] != '\0') + { + char *text; + + text = get_name_for_lang_code (pd, code); + language_editor_add (pd, code, text); + g_free (text); + } + +#else /* !HAVE_ISO_CODES */ + int i; for (i = 0; i < n_languages; i++) @@ -1080,7 +1381,7 @@ create_language_section (EphyDialog *dialog) { char *text; - text = g_strdup_printf (_("Custom [%s]"), code); + text = g_strdup_printf (Q_("language|User defined (%s)"), code); language_editor_add (pd, code, text); g_free (text); @@ -1094,6 +1395,7 @@ create_language_section (EphyDialog *dialog) { language_editor_add (pd, code, _(languages[i].name)); } +#endif /* HAVE_ISO_CODES */ } language_editor_update_buttons (pd); -- cgit v1.2.3