Index: trunk/src/org/openstreetmap/josm/data/validation/tests/TagChecker.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/validation/tests/TagChecker.java	(revision 8752)
+++ trunk/src/org/openstreetmap/josm/data/validation/tests/TagChecker.java	(revision 8753)
@@ -71,6 +71,6 @@
     public static final String SPELL_FILE = "resource://data/validator/words.cfg";
 
-    /** The spell check key substitutions: the key should be substituted by the value */
-    private static volatile Map<String, String> spellCheckKeyData;
+    /** Normalized keys: the key should be substituted by the value if the key was not found in presets */
+    private static final Map<String, String> harmonizedKeys = new HashMap<>();
     /** The spell check preset values */
     private static volatile MultiMap<String, String> presetsValueData;
@@ -126,4 +126,5 @@
     protected static final int LOW_CHAR_KEY      = 1211;
     protected static final int MISSPELLED_VALUE  = 1212;
+    protected static final int MISSPELLED_KEY    = 1213;
     /** 1250 and up is used by tagcheck */
 
@@ -161,6 +162,5 @@
         ignoreDataEndsWith.clear();
         ignoreDataKeyPair.clear();
-
-        spellCheckKeyData = new HashMap<>();
+        harmonizedKeys.clear();
 
         String errorSources = "";
