Index: applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/ErrorTreePanel.java
===================================================================
--- applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/ErrorTreePanel.java	(revision 9585)
+++ applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/ErrorTreePanel.java	(revision 9598)
@@ -4,8 +4,12 @@
 import java.util.Map.Entry;
 
+import java.awt.event.MouseEvent;
+
 import javax.swing.JTree;
+import javax.swing.ToolTipManager;
 import javax.swing.tree.*;
 
 import org.openstreetmap.josm.plugins.validator.util.Bag;
+import org.openstreetmap.josm.plugins.validator.util.MultipleNameVisitor;
 
 /**
@@ -16,23 +20,25 @@
  * @author frsantos
  */
+
 public class ErrorTreePanel extends JTree
 {
-    /** Serializable ID */
-    private static final long serialVersionUID = 2952292777351992696L;
-
-    /**
-     * The validation data.
-     */
+	/** Serializable ID */
+	private static final long serialVersionUID = 2952292777351992696L;
+
+	/**
+	 * The validation data.
+	 */
 	protected DefaultTreeModel treeModel = new DefaultTreeModel(new DefaultMutableTreeNode());
 
-    /** The list of errors shown in the tree */
-    private List<TestError> errors;
-    /**
-     * Constructor
-     * @param errors The list of errors
-     */
-    public ErrorTreePanel(List<TestError> errors) 
-    {
-        this.setModel(treeModel);
+	/** The list of errors shown in the tree */
+	private List<TestError> errors;
+	/**
+	 * Constructor
+	 * @param errors The list of errors
+	 */
+	public ErrorTreePanel(List<TestError> errors)
+	{
+		ToolTipManager.sharedInstance().registerComponent(this);
+		this.setModel(treeModel);
 		this.setRootVisible(false);
 		this.setShowsRootHandles(true);
@@ -41,18 +47,41 @@
 		this.setCellRenderer(new ErrorTreeRenderer());
 		this.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
-        setErrorList(errors);
-    }
-
-    /**
-     * Constructor
-     */
-    public ErrorTreePanel() 
-    {
-        this(null);
-    }
-    
-    @Override 
-    public void setVisible(boolean v) 
-    {
+		setErrorList(errors);
+		}
+
+	public String getToolTipText(MouseEvent e) {
+		String res = null;
+		TreePath path = getPathForLocation(e.getX(), e.getY());
+		if (path != null)
+		{
+			DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
+			Object nodeInfo = node.getUserObject();
+
+			if (nodeInfo instanceof TestError)
+			{
+				TestError error = (TestError)nodeInfo;
+				MultipleNameVisitor v = new MultipleNameVisitor();
+				v.visit(error.getPrimitives());
+				res = "<html>" + v.getText() + "<br>" + error.getMessage();
+				String d = error.getDescription();
+				if(d != null)
+					res += "<br>" + d;
+				res += "</html>";
+			}
+			else
+				res = node.toString();
+		}
+		return res;
+	}
+
+	/** Constructor */
+	public ErrorTreePanel()
+	{
+		this(null);
+	}
+
+	@Override
+	public void setVisible(boolean v)
+	{
 		if (v)
 			buildTree();
@@ -61,10 +90,9 @@
 		super.setVisible(v);
 	}
-    
-    
+
 	/**
 	 * Builds the errors tree
 	 */
-	public void buildTree() 
+	public void buildTree()
 	{
 		DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode();
@@ -76,25 +104,25 @@
 		}
 
-        // Remember the currently expanded rows
-        Set<Object> oldSelectedRows = new HashSet<Object>();
-        Enumeration<TreePath> expanded = getExpandedDescendants( new TreePath(getRoot()) );
-        if( expanded != null )
-        {
-            while( expanded.hasMoreElements() )
-            {
-                TreePath path = expanded.nextElement();
-                DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent(); 
-                Object userObject = node.getUserObject();
-                if( userObject instanceof Severity )
-                    oldSelectedRows.add(userObject);
-                else if (userObject instanceof String)
-                {
-                    String msg = (String)userObject;
-                    msg = msg.substring(0, msg.lastIndexOf(" ("));
-                    oldSelectedRows.add(msg);
-                }
-            }
-        }
-        
+		// Remember the currently expanded rows
+		Set<Object> oldSelectedRows = new HashSet<Object>();
+		Enumeration<TreePath> expanded = getExpandedDescendants( new TreePath(getRoot()) );
+		if( expanded != null )
+		{
+			while( expanded.hasMoreElements() )
+			{
+				TreePath path = expanded.nextElement();
+				DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent(); 
+				Object userObject = node.getUserObject();
+				if( userObject instanceof Severity )
+					oldSelectedRows.add(userObject);
+				else if (userObject instanceof String)
+				{
+					String msg = (String)userObject;
+					msg = msg.substring(0, msg.lastIndexOf(" ("));
+					oldSelectedRows.add(msg);
+				}
+			}
+		}
+
 		Map<Severity, Bag<String, TestError>> errorTree = new HashMap<Severity, Bag<String, TestError>>();
 		for(Severity s : Severity.values())
@@ -102,24 +130,24 @@
 			errorTree.put(s, new Bag<String, TestError>(20));
 		}
-		
+
 		for(TestError e : errors)
 		{
 			errorTree.get(e.getSeverity()).add(e.getMessage(), e);
 		}
-		
-        List<TreePath> expandedPaths = new ArrayList<TreePath>();
+
+		List<TreePath> expandedPaths = new ArrayList<TreePath>();
 		for(Severity s : Severity.values())
 		{
-			Bag<String,	TestError> severityErrors = errorTree.get(s);
+			Bag<String, TestError> severityErrors = errorTree.get(s);
 			if( severityErrors.isEmpty() )
 				continue;
-			
+
 			// Severity node
 			DefaultMutableTreeNode severityNode = new DefaultMutableTreeNode(s);
 			rootNode.add(severityNode);
-            
+
 			if( oldSelectedRows.contains(s))
-                expandedPaths.add( new TreePath( new Object[] {rootNode, severityNode} ) );
-            
+				expandedPaths.add( new TreePath( new Object[] {rootNode, severityNode} ) );
+
 			for(Entry<String, List<TestError>> msgErrors : severityErrors.entrySet()  )
 			{
@@ -130,7 +158,7 @@
 				severityNode.add(messageNode);
 
-                if( oldSelectedRows.contains(msgErrors.getKey()))
-                    expandedPaths.add( new TreePath( new Object[] {rootNode, severityNode, messageNode} ) );
-                
+				if( oldSelectedRows.contains(msgErrors.getKey()))
+					 expandedPaths.add( new TreePath( new Object[] {rootNode, severityNode, messageNode} ) );
+
 				for (TestError error : errors) 
 				{
@@ -142,21 +170,21 @@
 		}
 
-        treeModel.setRoot(rootNode);
-        for( TreePath path : expandedPaths)
-        {
-            this.expandPath(path);
-        }
-	}
-
-    /**
-     * Sets the errors list used by a data layer
-     * @param errors The error list that is used by a data layer
-     */
-    public void setErrorList(List<TestError> errors)
-    {
-    	this.errors = errors;
-        if( isVisible() )
-        	buildTree();
-    }
+		treeModel.setRoot(rootNode);
+		for( TreePath path : expandedPaths)
+		{
+			this.expandPath(path);
+		}
+	}
+
+	/**
+	 * Sets the errors list used by a data layer
+	 * @param errors The error list that is used by a data layer
+	 */
+	public void setErrorList(List<TestError> errors)
+	{
+		this.errors = errors;
+		if( isVisible() )
+			buildTree();
+	}
 
 	/**
@@ -195,28 +223,28 @@
 	}
 
-    /**
-     * Expands all tree
-     */
-    @SuppressWarnings("unchecked")
-    public void expandAll()
-    {
-        DefaultMutableTreeNode root = getRoot();
-        
-        int row = 0;
-        Enumeration<DefaultMutableTreeNode> children = root.breadthFirstEnumeration();
-        while( children.hasMoreElements() )
-        {
-            children.nextElement();
-            expandRow(row++);
-        }
-    }
-    
-    /**
-     * Returns the root node model. 
-     * @return The root node model
-     */
-    public DefaultMutableTreeNode getRoot()
-    {
-        return (DefaultMutableTreeNode) treeModel.getRoot();
-    }
+	/**
+	 * Expands all tree
+	 */
+	@SuppressWarnings("unchecked")
+	public void expandAll()
+	{
+		DefaultMutableTreeNode root = getRoot();
+
+		int row = 0;
+		Enumeration<DefaultMutableTreeNode> children = root.breadthFirstEnumeration();
+		while( children.hasMoreElements() )
+		{
+			children.nextElement();
+			expandRow(row++);
+		}
+	}
+
+	/**
+	 * Returns the root node model.
+	 * @return The root node model
+	 */
+	public DefaultMutableTreeNode getRoot()
+	{
+		return (DefaultMutableTreeNode) treeModel.getRoot();
+	}
 }
