diff options
Diffstat (limited to 'lib/ephy-langs.c')
-rw-r--r-- | lib/ephy-langs.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/lib/ephy-langs.c b/lib/ephy-langs.c index ff05c34e1..bf86010bf 100644 --- a/lib/ephy-langs.c +++ b/lib/ephy-langs.c @@ -24,6 +24,8 @@ #include <glib/gi18n.h> +#include <string.h> + static const EphyFontsLanguageInfo font_languages [] = { { N_("Arabic"), "ar" }, @@ -57,3 +59,139 @@ ephy_font_n_languages (void) { return n_font_languages; } + +/* sanitise the languages list according to the rules for HTTP accept-language + * in RFC 2616, Sect. 14.4 + */ +void +ephy_langs_sanitise (GArray *array) +{ + char *lang1, *lang2; + int i, j; + + /* if we have 'xy-ab' in list but not 'xy', append 'xy' */ + for (i = 0; i < array->len; i++) + { + gboolean found = FALSE; + char *dash, *prefix; + + lang1 = (char *) g_array_index (array,char *, i); + + dash = strchr (lang1, '-'); + if (dash == NULL) continue; + + for (j = i + 1; j < array->len; j++) + { + lang2 = (char *) g_array_index (array, char *, j); + if (strchr (lang2, '-') == NULL && + g_str_has_prefix (lang1, lang2)) + { + found = TRUE; + } + } + + if (found == FALSE) + { + prefix = g_strndup (lang1, dash - lang1); + g_array_append_val (array, prefix); + } + } + + /* uniquify */ + for (i = 0; i < array->len - 1; i++) + { + for (j = array->len - 1; j > i; j--) + { + lang1 = (char *) g_array_index (array,char *, i); + lang2 = (char *) g_array_index (array, char *, j); + + if (strcmp (lang1, lang2) == 0) + { + g_array_remove_index (array, j); + g_free (lang2); + } + } + } + + /* move 'xy' code behind all 'xy-ab' codes */ + for (i = array->len - 2; i >= 0; i--) + { + for (j = array->len - 1; j > i; j--) + { + lang1 = (char *) g_array_index (array, char *, i); + lang2 = (char *) g_array_index (array, char *, j); + + if (strchr (lang1, '-') == NULL && + strchr (lang2, '-') != NULL && + g_str_has_prefix (lang2, lang1)) + { + g_array_insert_val (array, j + 1, lang1); + g_array_remove_index (array, i); + break; + } + } + } +} + +void +ephy_langs_append_languages (GArray *array) +{ + const char * const * languages; + const char *system_lang; + char *lang; + int i; + + /** + * This is a comma separated list of language ranges, as specified + * by RFC 2616, 14.4. + * Always include the basic language code last. + * + * Examples: + * "pt" translation: "pt" + * "pt_BR" translation: "pt-br,pt" + * "zh_CN" translation: "zh-cn,zh" + * "zh_HK" translation: "zh-hk,zh" or maybe "zh-hk,zh-tw,zh" + */ + system_lang = _("system-language"); + + /* FIXME: use system_language when given, instead of g_get_language_names () ? */ + languages = g_get_language_names (); + g_return_if_fail (languages != NULL); + + /* FIXME: maybe just use the first, instead of all of them? */ + for (i = 0; languages[i] != NULL; i++) + { + + if (strstr (languages[i], ".") == 0 && + strstr (languages[i], "@") == 0 && + strcmp (languages[i], "C") != 0) + { + /* change to lowercase and '_' to '-' */ + lang = g_strdelimit (g_ascii_strdown + (languages[i], -1), "_", '-'); + + g_array_append_val (array, lang); + } + } + + /* Fallback: add "en" if list is empty */ + if (array->len == 0) + { + lang = g_strdup ("en"); + g_array_append_val (array, lang); + } +} + +char ** +ephy_langs_get_languages (void) +{ + GArray *array; + + array = g_array_new (TRUE, FALSE, sizeof (char *)); + + ephy_langs_append_languages (array); + + ephy_langs_sanitise (array); + + return (char **) g_array_free (array, FALSE); +} |