mirror of https://github.com/GNOME/gimp.git
Bug 704592 - only load language lists once at gui startup.
Improvements: - setenv/getenv() are not thread-safe, hence they should be run only at startup before any threading occurs. - it is counter-productive to load the huge ISO-639 XML file each time the user opens the Preferences dialog or the text tool options.
This commit is contained in:
parent
37195c8d4e
commit
a129f84c68
|
@ -60,6 +60,7 @@
|
|||
#include "widgets/gimpsessioninfo.h"
|
||||
#include "widgets/gimpuimanager.h"
|
||||
#include "widgets/gimpwidgets-utils.h"
|
||||
#include "widgets/gimplanguagestore-parser.h"
|
||||
|
||||
#include "actions/actions.h"
|
||||
#include "actions/windows-commands.h"
|
||||
|
@ -199,6 +200,7 @@ gui_init (Gimp *gimp,
|
|||
the_gui_gimp = gimp;
|
||||
|
||||
gui_unique_init (gimp);
|
||||
gimp_language_store_parser_init ();
|
||||
|
||||
gimp_widgets_init (gui_help_func,
|
||||
gui_get_foreground_func,
|
||||
|
@ -601,6 +603,8 @@ gui_exit_callback (Gimp *gimp,
|
|||
gimp_tools_save (gimp, gui_config->save_tool_options, FALSE);
|
||||
gimp_tools_exit (gimp);
|
||||
|
||||
gimp_language_store_parser_clean ();
|
||||
|
||||
return FALSE; /* continue exiting */
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* gimplanguagestore-parser.c
|
||||
* Copyright (C) 2008, 2009 Sven Neumann <sven@gimp.org>
|
||||
* Copyright (C) 2013 Jehan <jehan at girinstud.io>
|
||||
*
|
||||
* 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
|
||||
|
@ -50,28 +51,300 @@ typedef struct
|
|||
IsoCodesParserState state;
|
||||
IsoCodesParserState last_known_state;
|
||||
gint unknown_depth;
|
||||
GimpLanguageStore *store;
|
||||
GHashTable *base_lang_list;
|
||||
} IsoCodesParser;
|
||||
|
||||
|
||||
static void iso_codes_parser_start_element (GMarkupParseContext *context,
|
||||
const gchar *element_name,
|
||||
const gchar **attribute_names,
|
||||
const gchar **attribute_values,
|
||||
gpointer user_data,
|
||||
GError **error);
|
||||
static void iso_codes_parser_end_element (GMarkupParseContext *context,
|
||||
const gchar *element_name,
|
||||
gpointer user_data,
|
||||
GError **error);
|
||||
static gboolean parse_iso_codes (GHashTable *base_lang_list,
|
||||
GError **error);
|
||||
static void iso_codes_parser_init (void);
|
||||
static void iso_codes_parser_start_element (GMarkupParseContext *context,
|
||||
const gchar *element_name,
|
||||
const gchar **attribute_names,
|
||||
const gchar **attribute_values,
|
||||
gpointer user_data,
|
||||
GError **error);
|
||||
static void iso_codes_parser_end_element (GMarkupParseContext *context,
|
||||
const gchar *element_name,
|
||||
gpointer user_data,
|
||||
GError **error);
|
||||
|
||||
static void iso_codes_parser_start_unknown (IsoCodesParser *parser);
|
||||
static void iso_codes_parser_end_unknown (IsoCodesParser *parser);
|
||||
static void iso_codes_parser_start_unknown (IsoCodesParser *parser);
|
||||
static void iso_codes_parser_end_unknown (IsoCodesParser *parser);
|
||||
|
||||
static void gimp_language_store_self_l10n (GimpLanguageStore *store,
|
||||
const gchar *lang,
|
||||
const gchar *code);
|
||||
/*
|
||||
* Language lists that we want to generate only once at program startup:
|
||||
* @l10n_lang_list: all available localizations self-localized;
|
||||
* @all_lang_list: all known languages, in the user-selected language.
|
||||
*/
|
||||
static GHashTable *l10n_lang_list = NULL;
|
||||
static GHashTable *all_lang_list = NULL;
|
||||
|
||||
/********************\
|
||||
* Public Functions *
|
||||
\********************/
|
||||
|
||||
/*
|
||||
* Initialize and run the language listing parser. This call must be
|
||||
* made only once, at program initialization, but after language_init().
|
||||
*/
|
||||
void
|
||||
gimp_language_store_parser_init (void)
|
||||
{
|
||||
GHashTable *base_lang_list;
|
||||
gchar *current_env = g_strdup (g_getenv ("LANGUAGE"));
|
||||
GDir *locales_dir;
|
||||
GHashTableIter lang_iter;
|
||||
gpointer key;
|
||||
|
||||
if (l10n_lang_list != NULL)
|
||||
{
|
||||
g_warning ("gimp_language_store_parser_init() must be run only once.");
|
||||
return;
|
||||
}
|
||||
|
||||
l10n_lang_list = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
(GDestroyNotify) g_free,
|
||||
(GDestroyNotify) g_free);
|
||||
all_lang_list = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
(GDestroyNotify) g_free,
|
||||
(GDestroyNotify) g_free);
|
||||
base_lang_list = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
(GDestroyNotify) g_free,
|
||||
(GDestroyNotify) g_free);
|
||||
|
||||
/* Check all locales we have translations for. */
|
||||
locales_dir = g_dir_open (gimp_locale_directory (), 0, NULL);
|
||||
if (locales_dir)
|
||||
{
|
||||
const gchar *locale;
|
||||
|
||||
while ((locale = g_dir_read_name (locales_dir)) != NULL)
|
||||
{
|
||||
gchar *filename = g_build_filename (gimp_locale_directory (),
|
||||
locale,
|
||||
"LC_MESSAGES",
|
||||
GETTEXT_PACKAGE ".mo",
|
||||
NULL);
|
||||
if (g_file_test (filename, G_FILE_TEST_EXISTS))
|
||||
{
|
||||
gchar *delimiter = strchr (locale, '_');
|
||||
gchar *base_code = NULL;
|
||||
|
||||
if (delimiter)
|
||||
base_code = g_strndup (locale, delimiter - locale);
|
||||
else
|
||||
base_code = g_strdup (locale);
|
||||
|
||||
delimiter = strchr (base_code, '@');
|
||||
|
||||
if (delimiter)
|
||||
{
|
||||
gchar *temp = base_code;
|
||||
base_code = g_strndup (base_code, delimiter - base_code);
|
||||
g_free (temp);
|
||||
}
|
||||
|
||||
/* Save the full language code. */
|
||||
g_hash_table_insert (l10n_lang_list, g_strdup (locale), NULL);
|
||||
/* Save the base language code. */
|
||||
g_hash_table_insert (base_lang_list, base_code, NULL);
|
||||
}
|
||||
|
||||
g_free (filename);
|
||||
}
|
||||
|
||||
g_dir_close (locales_dir);
|
||||
}
|
||||
|
||||
/* Parse ISO-639 file to get full list of language and their names. */
|
||||
parse_iso_codes (base_lang_list, NULL);
|
||||
|
||||
/* Generate the localized language names. */
|
||||
g_hash_table_iter_init (&lang_iter, l10n_lang_list);
|
||||
while (g_hash_table_iter_next (&lang_iter, &key, NULL))
|
||||
{
|
||||
gchar *code = GINT_TO_POINTER (key);
|
||||
gchar *english_name;
|
||||
gchar *delimiter = strchr (code, '_');
|
||||
gchar *base_code;
|
||||
|
||||
if (delimiter)
|
||||
base_code = g_strndup (code, delimiter - code);
|
||||
else
|
||||
base_code = g_strdup (code);
|
||||
|
||||
delimiter = strchr (base_code, '@');
|
||||
|
||||
if (delimiter)
|
||||
{
|
||||
gchar *temp = base_code;
|
||||
base_code = g_strndup (base_code, delimiter - base_code);
|
||||
g_free (temp);
|
||||
}
|
||||
|
||||
english_name = GINT_TO_POINTER (g_hash_table_lookup (base_lang_list, base_code));
|
||||
|
||||
if (english_name)
|
||||
{
|
||||
gchar *localized_name;
|
||||
gchar *semicolon;
|
||||
|
||||
/* If possible, we want to localize a language in itself.
|
||||
* If it fails, gettext fallbacks to C (en_US) itself.
|
||||
*/
|
||||
g_setenv ("LANGUAGE", code, TRUE);
|
||||
setlocale (LC_ALL, "");
|
||||
|
||||
localized_name = g_strdup (dgettext ("iso_639", english_name));
|
||||
|
||||
/* If original and localized names are the same for other than English,
|
||||
* maybe localization failed. Try now in the main dialect. */
|
||||
if (g_strcmp0 (english_name, localized_name) == 0 &&
|
||||
g_strcmp0 (base_code, "en") != 0 &&
|
||||
g_strcmp0 (code, base_code) != 0)
|
||||
{
|
||||
g_free (localized_name);
|
||||
|
||||
g_setenv ("LANGUAGE", base_code, TRUE);
|
||||
setlocale (LC_ALL, "");
|
||||
|
||||
localized_name = g_strdup (dgettext ("iso_639", english_name));
|
||||
}
|
||||
|
||||
/* there might be several language names; use the first one */
|
||||
semicolon = strchr (localized_name, ';');
|
||||
|
||||
if (semicolon)
|
||||
{
|
||||
gchar *temp = localized_name;
|
||||
localized_name = g_strndup (localized_name, semicolon - localized_name);
|
||||
g_free (temp);
|
||||
}
|
||||
|
||||
g_hash_table_replace (l10n_lang_list, g_strdup(code),
|
||||
g_strdup_printf ("%s [%s]",
|
||||
localized_name ?
|
||||
localized_name : "???",
|
||||
code));
|
||||
g_free (localized_name);
|
||||
}
|
||||
|
||||
g_free (base_code);
|
||||
}
|
||||
|
||||
/* Add special entries for system locale.
|
||||
* We want the system locale to be localized in itself. */
|
||||
g_setenv ("LANGUAGE", setlocale (LC_ALL, NULL), TRUE);
|
||||
setlocale (LC_ALL, "");
|
||||
|
||||
/* g_str_hash() does not accept NULL. I give an empty code instead.
|
||||
* Other solution would to create a custom hash. */
|
||||
g_hash_table_insert (l10n_lang_list, g_strdup(""),
|
||||
g_strdup (_("System Language")));
|
||||
|
||||
/* Go back to original localization. */
|
||||
if (current_env)
|
||||
{
|
||||
g_setenv ("LANGUAGE", current_env, TRUE);
|
||||
g_free (current_env);
|
||||
}
|
||||
else
|
||||
g_unsetenv ("LANGUAGE");
|
||||
setlocale (LC_ALL, "");
|
||||
|
||||
/* Add special entry for C (en_US). */
|
||||
g_hash_table_insert (l10n_lang_list, g_strdup ("en_US"),
|
||||
g_strdup ("English [en_US]"));
|
||||
|
||||
g_hash_table_destroy (base_lang_list);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_language_store_parser_clean (void)
|
||||
{
|
||||
g_hash_table_destroy (l10n_lang_list);
|
||||
g_hash_table_destroy (all_lang_list);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a Hash table of languages.
|
||||
* Keys and values are respectively language codes and names from the
|
||||
* ISO-639 standard code.
|
||||
*
|
||||
* If @localization_only is TRUE, it returns only the list of available
|
||||
* GIMP localizations, and language names are translated in their own
|
||||
* locale.
|
||||
* If @localization_only is FALSE, the full list of ISO-639 languages
|
||||
* is returned, and language names are in the user-set locale.
|
||||
*
|
||||
* Do not free the list or elements of the list.
|
||||
*/
|
||||
GHashTable *
|
||||
gimp_language_store_parser_get_languages (gboolean localization_only)
|
||||
{
|
||||
if (localization_only)
|
||||
return l10n_lang_list;
|
||||
else
|
||||
return all_lang_list;
|
||||
}
|
||||
|
||||
/*****************************\
|
||||
* Private Parsing Functions *
|
||||
\*****************************/
|
||||
|
||||
/*
|
||||
* Parse the ISO-639 code list if available on this system, and fill
|
||||
* @base_lang_list with English names of all needed base codes.
|
||||
*
|
||||
* It will also fill the static @all_lang_list.
|
||||
*/
|
||||
static gboolean
|
||||
parse_iso_codes (GHashTable *base_lang_list,
|
||||
GError **error)
|
||||
{
|
||||
gboolean success = TRUE;
|
||||
#ifdef HAVE_ISO_CODES
|
||||
static const GMarkupParser markup_parser =
|
||||
{
|
||||
iso_codes_parser_start_element,
|
||||
iso_codes_parser_end_element,
|
||||
NULL, /* characters */
|
||||
NULL, /* passthrough */
|
||||
NULL /* error */
|
||||
};
|
||||
|
||||
GimpXmlParser *xml_parser;
|
||||
gchar *filename;
|
||||
IsoCodesParser parser = { 0, };
|
||||
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
|
||||
iso_codes_parser_init ();
|
||||
|
||||
parser.base_lang_list = g_hash_table_ref (base_lang_list);
|
||||
|
||||
xml_parser = gimp_xml_parser_new (&markup_parser, &parser);
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
filename = g_build_filename (gimp_data_directory (),
|
||||
"..", "..", "xml", "iso-codes", "iso_639.xml",
|
||||
NULL);
|
||||
#else
|
||||
filename = g_build_filename (ISO_CODES_LOCATION, "iso_639.xml", NULL);
|
||||
#endif
|
||||
|
||||
success = gimp_xml_parser_parse_file (xml_parser, filename, error);
|
||||
|
||||
g_free (filename);
|
||||
|
||||
gimp_xml_parser_free (xml_parser);
|
||||
g_hash_table_unref (parser.base_lang_list);
|
||||
|
||||
#endif
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static void
|
||||
iso_codes_parser_init (void)
|
||||
|
@ -93,55 +366,6 @@ iso_codes_parser_init (void)
|
|||
initialized = TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gimp_language_store_parse_iso_codes (GimpLanguageStore *store,
|
||||
GError **error)
|
||||
{
|
||||
#ifdef HAVE_ISO_CODES
|
||||
static const GMarkupParser markup_parser =
|
||||
{
|
||||
iso_codes_parser_start_element,
|
||||
iso_codes_parser_end_element,
|
||||
NULL, /* characters */
|
||||
NULL, /* passthrough */
|
||||
NULL /* error */
|
||||
};
|
||||
|
||||
GimpXmlParser *xml_parser;
|
||||
gchar *filename;
|
||||
gboolean success;
|
||||
IsoCodesParser parser = { 0, };
|
||||
|
||||
g_return_val_if_fail (GIMP_IS_LANGUAGE_STORE (store), FALSE);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
|
||||
iso_codes_parser_init ();
|
||||
|
||||
parser.store = g_object_ref (store);
|
||||
|
||||
xml_parser = gimp_xml_parser_new (&markup_parser, &parser);
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
filename = g_build_filename (gimp_data_directory (),
|
||||
"..", "..", "xml", "iso-codes", "iso_639.xml",
|
||||
NULL);
|
||||
#else
|
||||
filename = g_build_filename (ISO_CODES_LOCATION, "iso_639.xml", NULL);
|
||||
#endif
|
||||
|
||||
success = gimp_xml_parser_parse_file (xml_parser, filename, error);
|
||||
|
||||
g_free (filename);
|
||||
|
||||
gimp_xml_parser_free (xml_parser);
|
||||
g_object_unref (parser.store);
|
||||
|
||||
return success;
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
iso_codes_parser_entry (IsoCodesParser *parser,
|
||||
const gchar **names,
|
||||
|
@ -153,101 +377,41 @@ iso_codes_parser_entry (IsoCodesParser *parser,
|
|||
while (*names && *values)
|
||||
{
|
||||
if (strcmp (*names, "name") == 0)
|
||||
{
|
||||
lang = *values;
|
||||
}
|
||||
lang = *values;
|
||||
else if (strcmp (*names, "iso_639_2B_code") == 0 && code == NULL)
|
||||
{
|
||||
/* 2-letter ISO 639-1 codes have priority.
|
||||
* But some languages have no 2-letter code.
|
||||
* Ex: Asturian (ast).
|
||||
*/
|
||||
code = *values;
|
||||
}
|
||||
/* 2-letter ISO 639-1 codes have priority.
|
||||
* But some languages have no 2-letter code. Ex: Asturian (ast).
|
||||
*/
|
||||
code = *values;
|
||||
else if (strcmp (*names, "iso_639_2T_code") == 0 && code == NULL)
|
||||
{
|
||||
code = *values;
|
||||
}
|
||||
code = *values;
|
||||
else if (strcmp (*names, "iso_639_1_code") == 0)
|
||||
{
|
||||
code = *values;
|
||||
}
|
||||
code = *values;
|
||||
|
||||
names++;
|
||||
values++;
|
||||
}
|
||||
|
||||
/* This is a hack for some special exception.
|
||||
* It seems localization won't work for the base language "zh". Probably because
|
||||
* written locale dialect are too different. So we have to be accurate and localize
|
||||
* separately each Chinese dialect we support.
|
||||
*
|
||||
* There was unfortunately no cleaner way to achieve this since there is no standardized
|
||||
* link between regions in iso-3166 and base languages in iso-639, which would allow
|
||||
* automatization for generating locale dialects codes.
|
||||
*/
|
||||
if (g_strcmp0 (code, "zh") == 0)
|
||||
{
|
||||
gimp_language_store_self_l10n (parser->store, "Chinese", "zh_CN");
|
||||
gimp_language_store_self_l10n (parser->store, "Chinese", "zh_TW");
|
||||
gimp_language_store_self_l10n (parser->store, "Chinese", "zh_HK");
|
||||
}
|
||||
else
|
||||
gimp_language_store_self_l10n (parser->store, lang, code);
|
||||
}
|
||||
|
||||
/* If possible, we want to localize a language in itself.
|
||||
* If it fails, fallback to the currently selected language, then to system lang.
|
||||
* Only fallback to C (en_US) as a last resort.
|
||||
*/
|
||||
static void
|
||||
gimp_language_store_self_l10n (GimpLanguageStore *store,
|
||||
const gchar *lang,
|
||||
const gchar *code)
|
||||
{
|
||||
if (lang && *lang && code && *code)
|
||||
{
|
||||
const gchar *semicolon;
|
||||
gchar *semicolon;
|
||||
gchar *localized_name = g_strdup (dgettext ("iso_639", lang));
|
||||
|
||||
/* English does not need localization. */
|
||||
if (g_strcmp0 (code, "en") != 0)
|
||||
{
|
||||
gchar *current_lang = g_strdup (g_getenv ("LANGUAGE"));
|
||||
gchar *temp_lang;
|
||||
|
||||
if (current_lang)
|
||||
temp_lang = g_strdup_printf ("%s:%s:%s", code, current_lang, setlocale (LC_ALL, NULL));
|
||||
else
|
||||
temp_lang = g_strdup (code);
|
||||
|
||||
/* Temporarily change the localization language. */
|
||||
g_setenv ("LANGUAGE", temp_lang, TRUE);
|
||||
setlocale (LC_ALL, "");
|
||||
lang = dgettext ("iso_639", lang);
|
||||
if (current_lang)
|
||||
g_setenv ("LANGUAGE", current_lang, TRUE);
|
||||
else
|
||||
g_unsetenv("LANGUAGE");
|
||||
setlocale (LC_ALL, "");
|
||||
|
||||
g_free (current_lang);
|
||||
g_free (temp_lang);
|
||||
}
|
||||
/* If the language is in our base table, we save its standard English name. */
|
||||
if (g_hash_table_contains (parser->base_lang_list, code))
|
||||
g_hash_table_replace (parser->base_lang_list, g_strdup (code), g_strdup (lang));
|
||||
|
||||
/* there might be several language names; use the first one */
|
||||
semicolon = strchr (lang, ';');
|
||||
semicolon = strchr (localized_name, ';');
|
||||
|
||||
if (semicolon)
|
||||
{
|
||||
gchar *first = g_strndup (lang, semicolon - lang);
|
||||
|
||||
gimp_language_store_add (store, first, code);
|
||||
g_free (first);
|
||||
}
|
||||
else
|
||||
{
|
||||
gimp_language_store_add (store, lang, code);
|
||||
gchar *temp = localized_name;
|
||||
localized_name = g_strndup (localized_name, semicolon - localized_name);
|
||||
g_free (temp);
|
||||
}
|
||||
/* In any case, we save the name in user-set language for all lang. */
|
||||
g_hash_table_insert (all_lang_list, g_strdup (code), localized_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* gimplanguagestore-parser.h
|
||||
* Copyright (C) 2008, 2009 Sven Neumann <sven@gimp.org>
|
||||
* Copyright (C) 2013 Jehan <jehan at girinstud.io>
|
||||
*
|
||||
* 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
|
||||
|
@ -22,8 +23,10 @@
|
|||
#define __GIMP_LANGUAGE_STORE_PARSER_H__
|
||||
|
||||
|
||||
gboolean gimp_language_store_parse_iso_codes (GimpLanguageStore *store,
|
||||
GError **error);
|
||||
void gimp_language_store_parser_init (void);
|
||||
|
||||
void gimp_language_store_parser_clean (void);
|
||||
|
||||
GHashTable* gimp_language_store_parser_get_languages (gboolean localization_only);
|
||||
|
||||
#endif /* __GIMP_LANGUAGE_STORE_PARSER_H__ */
|
||||
|
|
|
@ -76,9 +76,20 @@ gimp_language_store_init (GimpLanguageStore *store)
|
|||
static void
|
||||
gimp_language_store_constructed (GObject *object)
|
||||
{
|
||||
GHashTable *lang_list;
|
||||
GHashTableIter lang_iter;
|
||||
gpointer code;
|
||||
gpointer name;
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->constructed (object);
|
||||
|
||||
gimp_language_store_parse_iso_codes (GIMP_LANGUAGE_STORE (object), NULL);
|
||||
lang_list = gimp_language_store_parser_get_languages (FALSE);
|
||||
g_hash_table_iter_init (&lang_iter, lang_list);
|
||||
|
||||
while (g_hash_table_iter_next (&lang_iter, &code, &name))
|
||||
GIMP_LANGUAGE_STORE_GET_CLASS (object)->add (GIMP_LANGUAGE_STORE (object),
|
||||
GINT_TO_POINTER (name),
|
||||
GINT_TO_POINTER (code));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -109,10 +120,10 @@ gimp_language_store_sort (GtkTreeModel *model,
|
|||
gtk_tree_model_get_value (model, a, GIMP_LANGUAGE_STORE_CODE, &avalue);
|
||||
gtk_tree_model_get_value (model, b, GIMP_LANGUAGE_STORE_CODE, &bvalue);
|
||||
|
||||
if (! g_value_get_string (&avalue))
|
||||
if (g_strcmp0 ("", g_value_get_string (&avalue)) == 0)
|
||||
cmp = -1;
|
||||
|
||||
if (! g_value_get_string (&bvalue))
|
||||
if (g_strcmp0 ("", g_value_get_string (&bvalue)) == 0)
|
||||
cmp = 1;
|
||||
|
||||
g_value_unset (&avalue);
|
||||
|
@ -140,17 +151,6 @@ gimp_language_store_new (void)
|
|||
return g_object_new (GIMP_TYPE_LANGUAGE_STORE, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_language_store_add (GimpLanguageStore *store,
|
||||
const gchar *label,
|
||||
const gchar *code)
|
||||
{
|
||||
g_return_if_fail (GIMP_IS_LANGUAGE_STORE (store));
|
||||
g_return_if_fail (label != NULL);
|
||||
|
||||
GIMP_LANGUAGE_STORE_GET_CLASS (store)->add (store, label, code);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gimp_language_store_lookup (GimpLanguageStore *store,
|
||||
const gchar *code,
|
||||
|
|
|
@ -62,10 +62,4 @@ gboolean gimp_language_store_lookup (GimpLanguageStore *store,
|
|||
const gchar *code,
|
||||
GtkTreeIter *iter);
|
||||
|
||||
/* used from gimplanguagestore-parser.c */
|
||||
void gimp_language_store_add (GimpLanguageStore *store,
|
||||
const gchar *label,
|
||||
const gchar *code);
|
||||
|
||||
|
||||
#endif /* __GIMP_LANGUAGE_STORE_H__ */
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <locale.h>
|
||||
#include <string.h>
|
||||
|
||||
|
@ -31,8 +29,6 @@
|
|||
|
||||
#include "gimptranslationstore.h"
|
||||
|
||||
#include "gimp-intl.h"
|
||||
|
||||
|
||||
struct _GimpTranslationStoreClass
|
||||
{
|
||||
|
@ -42,19 +38,11 @@ struct _GimpTranslationStoreClass
|
|||
struct _GimpTranslationStore
|
||||
{
|
||||
GimpLanguageStore parent_instance;
|
||||
|
||||
GHashTable *map;
|
||||
};
|
||||
|
||||
|
||||
static void gimp_translation_store_constructed (GObject *object);
|
||||
|
||||
static void gimp_translation_store_add (GimpLanguageStore *store,
|
||||
const gchar *lang,
|
||||
const gchar *code);
|
||||
|
||||
static void gimp_translation_store_populate (GimpTranslationStore *store);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (GimpTranslationStore, gimp_translation_store,
|
||||
GIMP_TYPE_LANGUAGE_STORE)
|
||||
|
@ -66,134 +54,30 @@ static void
|
|||
gimp_translation_store_class_init (GimpTranslationStoreClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GimpLanguageStoreClass *store_class = GIMP_LANGUAGE_STORE_CLASS (klass);
|
||||
|
||||
object_class->constructed = gimp_translation_store_constructed;
|
||||
|
||||
store_class->add = gimp_translation_store_add;
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_translation_store_init (GimpTranslationStore *store)
|
||||
{
|
||||
store->map = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
(GDestroyNotify) g_free,
|
||||
(GDestroyNotify) g_free);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_translation_store_constructed (GObject *object)
|
||||
{
|
||||
GimpTranslationStore *store = GIMP_TRANSLATION_STORE (object);
|
||||
gchar *current_lang = g_strdup (g_getenv ("LANGUAGE"));
|
||||
gchar *label;
|
||||
GHashTable *lang_list;
|
||||
GHashTableIter lang_iter;
|
||||
gpointer code;
|
||||
gpointer name;
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->constructed (object);
|
||||
lang_list = gimp_language_store_parser_get_languages (TRUE);
|
||||
g_hash_table_iter_init (&lang_iter, lang_list);
|
||||
|
||||
gimp_translation_store_populate (store);
|
||||
|
||||
/* we don't need the map any longer */
|
||||
g_hash_table_unref (store->map);
|
||||
store->map = NULL;
|
||||
|
||||
/* add special entries for system locale and for "C".
|
||||
* We want the system locale to be localized in itself. */
|
||||
g_setenv ("LANGUAGE", setlocale (LC_ALL, NULL), TRUE);
|
||||
setlocale (LC_ALL, "");
|
||||
label = g_strdup_printf ("%s", _("System Language"));
|
||||
if (current_lang)
|
||||
g_setenv ("LANGUAGE", current_lang, TRUE);
|
||||
else
|
||||
g_unsetenv ("LANGUAGE");
|
||||
setlocale (LC_ALL, "");
|
||||
g_free (current_lang);
|
||||
|
||||
GIMP_LANGUAGE_STORE_CLASS (parent_class)->add (GIMP_LANGUAGE_STORE (store),
|
||||
label,
|
||||
NULL);
|
||||
g_free (label);
|
||||
|
||||
label = g_strdup_printf ("%s [%s]", "English", "en_US");
|
||||
GIMP_LANGUAGE_STORE_CLASS (parent_class)->add (GIMP_LANGUAGE_STORE (store),
|
||||
label, "en_US");
|
||||
g_free (label);
|
||||
}
|
||||
|
||||
static const gchar *
|
||||
gimp_translation_store_map (GimpTranslationStore *store,
|
||||
const gchar *locale)
|
||||
{
|
||||
const gchar *lang;
|
||||
|
||||
/* A locale directory name is typically of the form language[_territory] */
|
||||
lang = g_hash_table_lookup (store->map, locale);
|
||||
|
||||
if (! lang)
|
||||
{
|
||||
/* strip off the territory suffix */
|
||||
const gchar *delimiter = strchr (locale, '_');
|
||||
|
||||
if (delimiter)
|
||||
{
|
||||
gchar *copy;
|
||||
|
||||
copy = g_strndup (locale, delimiter - locale);
|
||||
lang = g_hash_table_lookup (store->map, copy);
|
||||
g_free (copy);
|
||||
}
|
||||
}
|
||||
|
||||
return lang;
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_translation_store_populate (GimpTranslationStore *store)
|
||||
{
|
||||
/* FIXME: this should better be done asynchronously */
|
||||
GDir *dir = g_dir_open (gimp_locale_directory (), 0, NULL);
|
||||
const gchar *dirname;
|
||||
|
||||
if (! dir)
|
||||
return;
|
||||
|
||||
while ((dirname = g_dir_read_name (dir)) != NULL)
|
||||
{
|
||||
gchar *filename = g_build_filename (gimp_locale_directory (),
|
||||
dirname,
|
||||
"LC_MESSAGES",
|
||||
GETTEXT_PACKAGE ".mo",
|
||||
NULL);
|
||||
if (g_file_test (filename, G_FILE_TEST_EXISTS))
|
||||
{
|
||||
const gchar *lang = gimp_translation_store_map (store, dirname);
|
||||
|
||||
if (lang)
|
||||
{
|
||||
GimpLanguageStore *language_store = GIMP_LANGUAGE_STORE (store);
|
||||
gchar *label;
|
||||
|
||||
label = g_strdup_printf ("%s [%s]", lang, dirname);
|
||||
|
||||
GIMP_LANGUAGE_STORE_CLASS (parent_class)->add (language_store,
|
||||
label, dirname);
|
||||
g_free (label);
|
||||
}
|
||||
}
|
||||
|
||||
g_free (filename);
|
||||
}
|
||||
|
||||
g_dir_close (dir);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_translation_store_add (GimpLanguageStore *store,
|
||||
const gchar *lang,
|
||||
const gchar *code)
|
||||
{
|
||||
g_hash_table_replace (GIMP_TRANSLATION_STORE (store)->map,
|
||||
g_strdup (code),
|
||||
g_strdup (lang));
|
||||
while (g_hash_table_iter_next (&lang_iter, &code, &name))
|
||||
GIMP_LANGUAGE_STORE_GET_CLASS (object)->add (GIMP_LANGUAGE_STORE (object),
|
||||
GINT_TO_POINTER (name),
|
||||
GINT_TO_POINTER (code));
|
||||
}
|
||||
|
||||
GtkListStore *
|
||||
|
|
Loading…
Reference in New Issue