diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0a59aee..14bcb94 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -22,6 +22,9 @@ set(RELEASE_NAME "Lightweight email client for GNOME.")
 set(VERSION "0.11.0")
 set(VERSION_INFO "Release")
 set(LANGUAGE_SUPPORT_DIRECTORY ${CMAKE_INSTALL_PREFIX}/share/locale)
+# set(ISOCODES_DIRECTORY ${CMAKE_INSTALL_PREFIX}/share/xml/iso-codes)
+
+find_path(ISOCODES_DIRECTORY NAMES iso_639.xml PATHS ${CMAKE_INSTALL_PREFIX} /usr/share/xml/iso-codes)
 
 # Packaging filenamesnames.
 set(ARCHIVE_BASE_NAME ${CMAKE_PROJECT_NAME}-${VERSION})
@@ -67,6 +70,8 @@ pkg_check_modules(WEBKITGTK110X QUIET webkitgtk-3.0>=1.10.0 webkitgtk-3.0<=1.10.
 
 pkg_check_modules(GTK312X QUIET gtk+-3.0>=3.12.0)
 
+pkg_check_modules(ENCHANT QUIET enchant)
+
 pkg_check_modules(SQLITE311 QUIET sqlite3>=3.11.0)
 pkg_check_modules(SQLITE312 QUIET sqlite3>=3.12.0)
 if (SQLITE311_FOUND AND NOT SQLITE312_FOUND)
@@ -84,6 +89,7 @@ endif ()
 # GResources
 include(GlibCompileResourcesSupport)
 
+
 #
 # Uninstall target
 #
diff --git a/bindings/vapi/enchant.vapi b/bindings/vapi/enchant.vapi
new file mode 100644
index 0000000..c4a030f
--- /dev/null
+++ b/bindings/vapi/enchant.vapi
@@ -0,0 +1,34 @@
+[CCode (cheader_filename = "enchant.h")]
+namespace Enchant {
+	public delegate void BrokerDescribeFn (string provider_name, string provider_desc, string provider_dll_file);
+	public delegate void DictDescribeFn (string lang_tag, string provider_name, string provider_desc, string provider_file);
+
+	[Compact]
+	[CCode (free_function = "enchant_broker_free")]
+	public class Broker {
+		[CCode (cname = "enchant_broker_init")]
+		public Broker ();
+
+		public unowned Dict request_dict (string tag);
+		public unowned Dict request_pwl_dict (string pwl);
+		public void free_dict (Dict dict);
+		public int dict_exists (string tag);
+		public void set_ordering (string tag, string ordering);
+		public void describe (BrokerDescribeFn fn);
+		public void list_dicts (DictDescribeFn fn);
+		public unowned string get_error ();
+	}
+
+	[Compact]
+	public class Dict {
+		public int check (string word, long len = -1);
+		public unowned string[] suggest (string word, long len = -1);
+		public void free_string_list ([CCode (array_length = false)] string[] string_list);
+		public void add_to_session (string word, long len = -1);
+		public int is_in_session (string word, long len = -1);
+		public void store_replacement ( string mis, long mis_len, string cor, long cor_len);
+		public void add_to_pwl ( string word, long len = -1);
+		public void describe (DictDescribeFn fn);
+		public unowned string get_error ();
+	}
+}
diff --git a/desktop/org.yorba.geary.gschema.xml b/desktop/org.yorba.geary.gschema.xml
index 2c435b3..b59949b 100644
--- a/desktop/org.yorba.geary.gschema.xml
+++ b/desktop/org.yorba.geary.gschema.xml
@@ -73,6 +73,11 @@
         <summary>enable inline spell checking</summary>
         <description>True to spell check while typing.</description>
     </key>
+    <key name="spell-check-languages" type="as">
+         <default>[]</default>
+         <summary>Languages that shall be used in the spell checker</summary>
+         <description>A comma separated list of the languages to use in the spell checker</description>
+    </key>
     <key name="play-sounds" type="b">
         <default>true</default>
         <summary>enable notification sounds</summary>
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 124cd18..83c2b73 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -554,6 +554,7 @@ pkg_check_modules(DEPS REQUIRED
     libxml-2.0>=2.7.8
     gcr-3>=3.10.1
     gobject-introspection-1.0
+    enchant>=1.6
     ${EXTRA_CLIENT_PKG_CONFIG}
 )
 
@@ -564,7 +565,7 @@ set(ENGINE_PACKAGES
 # webkitgtk-3.0 is listed as a custom VAPI (below) to ensure it's treated as a dependency and
 # built before compilation
 set(CLIENT_PACKAGES
-    gtk+-3.0 libsecret-1 libsoup-2.4 libnotify libcanberra gcr-3 ${EXTRA_CLIENT_PACKAGES}
+    gtk+-3.0 libsecret-1 libsoup-2.4 libnotify libcanberra gcr-3 enchant ${EXTRA_CLIENT_PACKAGES}
 )
 
 set(CONSOLE_PACKAGES
@@ -582,6 +583,7 @@ set(CFLAGS
     -D_GSETTINGS_DIR=\"${CMAKE_BINARY_DIR}/gsettings\"
     -DGETTEXT_PACKAGE=\"${GETTEXT_PACKAGE}\"
     -DLANGUAGE_SUPPORT_DIRECTORY=\"${LANGUAGE_SUPPORT_DIRECTORY}\"
+    -DISOCODES_DIRECTORY=\"${ISOCODES_DIRECTORY}\"
     -DGCR_API_SUBJECT_TO_CHANGE
     -g
 )
diff --git a/src/client/application/geary-config.vala b/src/client/application/geary-config.vala
index dec799e..c4d952a 100644
--- a/src/client/application/geary-config.vala
+++ b/src/client/application/geary-config.vala
@@ -23,6 +23,7 @@ public class Configuration {
     public const string STARTUP_NOTIFICATIONS_KEY = "startup-notifications";
     public const string ASK_OPEN_ATTACHMENT_KEY = "ask-open-attachment";
     public const string COMPOSE_AS_HTML_KEY = "compose-as-html";
+    public const string SPELL_CHECK_LANGUAGES = "spell-check-languages";
     
     public Settings settings { get; private set; }
     
@@ -79,6 +80,18 @@ public class Configuration {
         get { return settings.get_boolean(SPELL_CHECK_KEY); }
     }
 
+    public string[] spell_check_languages {
+        owned get { 
+			string[] langs = settings.get_strv(SPELL_CHECK_LANGUAGES);
+			if (langs.length == 0) {
+				langs = International.get_user_preferred_languages();
+				settings.set_strv(SPELL_CHECK_LANGUAGES, langs);
+			} 
+			return langs;
+		}
+        set { settings.set_strv(SPELL_CHECK_LANGUAGES, value); }
+    }
+
     public bool play_sounds {
         get { return settings.get_boolean(PLAY_SOUNDS_KEY); }
     }
diff --git a/src/client/composer/composer-widget.vala b/src/client/composer/composer-widget.vala
index db571c1..94709db 100644
--- a/src/client/composer/composer-widget.vala
+++ b/src/client/composer/composer-widget.vala
@@ -579,6 +579,8 @@ public class ComposerWidget : Gtk.EventBox {
         
         WebKit.WebSettings s = editor.settings;
         s.enable_spell_checking = GearyApplication.instance.config.spell_check;
+        s.spell_checking_languages = string.joinv(",", 
+			GearyApplication.instance.config.spell_check_languages);
         s.auto_load_images = false;
         s.enable_scripts = false;
         s.enable_java_applet = false;
@@ -2159,12 +2161,52 @@ public class ComposerWidget : Gtk.EventBox {
         select_all_item.activate.connect(on_select_all);
         context_menu.append(select_all_item);
         
+        // Language chooser
+        Gtk.MenuItem language_chooser_item = new Gtk.MenuItem.with_mnemonic(_("Language"));
+        Gtk.Menu language_submenu = new Gtk.Menu();
+        language_chooser_item.set_submenu(language_submenu);
+               
+        foreach (string lang in  International.get_available_dictionaries()) {
+			string? lang_name = International.official_name_from_locale(lang);			
+			Gtk.CheckMenuItem lang_item = new Gtk.CheckMenuItem.with_label(
+				lang_name != null ? lang_name + " (" + lang + ")" : lang);
+			language_submenu.append(lang_item);			
+			lang_item.set_active(lang in GearyApplication.instance.config.spell_check_languages);
+			lang_item.toggled.connect (() => {
+				toggle_spell_checking_languages(lang);
+			});
+		}
+
+        context_menu.append(language_chooser_item);
+
         context_menu.show_all();
         
         update_actions();
         
         return false;
     }
+
+    private void toggle_spell_checking_languages(string lang) {
+		WebKit.WebSettings s = editor.settings;
+		
+		if (lang in GearyApplication.instance.config.spell_check_languages) {
+			string[] new_languages = {};
+			foreach (string l in GearyApplication.instance.config.spell_check_languages) {
+				if (l != lang) {
+					new_languages += l;
+				}
+			}
+			GearyApplication.instance.config.spell_check_languages = new_languages;
+		}
+		else {
+			string[] current_langs = GearyApplication.instance.config.spell_check_languages;
+			current_langs += lang;
+			GearyApplication.instance.config.spell_check_languages = current_langs;
+		}
+		
+		s.spell_checking_languages = string.joinv(",", 
+			GearyApplication.instance.config.spell_check_languages);
+	}
     
     private bool on_editor_key_press(Gdk.EventKey event) {
         // widget's keypress override doesn't receive non-modifier keys when the editor processes
diff --git a/src/client/util/util-international.vala b/src/client/util/util-international.vala
index d0d9005..46823d3 100644
--- a/src/client/util/util-international.vala
+++ b/src/client/util/util-international.vala
@@ -5,9 +5,12 @@
  */
 
 extern const string LANGUAGE_SUPPORT_DIRECTORY;
+extern const string ISOCODES_DIRECTORY;
 public const string TRANSLATABLE = "translatable";
 
 namespace International {
+	
+private GLib.HashTable<string, string> official_names = null;
 
 public const string SYSTEM_LOCALE = "";
 
@@ -23,5 +26,79 @@ private string get_langpack_dir_path(string program_path) {
     return LANGUAGE_SUPPORT_DIRECTORY;
 }
 
+public string[] get_available_dictionaries() {
+	string[] dictionaries = {};
+	
+	Enchant.Broker broker = new Enchant.Broker();
+	broker.list_dicts((lang_tag, provider_name, provider_desc, provider_file) => {
+		dictionaries += lang_tag;
+	});
+	
+	return dictionaries; 
+}
+
+public string[] get_user_preferred_languages() {
+	string[] output = {};
+	foreach (unowned string lang in GLib.Intl.get_language_names()) {
+		if (lang != "C")
+			output += lang;
+	}
+	return output;
+}
+
+public string? official_name_from_locale (string locale) {
+	if (official_names == null) {
+		official_names = new HashTable<string, string>(GLib.str_hash, GLib.str_equal);	
+			
+		unowned Xml.Doc doc = Xml.Parser.parse_file(
+			GLib.Path.build_filename(ISOCODES_DIRECTORY, "iso_639.xml"));
+		if (doc == null) {
+			return null;
+		}
+		else {
+			unowned Xml.Node root = doc.get_root_element();
+			for (unowned Xml.Node entry = root.children; entry != null; entry = entry.next) {
+				if (entry.type == Xml.ElementType.ELEMENT_NODE) {
+					string? iso_639_1 = null;
+					string? language_name = null;
+					
+					for (unowned Xml.Attr a = entry.properties; a != null; a = a.next) {				
+						switch (a.name) {
+							case "iso_639_1_code":
+								iso_639_1 = a.children->content;
+								break;
+							case "name":
+								language_name = a.children->content;
+								break;
+							default:
+								break;
+						}
+						
+						if (language_name != null) {
+							if (iso_639_1 != null) {
+								// Try to get a translation for the name, if available
+								string current_locale = GLib.Intl.setlocale(
+									GLib.LocaleCategory.MESSAGES, null);
+								GLib.Intl.setlocale(GLib.LocaleCategory.MESSAGES, iso_639_1);
+								official_names.insert(iso_639_1, 
+									GLib.dgettext("iso_639", language_name));
+								GLib.Intl.setlocale(GLib.LocaleCategory.MESSAGES, current_locale);
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	
+	// Look for the name of language matching only the part before the _
+	int pos = -1;
+	if ("_" in locale) {
+		pos = locale.index_of_char('_');
+	}
+	
+	return official_names.get(locale.substring(0, pos));
+}
+
 }
 
