--- django/db/models/options.py	2013-09-09 17:20:13.000000000 -0700
+++ django/db/models/options.py	2013-09-09 17:26:05.000000000 -0700
@@ -4,6 +4,7 @@
 import re
 from bisect import bisect
 import warnings
+import logging
 
 from django.conf import settings
 from django.db.models.fields.related import ManyToManyRel
@@ -15,6 +16,8 @@
 from django.utils.encoding import force_text, smart_text, python_2_unicode_compatible
 from django.utils.translation import activate, deactivate_all, get_language, string_concat
 
+logger = logging.getLogger('django.models')
+
 # Calculate the verbose_name by converting from InitialCaps to "lowercase with spaces".
 get_verbose_name = lambda class_name: re.sub('(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))', ' \\1', class_name).lower().strip()
 
@@ -121,9 +124,16 @@
             if self.verbose_name_plural is None:
                 self.verbose_name_plural = string_concat(self.verbose_name, 's')
 
-            # Any leftover attributes must be invalid.
+            # Any leftover attributes are unknown to Django, and might be typos.
             if meta_attrs != {}:
-                raise TypeError("'class Meta' got invalid attribute(s): %s" % ','.join(meta_attrs.keys()))
+                # Use difflib to check for close string matches, and warn the
+                # user if any are found with a greater than 80% confidence.
+                from difflib import get_close_matches
+                for unknown_attr in six.iterkeys(meta_attrs):
+                    matches = get_close_matches(unknown_attr, DEFAULT_NAMES, 1, 0.8)
+                    if matches:
+                        logger.warning("Unknown Meta option '%s' found, did you mean '%s'?"
+                                % (unknown_attr, matches[0]))
         else:
             self.verbose_name_plural = string_concat(self.verbose_name, 's')
         del self.meta
