]> spindle.queued.net Git - midori/commitdiff
Implement 'Preferred languages' preference, ACCEPT_LANGUAGE header
authorAndré Stösel <Midori-Plugin@PyIT.de>
Wed, 6 Jan 2010 23:49:41 +0000 (00:49 +0100)
committerChristian Dywan <christian@twotoasts.de>
Thu, 7 Jan 2010 00:35:51 +0000 (01:35 +0100)
midori/main.c
midori/midori-preferences.c
midori/midori-websettings.c
midori/sokoke.c
midori/sokoke.h

index 2c4c614f734742bd73fc1cc95f3ba1bb218e830b..fe0789c2980fd60d76cfc8364b79900b2c697c22 100644 (file)
@@ -1116,6 +1116,34 @@ soup_session_settings_notify_ident_string_cb (MidoriWebSettings* settings,
 }
 #endif
 
+static void
+midori_soup_session_settings_accept_language_cb (SoupSession*       session,
+                                                 SoupMessage*       msg,
+                                                 MidoriWebSettings* settings)
+{
+    gchar* languages = katze_object_get_string (settings, "preferred-languages");
+    gchar* accpt;
+
+    /* Empty, use the system locales */
+    if (!(languages && *languages))
+        accpt = sokoke_accept_languages (g_get_language_names ());
+    /* No =, no ., looks like a list of language names */
+    else if (!(strchr (languages, '=') && strchr (languages, '.')))
+    {
+        gchar ** lang_names = g_strsplit_set (languages, ",; ", -1);
+        accpt = sokoke_accept_languages ((const gchar* const *)lang_names);
+        g_strfreev (lang_names);
+    }
+    /* Presumably a well formatted list including priorities */
+    else
+        accpt = languages;
+
+    if (accpt != languages)
+        g_free (languages);
+    soup_message_headers_append (msg->request_headers, "ACCEPT_LANGUAGE", accpt);
+    g_free (accpt);
+}
+
 static void
 midori_soup_session_debug (SoupSession* session)
 {
@@ -1150,6 +1178,9 @@ midori_soup_session_prepare (SoupSession*       session,
         G_CALLBACK (soup_session_settings_notify_ident_string_cb), session);
     #endif
 
+    g_signal_connect (session, "request-queued",
+        G_CALLBACK (midori_soup_session_settings_accept_language_cb), settings);
+
     config_file = build_config_filename ("logins");
     feature = g_object_new (KATZE_TYPE_HTTP_AUTH, "filename", config_file, NULL);
     g_free (config_file);
index 75d7a67e23d92ed24baf9298a1064d0a96842bf7..82c5241a568846ee821da4df04a1daf73b7af5e1 100644 (file)
@@ -495,6 +495,11 @@ midori_preferences_set_settings (MidoriPreferences* preferences,
     INDENTED_ADD (label);
     button = katze_property_proxy (settings, "identify-as", "custom-ident-string");
     SPANNED_ADD (button);
+    label = katze_property_label (settings, "preferred-languages");
+    INDENTED_ADD (label);
+    entry = katze_property_proxy (settings, "preferred-languages", NULL);
+    SPANNED_ADD (entry);
+
 
     /* Page "Privacy" */
     PAGE_NEW (GTK_STOCK_INDEX, _("Privacy"));
index 9c04704b02d171f275c9827d6be5f0e27ee22df1..33e1b552c3ab5057e27b29607b9249d8f67d535b 100644 (file)
@@ -86,6 +86,7 @@ struct _MidoriWebSettings
     gboolean remember_last_downloaded_files;
 
     gchar* http_proxy;
+    gchar* http_accept_language;
     gboolean auto_detect_proxy;
     MidoriIdentity identify_as;
     gchar* ident_string;
@@ -170,6 +171,7 @@ enum
     PROP_AUTO_DETECT_PROXY,
     PROP_IDENTIFY_AS,
     PROP_IDENT_STRING,
+    PROP_PREFERRED_LANGUAGES,
 
     PROP_CLEAR_PRIVATE_DATA
 };
@@ -1048,6 +1050,22 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
                                      NULL,
                                      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+    /**
+    * MidoriWebSettings:preferred-languages:
+    *
+    * A comma separated list of languages preferred for rendering multilingual webpages.
+    *
+    * Since: 0.2.3
+    */
+    g_object_class_install_property (gobject_class,
+                                     PROP_PREFERRED_LANGUAGES,
+                                     g_param_spec_string (
+                                     "preferred-languages",
+                                     _("Preferred languages"),
+        _("A comma separated list of languages preferred for rendering multilingual webpages, for example \"de\", \"ru,nl\" or \"en-us;q=1.0, fr-fr;q=0.667\""),
+                                     NULL,
+                                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
     /**
      * MidoriWebSettings:clear-private-data:
      *
@@ -1462,6 +1480,9 @@ midori_web_settings_set_property (GObject*      object,
             #endif
         }
         break;
+    case PROP_PREFERRED_LANGUAGES:
+        katze_assign (web_settings->http_accept_language, g_value_dup_string (value));
+        break;
     case PROP_CLEAR_PRIVATE_DATA:
         web_settings->clear_private_data = g_value_get_int (value);
         break;
@@ -1677,6 +1698,9 @@ midori_web_settings_get_property (GObject*    object,
         }
         g_value_set_string (value, web_settings->ident_string);
         break;
+    case PROP_PREFERRED_LANGUAGES:
+        g_value_set_string (value, web_settings->http_accept_language);
+        break;
     case PROP_CLEAR_PRIVATE_DATA:
         g_value_set_int (value, web_settings->clear_private_data);
         break;
index bd74132f84931c97188fd535a731ae50adb0a1a4..c917d7e2fe353a264e8a080918842bea4edda9b1 100644 (file)
@@ -1633,3 +1633,89 @@ sokoke_prefetch_uri (const char* uri)
     soup_uri_free (s_uri);
     return TRUE;
 }
+
+/* Provide a new way for SoupSession to assume an 'Accept-Language'
+   string automatically from the return value of g_get_language_names(),
+   properly formatted according to RFC2616.
+   Copyright (C) 2009 Mario Sanchez Prada <msanchez@igalia.com>
+   Copyright (C) 2009 Dan Winship <danw@gnome.org>
+   Mostly copied from libSoup 2.29, coding style adjusted */
+
+/* Converts a language in POSIX format and to be RFC2616 compliant    */
+/* Based on code from epiphany-webkit (ephy_langs_append_languages()) */
+static gchar *
+sokoke_posix_lang_to_rfc2616 (const gchar *language)
+{
+    if (!strchr (language, '.') && !strchr (language, '@') && language[0] != 'C')
+        /* change to lowercase and '_' to '-' */
+        return g_strdelimit (g_ascii_strdown (language, -1), "_", '-');
+
+    return NULL;
+}
+
+/* Adds a quality value to a string (any value between 0 and 1). */
+static gchar *
+sokoke_add_quality_value (const gchar *str,
+                          float        qvalue)
+{
+    if ((qvalue >= 0.0) && (qvalue <= 1.0))
+    {
+        int qv_int = (qvalue * 1000 + 0.5);
+        return g_strdup_printf ("%s;q=%d.%d",
+                                str, (int) (qv_int / 1000), qv_int % 1000);
+    }
+
+    return g_strdup (str);
+}
+
+/* Returns a RFC2616 compliant languages list from system locales */
+gchar *
+sokoke_accept_languages (const gchar* const * lang_names)
+{
+    GArray *langs_garray = NULL;
+    char *cur_lang = NULL;
+    char *prev_lang = NULL;
+    char **langs_array;
+    char *langs_str;
+    float delta;
+    int i, n_lang_names;
+
+    /* Calculate delta for setting the quality values */
+    n_lang_names = g_strv_length ((gchar **)lang_names);
+    delta = 0.999 / (n_lang_names - 1);
+
+    /* Build the array of languages */
+    langs_garray = g_array_new (TRUE, FALSE, sizeof (char*));
+    for (i = 0; lang_names[i] != NULL; i++)
+    {
+        cur_lang = sokoke_posix_lang_to_rfc2616 (lang_names[i]);
+
+        /* Apart from getting a valid RFC2616 compliant
+           language, also get rid of extra variants */
+        if (cur_lang && (!prev_lang ||
+           (!strcmp (prev_lang, cur_lang) || !strstr (prev_lang, cur_lang))))
+        {
+
+            gchar *qv_lang = NULL;
+
+            /* Save reference for further comparison */
+            prev_lang = cur_lang;
+
+            /* Add the quality value and append it */
+            qv_lang = sokoke_add_quality_value (cur_lang, 1 - i * delta);
+            g_array_append_val (langs_garray, qv_lang);
+        }
+    }
+
+    /* Fallback: add "en" if list is empty */
+    if (langs_garray->len == 0)
+    {
+        gchar* fallback = g_strdup ("en");
+        g_array_append_val (langs_garray, fallback);
+    }
+
+    langs_array = (char **) g_array_free (langs_garray, FALSE);
+    langs_str = g_strjoinv (", ", langs_array);
+
+    return langs_str;
+}
index 621ca9991a07a7b9548f118e46d793105a2936f6..1960650ee6b61bb20962ac9deca5d885842860c6 100644 (file)
@@ -204,4 +204,7 @@ sokoke_file_chooser_dialog_new          (const gchar*         title,
 gboolean
 sokoke_prefetch_uri                     (const char* uri);
 
+gchar *
+sokoke_accept_languages                 (const gchar* const * lang_names);
+
 #endif /* !__SOKOKE_H__ */