@@ -229,5 +229,5 @@
                         okValue = line.substring(1);
                     } else if (line.charAt(0) == '-' && okValue != null) {
-                        spellCheckKeyData.put(line.substring(1), okValue);
+                        harmonizedKeys.put(harmonizeKey(line.substring(1)), okValue);
                     } else {
                         Main.error(tr("Invalid spellcheck line: {0}", line));
@@ -291,4 +291,5 @@
             try {
                 presetsValueData.putAll(ky.key, values);
+                harmonizedKeys.put(harmonizeKey(ky.key), ky.key);
             } catch (NullPointerException e) {
                 Main.error(p+": Unable to initialize "+ky);
@@ -360,9 +361,4 @@
                 withErrors.put(p, "EV");
             }
-            if (checkKeys && spellCheckKeyData.containsKey(key) && !withErrors.contains(p, "IPK")) {
-                errors.add(new TestError(this, Severity.WARNING, tr("Invalid property key"),
-                        tr(s, key), MessageFormat.format(s, key), INVALID_KEY, p));
-                withErrors.put(p, "IPK");
-            }
             if (checkKeys && key != null && key.indexOf(' ') >= 0 && !withErrors.contains(p, "IPK")) {
                 errors.add(new TestError(this, Severity.WARNING, tr("Invalid white space in property key"),
@@ -412,11 +408,23 @@
                 if (!ignore) {
                     if (!keyInPresets) {
-                        String i = marktr("Key ''{0}'' not in presets.");
-                        errors.add(new TestError(this, Severity.OTHER, tr("Presets do not contain property key"),
-                                tr(i, key), MessageFormat.format(i, key), INVALID_VALUE, p));
-                        withErrors.put(p, "UPK");
+                        String prettifiedKey = harmonizeKey(key);
+                        String fixedKey = harmonizedKeys.get(prettifiedKey);
+                        if (fixedKey != null && !"".equals(fixedKey)) {
+                            // misspelled preset key
+                            String i = marktr("Key ''{0}'' looks like ''{1}''.");
+                            errors.add(new FixableTestError(this, Severity.WARNING, tr("Misspelled property key"),
+                                    tr(i, key, fixedKey),
+                                    MessageFormat.format(i, key, fixedKey), MISSPELLED_KEY, p,
+                                    new ChangePropertyKeyCommand(p, key, fixedKey)));
+                            withErrors.put(p, "WPK");
+                        } else {
+                            String i = marktr("Key ''{0}'' not in presets.");
+                            errors.add(new TestError(this, Severity.OTHER, tr("Presets do not contain property key"),
+                                    tr(i, key), MessageFormat.format(i, key), INVALID_VALUE, p));
+                            withErrors.put(p, "UPK");
+                        }
                     } else if (!tagInPresets) {
                         // try to fix common typos and check again if value is still unknown
-                        String fixedValue = prettifyValue(prop.getValue());
+                        String fixedValue = harmonizeValue(prop.getValue());
                         Map<String, String> possibleValues = getPossibleValues(values);
                         if (possibleValues.containsKey(fixedValue)) {
@@ -465,8 +473,11 @@
     }
 
-    private static String prettifyValue(String value) {
-        // convert to lower case, replace ' ' or '-' with '_'
+    private static String harmonizeKey(String key) {
+        key = key.toLowerCase(Locale.ENGLISH).replace('-', '_').replace(':', '_').replace(' ', '_');
+        return Utils.strip(key, "-_;:,");
+    }
+
+    private static String harmonizeValue(String value) {
         value = value.toLowerCase(Locale.ENGLISH).replace('-', '_').replace(' ', '_');
-        // remove trailing or leading special chars
         return Utils.strip(value, "-_;:,");
     }
@@ -612,9 +623,4 @@
                         if (!evalue.equals(value)) {
                             commands.add(new ChangePropertyCommand(p, key, evalue));
-                        } else {
-                            String replacementKey = spellCheckKeyData.get(key);
-                            if (replacementKey != null) {
-                                commands.add(new ChangePropertyKeyCommand(p, key, replacementKey));
-                            }
                         }
                     }
Index: trunk/test/unit/org/openstreetmap/josm/data/validation/tests/TagCheckerTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/data/validation/tests/TagCheckerTest.java	(revision 8753)
+++ trunk/test/unit/org/openstreetmap/josm/data/validation/tests/TagCheckerTest.java	(revision 8753)
@@ -0,0 +1,68 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.data.validation.tests;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.openstreetmap.josm.JOSMFixture;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.OsmUtils;
+import org.openstreetmap.josm.data.validation.TestError;
+import org.openstreetmap.josm.gui.tagging.TaggingPresets;
+
+public class TagCheckerTest {
+    /**
+     * Setup test.
+     */
+    @BeforeClass
+    public static void setUp() {
+        JOSMFixture.createUnitTestFixture().init();
+        TaggingPresets.readFromPreferences();
+    }
+
+    List<TestError> test(OsmPrimitive primitive) throws IOException {
+        final TagChecker checker = new TagChecker();
+        checker.initialize();
+        checker.startTest(null);
+        checker.check(primitive);
+        return checker.getErrors();
+    }
+
+    @Test
+    public void testInvalidKey() throws Exception {
+        final List<TestError> errors = test(OsmUtils.createPrimitive("node Name=Main"));
+        assertThat(errors.size(), is(1));
+        assertThat(errors.get(0).getMessage(), is("Misspelled property key"));
+        assertThat(errors.get(0).getDescription(), is("Key 'Name' looks like 'name'."));
+    }
+
+    @Test
+    public void testMisspelledKey() throws Exception {
+        final List<TestError> errors = test(OsmUtils.createPrimitive("node landuse;=forest"));
+        assertThat(errors.size(), is(1));
+        assertThat(errors.get(0).getMessage(), is("Misspelled property key"));
+        assertThat(errors.get(0).getDescription(), is("Key 'landuse;' looks like 'landuse'."));
+    }
+
+    @Test
+    public void testTranslatedNameKey() throws Exception {
+        final List<TestError> errors = test(OsmUtils.createPrimitive("node namez=Baz"));
+        assertThat(errors.size(), is(1));
+        assertThat(errors.get(0).getMessage(), is("Presets do not contain property key"));
+        assertThat(errors.get(0).getDescription(), is("Key 'namez' not in presets."));
+    }
+
+    @Test
+    public void testMisspelledTag() throws Exception {
+        final List<TestError> errors = test(OsmUtils.createPrimitive("node landuse=forrest"));
+        assertThat(errors.size(), is(1));
+        assertThat(errors.get(0).getMessage(), is("Presets do not contain property value"));
+        assertThat(errors.get(0).getDescription(), is("Value 'forrest' for key 'landuse' not in presets."));
+    }
+
+}
