Index: /trunk/src/org/openstreetmap/josm/data/validation/tests/OpeningHourTest.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/validation/tests/OpeningHourTest.java	(revision 17642)
+++ /trunk/src/org/openstreetmap/josm/data/validation/tests/OpeningHourTest.java	(revision 17643)
@@ -125,4 +125,14 @@
     @Override
     public void check(final OsmPrimitive p) {
+        addErrorsForPrimitive(p, this.errors);
+    }
+
+    /**
+     * Checks the tags of the given primitive and adds validation errors to the given list.
+     * @param p The primitive to test
+     * @param errors The list to add validation errors to
+     * @since 17643
+     */
+    public void addErrorsForPrimitive(OsmPrimitive p, Collection<TestError> errors) {
         if (p.isTagged()) {
             for (String key : KEYS_TO_CHECK) {
Index: /trunk/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPreset.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPreset.java	(revision 17642)
+++ /trunk/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPreset.java	(revision 17643)
@@ -317,4 +317,8 @@
             pp.add(label);
         }
+        JLabel validationLabel = new JLabel(ImageProvider.get("warning-small", ImageProvider.ImageSizes.LARGEICON));
+        validationLabel.setVisible(false);
+        pp.add(validationLabel);
+
         final int count = pp.getComponentCount();
         if (preset_name_label) {
@@ -353,4 +357,9 @@
         if (selected.isEmpty() && !supportsRelation()) {
             GuiHelper.setEnabledRec(items, false);
+        }
+
+        if (selected.size() == 1 && Config.getPref().getBoolean("taggingpreset.validator", false)) {
+            itemGuiSupport.addListener((source, key, newValue) ->
+                    TaggingPresetValidation.validateAsync(selected.iterator().next(), validationLabel, getChangedTags()));
         }
 
Index: /trunk/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetValidation.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetValidation.java	(revision 17643)
+++ /trunk/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetValidation.java	(revision 17643)
@@ -0,0 +1,96 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.tagging.presets;
+
+import org.openstreetmap.josm.command.Command;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Relation;
+import org.openstreetmap.josm.data.osm.Tag;
+import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.data.preferences.sources.ValidatorPrefHelper;
+import org.openstreetmap.josm.data.validation.OsmValidator;
+import org.openstreetmap.josm.data.validation.TestError;
+import org.openstreetmap.josm.data.validation.tests.MapCSSTagChecker;
+import org.openstreetmap.josm.data.validation.tests.OpeningHourTest;
+import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.gui.util.GuiHelper;
+import org.openstreetmap.josm.tools.Logging;
+import org.openstreetmap.josm.tools.Utils;
+
+import javax.swing.JLabel;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+/**
+ * Validates the preset user input a the given primitive.
+ */
+interface TaggingPresetValidation {
+
+    /**
+     * Asynchronously validates the user input for the given primitive.
+     * @param original the primitive
+     * @param validationLabel the label for validation errors
+     * @param changedTags the list of tags that are set by this preset
+     */
+    static void validateAsync(OsmPrimitive original, JLabel validationLabel, List<Tag> changedTags) {
+        OsmPrimitive primitive = applyChangedTags(original, changedTags);
+        MainApplication.worker.execute(() -> validate(primitive, validationLabel));
+    }
+
+    /**
+     * Validates the user input for the given primitive.
+     * @param primitive the primitive
+     * @param validationLabel the label for validation errors
+     */
+    static void validate(OsmPrimitive primitive, JLabel validationLabel) {
+        try {
+            MapCSSTagChecker mapCSSTagChecker = OsmValidator.getTest(MapCSSTagChecker.class);
+            OpeningHourTest openingHourTest = OsmValidator.getTest(OpeningHourTest.class);
+            OsmValidator.initializeTests(Arrays.asList(mapCSSTagChecker, openingHourTest));
+
+            List<TestError> errors = new ArrayList<>();
+            openingHourTest.addErrorsForPrimitive(primitive, errors);
+            errors.addAll(mapCSSTagChecker.getErrorsForPrimitive(primitive, ValidatorPrefHelper.PREF_OTHER.get()));
+
+            boolean visible = !errors.isEmpty();
+            String toolTipText = "<html>" + Utils.joinAsHtmlUnorderedList(Utils.transform(errors, e ->
+                    e.getDescription() == null ? e.getMessage() : tr("{0} ({1})", e.getMessage(), e.getDescription())));
+            GuiHelper.runInEDTAndWait(() -> {
+                validationLabel.setVisible(visible);
+                validationLabel.setToolTipText(toolTipText);
+            });
+        } catch (Exception e) {
+            Logging.warn("Failed to validate {0}", primitive);
+            Logging.warn(e);
+        } finally {
+            primitive.getDataSet().clear();
+        }
+    }
+
+    static OsmPrimitive applyChangedTags(OsmPrimitive original, List<Tag> changedTags) {
+        OsmPrimitive primitive = clone(original);
+        new DataSet(primitive);
+        Command command = TaggingPreset.createCommand(Collections.singleton(primitive), changedTags);
+        if (command != null) {
+            command.executeCommand();
+        }
+        return primitive;
+    }
+
+    static OsmPrimitive clone(OsmPrimitive original) {
+        if (original instanceof Node) {
+            return new Node(((Node) original));
+        } else if (original instanceof Way) {
+            return new Way(((Way) original), false, false);
+        } else if (original instanceof Relation) {
+            return new Relation(((Relation) original), false, false);
+        } else {
+            throw new IllegalStateException();
+        }
+    }
+}
Index: /trunk/test/unit/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetValidationTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetValidationTest.java	(revision 17643)
+++ /trunk/test/unit/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetValidationTest.java	(revision 17643)
@@ -0,0 +1,55 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.tagging.presets;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.OsmUtils;
+import org.openstreetmap.josm.data.validation.OsmValidator;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+
+import javax.swing.JLabel;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Unit tests for {@code TaggingPresetValidation}
+ */
+class TaggingPresetValidationTest {
+
+    /**
+     * Setup test.
+     */
+    @RegisterExtension
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules rule = new JOSMTestRules().projection();
+
+    @BeforeEach
+    void setUp() {
+        OsmValidator.initialize();
+    }
+
+    /**
+     * Tests {@link TaggingPresetValidation#validate}
+     */
+    @Test
+    void validate() {
+        JLabel label = new JLabel();
+        OsmPrimitive primitive = OsmUtils.createPrimitive("way incline=10m width=1mm opening_hours=\"Mo-Fr 8-10\"");
+        new DataSet(primitive);
+
+        TaggingPresetValidation.validate(primitive, label);
+
+        assertTrue(label.isVisible());
+        assertEquals("<html><ul>" +
+                "<li>Opening hours syntax (Hours without minutes)</li>" +
+                "<li>unusual value of width: meters is default; point is decimal separator; if units, put space then unit</li>" +
+                "<li>unusual value of incline, use x% or x° or up or down instead</li>" +
+                "<li>suspicious tag combination (width on suspicious object)</li>" +
+                "<li>suspicious tag combination (incline on suspicious object)</li></ul>", label.getToolTipText());
+    }
+}
