diff --git a/desktop/org.yorba.geary.gschema.xml b/desktop/org.yorba.geary.gschema.xml
index 2c435b3..10d17b3 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="s">
+         <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/client/application/geary-config.vala b/src/client/application/geary-config.vala
index dec799e..f250f7b 100644
--- a/src/client/application/geary-config.vala
+++ b/src/client/application/geary-config.vala
@@ -23,11 +23,14 @@ 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; }
     
     public Settings gnome_interface;
     private Settings? indicator_datetime;
+
+    private string? _spell_check_languages = null;
     
     public int window_width {
         get { return settings.get_int(WINDOW_WIDTH_KEY); }
@@ -79,6 +82,16 @@ public class Configuration {
         get { return settings.get_boolean(SPELL_CHECK_KEY); }
     }
 
+    private weak string _get_spell_check_languages() {
+        _spell_check_languages = settings.get_string(SPELL_CHECK_LANGUAGES);
+        return _spell_check_languages;
+    }
+
+    public string spell_check_languages {
+        get { return _get_spell_check_languages(); }
+        set { settings.set_string(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..0906991 100644
--- a/src/client/composer/composer-widget.vala
+++ b/src/client/composer/composer-widget.vala
@@ -269,6 +269,8 @@ public class ComposerWidget : Gtk.EventBox {
     private uint draft_save_timeout_id = 0;
     private bool is_closing = false;
     
+    private GLib.GenericSet<string> spell_check_languages = null;
+    
     public WebKit.WebView editor;
     // We need to keep a reference to the edit-fixer in composer-window, so it doesn't get
     // garbage-collected.
@@ -579,12 +581,18 @@ public class ComposerWidget : Gtk.EventBox {
         
         WebKit.WebSettings s = editor.settings;
         s.enable_spell_checking = GearyApplication.instance.config.spell_check;
+        s.spell_checking_languages = GearyApplication.instance.config.spell_check_languages;
         s.auto_load_images = false;
         s.enable_scripts = false;
         s.enable_java_applet = false;
         s.enable_plugins = false;
         editor.settings = s;
         
+        spell_check_languages = new GLib.GenericSet<string>(str_hash, str_equal);
+        foreach (string lang in s.spell_checking_languages.split(",")) {
+			spell_check_languages.add(lang.strip());
+		}
+        
         scroll.add(editor);
         scroll.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC);
         
@@ -2159,12 +2167,55 @@ 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 get_user_preferred_languages()) {
+			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(spell_check_languages.contains(lang));
+			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 (spell_check_languages.contains(lang)) {
+			spell_check_languages.remove(lang);
+		}
+		else {
+			spell_check_languages.add(lang);
+		}
+		
+		string[] langs = {};
+		spell_check_languages.foreach ((l) => langs += l);		
+		s.spell_checking_languages = string.joinv(",", langs);
+		GearyApplication.instance.config.spell_check_languages = s.spell_checking_languages;
+	}
+
+    private string[] get_user_preferred_languages() {
+		string[] output = {};
+		foreach (string lang in GLib.Intl.get_language_names()) {
+			if (lang != "C")
+				output += lang;
+		}
+		return output;
+	}
     
     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..31b105b 100644
--- a/src/client/util/util-international.vala
+++ b/src/client/util/util-international.vala
@@ -8,6 +8,8 @@ extern const string LANGUAGE_SUPPORT_DIRECTORY;
 public const string TRANSLATABLE = "translatable";
 
 namespace International {
+	
+private GLib.HashTable<string, string> official_names = null;
 
 public const string SYSTEM_LOCALE = "";
 
@@ -23,5 +25,71 @@ private string get_langpack_dir_path(string program_path) {
     return LANGUAGE_SUPPORT_DIRECTORY;
 }
 
+public string[] get_available_locales() {
+	string[] locales = {};
+	
+	GLib.File dictionary_directory = File.new_for_path("/usr/share/hunspell");
+	
+	try {
+		GLib.FileEnumerator e = dictionary_directory.enumerate_children(
+			FileAttribute.STANDARD_NAME, 0);			
+		for (GLib.FileInfo info = e.next_file(); info != null; info = e.next_file()) {
+			string name = info.get_name();
+			if (name.len() > 4 && !("-" in name) && name.substring(-4) == ".dic") {
+				locales += name.substring(0, name.len() - 4);
+			}
+		}		
+	} catch (GLib.Error e) {
+		return locales;
+	}
+	return locales;
+}
+
+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("/usr/share/xml/iso-codes/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)
+								official_names.insert(iso_639_1, language_name);
+						}
+					}
+				}
+			}
+		}
+	}
+	
+	// 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));
+}
+
 }
 
