[evolution] Bug 228772 - Allow to specify a default language for a given identity
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution] Bug 228772 - Allow to specify a default language for a given identity
- Date: Mon, 8 Oct 2018 17:05:40 +0000 (UTC)
commit 65f7ba867d3f367a46a1a7a8d766a98190eeb1d0
Author: Milan Crha <mcrha redhat com>
Date: Mon Oct 8 19:05:54 2018 +0200
Bug 228772 - Allow to specify a default language for a given identity
Closes https://bugzilla.gnome.org/show_bug.cgi?id=228772
data/org.gnome.evolution.mail.gschema.xml.in | 4 +
src/addressbook/gui/contact-editor/test-editor.c | 2 +-
src/composer/e-composer-private.c | 103 +++++++
src/composer/e-composer-private.h | 2 +
src/e-util/e-html-editor-actions.c | 38 +++
src/e-util/e-html-editor-private.h | 3 +
src/e-util/e-html-editor.c | 1 +
src/e-util/e-misc-utils.c | 303 ++++++++++++++++++++
src/e-util/e-misc-utils.h | 2 +
src/e-util/e-spell-checker.c | 6 +-
src/e-util/e-spell-dictionary.c | 252 +---------------
src/e-util/evolution-source-viewer.c | 2 +-
src/e-util/test-accounts-window.c | 2 +-
src/e-util/test-calendar.c | 2 +-
src/e-util/test-category-completion.c | 2 +-
src/e-util/test-contact-store.c | 2 +-
src/e-util/test-dateedit.c | 2 +-
src/e-util/test-html-editor-units.c | 3 +-
src/e-util/test-html-editor.c | 3 +-
src/e-util/test-mail-signatures.c | 2 +-
src/e-util/test-name-selector.c | 2 +-
src/e-util/test-preferences-window.c | 2 +-
src/e-util/test-proxy-preferences.c | 2 +-
src/e-util/test-source-combo-box.c | 2 +-
src/e-util/test-source-config.c | 2 +-
src/e-util/test-source-selector.c | 2 +-
src/e-util/test-tree-view-frame.c | 2 +-
src/mail/CMakeLists.txt | 1 +
src/mail/e-mail-config-composing-page.c | 64 ++++-
src/mail/em-composer-utils.c | 317 ++++++++++++++++++---
src/mail/em-composer-utils.h | 9 +-
src/mail/mail-config.ui | 66 ++++-
src/modules/backup-restore/evolution-backup-tool.c | 2 +-
src/modules/mail/em-composer-prefs.c | 13 +
.../attachment-reminder/attachment-reminder.c | 11 +-
src/shell/main.c | 4 +-
36 files changed, 888 insertions(+), 349 deletions(-)
---
diff --git a/data/org.gnome.evolution.mail.gschema.xml.in b/data/org.gnome.evolution.mail.gschema.xml.in
index c1c4788aad..44c9ba7825 100644
--- a/data/org.gnome.evolution.mail.gschema.xml.in
+++ b/data/org.gnome.evolution.mail.gschema.xml.in
@@ -476,6 +476,10 @@
<default>'quoted'</default>
<_summary>Default reply style</_summary>
</key>
+ <key name="composer-attribution-language" type="s">
+ <default>''</default>
+ <_summary>Forward and reply attribution language tag, like en_US. Empty string means to use the same
language as the user interface.</_summary>
+ </key>
<key name="prompt-on-accel-send" type="b">
<default>true</default>
<_summary>Prompt on send when using key accelerator (Ctrl+Enter)</_summary>
diff --git a/src/addressbook/gui/contact-editor/test-editor.c
b/src/addressbook/gui/contact-editor/test-editor.c
index e93d410d97..27aea80393 100644
--- a/src/addressbook/gui/contact-editor/test-editor.c
+++ b/src/addressbook/gui/contact-editor/test-editor.c
@@ -108,7 +108,7 @@ main (gint argc,
gtk_main ();
- e_util_cleanup_settings ();
+ e_misc_util_free_global_memory ();
return 0;
}
diff --git a/src/composer/e-composer-private.c b/src/composer/e-composer-private.c
index 5475ae7c68..66d6605a94 100644
--- a/src/composer/e-composer-private.c
+++ b/src/composer/e-composer-private.c
@@ -83,6 +83,105 @@ composer_update_gallery_visibility (EMsgComposer *composer)
}
}
+static gchar *
+e_composer_extract_lang_from_source (ESourceRegistry *registry,
+ const gchar *uid)
+{
+ ESource *source;
+ gchar *lang = NULL;
+
+ g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+ g_return_val_if_fail (uid != NULL, NULL);
+
+ source = e_source_registry_ref_source (registry, uid);
+ if (source && e_source_has_extension (source, E_SOURCE_EXTENSION_MAIL_COMPOSITION)) {
+ ESourceMailComposition *mail_composition;
+
+ mail_composition = e_source_get_extension (source, E_SOURCE_EXTENSION_MAIL_COMPOSITION);
+ lang = e_source_mail_composition_dup_language (mail_composition);
+
+ if (lang && !*lang) {
+ g_free (lang);
+ lang = NULL;
+ }
+ }
+
+ g_clear_object (&source);
+
+ return lang;
+}
+
+static void
+e_composer_from_changed_cb (EComposerFromHeader *header,
+ EMsgComposer *composer)
+{
+ gchar *current_uid;
+
+ g_return_if_fail (E_IS_MSG_COMPOSER (composer));
+
+ current_uid = e_composer_from_header_dup_active_id (header, NULL, NULL);
+
+ if (current_uid && g_strcmp0 (composer->priv->previous_identity_uid, current_uid) != 0) {
+ gchar *previous_lang = NULL, *current_lang = NULL;
+ ESourceRegistry *registry;
+
+ registry = e_composer_header_get_registry (E_COMPOSER_HEADER (header));
+
+ if (composer->priv->previous_identity_uid)
+ previous_lang = e_composer_extract_lang_from_source (registry,
composer->priv->previous_identity_uid);
+
+ current_lang = e_composer_extract_lang_from_source (registry, current_uid);
+
+ if (g_strcmp0 (previous_lang, current_lang) != 0) {
+ GSettings *settings;
+ gchar **strv;
+ gboolean have_previous, have_current;
+ gint ii;
+
+ settings = e_util_ref_settings ("org.gnome.evolution.mail");
+ strv = g_settings_get_strv (settings, "composer-spell-languages");
+ g_object_unref (settings);
+
+ have_previous = !previous_lang;
+ have_current = !current_lang;
+
+ for (ii = 0; strv && strv[ii] && (!have_previous || !have_current); ii++) {
+ have_previous = have_previous || g_strcmp0 (previous_lang, strv[ii]) == 0;
+ have_current = have_current || g_strcmp0 (current_lang, strv[ii]) == 0;
+ }
+
+ g_strfreev (strv);
+
+ if (!have_previous || !have_current) {
+ ESpellChecker *spell_checker;
+ EHTMLEditor *editor;
+
+ editor = e_msg_composer_get_editor (composer);
+ spell_checker = e_content_editor_ref_spell_checker
(e_html_editor_get_content_editor (editor));
+
+ if (!have_previous)
+ e_spell_checker_set_language_active (spell_checker, previous_lang,
FALSE);
+
+ if (!have_current)
+ e_spell_checker_set_language_active (spell_checker, current_lang,
TRUE);
+
+ g_clear_object (&spell_checker);
+
+ e_html_editor_update_spell_actions (editor);
+ g_signal_emit_by_name (editor, "spell-languages-changed");
+ }
+ }
+
+ g_free (previous_lang);
+ g_free (current_lang);
+
+ g_free (composer->priv->previous_identity_uid);
+ composer->priv->previous_identity_uid = current_uid;
+ } else {
+ g_free (current_uid);
+ }
+}
+
void
e_composer_private_constructed (EMsgComposer *composer)
{
@@ -307,6 +406,9 @@ e_composer_private_constructed (EMsgComposer *composer)
action, "active",
G_BINDING_BIDIRECTIONAL |
G_BINDING_SYNC_CREATE);
+
+ g_signal_connect (header, "changed",
+ G_CALLBACK (e_composer_from_changed_cb), composer);
continue;
case E_COMPOSER_HEADER_BCC:
@@ -449,6 +551,7 @@ e_composer_private_finalize (EMsgComposer *composer)
g_free (composer->priv->charset);
g_free (composer->priv->mime_type);
g_free (composer->priv->mime_body);
+ g_free (composer->priv->previous_identity_uid);
}
gchar *
diff --git a/src/composer/e-composer-private.h b/src/composer/e-composer-private.h
index 9ceb900e22..4a2e2e3e06 100644
--- a/src/composer/e-composer-private.h
+++ b/src/composer/e-composer-private.h
@@ -119,6 +119,8 @@ struct _EMsgComposerPrivate {
gulong notify_subject_changed_handler;
gulong drag_data_received_handler_id;
+
+ gchar *previous_identity_uid;
};
void e_composer_private_constructed (EMsgComposer *composer);
diff --git a/src/e-util/e-html-editor-actions.c b/src/e-util/e-html-editor-actions.c
index e32249eb17..8f7eeceed4 100644
--- a/src/e-util/e-html-editor-actions.c
+++ b/src/e-util/e-html-editor-actions.c
@@ -1999,3 +1999,41 @@ editor_actions_bind (EHTMLEditor *editor)
editor->priv->suggestion_actions, "sensitive",
G_BINDING_SYNC_CREATE);
}
+
+void
+editor_actions_update_spellcheck_languages_menu (EHTMLEditor *editor,
+ const gchar * const *languages)
+{
+ GHashTable *active;
+ GList *actions, *link;
+ gint ii;
+
+ g_return_if_fail (E_IS_HTML_EDITOR (editor));
+
+ active = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+ for (ii = 0; languages && languages[ii]; ii++) {
+ g_hash_table_insert (active, g_strdup (languages[ii]), NULL);
+ }
+
+ actions = gtk_action_group_list_actions (editor->priv->language_actions);
+ for (link = actions; link; link = g_list_next (link)) {
+ GtkToggleAction *toggle_action;
+ gboolean is_active;
+
+ if (!GTK_IS_TOGGLE_ACTION (link->data))
+ continue;
+
+ is_active = g_hash_table_contains (active, gtk_action_get_name (link->data));
+ toggle_action = GTK_TOGGLE_ACTION (link->data);
+
+ if ((gtk_toggle_action_get_active (toggle_action) ? 1 : 0) != (is_active ? 1 : 0)) {
+ g_signal_handlers_block_by_func (toggle_action, action_language_cb, editor);
+ gtk_toggle_action_set_active (toggle_action, is_active);
+ g_signal_handlers_unblock_by_func (toggle_action, action_language_cb, editor);
+ }
+ }
+
+ g_hash_table_destroy (active);
+ g_list_free (actions);
+}
diff --git a/src/e-util/e-html-editor-private.h b/src/e-util/e-html-editor-private.h
index 733bec0317..b652f0a538 100644
--- a/src/e-util/e-html-editor-private.h
+++ b/src/e-util/e-html-editor-private.h
@@ -97,6 +97,9 @@ struct _EHTMLEditorPrivate {
void editor_actions_init (EHTMLEditor *editor);
void editor_actions_bind (EHTMLEditor *editor);
+void editor_actions_update_spellcheck_languages_menu
+ (EHTMLEditor *editor,
+ const gchar * const *languages);
const gchar * e_html_editor_get_content_editor_name
(EHTMLEditor *editor);
diff --git a/src/e-util/e-html-editor.c b/src/e-util/e-html-editor.c
index 9b46be681c..e4a7538ac9 100644
--- a/src/e-util/e-html-editor.c
+++ b/src/e-util/e-html-editor.c
@@ -485,6 +485,7 @@ html_editor_spell_languages_changed (EHTMLEditor *editor)
E_HTML_EDITOR_SPELL_CHECK_DIALOG (
editor->priv->spell_check_dialog));
+ editor_actions_update_spellcheck_languages_menu (editor, (const gchar * const *) languages);
g_clear_object (&spell_checker);
g_strfreev (languages);
}
diff --git a/src/e-util/e-misc-utils.c b/src/e-util/e-misc-utils.c
index fffd9207bf..21896b470b 100644
--- a/src/e-util/e-misc-utils.c
+++ b/src/e-util/e-misc-utils.c
@@ -63,6 +63,8 @@
#include "e-client-cache.h"
#include "e-filter-option.h"
#include "e-mktemp.h"
+#include "e-simple-async-result.h"
+#include "e-spell-checker.h"
#include "e-util-private.h"
#include "e-xml-utils.h"
@@ -4236,3 +4238,304 @@ e_util_query_ldap_root_dse_sync (const gchar *host,
return FALSE;
#endif
}
+
+static GHashTable *iso_639_table = NULL;
+static GHashTable *iso_3166_table = NULL;
+
+#ifdef HAVE_ISO_CODES
+
+#define ISOCODESLOCALEDIR ISO_CODES_PREFIX "/share/locale"
+
+#ifdef G_OS_WIN32
+#ifdef DATADIR
+#undef DATADIR
+#endif
+#include <shlobj.h>
+
+static gchar *
+_get_iso_codes_prefix (void)
+{
+ static gchar retval[1000];
+ static gint beenhere = 0;
+ gchar *temp_dir = 0;
+
+ if (beenhere)
+ return retval;
+
+ if (!(temp_dir = g_win32_get_package_installation_directory_of_module (_e_get_dll_hmodule ()))) {
+ strcpy (retval, ISO_CODES_PREFIX);
+ return retval;
+ }
+
+ strcpy (retval, temp_dir);
+ g_free (temp_dir);
+ beenhere = 1;
+ return retval;
+}
+
+static gchar *
+_get_isocodeslocaledir (void)
+{
+ static gchar retval[1000];
+ static gint beenhere = 0;
+
+ if (beenhere)
+ return retval;
+
+ g_snprintf (retval, sizeof (retval), "%s\\share\\locale", _get_iso_codes_prefix ());
+ beenhere = 1;
+ return retval;
+}
+
+#undef ISO_CODES_PREFIX
+#define ISO_CODES_PREFIX _get_iso_codes_prefix ()
+
+#undef ISOCODESLOCALEDIR
+#define ISOCODESLOCALEDIR _get_isocodeslocaledir ()
+
+#endif
+
+#define ISO_639_DOMAIN "iso_639"
+#define ISO_3166_DOMAIN "iso_3166"
+
+static void
+iso_639_start_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ gpointer data,
+ GError **error)
+{
+ GHashTable *hash_table = data;
+ const gchar *iso_639_1_code = NULL;
+ const gchar *iso_639_2_code = NULL;
+ const gchar *name = NULL;
+ const gchar *code = NULL;
+ gint ii;
+
+ if (g_strcmp0 (element_name, "iso_639_entry") != 0) {
+ return;
+ }
+
+ for (ii = 0; attribute_names[ii] != NULL; ii++) {
+ if (strcmp (attribute_names[ii], "name") == 0)
+ name = attribute_values[ii];
+ else if (strcmp (attribute_names[ii], "iso_639_1_code") == 0)
+ iso_639_1_code = attribute_values[ii];
+ else if (strcmp (attribute_names[ii], "iso_639_2T_code") == 0)
+ iso_639_2_code = attribute_values[ii];
+ }
+
+ code = (iso_639_1_code != NULL) ? iso_639_1_code : iso_639_2_code;
+
+ if (code != NULL && *code != '\0' && name != NULL && *name != '\0')
+ g_hash_table_insert (
+ hash_table, g_strdup (code),
+ g_strdup (dgettext (ISO_639_DOMAIN, name)));
+}
+
+static void
+iso_3166_start_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ gpointer data,
+ GError **error)
+{
+ GHashTable *hash_table = data;
+ const gchar *name = NULL;
+ const gchar *code = NULL;
+ gint ii;
+
+ if (strcmp (element_name, "iso_3166_entry") != 0)
+ return;
+
+ for (ii = 0; attribute_names[ii] != NULL; ii++) {
+ if (strcmp (attribute_names[ii], "name") == 0)
+ name = attribute_values[ii];
+ else if (strcmp (attribute_names[ii], "alpha_2_code") == 0)
+ code = attribute_values[ii];
+ }
+
+ if (code != NULL && *code != '\0' && name != NULL && *name != '\0')
+ g_hash_table_insert (
+ hash_table, g_ascii_strdown (code, -1),
+ g_strdup (dgettext (ISO_3166_DOMAIN, name)));
+}
+
+static GMarkupParser iso_639_parser = {
+ iso_639_start_element,
+ NULL, NULL, NULL, NULL
+};
+
+static GMarkupParser iso_3166_parser = {
+ iso_3166_start_element,
+ NULL, NULL, NULL, NULL
+};
+
+static void
+iso_codes_parse (const GMarkupParser *parser,
+ const gchar *basename,
+ GHashTable *hash_table)
+{
+ GMappedFile *mapped_file;
+ gchar *filename;
+ GError *error = NULL;
+
+ filename = g_build_filename (
+ ISO_CODES_PREFIX, "share", "xml",
+ "iso-codes", basename, NULL);
+ mapped_file = g_mapped_file_new (filename, FALSE, &error);
+ g_free (filename);
+
+ if (mapped_file != NULL) {
+ GMarkupParseContext *context;
+ const gchar *contents;
+ gsize length;
+
+ context = g_markup_parse_context_new (
+ parser, 0, hash_table, NULL);
+ contents = g_mapped_file_get_contents (mapped_file);
+ length = g_mapped_file_get_length (mapped_file);
+ g_markup_parse_context_parse (
+ context, contents, length, &error);
+ g_markup_parse_context_free (context);
+#if GLIB_CHECK_VERSION(2,21,3)
+ g_mapped_file_unref (mapped_file);
+#else
+ g_mapped_file_free (mapped_file);
+#endif
+ }
+
+ if (error != NULL) {
+ g_warning ("%s: %s", basename, error->message);
+ g_error_free (error);
+ }
+}
+
+#endif /* HAVE_ISO_CODES */
+
+/**
+ * e_util_get_language_name:
+ * @language_tag: Language tag to get its name for
+ *
+ * Returns: (transfer full): Newly allocated string with localized language name
+ *
+ * Since: 3.32
+ **/
+gchar *
+e_util_get_language_name (const gchar *language_tag)
+{
+ const gchar *iso_639_name;
+ const gchar *iso_3166_name;
+ gchar *language_name;
+ gchar *lowercase;
+ gchar **tokens;
+
+ g_return_val_if_fail (language_tag != NULL, NULL);
+
+ /* Split language code into lowercase tokens. */
+ lowercase = g_ascii_strdown (language_tag, -1);
+ tokens = g_strsplit (lowercase, "_", -1);
+ g_free (lowercase);
+
+ g_return_val_if_fail (tokens != NULL, NULL);
+
+ if (!iso_639_table && !iso_3166_table) {
+#if defined (ENABLE_NLS) && defined (HAVE_ISO_CODES)
+ 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");
+#endif /* ENABLE_NLS && HAVE_ISO_CODES */
+
+ iso_639_table = g_hash_table_new_full (
+ (GHashFunc) g_str_hash,
+ (GEqualFunc) g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_free);
+
+ iso_3166_table = g_hash_table_new_full (
+ (GHashFunc) g_str_hash,
+ (GEqualFunc) g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_free);
+
+#ifdef HAVE_ISO_CODES
+ iso_codes_parse (
+ &iso_639_parser, "iso_639.xml", iso_639_table);
+ iso_codes_parse (
+ &iso_3166_parser, "iso_3166.xml", iso_3166_table);
+#endif /* HAVE_ISO_CODES */
+ }
+
+ iso_639_name = g_hash_table_lookup (iso_639_table, tokens[0]);
+
+ if (iso_639_name == NULL) {
+ language_name = g_strdup_printf (
+ /* Translators: %s is the language ISO code. */
+ C_("language", "Unknown (%s)"), language_tag);
+ goto exit;
+ }
+
+ if (g_strv_length (tokens) < 2) {
+ language_name = g_strdup (iso_639_name);
+ goto exit;
+ }
+
+ iso_3166_name = g_hash_table_lookup (iso_3166_table, tokens[1]);
+
+ if (iso_3166_name != NULL)
+ language_name = g_strdup_printf (
+ /* Translators: The first %s is the language name, and the
+ * second is the country name. Example: "French (France)" */
+ C_("language", "%s (%s)"), iso_639_name, iso_3166_name);
+ else
+ language_name = g_strdup_printf (
+ /* Translators: The first %s is the language name, and the
+ * second is the country name. Example: "French (France)" */
+ C_("language", "%s (%s)"), iso_639_name, tokens[1]);
+
+ exit:
+ g_strfreev (tokens);
+
+ if (language_name) {
+ gchar *ptr;
+
+ /* When the name has two or more ';' then strip the string at the second of them */
+ ptr = strchr (language_name, ';');
+ if (ptr)
+ ptr = strchr (ptr + 1, ';');
+ if (ptr)
+ *ptr = '\0';
+ }
+
+ return language_name;
+}
+
+/**
+ * e_misc_util_free_global_memory:
+ *
+ * Frees global memory allocated by evolution-util library.
+ * This is usually called at the end of the application.
+ *
+ * Since: 3.32
+ **/
+void
+e_misc_util_free_global_memory (void)
+{
+ if (iso_639_table) {
+ g_hash_table_destroy (iso_639_table);
+ iso_639_table = NULL;
+ }
+
+ if (iso_3166_table) {
+ g_hash_table_destroy (iso_3166_table);
+ iso_3166_table = NULL;
+ }
+
+ e_util_cleanup_settings ();
+ e_spell_checker_free_global_memory ();
+ e_simple_async_result_free_global_memory ();
+}
diff --git a/src/e-util/e-misc-utils.h b/src/e-util/e-misc-utils.h
index e170e1993c..3b8e976758 100644
--- a/src/e-util/e-misc-utils.h
+++ b/src/e-util/e-misc-utils.h
@@ -347,6 +347,8 @@ gboolean e_util_query_ldap_root_dse_sync (const gchar *host,
gchar ***out_root_dse,
GCancellable *cancellable,
GError **error);
+gchar * e_util_get_language_name (const gchar *language_tag);
+void e_misc_util_free_global_memory (void);
G_END_DECLS
diff --git a/src/e-util/e-spell-checker.c b/src/e-util/e-spell-checker.c
index 5ae1fa66a4..3e121de430 100644
--- a/src/e-util/e-spell-checker.c
+++ b/src/e-util/e-spell-checker.c
@@ -429,7 +429,8 @@ e_spell_checker_get_language_active (ESpellChecker *checker,
g_return_val_if_fail (language_code != NULL, FALSE);
dictionary = e_spell_checker_ref_dictionary (checker, language_code);
- g_return_val_if_fail (dictionary != NULL, FALSE);
+ if (!dictionary)
+ return FALSE;
active_dictionaries = checker->priv->active_dictionaries;
active = g_hash_table_contains (active_dictionaries, dictionary);
@@ -452,7 +453,8 @@ e_spell_checker_set_language_active (ESpellChecker *checker,
g_return_if_fail (language_code != NULL);
dictionary = e_spell_checker_ref_dictionary (checker, language_code);
- g_return_if_fail (dictionary != NULL);
+ if (!dictionary)
+ return;
active_dictionaries = checker->priv->active_dictionaries;
is_active = g_hash_table_contains (active_dictionaries, dictionary);
diff --git a/src/e-util/e-spell-dictionary.c b/src/e-util/e-spell-dictionary.c
index a8f4df8a3f..4f0af47218 100644
--- a/src/e-util/e-spell-dictionary.c
+++ b/src/e-util/e-spell-dictionary.c
@@ -20,7 +20,7 @@
#include <enchant.h>
-#include "e-util-private.h"
+#include "e-misc-utils.h"
#include "e-spell-dictionary.h"
#include "e-spell-checker.h"
@@ -50,187 +50,11 @@ struct _ESpellDictionaryPrivate {
gchar *collate_key;
};
-#define ISO_639_DOMAIN "iso_639"
-#define ISO_3166_DOMAIN "iso_3166"
-
-static GHashTable *iso_639_table = NULL;
-static GHashTable *iso_3166_table = NULL;
-
G_DEFINE_TYPE (
ESpellDictionary,
e_spell_dictionary,
G_TYPE_OBJECT);
-#ifdef HAVE_ISO_CODES
-
-#define ISOCODESLOCALEDIR ISO_CODES_PREFIX "/share/locale"
-
-#ifdef G_OS_WIN32
-#ifdef DATADIR
-#undef DATADIR
-#endif
-#include <shlobj.h>
-
-static gchar *
-_get_iso_codes_prefix (void)
-{
- static gchar retval[1000];
- static gint beenhere = 0;
- gchar *temp_dir = 0;
-
- if (beenhere)
- return retval;
-
- if (!(temp_dir = g_win32_get_package_installation_directory_of_module (_e_get_dll_hmodule ()))) {
- strcpy (retval, ISO_CODES_PREFIX);
- return retval;
- }
-
- strcpy (retval, temp_dir);
- g_free (temp_dir);
- beenhere = 1;
- return retval;
-}
-
-static gchar *
-_get_isocodeslocaledir (void)
-{
- static gchar retval[1000];
- static gint beenhere = 0;
-
- if (beenhere)
- return retval;
-
- g_snprintf (retval, sizeof (retval), "%s\\share\\locale", _get_iso_codes_prefix ());
- beenhere = 1;
- return retval;
-}
-
-#undef ISO_CODES_PREFIX
-#define ISO_CODES_PREFIX _get_iso_codes_prefix ()
-
-#undef ISOCODESLOCALEDIR
-#define ISOCODESLOCALEDIR _get_isocodeslocaledir ()
-
-#endif
-
-static void
-iso_639_start_element (GMarkupParseContext *context,
- const gchar *element_name,
- const gchar **attribute_names,
- const gchar **attribute_values,
- gpointer data,
- GError **error)
-{
- GHashTable *hash_table = data;
- const gchar *iso_639_1_code = NULL;
- const gchar *iso_639_2_code = NULL;
- const gchar *name = NULL;
- const gchar *code = NULL;
- gint ii;
-
- if (g_strcmp0 (element_name, "iso_639_entry") != 0) {
- return;
- }
-
- for (ii = 0; attribute_names[ii] != NULL; ii++) {
- if (strcmp (attribute_names[ii], "name") == 0)
- name = attribute_values[ii];
- else if (strcmp (attribute_names[ii], "iso_639_1_code") == 0)
- iso_639_1_code = attribute_values[ii];
- else if (strcmp (attribute_names[ii], "iso_639_2T_code") == 0)
- iso_639_2_code = attribute_values[ii];
- }
-
- code = (iso_639_1_code != NULL) ? iso_639_1_code : iso_639_2_code;
-
- if (code != NULL && *code != '\0' && name != NULL && *name != '\0')
- g_hash_table_insert (
- hash_table, g_strdup (code),
- g_strdup (dgettext (ISO_639_DOMAIN, name)));
-}
-
-static void
-iso_3166_start_element (GMarkupParseContext *context,
- const gchar *element_name,
- const gchar **attribute_names,
- const gchar **attribute_values,
- gpointer data,
- GError **error)
-{
- GHashTable *hash_table = data;
- const gchar *name = NULL;
- const gchar *code = NULL;
- gint ii;
-
- if (strcmp (element_name, "iso_3166_entry") != 0)
- return;
-
- for (ii = 0; attribute_names[ii] != NULL; ii++) {
- if (strcmp (attribute_names[ii], "name") == 0)
- name = attribute_values[ii];
- else if (strcmp (attribute_names[ii], "alpha_2_code") == 0)
- code = attribute_values[ii];
- }
-
- if (code != NULL && *code != '\0' && name != NULL && *name != '\0')
- g_hash_table_insert (
- hash_table, g_ascii_strdown (code, -1),
- g_strdup (dgettext (ISO_3166_DOMAIN, name)));
-}
-
-static GMarkupParser iso_639_parser = {
- iso_639_start_element,
- NULL, NULL, NULL, NULL
-};
-
-static GMarkupParser iso_3166_parser = {
- iso_3166_start_element,
- NULL, NULL, NULL, NULL
-};
-
-static void
-iso_codes_parse (const GMarkupParser *parser,
- const gchar *basename,
- GHashTable *hash_table)
-{
- GMappedFile *mapped_file;
- gchar *filename;
- GError *error = NULL;
-
- filename = g_build_filename (
- ISO_CODES_PREFIX, "share", "xml",
- "iso-codes", basename, NULL);
- mapped_file = g_mapped_file_new (filename, FALSE, &error);
- g_free (filename);
-
- if (mapped_file != NULL) {
- GMarkupParseContext *context;
- const gchar *contents;
- gsize length;
-
- context = g_markup_parse_context_new (
- parser, 0, hash_table, NULL);
- contents = g_mapped_file_get_contents (mapped_file);
- length = g_mapped_file_get_length (mapped_file);
- g_markup_parse_context_parse (
- context, contents, length, &error);
- g_markup_parse_context_free (context);
-#if GLIB_CHECK_VERSION(2,21,3)
- g_mapped_file_unref (mapped_file);
-#else
- g_mapped_file_free (mapped_file);
-#endif
- }
-
- if (error != NULL) {
- g_warning ("%s: %s", basename, error->message);
- g_error_free (error);
- }
-}
-
-#endif /* HAVE_ISO_CODES */
-
struct _enchant_dict_description_data {
gchar *language_tag;
gchar *dict_name;
@@ -244,51 +68,9 @@ describe_dictionary (const gchar *language_tag,
gpointer user_data)
{
struct _enchant_dict_description_data *data = user_data;
- const gchar *iso_639_name;
- const gchar *iso_3166_name;
- gchar *language_name;
- gchar *lowercase;
- gchar **tokens;
-
- /* Split language code into lowercase tokens. */
- lowercase = g_ascii_strdown (language_tag, -1);
- tokens = g_strsplit (lowercase, "_", -1);
- g_free (lowercase);
-
- g_return_if_fail (tokens != NULL);
-
- iso_639_name = g_hash_table_lookup (iso_639_table, tokens[0]);
-
- if (iso_639_name == NULL) {
- language_name = g_strdup_printf (
- /* Translators: %s is the language ISO code. */
- C_("language", "Unknown (%s)"), language_tag);
- goto exit;
- }
-
- if (g_strv_length (tokens) < 2) {
- language_name = g_strdup (iso_639_name);
- goto exit;
- }
-
- iso_3166_name = g_hash_table_lookup (iso_3166_table, tokens[1]);
-
- if (iso_3166_name != NULL)
- language_name = g_strdup_printf (
- /* Translators: The first %s is the language name, and the
- * second is the country name. Example: "French (France)" */
- C_("language", "%s (%s)"), iso_639_name, iso_3166_name);
- else
- language_name = g_strdup_printf (
- /* Translators: The first %s is the language name, and the
- * second is the country name. Example: "French (France)" */
- C_("language", "%s (%s)"), iso_639_name, tokens[1]);
-
-exit:
- g_strfreev (tokens);
data->language_tag = g_strdup (language_tag);
- data->dict_name = language_name;
+ data->dict_name = e_util_get_language_name (language_tag);
}
static void
@@ -405,35 +187,6 @@ static void
e_spell_dictionary_init (ESpellDictionary *dictionary)
{
dictionary->priv = E_SPELL_DICTIONARY_GET_PRIVATE (dictionary);
-
- if (!iso_639_table && !iso_3166_table) {
-#if defined (ENABLE_NLS) && defined (HAVE_ISO_CODES)
- 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");
-#endif /* ENABLE_NLS && HAVE_ISO_CODES */
-
- iso_639_table = g_hash_table_new_full (
- (GHashFunc) g_str_hash,
- (GEqualFunc) g_str_equal,
- (GDestroyNotify) g_free,
- (GDestroyNotify) g_free);
-
- iso_3166_table = g_hash_table_new_full (
- (GHashFunc) g_str_hash,
- (GEqualFunc) g_str_equal,
- (GDestroyNotify) g_free,
- (GDestroyNotify) g_free);
-
-#ifdef HAVE_ISO_CODES
- iso_codes_parse (
- &iso_639_parser, "iso_639.xml", iso_639_table);
- iso_codes_parse (
- &iso_3166_parser, "iso_3166.xml", iso_3166_table);
-#endif /* HAVE_ISO_CODES */
- }
}
ESpellDictionary *
@@ -799,4 +552,3 @@ e_spell_dictionary_store_correction (ESpellDictionary *dictionary,
g_object_unref (spell_checker);
}
-
diff --git a/src/e-util/evolution-source-viewer.c b/src/e-util/evolution-source-viewer.c
index 069d6258a9..385146edb2 100644
--- a/src/e-util/evolution-source-viewer.c
+++ b/src/e-util/evolution-source-viewer.c
@@ -1177,7 +1177,7 @@ main (gint argc,
gtk_main ();
- e_util_cleanup_settings ();
+ e_misc_util_free_global_memory ();
return 0;
}
diff --git a/src/e-util/test-accounts-window.c b/src/e-util/test-accounts-window.c
index 80051e21b1..ca26579da6 100644
--- a/src/e-util/test-accounts-window.c
+++ b/src/e-util/test-accounts-window.c
@@ -70,7 +70,7 @@ main (gint argc,
g_object_unref (registry);
g_list_free_full (modules, (GDestroyNotify) g_type_module_unuse);
- e_util_cleanup_settings ();
+ e_misc_util_free_global_memory ();
return 0;
}
diff --git a/src/e-util/test-calendar.c b/src/e-util/test-calendar.c
index d3683a0a25..031d39f174 100644
--- a/src/e-util/test-calendar.c
+++ b/src/e-util/test-calendar.c
@@ -96,7 +96,7 @@ main (gint argc,
gtk_main ();
- e_util_cleanup_settings ();
+ e_misc_util_free_global_memory ();
return 0;
}
diff --git a/src/e-util/test-category-completion.c b/src/e-util/test-category-completion.c
index e8b35d96d3..3b68e4ba59 100644
--- a/src/e-util/test-category-completion.c
+++ b/src/e-util/test-category-completion.c
@@ -62,7 +62,7 @@ main (gint argc,
gtk_main ();
- e_util_cleanup_settings ();
+ e_misc_util_free_global_memory ();
return 0;
}
diff --git a/src/e-util/test-contact-store.c b/src/e-util/test-contact-store.c
index cf391022a1..6f862efd8b 100644
--- a/src/e-util/test-contact-store.c
+++ b/src/e-util/test-contact-store.c
@@ -142,7 +142,7 @@ main (gint argc,
gtk_main ();
- e_util_cleanup_settings ();
+ e_misc_util_free_global_memory ();
return 0;
}
diff --git a/src/e-util/test-dateedit.c b/src/e-util/test-dateedit.c
index def69dbde9..9ffb9067e8 100644
--- a/src/e-util/test-dateedit.c
+++ b/src/e-util/test-dateedit.c
@@ -184,7 +184,7 @@ main (gint argc,
gtk_main ();
- e_util_cleanup_settings ();
+ e_misc_util_free_global_memory ();
return 0;
}
diff --git a/src/e-util/test-html-editor-units.c b/src/e-util/test-html-editor-units.c
index 63e5600d0f..9d3035f9bd 100644
--- a/src/e-util/test-html-editor-units.c
+++ b/src/e-util/test-html-editor-units.c
@@ -2906,8 +2906,7 @@ main (gint argc,
res = g_test_run ();
- e_util_cleanup_settings ();
- e_spell_checker_free_global_memory ();
+ e_misc_util_free_global_memory ();
test_utils_free_global_memory ();
g_unlink (test_keyfile_filename);
diff --git a/src/e-util/test-html-editor.c b/src/e-util/test-html-editor.c
index c567c2808d..1e40fa0120 100644
--- a/src/e-util/test-html-editor.c
+++ b/src/e-util/test-html-editor.c
@@ -580,8 +580,7 @@ main (gint argc,
gtk_main ();
- e_util_cleanup_settings ();
- e_spell_checker_free_global_memory ();
+ e_misc_util_free_global_memory ();
return 0;
}
diff --git a/src/e-util/test-mail-signatures.c b/src/e-util/test-mail-signatures.c
index 97702fb4e2..bfbea91ceb 100644
--- a/src/e-util/test-mail-signatures.c
+++ b/src/e-util/test-mail-signatures.c
@@ -190,7 +190,7 @@ main (gint argc,
gtk_main ();
- e_util_cleanup_settings ();
+ e_misc_util_free_global_memory ();
return 0;
}
diff --git a/src/e-util/test-name-selector.c b/src/e-util/test-name-selector.c
index feafaf79d2..0696e28be4 100644
--- a/src/e-util/test-name-selector.c
+++ b/src/e-util/test-name-selector.c
@@ -106,7 +106,7 @@ main (gint argc,
g_object_unref (registry);
g_object_unref (client_cache);
- e_util_cleanup_settings ();
+ e_misc_util_free_global_memory ();
return 0;
}
diff --git a/src/e-util/test-preferences-window.c b/src/e-util/test-preferences-window.c
index 33bbd50e42..9b4c13c1b0 100644
--- a/src/e-util/test-preferences-window.c
+++ b/src/e-util/test-preferences-window.c
@@ -103,7 +103,7 @@ main (gint argc,
gtk_main ();
- e_util_cleanup_settings ();
+ e_misc_util_free_global_memory ();
return 0;
}
diff --git a/src/e-util/test-proxy-preferences.c b/src/e-util/test-proxy-preferences.c
index a072cc17a8..02c05bfd91 100644
--- a/src/e-util/test-proxy-preferences.c
+++ b/src/e-util/test-proxy-preferences.c
@@ -80,7 +80,7 @@ main (gint argc,
gtk_main ();
- e_util_cleanup_settings ();
+ e_misc_util_free_global_memory ();
return 0;
}
diff --git a/src/e-util/test-source-combo-box.c b/src/e-util/test-source-combo-box.c
index 334ba8667a..294c9d21f8 100644
--- a/src/e-util/test-source-combo-box.c
+++ b/src/e-util/test-source-combo-box.c
@@ -102,7 +102,7 @@ main (gint argc,
gtk_main ();
- e_util_cleanup_settings ();
+ e_misc_util_free_global_memory ();
return 0;
}
diff --git a/src/e-util/test-source-config.c b/src/e-util/test-source-config.c
index 9d41813caf..22e2003fa1 100644
--- a/src/e-util/test-source-config.c
+++ b/src/e-util/test-source-config.c
@@ -54,7 +54,7 @@ main (gint argc,
gtk_main ();
- e_util_cleanup_settings ();
+ e_misc_util_free_global_memory ();
return 0;
}
diff --git a/src/e-util/test-source-selector.c b/src/e-util/test-source-selector.c
index 49ed0d3862..2d5df38c0b 100644
--- a/src/e-util/test-source-selector.c
+++ b/src/e-util/test-source-selector.c
@@ -887,7 +887,7 @@ main (gint argc,
gtk_main ();
g_object_unref (registry);
- e_util_cleanup_settings ();
+ e_misc_util_free_global_memory ();
return 0;
}
diff --git a/src/e-util/test-tree-view-frame.c b/src/e-util/test-tree-view-frame.c
index b9464bca97..b5bfa3ee61 100644
--- a/src/e-util/test-tree-view-frame.c
+++ b/src/e-util/test-tree-view-frame.c
@@ -371,7 +371,7 @@ main (gint argc,
gtk_main ();
- e_util_cleanup_settings ();
+ e_misc_util_free_global_memory ();
return 0;
}
diff --git a/src/mail/CMakeLists.txt b/src/mail/CMakeLists.txt
index c89e451225..32cb8a7923 100644
--- a/src/mail/CMakeLists.txt
+++ b/src/mail/CMakeLists.txt
@@ -219,6 +219,7 @@ target_compile_definitions(evolution-mail PRIVATE
-DG_LOG_DOMAIN=\"evolution-mail\"
-DEVOLUTION_PRIVDATADIR=\"${privdatadir}\"
-DEVOLUTION_ETSPECDIR=\"${etspecdir}\"
+ -DEVOLUTION_LOCALEDIR=\"${LOCALE_INSTALL_DIR}\"
)
target_compile_options(evolution-mail PUBLIC
diff --git a/src/mail/e-mail-config-composing-page.c b/src/mail/e-mail-config-composing-page.c
index d00c45e0c3..394561fae6 100644
--- a/src/mail/e-mail-config-composing-page.c
+++ b/src/mail/e-mail-config-composing-page.c
@@ -21,6 +21,7 @@
#include "e-mail-config-page.h"
#include "e-mail-config-activity-page.h"
+#include "em-composer-utils.h"
#include "e-mail-config-composing-page.h"
@@ -148,6 +149,16 @@ mail_config_composing_fill_reply_style_combox (GtkComboBoxText *combo)
g_type_class_unref (enum_class);
}
+static void
+mail_config_composing_fill_language_combox (GtkComboBoxText *combo)
+{
+ g_return_if_fail (GTK_IS_COMBO_BOX_TEXT (combo));
+
+ gtk_combo_box_text_append (combo, NULL, _("Use global setting"));
+
+ em_utils_add_installed_languages (combo);
+}
+
static gboolean
mail_config_composing_page_reply_style_to_string (GBinding *binding,
const GValue *source_value,
@@ -399,7 +410,7 @@ mail_config_composing_page_constructed (GObject *object)
widget = gtk_label_new (markup);
gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
- gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 1, 1);
+ gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 2, 1);
gtk_widget_show (widget);
g_free (markup);
@@ -407,7 +418,7 @@ mail_config_composing_page_constructed (GObject *object)
widget = gtk_label_new_with_mnemonic (text);
gtk_widget_set_margin_left (widget, 12);
gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
- gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1);
+ gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 2, 1);
gtk_widget_show (widget);
label = GTK_LABEL (widget);
@@ -416,7 +427,7 @@ mail_config_composing_page_constructed (GObject *object)
gtk_widget_set_hexpand (widget, TRUE);
gtk_widget_set_margin_left (widget, 12);
gtk_label_set_mnemonic_widget (label, widget);
- gtk_grid_attach (GTK_GRID (container), widget, 0, 2, 1, 1);
+ gtk_grid_attach (GTK_GRID (container), widget, 0, 2, 2, 1);
gtk_widget_show (widget);
e_binding_bind_property_full (
@@ -432,7 +443,7 @@ mail_config_composing_page_constructed (GObject *object)
widget = gtk_label_new_with_mnemonic (text);
gtk_widget_set_margin_left (widget, 12);
gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
- gtk_grid_attach (GTK_GRID (container), widget, 0, 3, 1, 1);
+ gtk_grid_attach (GTK_GRID (container), widget, 0, 3, 2, 1);
gtk_widget_show (widget);
label = GTK_LABEL (widget);
@@ -441,7 +452,7 @@ mail_config_composing_page_constructed (GObject *object)
gtk_widget_set_hexpand (widget, TRUE);
gtk_widget_set_margin_left (widget, 12);
gtk_label_set_mnemonic_widget (label, widget);
- gtk_grid_attach (GTK_GRID (container), widget, 0, 4, 1, 1);
+ gtk_grid_attach (GTK_GRID (container), widget, 0, 4, 2, 1);
gtk_widget_show (widget);
e_binding_bind_property_full (
@@ -453,25 +464,21 @@ mail_config_composing_page_constructed (GObject *object)
mail_config_composing_page_string_to_addrs,
NULL, (GDestroyNotify) NULL);
- widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
- gtk_grid_attach (GTK_GRID (container), widget, 0, 5, 1, 1);
- gtk_widget_show (widget);
-
- container = widget;
-
text = _("Re_ply style:");
widget = gtk_label_new_with_mnemonic (text);
+ gtk_widget_set_hexpand (widget, FALSE);
gtk_widget_set_margin_left (widget, 12);
gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
- gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ gtk_grid_attach (GTK_GRID (container), widget, 0, 5, 1, 1);
gtk_widget_show (widget);
label = GTK_LABEL (widget);
widget = gtk_combo_box_text_new ();
- gtk_widget_set_hexpand (widget, FALSE);
+ gtk_widget_set_halign (widget, GTK_ALIGN_START);
+ gtk_widget_set_hexpand (widget, TRUE);
gtk_label_set_mnemonic_widget (label, widget);
- gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ gtk_grid_attach (GTK_GRID (container), widget, 1, 5, 1, 1);
gtk_widget_show (widget);
mail_config_composing_fill_reply_style_combox (GTK_COMBO_BOX_TEXT (widget));
@@ -485,6 +492,35 @@ mail_config_composing_page_constructed (GObject *object)
mail_config_composing_page_string_to_reply_style,
NULL, (GDestroyNotify) NULL);
+ widget = gtk_label_new_with_mnemonic (_("Lang_uage:"));
+ gtk_widget_set_hexpand (widget, FALSE);
+ gtk_widget_set_margin_left (widget, 12);
+ gtk_widget_set_tooltip_text (widget, _("Language for Reply and Forward attribution text"));
+ gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+ gtk_grid_attach (GTK_GRID (container), widget, 0, 6, 1, 1);
+ gtk_widget_show (widget);
+
+ label = GTK_LABEL (widget);
+
+ widget = gtk_combo_box_text_new ();
+ gtk_widget_set_halign (widget, GTK_ALIGN_START);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_widget_set_tooltip_text (widget, _("Language for Reply and Forward attribution text"));
+ gtk_label_set_mnemonic_widget (label, widget);
+ gtk_grid_attach (GTK_GRID (container), widget, 1, 6, 1, 1);
+ gtk_widget_show (widget);
+
+ mail_config_composing_fill_language_combox (GTK_COMBO_BOX_TEXT (widget));
+
+ e_binding_bind_property (
+ composition_ext, "language",
+ widget, "active-id",
+ G_BINDING_BIDIRECTIONAL |
+ G_BINDING_SYNC_CREATE);
+
+ if (gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) == -1)
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
+
widget = gtk_check_button_new_with_mnemonic (_("Start _typing at the bottom"));
gtk_widget_set_margin_left (widget, 12);
gtk_box_pack_start (GTK_BOX (main_box), widget, FALSE, FALSE, 0);
diff --git a/src/mail/em-composer-utils.c b/src/mail/em-composer-utils.c
index 340dddabc4..5dadc5f5ad 100644
--- a/src/mail/em-composer-utils.c
+++ b/src/mail/em-composer-utils.c
@@ -23,6 +23,7 @@
#include "evolution-config.h"
+#include <locale.h>
#include <string.h>
#include <gtk/gtk.h>
#include <glib/gi18n.h>
@@ -2007,6 +2008,129 @@ traverse_parts (GSList *clues,
}
}
+static void
+emcu_change_locale (const gchar *lc_messages,
+ const gchar *lc_time,
+ gchar **out_lc_messages,
+ gchar **out_lc_time)
+{
+ gboolean success;
+ gchar *previous;
+
+ if (lc_messages) {
+ #if defined(LC_MESSAGES)
+ previous = g_strdup (setlocale (LC_MESSAGES, NULL));
+ success = setlocale (LC_MESSAGES, lc_messages) != NULL;
+ #else
+ previous = g_strdup (setlocale (LC_ALL, NULL));
+ success = setlocale (LC_ALL, lc_messages) != NULL;
+ #endif
+
+ if (out_lc_messages)
+ *out_lc_messages = success ? g_strdup (previous) : NULL;
+
+ g_free (previous);
+ }
+
+ if (lc_time) {
+ #if defined(LC_TIME)
+ previous = g_strdup (setlocale (LC_TIME, NULL));
+ success = setlocale (LC_ALL, lc_time) != NULL;
+ #elif defined(LC_MESSAGES)
+ previous = g_strdup (setlocale (LC_ALL, NULL));
+ success = setlocale (LC_ALL, lc_time) != NULL;
+ #else
+ previous = NULL;
+ success = FALSE;
+ #endif
+
+ if (out_lc_time)
+ *out_lc_time = success ? g_strdup (previous) : NULL;
+
+ g_free (previous);
+ }
+}
+
+static void
+emcu_prepare_attribution_locale (EMsgComposer *composer,
+ gchar **out_lc_messages,
+ gchar **out_lc_time)
+{
+ EComposerHeaderTable *table;
+ ESource *source = NULL;
+ gchar *uid, *lang = NULL;
+
+ g_return_if_fail (out_lc_messages != NULL);
+ g_return_if_fail (out_lc_time != NULL);
+
+ if (!composer)
+ return;
+
+ table = e_msg_composer_get_header_table (composer);
+ uid = e_composer_header_table_dup_identity_uid (table, NULL, NULL);
+ if (uid)
+ source = e_composer_header_table_ref_source (table, uid);
+ g_free (uid);
+
+ if (source && e_source_has_extension (source, E_SOURCE_EXTENSION_MAIL_COMPOSITION)) {
+ ESourceMailComposition *extension;
+
+ extension = e_source_get_extension (source, E_SOURCE_EXTENSION_MAIL_COMPOSITION);
+ lang = e_source_mail_composition_dup_language (extension);
+ }
+
+ g_clear_object (&source);
+
+ if (!lang || !*lang) {
+ GSettings *settings;
+
+ g_free (lang);
+
+ settings = e_util_ref_settings ("org.gnome.evolution.mail");
+ lang = g_settings_get_string (settings, "composer-attribution-language");
+ g_object_unref (settings);
+
+ if (!lang || !*lang)
+ g_clear_pointer (&lang, g_free);
+ }
+
+ if (!lang) {
+ /* Set the locale always, even when using the user interface
+ language, because gettext() can return wrong text (in the previously
+ used language) */
+ #if defined(LC_MESSAGES)
+ lang = g_strdup (setlocale (LC_MESSAGES, NULL));
+ #else
+ lang = g_strdup (setlocale (LC_ALL, NULL));
+ #endif
+ }
+
+ if (lang) {
+ if (!strchr (lang, '.')) {
+ gchar *tmp;
+
+ tmp = g_strconcat (lang, ".utf8", NULL);
+ g_free (lang);
+ lang = tmp;
+ }
+
+ emcu_change_locale (lang, lang, out_lc_messages, out_lc_time);
+
+ g_free (lang);
+ }
+}
+
+/* Takes ownership (frees) the 'restore_locale' */
+static void
+emcu_restore_locale_after_attribution (gchar *restore_lc_messages,
+ gchar *restore_lc_time)
+{
+ emcu_change_locale (restore_lc_messages, restore_lc_time, NULL, NULL);
+
+ g_free (restore_lc_messages);
+ g_free (restore_lc_time);
+}
+
/* Editing messages... */
typedef enum {
@@ -2041,9 +2165,11 @@ static struct {
};
static gchar *
-quoting_text (QuotingTextEnum type)
+quoting_text (QuotingTextEnum type,
+ EMsgComposer *composer)
{
GSettings *settings;
+ gchar *restore_lc_messages = NULL, *restore_lc_time = NULL;
gchar *text;
settings = e_util_ref_settings ("org.gnome.evolution.mail");
@@ -2055,11 +2181,19 @@ quoting_text (QuotingTextEnum type)
g_free (text);
- return g_strdup (_(conf_messages[type].message));
+ if (composer)
+ emcu_prepare_attribution_locale (composer, &restore_lc_messages, &restore_lc_time);
+
+ text = g_strdup (_(conf_messages[type].message));
+
+ emcu_restore_locale_after_attribution (restore_lc_messages, restore_lc_time);
+
+ return text;
}
/**
* em_composer_utils_get_forward_marker:
+ * @composer: an #EMsgComposer from which to get the identity information
*
* Returns: (transfer full): a text marker which is used for inline forwarded messages.
* Free returned pointer with g_free(), when no longer needed.
@@ -2067,13 +2201,14 @@ quoting_text (QuotingTextEnum type)
* Since: 3.24
**/
gchar *
-em_composer_utils_get_forward_marker (void)
+em_composer_utils_get_forward_marker (EMsgComposer *composer)
{
- return quoting_text (QUOTING_FORWARD);
+ return quoting_text (QUOTING_FORWARD, composer);
}
/**
* em_composer_utils_get_original_marker:
+ * @composer: an #EMsgComposer from which to get the identity information
*
* Returns: (transfer full): a text marker which is used for inline message replies.
* Free returned pointer with g_free(), when no longer needed.
@@ -2081,9 +2216,9 @@ em_composer_utils_get_forward_marker (void)
* Since: 3.24
**/
gchar *
-em_composer_utils_get_original_marker (void)
+em_composer_utils_get_original_marker (EMsgComposer *composer)
{
- return quoting_text (QUOTING_ORIGINAL);
+ return quoting_text (QUOTING_ORIGINAL, composer);
}
static gboolean
@@ -2461,7 +2596,7 @@ forward_non_attached (EMsgComposer *composer,
EMailForwardStyle style)
{
CamelSession *session;
- gchar *text, *forward;
+ gchar *text, *forward, *subject;
guint32 validity_found = 0;
guint32 flags;
@@ -2474,16 +2609,17 @@ forward_non_attached (EMsgComposer *composer,
if (style == E_MAIL_FORWARD_STYLE_QUOTED)
flags |= E_MAIL_FORMATTER_QUOTE_FLAG_CITE;
- forward = quoting_text (QUOTING_FORWARD);
+ /* Setup composer's From account before calling quoting_text(),
+ because quoting_text() relies on that account. */
+ subject = mail_tool_generate_forward_subject (message);
+ set_up_new_composer (composer, subject, folder, message, uid);
+ g_free (subject);
+
+ forward = quoting_text (QUOTING_FORWARD, composer);
text = em_utils_message_to_html (session, message, forward, flags, NULL, NULL, NULL, &validity_found);
if (text != NULL) {
CamelDataWrapper *content;
- gchar *subject;
-
- subject = mail_tool_generate_forward_subject (message);
- set_up_new_composer (composer, subject, folder, message, uid);
- g_free (subject);
content = camel_medium_get_content (CAMEL_MEDIUM (message));
@@ -3413,7 +3549,8 @@ static struct {
};
static gchar *
-attribution_format (CamelMimeMessage *message)
+attribution_format (EMsgComposer *composer,
+ CamelMimeMessage *message)
{
register const gchar *inptr;
const gchar *start;
@@ -3423,8 +3560,11 @@ attribution_format (CamelMimeMessage *message)
struct tm tm;
time_t date;
gint type;
- gchar *format = quoting_text (QUOTING_ATTRIBUTION);
+ gchar *format, *restore_lc_messages = NULL, *restore_lc_time = NULL;
+
+ emcu_prepare_attribution_locale (composer, &restore_lc_messages, &restore_lc_time);
+ format = quoting_text (QUOTING_ATTRIBUTION, NULL);
str = g_string_new ("");
date = camel_mime_message_get_date (message, &tzone);
@@ -3559,6 +3699,8 @@ attribution_format (CamelMimeMessage *message)
}
}
+ emcu_restore_locale_after_attribution (restore_lc_messages, restore_lc_time);
+
s = str->str;
g_string_free (str, FALSE);
g_free (format);
@@ -3596,7 +3738,7 @@ composer_set_body (EMsgComposer *composer,
g_object_unref (part);
break;
case E_MAIL_REPLY_STYLE_OUTLOOK:
- original = quoting_text (QUOTING_ORIGINAL);
+ original = quoting_text (QUOTING_ORIGINAL, composer);
text = em_utils_message_to_html (
session, message, original, E_MAIL_FORMATTER_QUOTE_FLAG_HEADERS | keep_sig_flag,
parts_list, NULL, NULL, &validity_found);
@@ -3609,7 +3751,7 @@ composer_set_body (EMsgComposer *composer,
case E_MAIL_REPLY_STYLE_QUOTED:
default:
/* do what any sane user would want when replying... */
- credits = attribution_format (message);
+ credits = attribution_format (composer, message);
text = em_utils_message_to_html (
session, message, credits, E_MAIL_FORMATTER_QUOTE_FLAG_CITE | keep_sig_flag,
parts_list, NULL, NULL, &validity_found);
@@ -3623,24 +3765,6 @@ composer_set_body (EMsgComposer *composer,
g_object_unref (session);
}
-gchar *
-em_utils_construct_composer_text (CamelSession *session,
- CamelMimeMessage *message,
- EMailPartList *parts_list)
-{
- gchar *text, *credits;
-
- g_return_val_if_fail (CAMEL_IS_SESSION (session), NULL);
-
- credits = attribution_format (message);
- text = em_utils_message_to_html (
- session, message, credits, E_MAIL_FORMATTER_QUOTE_FLAG_CITE,
- parts_list, NULL, NULL, NULL);
- g_free (credits);
-
- return text;
-}
-
static gboolean
emcu_folder_is_inbox (CamelFolder *folder)
{
@@ -4816,3 +4940,126 @@ em_utils_apply_send_account_override_to_composer (EMsgComposer *composer,
g_free (alias_name);
g_free (alias_address);
}
+
+static GHashTable * /* gchar *lcmessages ~> gchar *localeID */
+em_enum_system_locales (void)
+{
+ GHashTable *locales;
+
+#ifdef G_OS_WIN32
+ /* Do not know how to test it right now (2018), the build
+ on Windows is blocked by WebKitGTK+ anyway. */
+ #warning See gtk/gtkmain.c and its usage of EnumSystemLocales()
+#else
+ GDir *dir;
+ const gchar *dirname;
+
+ locales = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ dir = g_dir_open ("/usr/lib/locale", 0, NULL);
+ if (dir) {
+ while (dirname = g_dir_read_name (dir), dirname) {
+ gchar *fullname, *ident = NULL, *ptr;
+
+ if (g_str_equal (dirname, ".") || g_str_equal (dirname, "..") || !strchr (dirname,
'_'))
+ continue;
+
+ fullname = g_strdup (dirname);
+ ptr = strrchr (fullname, '.');
+ if (ptr)
+ *ptr = '\0';
+
+ if (!g_hash_table_contains (locales, fullname)) {
+ gchar *at;
+
+ g_hash_table_insert (locales, g_strdup (fullname), g_strdup (fullname));
+
+ ident = g_strdup (fullname);
+ at = strchr (ident, '@');
+ if (at) {
+ *at = 0;
+ g_hash_table_insert (locales, g_strdup (ident), g_strdup (fullname));
+ }
+
+ ptr = strchr (ident, '_');
+ if (ptr) {
+ *ptr = '\0';
+
+ g_hash_table_insert (locales, g_strdup (ident), g_strdup (fullname));
+
+ if (at)
+ g_hash_table_insert (locales, g_strconcat (ident, "@", at +
1, NULL), g_strdup (fullname));
+ }
+ }
+
+ g_free (fullname);
+ g_free (ident);
+ }
+ }
+
+ g_dir_close (dir);
+#endif
+
+ return locales;
+}
+
+void
+em_utils_add_installed_languages (GtkComboBoxText *combo)
+{
+ GDir *dir;
+ GSList *langs = NULL, *link;
+ const gchar *dirname;
+ gint n_langs = 0;
+ GHashTable *system_locales;
+
+ g_return_if_fail (GTK_IS_COMBO_BOX_TEXT (combo));
+
+ dir = g_dir_open (EVOLUTION_LOCALEDIR, 0, NULL);
+ if (!dir)
+ return;
+
+ system_locales = em_enum_system_locales ();
+
+ while (dirname = g_dir_read_name (dir), dirname) {
+ gchar *filename;
+
+ if (g_str_equal (dirname, ".") || g_str_equal (dirname, ".."))
+ continue;
+
+ filename = g_build_filename (EVOLUTION_LOCALEDIR, dirname, "LC_MESSAGES", GETTEXT_PACKAGE
".mo", NULL);
+ if (filename && g_file_test (filename, G_FILE_TEST_EXISTS)) {
+ gchar *locale_name;
+
+ locale_name = g_hash_table_lookup (system_locales, dirname);
+ if (locale_name)
+ langs = g_slist_prepend (langs, g_strdup (locale_name));
+ }
+
+ g_free (filename);
+ }
+
+ g_hash_table_destroy (system_locales);
+ g_dir_close (dir);
+
+ langs = g_slist_sort (langs, (GCompareFunc) g_strcmp0);
+
+ for (link = langs; link; link = g_slist_next (link)) {
+ const gchar *lang = link->data;
+
+ if (lang) {
+ gchar *lang_name;
+
+ lang_name = e_util_get_language_name (lang);
+
+ gtk_combo_box_text_append (combo, lang, lang_name && *lang_name ? lang_name : lang);
+ n_langs++;
+
+ g_free (lang_name);
+ }
+ }
+
+ g_slist_free_full (langs, g_free);
+
+ if (n_langs > 10)
+ gtk_combo_box_set_wrap_width (GTK_COMBO_BOX (combo), 5);
+}
diff --git a/src/mail/em-composer-utils.h b/src/mail/em-composer-utils.h
index 73e0760901..4f7e7f4b43 100644
--- a/src/mail/em-composer-utils.h
+++ b/src/mail/em-composer-utils.h
@@ -65,10 +65,6 @@ void em_utils_forward_attachment (EMsgComposer *composer,
GPtrArray *uids);
void em_utils_redirect_message (EMsgComposer *composer,
CamelMimeMessage *message);
-gchar * em_utils_construct_composer_text
- (CamelSession *session,
- CamelMimeMessage *message,
- EMailPartList *source_formatter);
gboolean em_utils_is_munged_list_message (CamelMimeMessage *message);
void em_utils_get_reply_sender (CamelMimeMessage *message,
CamelInternetAddress *to,
@@ -114,9 +110,10 @@ void em_utils_apply_send_account_override_to_composer
(EMsgComposer *composer,
CamelFolder *folder);
gchar * em_composer_utils_get_forward_marker
- (void);
+ (EMsgComposer *composer);
gchar * em_composer_utils_get_original_marker
- (void);
+ (EMsgComposer *composer);
+void em_utils_add_installed_languages(GtkComboBoxText *combo);
G_END_DECLS
diff --git a/src/mail/mail-config.ui b/src/mail/mail-config.ui
index 2f6a8293f4..bc81ff6e6a 100644
--- a/src/mail/mail-config.ui
+++ b/src/mail/mail-config.ui
@@ -517,6 +517,23 @@
<property name="y_options"/>
</packing>
</child>
+ <child>
+ <object class="GtkLabel" id="lblForwardReplyAttribLanguage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Language:</property>
+ <property name="tooltip-text" translatable="yes">Language for Reply and Forward
attribution text</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">comboboxForwardReplyAttribLanguage</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
<child>
<object class="GtkCheckButton" id="chkReplyStartBottom">
<property name="label" translatable="yes">Start _typing at the bottom</property>
@@ -529,8 +546,8 @@
</object>
<packing>
<property name="right_attach">2</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
<property name="y_options"/>
</packing>
</child>
@@ -546,8 +563,8 @@
</object>
<packing>
<property name="right_attach">2</property>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
<property name="y_options"/>
</packing>
</child>
@@ -563,8 +580,8 @@
</object>
<packing>
<property name="right_attach">2</property>
- <property name="top_attach">4</property>
- <property name="bottom_attach">5</property>
+ <property name="top_attach">5</property>
+ <property name="bottom_attach">6</property>
<property name="y_options"/>
</packing>
</child>
@@ -580,8 +597,8 @@
</object>
<packing>
<property name="right_attach">2</property>
- <property name="top_attach">5</property>
- <property name="bottom_attach">6</property>
+ <property name="top_attach">6</property>
+ <property name="bottom_attach">7</property>
<property name="y_options"/>
</packing>
</child>
@@ -597,8 +614,8 @@
</object>
<packing>
<property name="right_attach">2</property>
- <property name="top_attach">6</property>
- <property name="bottom_attach">7</property>
+ <property name="top_attach">7</property>
+ <property name="bottom_attach">8</property>
<property name="y_options"/>
</packing>
</child>
@@ -614,8 +631,8 @@
</object>
<packing>
<property name="right_attach">2</property>
- <property name="top_attach">7</property>
- <property name="bottom_attach">8</property>
+ <property name="top_attach">8</property>
+ <property name="bottom_attach">9</property>
<property name="y_options"/>
</packing>
</child>
@@ -631,8 +648,8 @@
</object>
<packing>
<property name="right_attach">2</property>
- <property name="top_attach">8</property>
- <property name="bottom_attach">9</property>
+ <property name="top_attach">9</property>
+ <property name="bottom_attach">10</property>
<property name="y_options"/>
</packing>
</child>
@@ -685,6 +702,27 @@
<property name="bottom_attach">2</property>
</packing>
</child>
+ <child>
+ <object class="GtkAlignment" id="forward-reply-attrib-language-alignment">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="xscale">0</property>
+ <child>
+ <object class="GtkComboBoxText" id="comboboxForwardReplyAttribLanguage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip-text" translatable="yes">Language for Reply and Forward
attribution text</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ </packing>
+ </child>
</object>
</child>
</object>
diff --git a/src/modules/backup-restore/evolution-backup-tool.c
b/src/modules/backup-restore/evolution-backup-tool.c
index 0d30a7afc0..735b18459b 100644
--- a/src/modules/backup-restore/evolution-backup-tool.c
+++ b/src/modules/backup-restore/evolution-backup-tool.c
@@ -1072,7 +1072,7 @@ main (gint argc,
gtk_main ();
g_object_unref (cancellable);
- e_util_cleanup_settings ();
+ e_misc_util_free_global_memory ();
return result;
}
diff --git a/src/modules/mail/em-composer-prefs.c b/src/modules/mail/em-composer-prefs.c
index 31d5484401..b411599595 100644
--- a/src/modules/mail/em-composer-prefs.c
+++ b/src/modules/mail/em-composer-prefs.c
@@ -41,6 +41,7 @@
#include <mail/em-folder-selector.h>
#include <mail/em-folder-tree.h>
#include <mail/em-folder-tree-model.h>
+#include <mail/em-composer-utils.h>
#include <mail/e-mail-backend.h>
#include <mail/e-mail-junk-options.h>
#include <mail/e-mail-ui-session.h>
@@ -1335,6 +1336,18 @@ em_composer_prefs_construct (EMComposerPrefs *prefs,
widget, "active-id",
G_SETTINGS_BIND_DEFAULT);
+ widget = e_builder_get_widget (prefs->builder, "comboboxForwardReplyAttribLanguage");
+ gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (widget), NULL, _("Same as user interface"));
+ em_utils_add_installed_languages (GTK_COMBO_BOX_TEXT (widget));
+
+ g_settings_bind (
+ settings, "composer-attribution-language",
+ widget, "active-id",
+ G_SETTINGS_BIND_DEFAULT);
+
+ if (gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) == -1)
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
+
/* Signatures */
container = e_builder_get_widget (
prefs->builder, "signature-alignment");
diff --git a/src/plugins/attachment-reminder/attachment-reminder.c
b/src/plugins/attachment-reminder/attachment-reminder.c
index fe3df782d4..129ee06d51 100644
--- a/src/plugins/attachment-reminder/attachment-reminder.c
+++ b/src/plugins/attachment-reminder/attachment-reminder.c
@@ -73,7 +73,7 @@ GtkWidget * org_gnome_attachment_reminder_config_option
EConfigHookItemFactoryData *data);
static gboolean ask_for_missing_attachment (EPlugin *ep, GtkWindow *widget);
-static gboolean check_for_attachment_clues (GByteArray *msg_text, guint32 ar_flags);
+static gboolean check_for_attachment_clues (EMsgComposer *composer, GByteArray *msg_text, guint32 ar_flags);
static gboolean check_for_attachment (EMsgComposer *composer);
static guint32 get_flags_from_composer (EMsgComposer *composer);
static void commit_changes (UIData *ui);
@@ -101,7 +101,7 @@ org_gnome_evolution_attachment_reminder (EPlugin *ep,
return;
/* Set presend_check_status for the composer*/
- if (check_for_attachment_clues (raw_msg_barray, get_flags_from_composer (t->composer))) {
+ if (check_for_attachment_clues (t->composer, raw_msg_barray, get_flags_from_composer (t->composer))) {
if (!ask_for_missing_attachment (ep, (GtkWindow *) t->composer))
g_object_set_data (
G_OBJECT (t->composer),
@@ -239,7 +239,8 @@ censor_quoted_lines (GByteArray *msg_text,
/* check for the clues */
static gboolean
-check_for_attachment_clues (GByteArray *msg_text,
+check_for_attachment_clues (EMsgComposer *composer,
+ GByteArray *msg_text,
guint32 ar_flags)
{
GSettings *settings;
@@ -248,9 +249,9 @@ check_for_attachment_clues (GByteArray *msg_text,
gboolean found = FALSE;
if (ar_flags == AR_IS_FORWARD)
- marker = em_composer_utils_get_forward_marker ();
+ marker = em_composer_utils_get_forward_marker (composer);
else if (ar_flags == AR_IS_REPLY)
- marker = em_composer_utils_get_original_marker ();
+ marker = em_composer_utils_get_original_marker (composer);
settings = e_util_ref_settings ("org.gnome.evolution.plugin.attachment-reminder");
diff --git a/src/shell/main.c b/src/shell/main.c
index d667fc47dd..abc140d55f 100644
--- a/src/shell/main.c
+++ b/src/shell/main.c
@@ -696,9 +696,7 @@ exit:
gtk_accel_map_save (e_get_accels_filename ());
- e_util_cleanup_settings ();
- e_spell_checker_free_global_memory ();
- e_simple_async_result_free_global_memory ();
+ e_misc_util_free_global_memory ();
return 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]