Index: applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/ErrorTreeRenderer.java
===================================================================
--- applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/ErrorTreeRenderer.java	(revision 9585)
+++ applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/ErrorTreeRenderer.java	(revision 9598)
@@ -14,10 +14,10 @@
  * @author frsantos
  */
-public class ErrorTreeRenderer extends DefaultTreeCellRenderer 
+public class ErrorTreeRenderer extends DefaultTreeCellRenderer
 {
-    /** Serializable ID */
-    private static final long serialVersionUID = 5567632718124640198L;
+	/** Serializable ID */
+	private static final long serialVersionUID = 5567632718124640198L;
 
-    @Override
+	@Override
 	public Component getTreeCellRendererComponent(JTree tree, Object value,
 			boolean selected, boolean expanded, boolean leaf, int row,
@@ -27,12 +27,12 @@
 		
 		DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
-		Object nodeInfo = node.getUserObject();		
-		
-		if (nodeInfo instanceof Severity) 
+		Object nodeInfo = node.getUserObject();
+
+		if (nodeInfo instanceof Severity)
 		{
 			Severity s = (Severity)nodeInfo;
 			setIcon(ImageProvider.get("data", s.getIcon()));
 		}
-		else if (nodeInfo instanceof TestError) 
+		else if (nodeInfo instanceof TestError)
 		{
 			TestError error = (TestError)nodeInfo;
Index: applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/TestError.java
===================================================================
--- applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/TestError.java	(revision 9585)
+++ applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/TestError.java	(revision 9598)
@@ -24,4 +24,6 @@
 	/** The error message */
 	private String message;
+	/** Deeper error description */
+	private String description;
 	/** The affected primitives */
 	private List<? extends OsmPrimitive> primitives;
@@ -35,60 +37,71 @@
 	private boolean selected;
 	
-	public TestError(Test tester, Severity severity, String message,
+	/**
+	 * Constructors
+	 * @param tester The tester
+	 * @param severity The severity of this error
+	 * @param message The error message
+	 * @param primitive The affected primitive
+	 * @param primitives The affected primitives
+	 * @param internalCode The internal code
+	 */
+	public TestError(Test tester, Severity severity, String message, String description,
 			List<? extends OsmPrimitive> primitives, List<?> highlighted) {
 		this.tester = tester;
 		this.severity = severity;
 		this.message = message;
+		this.description = description;
 		this.primitives = primitives;
 		this.highlighted = highlighted;
 	}
-
-	/**
-	 * Constructor
-	 * @param tester The tester
-	 * @param severity The severity of this error
-	 * @param message The error message
-	 * @param primitives The affected primitives
-	 */
+	public TestError(Test tester, Severity severity, String message, List<? extends OsmPrimitive> primitives, List<?> highlighted)
+	{
+		this(tester, severity, message, null, primitives, highlighted);
+	}
+	public TestError(Test tester, Severity severity, String message, String description, List<? extends OsmPrimitive> primitives)
+	{
+		this(tester, severity, message, description, primitives, primitives);
+	}
 	public TestError(Test tester, Severity severity, String message, List<? extends OsmPrimitive> primitives)
 	{
-		this(tester, severity, message, primitives, primitives);
-	}
-	
-	/**
-	 * Constructor
-	 * @param tester The tester
-	 * @param severity The severity of this error
-	 * @param message The error message
-	 * @param primitive The affected primitive
-	 */
+		this(tester, severity, message, null, primitives, primitives);
+	}
 	public TestError(Test tester, Severity severity, String message, OsmPrimitive primitive)
 	{
-		this(tester, severity, message, Collections.singletonList(primitive));
-	}
-	
-	/**
-	 * Constructor
-	 * @param tester The tester
-	 * @param severity The severity of this error
-	 * @param message The error message
-	 * @param primitive The affected primitive
-	 * @param internalCode The internal code
-	 */
+		this(tester, severity, message, null, Collections.singletonList(primitive), Collections.singletonList(primitive));
+	}
+	public TestError(Test tester, Severity severity, String message, String description, OsmPrimitive primitive)
+	{
+		this(tester, severity, message, description, Collections.singletonList(primitive));
+	}
 	public TestError(Test tester, Severity severity, String message, OsmPrimitive primitive, int internalCode)
 	{
-		this(tester, severity, message, primitive);
+		this(tester, severity, message, null, primitive);
 		this.internalCode = internalCode;
 	}
-	
+	public TestError(Test tester, Severity severity, String message, String description, OsmPrimitive primitive, int internalCode)
+	{
+		this(tester, severity, message, description, primitive);
+		this.internalCode = internalCode;
+	}
+
 	/**
 	 * Gets the error message
 	 * @return the error message
 	 */
-	public String getMessage() 
+	public String getMessage()
 	{
 		return message;
 	}
-	
+
+	/**
+	 * Gets the error message
+	 * @return the error description
+	 */
+	public String getDescription()
+	{
+		return description;
+	}
+
 	/**
 	 * Sets the error message
Index: applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/ValidatorDialog.java
===================================================================
--- applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/ValidatorDialog.java	(revision 9585)
+++ applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/ValidatorDialog.java	(revision 9598)
@@ -261,14 +261,14 @@
     }
 
-	public void actionPerformed(ActionEvent e) 
+	public void actionPerformed(ActionEvent e)
 	{
 		String actionCommand = e.getActionCommand();
-		if( actionCommand.equals("select"))
+		if( actionCommand.equals("Select"))
 			setSelectedItems();
-		else if( actionCommand.equals("validate"))
+		else if( actionCommand.equals("Validate"))
 			plugin.validateAction.actionPerformed(e);
-		else if( actionCommand.equals("fix"))
+		else if( actionCommand.equals("Fix"))
 			fixErrors(e);
-		else if( actionCommand.equals("ignore"))
+		else if( actionCommand.equals("Ignore"))
 			ignoreErrors(e);
 	}
Index: applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/OverlappingWays.java
===================================================================
--- applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/OverlappingWays.java	(revision 9585)
+++ applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/OverlappingWays.java	(revision 9598)
@@ -70,5 +70,6 @@
 					else if (ws.way.get("railway") != null)
 						railway++;
-					if (OsmUtils.getOsmBoolean(ws.way.get("area")))
+					Boolean ar = OsmUtils.getOsmBoolean(ws.way.get("area"));
+					if (ar != null && ar)
 						area++;
 					if (ws.way.get("landuse") != null || ws.way.get("natural") != null
Index: applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/TagChecker.java
===================================================================
--- applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/TagChecker.java	(revision 9585)
+++ applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/TagChecker.java	(revision 9598)
@@ -194,11 +194,14 @@
 				else if(tagcheckerfile)
 				{
-					CheckerData d = new CheckerData();
-					String err = d.getData(line);
-
-					if(err == null)
-						checkerData.add(d);
-					else
-						System.err.println("Invalid tagchecker line - "+err+":" + line);
+					if(line.length() > 0)
+					{
+						CheckerData d = new CheckerData();
+						String err = d.getData(line);
+
+						if(err == null)
+							checkerData.add(d);
+						else
+							System.err.println("Invalid tagchecker line - "+err+":" + line);
+					}
 				}
 				else if( line.charAt(0) == '+' )
@@ -286,20 +289,20 @@
 			if( checkValues && (value==null || value.trim().length() == 0) && !withErrors.contains(p, "EV"))
 			{
-				errors.add( new TestError(this, Severity.WARNING, tr("Tags with empty values"), p, EMPTY_VALUES) );
+				errors.add( new TestError(this, Severity.WARNING, tr("Tags with empty values"), tr("Key ''{0}'' invalid.", key), p, EMPTY_VALUES) );
 				withErrors.add(p, "EV");
 			}
 			if( checkKeys && spellCheckKeyData.containsKey(key) && !withErrors.contains(p, "IPK"))
 			{
-				errors.add( new TestError(this, Severity.WARNING, tr("Invalid property key ''{0}''", key), p, INVALID_KEY) );
+				errors.add( new TestError(this, Severity.WARNING, tr("Invalid property key"), tr("Key ''{0}'' invalid.", key), p, INVALID_KEY) );
 				withErrors.add(p, "IPK");
 			}
 			if( checkKeys && key.indexOf(" ") >= 0 && !withErrors.contains(p, "IPK"))
 			{
-				errors.add( new TestError(this, Severity.WARNING, tr("Invalid white space in property key ''{0}''", key), p, INVALID_KEY) );
+				errors.add( new TestError(this, Severity.WARNING, tr("Invalid white space in property key"), tr("Key ''{0}'' invalid.", key), p, INVALID_KEY) );
 				withErrors.add(p, "IPK");
 			}
 			if( checkValues && value != null && (value.startsWith(" ") || value.endsWith(" ")) && !withErrors.contains(p, "SPACE"))
 			{
-				errors.add( new TestError(this, Severity.OTHER, tr("Property values start or end with white space"), p, INVALID_SPACE) );
+				errors.add( new TestError(this, Severity.OTHER, tr("Property values start or end with white space"), tr("Key ''{0}'' invalid.", key), p, INVALID_SPACE) );
 				withErrors.add(p, "SPACE");
 			}
@@ -309,5 +312,5 @@
 				if( values != null && !values.contains(prop.getValue()) && !withErrors.contains(p, "UPV"))
 				{
-					errors.add( new TestError(this, Severity.OTHER, tr("Unknown property values"), p, INVALID_VALUE) );
+					errors.add( new TestError(this, Severity.OTHER, tr("Unknown property values"), tr("Key ''{0}'' invalid.", key), p, INVALID_VALUE) );
 					withErrors.add(p, "UPV");
 				}
Index: applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/UnclosedWays.java
===================================================================
--- applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/UnclosedWays.java	(revision 9585)
+++ applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/UnclosedWays.java	(revision 9598)
@@ -129,5 +129,5 @@
 				List<OsmPrimitive> primitives = new ArrayList<OsmPrimitive>();
 				primitives.add(w);
-				errors.add(new TestError(this, Severity.WARNING, tr("Unclosed way: {0}",type), primitives));
+				errors.add(new TestError(this, Severity.WARNING, tr("Unclosed way"), type, primitives));
 				_errorWays.add(w,w);
 			}
Index: applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/util/MultipleNameVisitor.java
===================================================================
--- applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/util/MultipleNameVisitor.java	(revision 9585)
+++ applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/util/MultipleNameVisitor.java	(revision 9598)
@@ -34,4 +34,5 @@
 	{
 		String multipleName = null;
+		String multiplePluralClassname = null;
 		String firstName = null;
 		boolean initializedname = false;
@@ -56,25 +57,31 @@
 			osm.visit(this);
 			if (multipleClassname == null)
+			{
 				multipleClassname = className;
+				multiplePluralClassname = classNamePlural;
+			}
 			else if (!multipleClassname.equals(className))
+			{
 				multipleClassname = "object";
+				multiplePluralClassname = trn("object", "objects", 2);
+			}
 		}
-		
+
 		if( size == 1 )
 			displayName = name;
 		else if(multipleName != null)
-			displayName = size + " " + trn(multipleClassname, multipleClassname + "s", size) + ": " + multipleName;
+			displayName = size + " " + trn(multipleClassname, multiplePluralClassname, size) + ": " + multipleName;
 		else if(firstName != null)
-			displayName = size + " " + trn(multipleClassname, multipleClassname + "s", size) + ": " + tr("{0}, ...", firstName);
+			displayName = size + " " + trn(multipleClassname, multiplePluralClassname, size) + ": " + tr("{0}, ...", firstName);
 		else
-			displayName = size + " " + trn(multipleClassname, multipleClassname + "s", size);
+			displayName = size + " " + trn(multipleClassname, multiplePluralClassname, size);
 	}
 
 	@Override
-	public JLabel toLabel() 
+	public JLabel toLabel()
 	{
 		return new JLabel(getText(), getIcon(), JLabel.HORIZONTAL);
 	}
-	
+
 	/**
 	 * Gets the name of the items
Index: applications/editors/josm/plugins/validator/tagchecker.cfg
===================================================================
--- applications/editors/josm/plugins/validator/tagchecker.cfg	(revision 9585)
+++ applications/editors/josm/plugins/validator/tagchecker.cfg	(revision 9598)
@@ -22,9 +22,11 @@
 # with and logical and (&&).
 #
+# The comment at the end of a rule is displayed in validator
+#
 # Empty lines and space signs are ignored
 
-node : bridge == *
-node : highway == tertiary
-node : highway == secondary
-way  : highway == secondary && ref != *
-way  : highway == tertiary && ref != *
+node : bridge == *                                         # bridge tag on a node
+node : highway == tertiary                                 # wrong highway tag on a node
+node : highway == secondary                                # wrong highway tag on a node
+way  : highway == secondary && ref != *                    # highway without a reference
+way  : highway == tertiary && ref != *                     # highway without a reference
