[epiphany] Get rid of the hardcoded language list
- From: Michael Catanzaro <mcatanzaro src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [epiphany] Get rid of the hardcoded language list
- Date: Wed, 14 Nov 2018 21:35:33 +0000 (UTC)
commit ed366f8e849108db857d1a67bd7dfe39d18c8991
Author: Michael Catanzaro <mcatanzaro igalia com>
Date: Wed Nov 14 14:54:31 2018 -0600
Get rid of the hardcoded language list
This replaces languages.h and most of ephy-langs.c with a copy of
gnome-languages.c from GNOME desktop.
Languages are now translated in the language selection dialog, instead
of being shown in the current locale.
lib/contrib/gnome-languages.c | 1354 +++++++++++++++++++++++++++++++++++++++++
lib/contrib/gnome-languages.h | 54 ++
lib/ephy-langs.c | 169 -----
lib/ephy-langs.h | 7 -
lib/meson.build | 1 +
meson.build | 2 +
src/languages.h | 549 -----------------
src/prefs-dialog.c | 95 +--
8 files changed, 1442 insertions(+), 789 deletions(-)
---
diff --git a/lib/contrib/gnome-languages.c b/lib/contrib/gnome-languages.c
new file mode 100644
index 000000000..f5c31ce4a
--- /dev/null
+++ b/lib/contrib/gnome-languages.c
@@ -0,0 +1,1354 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2008 Red Hat, Inc,
+ * 2007 William Jon McCann <mccann jhu edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by : William Jon McCann <mccann jhu edu>
+ * Ray Strode <rstrode redhat com>
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <dirent.h>
+#include <locale.h>
+#include <langinfo.h>
+#include <sys/stat.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include "gnome-languages.h"
+
+#include <langinfo.h>
+#ifndef __LC_LAST
+#define __LC_LAST 13
+#endif
+
+#define ISO_CODES_DATADIR ISO_CODES_PREFIX "/share/xml/iso-codes"
+#define ISO_CODES_LOCALESDIR ISO_CODES_PREFIX "/share/locale"
+
+#if 0
+#include "default-input-sources.h"
+#endif
+
+typedef struct _GnomeLocale {
+ char *id;
+ char *name;
+ char *language_code;
+ char *territory_code;
+ char *codeset;
+ char *modifier;
+} GnomeLocale;
+
+static GHashTable *gnome_languages_map;
+static GHashTable *gnome_territories_map;
+static GHashTable *gnome_available_locales_map;
+static GHashTable *gnome_language_count_map;
+static GHashTable *gnome_territory_count_map;
+
+static char * construct_language_name (const char *language,
+ const char *territory,
+ const char *codeset,
+ const char *modifier);
+
+static gboolean language_name_is_valid (const char *language_name);
+
+static void
+gnome_locale_free (GnomeLocale *locale)
+{
+ if (locale == NULL) {
+ return;
+ }
+
+ g_free (locale->id);
+ g_free (locale->name);
+ g_free (locale->codeset);
+ g_free (locale->modifier);
+ g_free (locale->language_code);
+ g_free (locale->territory_code);
+ g_free (locale);
+}
+
+static char *
+normalize_codeset (const char *codeset)
+{
+ if (codeset == NULL)
+ return NULL;
+
+ if (g_str_equal (codeset, "UTF-8") ||
+ g_str_equal (codeset, "utf8"))
+ return g_strdup ("UTF-8");
+
+ return g_strdup (codeset);
+}
+
+/**
+ * gnome_parse_locale:
+ * @locale: a locale string
+ * @language_codep: (out) (allow-none) (transfer full): location to
+ * store the language code, or %NULL
+ * @country_codep: (out) (allow-none) (transfer full): location to
+ * store the country code, or %NULL
+ * @codesetp: (out) (allow-none) (transfer full): location to
+ * store the codeset, or %NULL
+ * @modifierp: (out) (allow-none) (transfer full): location to
+ * store the modifier, or %NULL
+ *
+ * Extracts the various components of a locale string of the form
+ * [language[_country][.codeset][@modifier]]. See
+ * http://en.wikipedia.org/wiki/Locale.
+ *
+ * Return value: %TRUE if parsing was successful.
+ *
+ * Since: 3.8
+ */
+gboolean
+gnome_parse_locale (const char *locale,
+ char **language_codep,
+ char **country_codep,
+ char **codesetp,
+ char **modifierp)
+{
+ static GRegex *re = NULL;
+ GMatchInfo *match_info;
+ gboolean res;
+ gboolean retval;
+
+ match_info = NULL;
+ retval = FALSE;
+
+ if (re == NULL) {
+ GError *error = NULL;
+ re = g_regex_new ("^(?P<language>[^_.@[:space:]]+)"
+ "(_(?P<territory>[[:upper:]]+))?"
+ "(\\.(?P<codeset>[-_0-9a-zA-Z]+))?"
+ "(@(?P<modifier>[[:ascii:]]+))?$",
+ 0, 0, &error);
+ if (re == NULL) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+ }
+
+ if (!g_regex_match (re, locale, 0, &match_info) ||
+ g_match_info_is_partial_match (match_info)) {
+ g_warning ("locale '%s' isn't valid\n", locale);
+ goto out;
+ }
+
+ res = g_match_info_matches (match_info);
+ if (! res) {
+ g_warning ("Unable to parse locale: %s", locale);
+ goto out;
+ }
+
+ retval = TRUE;
+
+ if (language_codep != NULL) {
+ *language_codep = g_match_info_fetch_named (match_info, "language");
+ }
+
+ if (country_codep != NULL) {
+ *country_codep = g_match_info_fetch_named (match_info, "territory");
+
+ if (*country_codep != NULL &&
+ *country_codep[0] == '\0') {
+ g_free (*country_codep);
+ *country_codep = NULL;
+ }
+ }
+
+ if (codesetp != NULL) {
+ *codesetp = g_match_info_fetch_named (match_info, "codeset");
+
+ if (*codesetp != NULL &&
+ *codesetp[0] == '\0') {
+ g_free (*codesetp);
+ *codesetp = NULL;
+ }
+ }
+
+ if (modifierp != NULL) {
+ *modifierp = g_match_info_fetch_named (match_info, "modifier");
+
+ if (*modifierp != NULL &&
+ *modifierp[0] == '\0') {
+ g_free (*modifierp);
+ *modifierp = NULL;
+ }
+ }
+
+ if (codesetp != NULL && *codesetp != NULL) {
+ g_autofree gchar *normalized_codeset = NULL;
+ g_autofree gchar *normalized_name = NULL;
+
+ normalized_codeset = normalize_codeset (*codesetp);
+ normalized_name = construct_language_name (language_codep ? *language_codep : NULL,
+ country_codep ? *country_codep : NULL,
+ normalized_codeset,
+ modifierp ? *modifierp : NULL);
+
+ if (language_name_is_valid (normalized_name)) {
+ g_free (*codesetp);
+ *codesetp = g_steal_pointer (&normalized_codeset);
+ }
+ }
+
+ out:
+ g_match_info_free (match_info);
+
+ return retval;
+}
+
+static char *
+construct_language_name (const char *language,
+ const char *territory,
+ const char *codeset,
+ const char *modifier)
+{
+ char *name;
+
+ g_assert (language != NULL && language[0] != 0);
+ g_assert (territory == NULL || territory[0] != 0);
+ g_assert (codeset == NULL || codeset[0] != 0);
+ g_assert (modifier == NULL || modifier[0] != 0);
+
+ name = g_strdup_printf ("%s%s%s%s%s%s%s",
+ language,
+ territory != NULL? "_" : "",
+ territory != NULL? territory : "",
+ codeset != NULL? "." : "",
+ codeset != NULL? codeset : "",
+ modifier != NULL? "@" : "",
+ modifier != NULL? modifier : "");
+
+ return name;
+}
+
+/**
+ * gnome_normalize_locale:
+ * @locale: a locale string
+ *
+ * Gets the normalized locale string in the form
+ * [language[_country][.codeset][@modifier]] for @name.
+ *
+ * Return value: (transfer full): normalized locale string. Caller
+ * takes ownership.
+ *
+ * Since: 3.8
+ */
+char *
+gnome_normalize_locale (const char *locale)
+{
+ char *normalized_name;
+ gboolean valid;
+ g_autofree char *language_code = NULL;
+ g_autofree char *territory_code = NULL;
+ g_autofree char *codeset = NULL;
+ g_autofree char *modifier = NULL;
+
+ if (locale[0] == '\0') {
+ return NULL;
+ }
+
+ valid = gnome_parse_locale (locale,
+ &language_code,
+ &territory_code,
+ &codeset, &modifier);
+ if (!valid)
+ return NULL;
+
+ normalized_name = construct_language_name (language_code,
+ territory_code,
+ codeset, modifier);
+ return normalized_name;
+}
+
+static gboolean
+language_name_is_valid (const char *language_name)
+{
+ gboolean is_valid;
+ int lc_type_id = LC_MESSAGES;
+ g_autofree char *old_locale = NULL;
+
+ old_locale = g_strdup (setlocale (lc_type_id, NULL));
+ is_valid = setlocale (lc_type_id, language_name) != NULL;
+ setlocale (lc_type_id, old_locale);
+
+ return is_valid;
+}
+
+static void
+language_name_get_codeset_details (const char *language_name,
+ char **pcodeset,
+ gboolean *is_utf8)
+{
+ g_autofree char *old_locale = NULL;
+ const char *codeset = NULL;
+
+ old_locale = g_strdup (setlocale (LC_CTYPE, NULL));
+
+ if (setlocale (LC_CTYPE, language_name) == NULL)
+ return;
+
+ codeset = nl_langinfo (CODESET);
+
+ if (pcodeset != NULL) {
+ *pcodeset = g_strdup (codeset);
+ }
+
+ if (is_utf8 != NULL) {
+ g_autofree char *normalized_codeset = normalize_codeset (codeset);
+
+ *is_utf8 = strcmp (normalized_codeset, "UTF-8") == 0;
+ }
+
+ setlocale (LC_CTYPE, old_locale);
+}
+
+/**
+ * gnome_language_has_translations:
+ * @code: an ISO 639 code string
+ *
+ * Returns %TRUE if there are translations for language @code.
+ *
+ * Return value: %TRUE if there are translations for language @code.
+ *
+ * Since: 3.8
+ */
+gboolean
+gnome_language_has_translations (const char *code)
+{
+ GDir *dir;
+ const char *name;
+ gboolean has_translations;
+ g_autofree char *path = NULL;
+
+ path = g_build_filename (LOCALEDIR, code, "LC_MESSAGES", NULL);
+
+ has_translations = FALSE;
+ dir = g_dir_open (path, 0, NULL);
+
+ if (dir == NULL) {
+ goto out;
+ }
+
+ do {
+ name = g_dir_read_name (dir);
+
+ if (name == NULL) {
+ break;
+ }
+
+ if (g_str_has_suffix (name, ".mo")) {
+ has_translations = TRUE;
+ break;
+ }
+ } while (name != NULL);
+ g_dir_close (dir);
+
+ out:
+ return has_translations;
+}
+
+static gboolean
+add_locale (const char *language_name,
+ gboolean utf8_only)
+{
+ GnomeLocale *locale;
+ GnomeLocale *old_locale;
+ g_autofree char *name = NULL;
+ gboolean is_utf8 = FALSE;
+ gboolean valid = FALSE;
+
+ g_return_val_if_fail (language_name != NULL, FALSE);
+ g_return_val_if_fail (*language_name != '\0', FALSE);
+
+ language_name_get_codeset_details (language_name, NULL, &is_utf8);
+
+ if (is_utf8) {
+ name = g_strdup (language_name);
+ } else if (utf8_only) {
+
+ if (strchr (language_name, '.'))
+ return FALSE;
+
+ /* If the locale name has no dot, assume that its
+ * encoding part is missing and try again after adding
+ * ".UTF-8". This catches locale names like "de_DE".
+ */
+ name = g_strdup_printf ("%s.UTF-8", language_name);
+
+ language_name_get_codeset_details (name, NULL, &is_utf8);
+ if (!is_utf8)
+ return FALSE;
+ } else {
+ name = g_strdup (language_name);
+ }
+
+ if (!language_name_is_valid (name)) {
+ g_debug ("Ignoring '%s' as a locale, since it's invalid", name);
+ return FALSE;
+ }
+
+ locale = g_new0 (GnomeLocale, 1);
+ valid = gnome_parse_locale (name,
+ &locale->language_code,
+ &locale->territory_code,
+ &locale->codeset,
+ &locale->modifier);
+ if (!valid) {
+ gnome_locale_free (locale);
+ return FALSE;
+ }
+
+ locale->id = construct_language_name (locale->language_code, locale->territory_code,
+ NULL, locale->modifier);
+ locale->name = construct_language_name (locale->language_code, locale->territory_code,
+ locale->codeset, locale->modifier);
+
+ if (!gnome_language_has_translations (locale->name) &&
+ !gnome_language_has_translations (locale->id) &&
+ !gnome_language_has_translations (locale->language_code) &&
+ utf8_only) {
+ g_debug ("Ignoring '%s' as a locale, since it lacks translations", locale->name);
+ gnome_locale_free (locale);
+ return FALSE;
+ }
+
+ if (!utf8_only) {
+ g_free (locale->id);
+ locale->id = g_strdup (locale->name);
+ }
+
+ old_locale = g_hash_table_lookup (gnome_available_locales_map, locale->id);
+ if (old_locale != NULL) {
+ if (strlen (old_locale->name) > strlen (locale->name)) {
+ gnome_locale_free (locale);
+ return FALSE;
+ }
+ }
+
+ g_hash_table_insert (gnome_available_locales_map, g_strdup (locale->id), locale);
+
+ return TRUE;
+}
+
+static int
+select_dirs (const struct dirent *dirent)
+{
+ int result = 0;
+
+ if (strcmp (dirent->d_name, ".") != 0 && strcmp (dirent->d_name, "..") != 0) {
+ mode_t mode = 0;
+
+#ifdef _DIRENT_HAVE_D_TYPE
+ if (dirent->d_type != DT_UNKNOWN && dirent->d_type != DT_LNK) {
+ mode = DTTOIF (dirent->d_type);
+ } else
+#endif
+ {
+ struct stat st;
+ g_autofree char *path = NULL;
+
+ path = g_build_filename (LIBLOCALEDIR, dirent->d_name, NULL);
+ if (g_stat (path, &st) == 0) {
+ mode = st.st_mode;
+ }
+ }
+
+ result = S_ISDIR (mode);
+ }
+
+ return result;
+}
+
+static gboolean
+collect_locales_from_directory (void)
+{
+ gboolean found_locales = FALSE;
+ struct dirent **dirents;
+ int ndirents;
+ int cnt;
+
+ ndirents = scandir (LIBLOCALEDIR, &dirents, select_dirs, alphasort);
+
+ for (cnt = 0; cnt < ndirents; ++cnt) {
+ if (add_locale (dirents[cnt]->d_name, TRUE))
+ found_locales = TRUE;
+ }
+
+ if (ndirents > 0) {
+ free (dirents);
+ }
+ return found_locales;
+}
+
+static gboolean
+collect_locales_from_localebin (void)
+{
+ gboolean found_locales = FALSE;
+ const gchar *argv[] = { "locale", "-a", NULL };
+ gchar **linep;
+ g_auto (GStrv) lines = NULL;
+ g_autofree gchar *output = NULL;
+
+ if (g_spawn_sync (NULL, (gchar **) argv, NULL,
+ G_SPAWN_SEARCH_PATH|G_SPAWN_STDERR_TO_DEV_NULL,
+ NULL, NULL, &output, NULL, NULL, NULL) == FALSE)
+ return FALSE;
+
+ g_return_val_if_fail (output != NULL, FALSE);
+
+ lines = g_strsplit (output, "\n", 0);
+ if (lines) {
+ linep = lines;
+ while (*linep) {
+ if (*linep[0] && add_locale (*linep, TRUE))
+ found_locales = TRUE;
+ linep++;
+ }
+ }
+
+ return found_locales;
+}
+
+static void
+count_languages_and_territories (void)
+{
+ gpointer value;
+ GHashTableIter iter;
+
+ gnome_language_count_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ gnome_territory_count_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+ g_hash_table_iter_init (&iter, gnome_available_locales_map);
+ while (g_hash_table_iter_next (&iter, NULL, &value)) {
+ GnomeLocale *locale;
+
+ locale = (GnomeLocale *) value;
+
+ if (locale->language_code != NULL) {
+ int count;
+
+ count = GPOINTER_TO_INT (g_hash_table_lookup (gnome_language_count_map,
locale->language_code));
+ count++;
+ g_hash_table_insert (gnome_language_count_map, g_strdup (locale->language_code),
GINT_TO_POINTER (count));
+ }
+
+ if (locale->territory_code != NULL) {
+ int count;
+
+ count = GPOINTER_TO_INT (g_hash_table_lookup (gnome_territory_count_map,
locale->territory_code));
+ count++;
+ g_hash_table_insert (gnome_territory_count_map, g_strdup (locale->territory_code),
GINT_TO_POINTER (count));
+ }
+ }
+}
+
+static void
+collect_locales (void)
+{
+ gboolean found_localebin_locales = FALSE;
+ gboolean found_dir_locales = FALSE;
+
+ if (gnome_available_locales_map == NULL) {
+ gnome_available_locales_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
(GDestroyNotify) gnome_locale_free);
+ }
+
+ found_localebin_locales = collect_locales_from_localebin ();
+
+ found_dir_locales = collect_locales_from_directory ();
+
+ if (!(found_localebin_locales || found_dir_locales)) {
+ g_warning ("Could not read list of available locales from libc, "
+ "guessing possible locales from available translations, "
+ "but list may be incomplete!");
+ }
+
+ count_languages_and_territories ();
+}
+
+static gint
+get_language_count (const char *language)
+{
+ if (gnome_language_count_map == NULL) {
+ collect_locales ();
+ }
+
+ return GPOINTER_TO_INT (g_hash_table_lookup (gnome_language_count_map, language));
+}
+
+static gboolean
+is_unique_language (const char *language)
+{
+ return get_language_count (language) == 1;
+}
+
+static gint
+get_territory_count (const char *territory)
+{
+ if (gnome_territory_count_map == NULL) {
+ collect_locales ();
+ }
+
+ return GPOINTER_TO_INT (g_hash_table_lookup (gnome_territory_count_map, territory));
+}
+
+static gboolean
+is_unique_territory (const char *territory)
+{
+ return get_territory_count (territory) == 1;
+}
+
+static gboolean
+is_fallback_language (const char *code)
+{
+ const char *fallback_language_names[] = { "C", "POSIX", NULL };
+ int i;
+
+ for (i = 0; fallback_language_names[i] != NULL; i++) {
+ if (strcmp (code, fallback_language_names[i]) == 0) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static const char *
+get_language (const char *code)
+{
+ const char *name;
+ int len;
+
+ g_assert (code != NULL);
+
+ if (is_fallback_language (code)) {
+ return "Unspecified";
+ }
+
+ len = strlen (code);
+ if (len != 2 && len != 3) {
+ return NULL;
+ }
+
+ name = (const char *) g_hash_table_lookup (gnome_languages_map, code);
+
+ return name;
+}
+
+static char *
+get_first_item_in_semicolon_list (const char *list)
+{
+ char **items;
+ char *item;
+
+ /* Some entries in iso codes have multiple values, separated
+ * by semicolons. Not really sure which one to pick, so
+ * we just arbitrarily pick the first one.
+ */
+ items = g_strsplit (list, "; ", 2);
+
+ item = g_strdup (items[0]);
+ g_strfreev (items);
+
+ return item;
+}
+
+static char *
+capitalize_utf8_string (const char *str)
+{
+ char first[8] = { 0 };
+
+ if (!str)
+ return NULL;
+
+ g_unichar_to_utf8 (g_unichar_totitle (g_utf8_get_char (str)), first);
+
+ return g_strconcat (first, g_utf8_offset_to_pointer (str, 1), NULL);
+}
+
+static char *
+get_translated_language (const char *code,
+ const char *locale)
+{
+ const char *language;
+ char *name;
+
+ language = get_language (code);
+
+ name = NULL;
+ if (language != NULL) {
+ const char *translated_name;
+ g_autofree char *old_locale = NULL;
+
+ if (locale != NULL) {
+ old_locale = g_strdup (setlocale (LC_MESSAGES, NULL));
+ setlocale (LC_MESSAGES, locale);
+ }
+
+ if (is_fallback_language (code)) {
+ name = g_strdup (_("Unspecified"));
+ } else {
+ g_autofree char *tmp = NULL;
+ translated_name = dgettext ("iso_639", language);
+ tmp = get_first_item_in_semicolon_list (translated_name);
+ name = capitalize_utf8_string (tmp);
+ }
+
+ if (locale != NULL) {
+ setlocale (LC_MESSAGES, old_locale);
+ }
+ }
+
+ return name;
+}
+
+static const char *
+get_territory (const char *code)
+{
+ const char *name;
+ int len;
+
+ g_assert (code != NULL);
+
+ len = strlen (code);
+ if (len != 2 && len != 3) {
+ return NULL;
+ }
+
+ name = (const char *) g_hash_table_lookup (gnome_territories_map, code);
+
+ return name;
+}
+
+static char *
+get_translated_territory (const char *code,
+ const char *locale)
+{
+ const char *territory;
+ char *name;
+
+ territory = get_territory (code);
+
+ name = NULL;
+ if (territory != NULL) {
+ const char *translated_territory;
+ g_autofree char *old_locale = NULL;
+ g_autofree char *tmp = NULL;
+
+ if (locale != NULL) {
+ old_locale = g_strdup (setlocale (LC_MESSAGES, NULL));
+ setlocale (LC_MESSAGES, locale);
+ }
+
+ translated_territory = dgettext ("iso_3166", territory);
+ tmp = get_first_item_in_semicolon_list (translated_territory);
+ name = capitalize_utf8_string (tmp);
+
+ if (locale != NULL) {
+ setlocale (LC_MESSAGES, old_locale);
+ }
+ }
+
+ return name;
+}
+
+static void
+languages_parse_start_tag (GMarkupParseContext *ctx,
+ const char *element_name,
+ const char **attr_names,
+ const char **attr_values,
+ gpointer user_data,
+ GError **error)
+{
+ const char *ccode_longB;
+ const char *ccode_longT;
+ const char *ccode;
+ const char *ccode_id;
+ const char *lang_name;
+
+ if (! (g_str_equal (element_name, "iso_639_entry") || g_str_equal (element_name, "iso_639_3_entry"))
+ || attr_names == NULL || attr_values == NULL) {
+ return;
+ }
+
+ ccode = NULL;
+ ccode_longB = NULL;
+ ccode_longT = NULL;
+ ccode_id = NULL;
+ lang_name = NULL;
+
+ while (*attr_names && *attr_values) {
+ if (g_str_equal (*attr_names, "iso_639_1_code")) {
+ /* skip if empty */
+ if (**attr_values) {
+ if (strlen (*attr_values) != 2) {
+ return;
+ }
+ ccode = *attr_values;
+ }
+ } else if (g_str_equal (*attr_names, "iso_639_2B_code")) {
+ /* skip if empty */
+ if (**attr_values) {
+ if (strlen (*attr_values) != 3) {
+ return;
+ }
+ ccode_longB = *attr_values;
+ }
+ } else if (g_str_equal (*attr_names, "iso_639_2T_code")) {
+ /* skip if empty */
+ if (**attr_values) {
+ if (strlen (*attr_values) != 3) {
+ return;
+ }
+ ccode_longT = *attr_values;
+ }
+ } else if (g_str_equal (*attr_names, "id")) {
+ /* skip if empty */
+ if (**attr_values) {
+ if (strlen (*attr_values) != 2 &&
+ strlen (*attr_values) != 3) {
+ return;
+ }
+ ccode_id = *attr_values;
+ }
+ } else if (g_str_equal (*attr_names, "name")) {
+ lang_name = *attr_values;
+ }
+
+ ++attr_names;
+ ++attr_values;
+ }
+
+ if (lang_name == NULL) {
+ return;
+ }
+
+ if (ccode != NULL) {
+ g_hash_table_insert (gnome_languages_map,
+ g_strdup (ccode),
+ g_strdup (lang_name));
+ }
+ if (ccode_longB != NULL) {
+ g_hash_table_insert (gnome_languages_map,
+ g_strdup (ccode_longB),
+ g_strdup (lang_name));
+ }
+ if (ccode_longT != NULL) {
+ g_hash_table_insert (gnome_languages_map,
+ g_strdup (ccode_longT),
+ g_strdup (lang_name));
+ }
+ if (ccode_id != NULL) {
+ g_hash_table_insert (gnome_languages_map,
+ g_strdup (ccode_id),
+ g_strdup (lang_name));
+ }
+}
+
+static void
+territories_parse_start_tag (GMarkupParseContext *ctx,
+ const char *element_name,
+ const char **attr_names,
+ const char **attr_values,
+ gpointer user_data,
+ GError **error)
+{
+ const char *acode_2;
+ const char *acode_3;
+ const char *ncode;
+ const char *territory_common_name;
+ const char *territory_name;
+
+ if (! g_str_equal (element_name, "iso_3166_entry") || attr_names == NULL || attr_values == NULL) {
+ return;
+ }
+
+ acode_2 = NULL;
+ acode_3 = NULL;
+ ncode = NULL;
+ territory_common_name = NULL;
+ territory_name = NULL;
+
+ while (*attr_names && *attr_values) {
+ if (g_str_equal (*attr_names, "alpha_2_code")) {
+ /* skip if empty */
+ if (**attr_values) {
+ if (strlen (*attr_values) != 2) {
+ return;
+ }
+ acode_2 = *attr_values;
+ }
+ } else if (g_str_equal (*attr_names, "alpha_3_code")) {
+ /* skip if empty */
+ if (**attr_values) {
+ if (strlen (*attr_values) != 3) {
+ return;
+ }
+ acode_3 = *attr_values;
+ }
+ } else if (g_str_equal (*attr_names, "numeric_code")) {
+ /* skip if empty */
+ if (**attr_values) {
+ if (strlen (*attr_values) != 3) {
+ return;
+ }
+ ncode = *attr_values;
+ }
+ } else if (g_str_equal (*attr_names, "common_name")) {
+ /* skip if empty */
+ if (**attr_values) {
+ territory_common_name = *attr_values;
+ }
+ } else if (g_str_equal (*attr_names, "name")) {
+ territory_name = *attr_values;
+ }
+
+ ++attr_names;
+ ++attr_values;
+ }
+
+ if (territory_common_name != NULL) {
+ territory_name = territory_common_name;
+ }
+
+ if (territory_name == NULL) {
+ return;
+ }
+
+ if (acode_2 != NULL) {
+ g_hash_table_insert (gnome_territories_map,
+ g_strdup (acode_2),
+ g_strdup (territory_name));
+ }
+ if (acode_3 != NULL) {
+ g_hash_table_insert (gnome_territories_map,
+ g_strdup (acode_3),
+ g_strdup (territory_name));
+ }
+ if (ncode != NULL) {
+ g_hash_table_insert (gnome_territories_map,
+ g_strdup (ncode),
+ g_strdup (territory_name));
+ }
+}
+
+static void
+languages_variant_init (const char *variant)
+{
+ gboolean res;
+ gsize buf_len;
+ g_autofree char *buf = NULL;
+ g_autofree char *filename = NULL;
+ g_autoptr (GError) error = NULL;
+
+ bindtextdomain (variant, ISO_CODES_LOCALESDIR);
+ bind_textdomain_codeset (variant, "UTF-8");
+
+ error = NULL;
+ filename = g_strdup_printf (ISO_CODES_DATADIR "/%s.xml", variant);
+ res = g_file_get_contents (filename,
+ &buf,
+ &buf_len,
+ &error);
+ if (res) {
+ g_autoptr (GMarkupParseContext) ctx = NULL;
+ GMarkupParser parser = { languages_parse_start_tag, NULL, NULL, NULL, NULL };
+
+ ctx = g_markup_parse_context_new (&parser, 0, NULL, NULL);
+
+ error = NULL;
+ res = g_markup_parse_context_parse (ctx, buf, buf_len, &error);
+
+ if (! res) {
+ g_warning ("Failed to parse '%s': %s\n",
+ filename,
+ error->message);
+ }
+ } else {
+ g_warning ("Failed to load '%s': %s\n",
+ filename,
+ error->message);
+ }
+}
+
+static void
+languages_init (void)
+{
+ if (gnome_languages_map)
+ return;
+
+ gnome_languages_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ languages_variant_init ("iso_639");
+ languages_variant_init ("iso_639_3");
+}
+
+static void
+territories_init (void)
+{
+ gboolean res;
+ gsize buf_len;
+ g_autofree char *buf = NULL;
+ g_autoptr (GError) error = NULL;
+
+ if (gnome_territories_map)
+ return;
+
+ bindtextdomain ("iso_3166", ISO_CODES_LOCALESDIR);
+ bind_textdomain_codeset ("iso_3166", "UTF-8");
+
+ gnome_territories_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ error = NULL;
+ res = g_file_get_contents (ISO_CODES_DATADIR "/iso_3166.xml",
+ &buf,
+ &buf_len,
+ &error);
+ if (res) {
+ g_autoptr (GMarkupParseContext) ctx = NULL;
+ GMarkupParser parser = { territories_parse_start_tag, NULL, NULL, NULL, NULL };
+
+ ctx = g_markup_parse_context_new (&parser, 0, NULL, NULL);
+
+ error = NULL;
+ res = g_markup_parse_context_parse (ctx, buf, buf_len, &error);
+
+ if (! res) {
+ g_warning ("Failed to parse '%s': %s\n",
+ ISO_CODES_DATADIR "/iso_3166.xml",
+ error->message);
+ }
+ } else {
+ g_warning ("Failed to load '%s': %s\n",
+ ISO_CODES_DATADIR "/iso_3166.xml",
+ error->message);
+ }
+}
+
+/**
+ * gnome_get_language_from_locale:
+ * @locale: a locale string
+ * @translation: (allow-none): a locale string
+ *
+ * Gets the language description for @locale. If @translation is
+ * provided the returned string is translated accordingly.
+ *
+ * Return value: (transfer full): the language description. Caller
+ * takes ownership.
+ *
+ * Since: 3.8
+ */
+char *
+gnome_get_language_from_locale (const char *locale,
+ const char *translation)
+{
+ GString *full_language;
+ g_autofree char *language_code = NULL;
+ g_autofree char *territory_code = NULL;
+ g_autofree char *codeset_code = NULL;
+ g_autofree char *langinfo_codeset = NULL;
+ g_autofree char *translated_language = NULL;
+ g_autofree char *translated_territory = NULL;
+ gboolean is_utf8 = TRUE;
+
+ g_return_val_if_fail (locale != NULL, NULL);
+ g_return_val_if_fail (*locale != '\0', NULL);
+
+ full_language = g_string_new (NULL);
+
+ languages_init ();
+ territories_init ();
+
+ gnome_parse_locale (locale,
+ &language_code,
+ &territory_code,
+ &codeset_code,
+ NULL);
+
+ if (language_code == NULL) {
+ goto out;
+ }
+
+ translated_language = get_translated_language (language_code, translation);
+ if (translated_language == NULL) {
+ goto out;
+ }
+
+ full_language = g_string_append (full_language, translated_language);
+
+ if (is_unique_language (language_code)) {
+ goto out;
+ }
+
+ if (territory_code != NULL) {
+ translated_territory = get_translated_territory (territory_code, translation);
+ }
+ if (translated_territory != NULL) {
+ g_string_append_printf (full_language,
+ " (%s)",
+ translated_territory);
+ }
+
+ language_name_get_codeset_details (locale, &langinfo_codeset, &is_utf8);
+
+ if (codeset_code == NULL && langinfo_codeset != NULL) {
+ codeset_code = g_strdup (langinfo_codeset);
+ }
+
+ if (!is_utf8 && codeset_code) {
+ g_string_append_printf (full_language,
+ " [%s]",
+ codeset_code);
+ }
+
+ out:
+ if (full_language->len == 0) {
+ g_string_free (full_language, TRUE);
+ return NULL;
+ }
+
+ return g_string_free (full_language, FALSE);
+}
+
+/**
+ * gnome_get_country_from_locale:
+ * @locale: a locale string
+ * @translation: (allow-none): a locale string
+ *
+ * Gets the country description for @locale. If @translation is
+ * provided the returned string is translated accordingly.
+ *
+ * Return value: (transfer full): the country description. Caller
+ * takes ownership.
+ *
+ * Since: 3.8
+ */
+char *
+gnome_get_country_from_locale (const char *locale,
+ const char *translation)
+{
+ GString *full_name;
+ g_autofree char *language_code = NULL;
+ g_autofree char *territory_code = NULL;
+ g_autofree char *codeset_code = NULL;
+ g_autofree char *langinfo_codeset = NULL;
+ g_autofree char *translated_language = NULL;
+ g_autofree char *translated_territory = NULL;
+ gboolean is_utf8 = TRUE;
+
+ g_return_val_if_fail (locale != NULL, NULL);
+ g_return_val_if_fail (*locale != '\0', NULL);
+
+ full_name = g_string_new (NULL);
+
+ languages_init ();
+ territories_init ();
+
+ gnome_parse_locale (locale,
+ &language_code,
+ &territory_code,
+ &codeset_code,
+ NULL);
+
+ if (territory_code == NULL) {
+ goto out;
+ }
+
+ translated_territory = get_translated_territory (territory_code, translation);
+ g_string_append (full_name, translated_territory);
+
+ if (is_unique_territory (territory_code)) {
+ goto out;
+ }
+
+ if (language_code != NULL) {
+ translated_language = get_translated_language (language_code, translation);
+ }
+ if (translated_language != NULL) {
+ g_string_append_printf (full_name,
+ " (%s)",
+ translated_language);
+ }
+
+ language_name_get_codeset_details (translation, &langinfo_codeset, &is_utf8);
+
+ if (codeset_code == NULL && langinfo_codeset != NULL) {
+ codeset_code = g_strdup (langinfo_codeset);
+ }
+
+ if (!is_utf8 && codeset_code) {
+ g_string_append_printf (full_name,
+ " [%s]",
+ codeset_code);
+ }
+
+ out:
+ if (full_name->len == 0) {
+ g_string_free (full_name, TRUE);
+ return NULL;
+ }
+
+ return g_string_free (full_name, FALSE);
+}
+
+/**
+ * gnome_get_all_locales:
+ *
+ * Gets all locales.
+ *
+ * Return value: (array zero-terminated=1) (element-type utf8) (transfer full):
+ * a newly allocated %NULL-terminated string array containing the
+ * all locales. Free with g_strfreev().
+ *
+ * Since: 3.8
+ */
+char **
+gnome_get_all_locales (void)
+{
+ GHashTableIter iter;
+ gpointer key, value;
+ GPtrArray *array;
+
+ if (gnome_available_locales_map == NULL) {
+ collect_locales ();
+ }
+
+ array = g_ptr_array_new ();
+ g_hash_table_iter_init (&iter, gnome_available_locales_map);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ GnomeLocale *locale;
+
+ locale = (GnomeLocale *) value;
+
+ g_ptr_array_add (array, g_strdup (locale->name));
+ }
+ g_ptr_array_add (array, NULL);
+
+ return (char **) g_ptr_array_free (array, FALSE);
+}
+
+/**
+ * gnome_get_language_from_code:
+ * @code: an ISO 639 code string
+ * @translation: (allow-none): a locale string
+ *
+ * Gets the language name for @code. If @translation is provided the
+ * returned string is translated accordingly.
+ *
+ * Return value: (transfer full): the language name. Caller takes
+ * ownership.
+ *
+ * Since: 3.8
+ */
+char *
+gnome_get_language_from_code (const char *code,
+ const char *translation)
+{
+ g_return_val_if_fail (code != NULL, NULL);
+
+ languages_init ();
+
+ return get_translated_language (code, translation);
+}
+
+/**
+ * gnome_get_country_from_code:
+ * @code: an ISO 3166 code string
+ * @translation: (allow-none): a locale string
+ *
+ * Gets the country name for @code. If @translation is provided the
+ * returned string is translated accordingly.
+ *
+ * Return value: (transfer full): the country name. Caller takes
+ * ownership.
+ *
+ * Since: 3.8
+ */
+char *
+gnome_get_country_from_code (const char *code,
+ const char *translation)
+{
+ g_return_val_if_fail (code != NULL, NULL);
+
+ territories_init ();
+
+ return get_translated_territory (code, translation);
+}
+
+#if 0
+/**
+ * gnome_get_input_source_from_locale:
+ * @locale: a locale string
+ * @type: (out) (transfer none): location to store the input source
+ * type
+ * @id: (out) (transfer none): location to store the input source
+ * identifier
+ *
+ * Gets the default input source's type and identifier for a given
+ * locale.
+ *
+ * Return value: %TRUE if a input source exists or %FALSE otherwise.
+ *
+ * Since: 3.8
+ */
+gboolean
+gnome_get_input_source_from_locale (const char *locale,
+ const char **type,
+ const char **id)
+{
+ static GHashTable *table = NULL;
+ DefaultInputSource *dis;
+ g_autofree gchar *l_code = NULL;
+ g_autofree gchar *c_code = NULL;
+ g_autofree gchar *key = NULL;
+ gint i;
+
+ g_return_val_if_fail (locale != NULL, FALSE);
+ g_return_val_if_fail (type != NULL, FALSE);
+ g_return_val_if_fail (id != NULL, FALSE);
+
+ if (!table) {
+ table = g_hash_table_new (g_str_hash, g_str_equal);
+ for (i = 0; default_input_sources[i].id; ++i) {
+ dis = &default_input_sources[i];
+ g_hash_table_insert (table, (gpointer) dis->locale, dis);
+ }
+ }
+
+ if (!gnome_parse_locale (locale, &l_code, &c_code, NULL, NULL))
+ return FALSE;
+
+ key = g_strconcat (l_code, "_", c_code, NULL);
+
+ dis = g_hash_table_lookup (table, key);
+ if (dis) {
+ *type = dis->type;
+ *id = dis->id;
+ }
+ return dis != NULL;
+}
+#endif
diff --git a/lib/contrib/gnome-languages.h b/lib/contrib/gnome-languages.h
new file mode 100644
index 000000000..26159e882
--- /dev/null
+++ b/lib/contrib/gnome-languages.h
@@ -0,0 +1,54 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2008 Red Hat, Inc.
+ * Copyright 2007 William Jon McCann <mccann jhu edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by: Ray Strode
+ * William Jon McCann
+ */
+
+#ifndef __GNOME_LANGUAGES_H
+#define __GNOME_LANGUAGES_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+char * gnome_get_language_from_locale (const char *locale,
+ const char *translation);
+char * gnome_get_country_from_locale (const char *locale,
+ const char *translation);
+char ** gnome_get_all_locales (void);
+gboolean gnome_parse_locale (const char *locale,
+ char **language_codep,
+ char **country_codep,
+ char **codesetp,
+ char **modifierp);
+char * gnome_normalize_locale (const char *locale);
+gboolean gnome_language_has_translations (const char *code);
+char * gnome_get_language_from_code (const char *code,
+ const char *translation);
+char * gnome_get_country_from_code (const char *code,
+ const char *translation);
+#if 0
+gboolean gnome_get_input_source_from_locale (const char *locale,
+ const char **type,
+ const char **id);
+#endif
+
+G_END_DECLS
+
+#endif /* __GNOME_LANGUAGES_H */
diff --git a/lib/ephy-langs.c b/lib/ephy-langs.c
index b061411b8..3b2978c64 100644
--- a/lib/ephy-langs.c
+++ b/lib/ephy-langs.c
@@ -21,10 +21,6 @@
#include "config.h"
#include "ephy-langs.h"
-#include "ephy-debug.h"
-
-#include <glib/gi18n.h>
-#include <libxml/xmlreader.h>
#include <string.h>
/* sanitise the languages list according to the rules for HTTP accept-language
@@ -101,7 +97,6 @@ ephy_langs_append_languages (GArray *array)
languages = g_get_language_names ();
g_assert (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 &&
@@ -133,167 +128,3 @@ ephy_langs_get_languages (void)
return (char **)(void *)g_array_free (array, FALSE);
}
-
-static void
-ephy_langs_bind_iso_domains (void)
-{
- static gboolean bound = FALSE;
-
- if (bound == FALSE) {
- bindtextdomain (ISO_639_DOMAIN, ISO_CODES_PREFIX "/share/locale");
- bind_textdomain_codeset (ISO_639_DOMAIN, "UTF-8");
-
- bindtextdomain (ISO_3166_DOMAIN, ISO_CODES_PREFIX "/share/locale");
- bind_textdomain_codeset (ISO_3166_DOMAIN, "UTF-8");
-
- bound = TRUE;
- }
-}
-
-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 *)"common_name");
- if (name == NULL)
- name = xmlTextReaderGetAttribute (reader, (const xmlChar *)"name");
-
- if (code != NULL && code[0] != '\0' && name != NULL && name[0] != '\0') {
- g_hash_table_insert (table, code, name);
- } else {
- xmlFree (code);
- xmlFree (name);
- }
-}
-
-typedef enum {
- STATE_START,
- STATE_STOP,
- STATE_ENTRIES,
-} ParserState;
-
-static void
-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);
- }
-
- g_free (filename);
-
- STOP_PROFILER ("Loading ISO codes")
-}
-
-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;
-}
diff --git a/lib/ephy-langs.h b/lib/ephy-langs.h
index 533300562..d40cc93ba 100644
--- a/lib/ephy-langs.h
+++ b/lib/ephy-langs.h
@@ -25,17 +25,10 @@
G_BEGIN_DECLS
-#define ISO_639_DOMAIN "iso_639"
-#define ISO_3166_DOMAIN "iso_3166"
-
void ephy_langs_append_languages (GArray *array);
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
diff --git a/lib/meson.build b/lib/meson.build
index 8196d1f68..866b26c4d 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -11,6 +11,7 @@ enums = gnome.mkenums_simple('ephy-lib-type-builtins',
libephymisc_sources = [
'contrib/eggtreemultidnd.c',
+ 'contrib/gnome-languages.c',
'contrib/gvdb/gvdb-builder.c',
'contrib/gvdb/gvdb-reader.c',
'ephy-dbus-util.c',
diff --git a/meson.build b/meson.build
index 8bd4a3b80..ccfc48088 100644
--- a/meson.build
+++ b/meson.build
@@ -12,6 +12,7 @@ prefix = get_option('prefix')
datadir = join_paths(prefix, get_option('datadir'))
libdir = join_paths(prefix, get_option('libdir'))
libexecdir = join_paths(prefix, get_option('libexecdir'))
+liblocaledir = join_paths(prefix, libdir, 'locale')
localedir = join_paths(prefix, get_option('localedir'))
pkgdatadir = join_paths(datadir, 'epiphany')
pkglibdir = join_paths(libdir, 'epiphany')
@@ -27,6 +28,7 @@ conf.set_quoted('DISTRIBUTOR_NAME', get_option('distributor_name'))
conf.set_quoted('EPHY_WEB_EXTENSIONS_DIR', webextensionsdir)
conf.set_quoted('GETTEXT_PACKAGE', meson.project_name())
conf.set_quoted('ISO_CODES_PREFIX', iso_codes_prefix)
+conf.set_quoted('LIBLOCALEDIR', liblocaledir)
conf.set_quoted('LOCALEDIR', localedir)
conf.set_quoted('PKGDATADIR', pkgdatadir)
conf.set_quoted('PKGLIBEXECDIR', pkglibexecdir)
diff --git a/src/prefs-dialog.c b/src/prefs-dialog.c
index 85c044138..5d919710d 100644
--- a/src/prefs-dialog.c
+++ b/src/prefs-dialog.c
@@ -47,7 +47,7 @@
#include "ephy-web-app-utils.h"
#include "clear-data-dialog.h"
#include "cookies-dialog.h"
-#include "languages.h"
+#include "gnome-languages.h"
#include "passwords-dialog.h"
#include "synced-tabs-dialog.h"
#include "webapp-additional-urls-dialog.h"
@@ -126,9 +126,6 @@ struct _PrefsDialog {
GtkTreeView *add_lang_treeview;
GtkTreeModel *lang_model;
- GHashTable *iso_639_table;
- GHashTable *iso_3166_table;
-
/* sync */
GtkWidget *sync_page_box;
GtkWidget *sync_firefox_iframe_box;
@@ -180,9 +177,6 @@ prefs_dialog_finalize (GObject *object)
g_object_unref (dialog->add_lang_dialog);
}
- g_hash_table_destroy (dialog->iso_639_table);
- g_hash_table_destroy (dialog->iso_3166_table);
-
if (dialog->fxa_web_view != NULL) {
webkit_user_content_manager_unregister_script_message_handler (dialog->fxa_manager,
"toChromeMessageHandler");
@@ -1238,50 +1232,6 @@ add_lang_dialog_response_cb (GtkWidget *widget,
gtk_widget_destroy (GTK_WIDGET (dialog));
}
-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_assert (len != 0);
-
- langname = (const char *)g_hash_table_lookup (pd->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->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 (C_("language", "%s (%s)"),
- dgettext (ISO_639_DOMAIN, langname),
- dgettext (ISO_3166_DOMAIN, localename));
- } else {
- name = g_strdup_printf (C_("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 (C_("language", "User defined (%s)"), code);
- }
-
- g_strfreev (str);
-
- return name;
-}
-
static void
add_system_language_entry (GtkListStore *store)
{
@@ -1322,8 +1272,9 @@ setup_add_language_dialog (PrefsDialog *dialog)
GtkTreeViewColumn *column;
GtkTreeSelection *selection;
GtkTreeIter iter;
- guint i;
+ guint i, n;
GtkBuilder *builder;
+ g_auto(GStrv) locales;
builder = gtk_builder_new_from_resource ("/org/gnome/epiphany/gtk/prefs-lang-dialog.ui");
ad = GTK_WIDGET (gtk_builder_get_object (builder, "add_language_dialog"));
@@ -1333,18 +1284,34 @@ setup_add_language_dialog (PrefsDialog *dialog)
store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
- for (i = 0; i < G_N_ELEMENTS (languages); i++) {
- const char *code = languages[i];
- char *name;
+ locales = gnome_get_all_locales ();
+ n = g_strv_length (locales);
+
+ for (i = 0; i < n; i++) {
+ const char *locale = locales[i];
+ g_autofree char *language_code = NULL;
+ g_autofree char *country_code = NULL;
+ g_autofree char *language_name = NULL;
+ g_autofree char *shortened_locale = NULL;
+
+ if (!gnome_parse_locale (locale, &language_code, &country_code, NULL, NULL))
+ break;
+
+ if (language_code == NULL)
+ break;
- name = get_name_for_lang_code (dialog, code);
+ language_name = gnome_get_language_from_locale (locale, locale);
+
+ if (country_code != NULL)
+ shortened_locale = g_strdup_printf ("%s-%s", language_code, country_code);
+ else
+ shortened_locale = g_strdup (language_code);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
- COL_LANG_NAME, name,
- COL_LANG_CODE, code,
+ COL_LANG_NAME, language_name,
+ COL_LANG_CODE, shortened_locale,
-1);
- g_free (name);
}
add_system_language_entry (store);
@@ -1513,9 +1480,6 @@ create_language_section (PrefsDialog *dialog)
char **list = NULL;
int i;
- dialog->iso_639_table = ephy_langs_iso_639_table ();
- dialog->iso_3166_table = ephy_langs_iso_3166_table ();
-
g_signal_connect (dialog->lang_add_button, "clicked",
G_CALLBACK (language_editor_add_button_clicked_cb), dialog);
g_signal_connect (dialog->lang_remove_button, "clicked",
@@ -1561,15 +1525,18 @@ create_language_section (PrefsDialog *dialog)
/* Fill languages editor */
for (i = 0; list[i]; i++) {
- const char *code = (const char *)list[i];
+ const char *code = list[i];
if (strcmp (code, "system") == 0) {
add_system_language_entry (store);
} else if (code[0] != '\0') {
char *text;
- text = get_name_for_lang_code (dialog, code);
+ /* Change hyphens to underscores. */
+ g_strdelimit ((char *)code, "-", '_');
+ text = gnome_get_language_from_locale (code, code);
language_editor_add (dialog, code, text);
+
g_free (text);
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]