Index: applications/editors/josm/plugins/tag2link/build.xml
===================================================================
--- applications/editors/josm/plugins/tag2link/build.xml	(revision 35133)
+++ applications/editors/josm/plugins/tag2link/build.xml	(revision 35134)
@@ -1,3 +1,3 @@
-﻿<?xml version="1.0" encoding="utf-8"?>
+﻿﻿<?xml version="1.0" encoding="utf-8"?>
 <project name="tag2link" default="dist" basedir=".">
 
@@ -5,5 +5,5 @@
     <property name="commit.message" value="Commit message"/>
     <!-- enter the *lowest* JOSM version this plugin is currently compatible with -->
-    <property name="plugin.main.version" value="12847"/>
+    <property name="plugin.main.version" value="15376"/>
 
     <property name="plugin.author" value="Don-vip &amp; FrViPofm"/>
Index: applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/Tag2LinkRuleChecker.java
===================================================================
--- applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/Tag2LinkRuleChecker.java	(revision 35133)
+++ applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/Tag2LinkRuleChecker.java	(revision 35134)
@@ -23,4 +23,5 @@
 import java.util.Locale;
 import java.util.Map;
+import java.util.function.BiFunction;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -28,4 +29,5 @@
 import org.openstreetmap.josm.data.osm.IPrimitive;
 import org.openstreetmap.josm.data.osm.Tag;
+import org.openstreetmap.josm.data.osm.Tags;
 import org.openstreetmap.josm.plugins.tag2link.data.Link;
 import org.openstreetmap.josm.plugins.tag2link.data.LinkPost;
@@ -48,5 +50,8 @@
     
     private static boolean initialized = false;
-    
+
+    private static final Pattern PLACEHOLDERS = Pattern.compile("%([^%]*)%");
+    private static final Pattern LANG = Pattern.compile(".*lang(?:\\((\\p{Lower}{2,})(?:,(\\p{Lower}{2,}))*\\))?.*");
+
     /**
      * Initializes the matching rules mechanism.
@@ -67,8 +72,8 @@
         return null;
     }
-    
+
     private static String replaceParams(String s, EvalResult eval) {
         String result = s;
-        Matcher m = Pattern.compile("%([^%]*)%").matcher(s);
+        Matcher m = PLACEHOLDERS.matcher(s);
         while (m.find()) {
             String arg = m.group(1);
@@ -79,5 +84,5 @@
             // No standard value found: test lang() function
             if (val == null) {
-                Matcher lm = Pattern.compile(".*lang(?:\\((\\p{Lower}{2,})(?:,(\\p{Lower}{2,}))*\\))?.*").matcher(arg);
+                Matcher lm = LANG.matcher(arg);
                 if (lm.matches()) {
                     String josmLang = Config.getPref().get("language");
@@ -107,5 +112,5 @@
             }
             
-            // Has a value been found ?
+            // Has a value been found?
             if (val != null) {
                 try {
@@ -114,5 +119,5 @@
                         val = val.replaceAll(" ", "_");
                     }
-                    // Encode param to be included in the URL, except if it is the URL itself !
+                    // Encode param to be included in the URL, except if it is the URL itself!
                     if (!m.group().equals(s)) {
                         val = URLEncoder.encode(val, UTF8_ENCODING);
@@ -124,5 +129,5 @@
                 }
             } else {
-                System.err.println("Invalid argument: "+arg);
+                Logging.error("Invalid argument: " + arg);
             }
         }
@@ -164,5 +169,5 @@
                     result.add(copy);
                 } catch (CloneNotSupportedException e) {
-                    System.err.println(e);
+                    Logging.error(e);
                 }
             }
@@ -170,5 +175,15 @@
         return result;
     }
-    
+
+    private static <T> Collection<Link> doGetLinks(BiFunction<Rule, T, EvalResult> evaluator, T obj) {
+        Collection<Link> result = new ArrayList<>();
+        for (Source source : sources) {
+            for (Rule rule : source.rules) {
+                result.addAll(processEval(evaluator.apply(rule, obj), rule, source));
+            }
+        }
+        return result;
+    }
+
     /**
      * Replies the links relevant to the given OSM primitive.
@@ -177,11 +192,5 @@
      */
     public static Collection<Link> getLinks(IPrimitive p) {
-        Collection<Link> result = new ArrayList<>();
-        for (Source source : sources) {
-            for (Rule rule : source.rules) {
-                result.addAll(processEval(rule.evaluates(p), rule, source));
-            }
-        }
-        return result;
+        return doGetLinks(Rule::evaluates, p);
     }
 
@@ -192,11 +201,14 @@
      */
     public static Collection<Link> getLinks(Tag tag) {
-        Collection<Link> result = new ArrayList<>();
-        for (Source source : sources) {
-            for (Rule rule : source.rules) {
-                result.addAll(processEval(rule.evaluates(tag), rule, source));
-            }
-        }
-        return result;
+        return doGetLinks(Rule::evaluates, tag);
+    }
+
+    /**
+     * Replies the links relevant to the given OSM tags.
+     * @param tags The OSM tags
+     * @return the links relevant to the {@code tags}.
+     */
+    public static Collection<Link> getLinks(Tags tags) {
+        return doGetLinks(Rule::evaluates, tags);
     }
 }
Index: applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/data/Condition.java
===================================================================
--- applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/data/Condition.java	(revision 35133)
+++ applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/data/Condition.java	(revision 35134)
@@ -40,7 +40,4 @@
     public String id;
     
-    /* (non-Javadoc)
-     * @see java.lang.Object#toString()
-     */
     @Override
     public String toString() {
Index: applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/data/Link.java
===================================================================
--- applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/data/Link.java	(revision 35133)
+++ applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/data/Link.java	(revision 35134)
@@ -45,7 +45,4 @@
     }
 
-    /* (non-Javadoc)
-     * @see java.lang.Object#toString()
-     */
     @Override
     public String toString() {
@@ -53,7 +50,4 @@
     }
 
-    /* (non-Javadoc)
-     * @see java.lang.Object#clone()
-     */
     @Override
     public Link clone() throws CloneNotSupportedException {
Index: applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/data/LinkPost.java
===================================================================
--- applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/data/LinkPost.java	(revision 35133)
+++ applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/data/LinkPost.java	(revision 35134)
@@ -59,7 +59,4 @@
     }
 
-    /* (non-Javadoc)
-     * @see org.openstreetmap.josm.plugins.tag2link.data.Link#containsParams()
-     */
     @Override
     public boolean containsParams() {
@@ -67,7 +64,4 @@
     }
 
-    /* (non-Javadoc)
-     * @see org.openstreetmap.josm.plugins.tag2link.data.Link#clone()
-     */
     @Override
     public LinkPost clone() throws CloneNotSupportedException {
Index: applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/data/Rule.java
===================================================================
--- applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/data/Rule.java	(revision 35133)
+++ applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/data/Rule.java	(revision 35134)
@@ -16,12 +16,16 @@
 package org.openstreetmap.josm.plugins.tag2link.data;
 
+import static java.util.Collections.singleton;
+
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.function.Function;
 import java.util.regex.Matcher;
 
 import org.openstreetmap.josm.data.osm.IPrimitive;
 import org.openstreetmap.josm.data.osm.Tag;
+import org.openstreetmap.josm.data.osm.Tags;
 
 public class Rule {
@@ -54,7 +58,4 @@
             }
         }
-        /* (non-Javadoc)
-         * @see java.lang.Object#toString()
-         */
         @Override
         public String toString() {
@@ -75,7 +76,4 @@
             return conditionsNumber > 0 && matchingTags.size() >= conditionsNumber;
         }
-        /* (non-Javadoc)
-         * @see java.lang.Object#toString()
-         */
         @Override
         public String toString() {
@@ -84,25 +82,27 @@
         }
     }
-    
-    public EvalResult evaluates(Map<String, String> tags) {
+
+    public EvalResult evaluates(Iterable<String> keys, Function<String, Iterable<String>> valuesFn) {
         EvalResult result = new EvalResult(conditions.size());
         for (Condition c : conditions) {
-            for (String key : tags.keySet()) {
+            for (String key : keys) {
                 Matcher keyMatcher = c.keyPattern.matcher(key);
                 if (keyMatcher.matches()) {
                     String idPrefix = c.id == null ? "" : c.id+".";
-                    MatchingTag tag = new MatchingTag(key, tags.get(key), idPrefix);
-                    tag.addParams(keyMatcher, "k");
-                    boolean matchingTag = true;
-                    if (c.valPattern != null) {
-                        Matcher valMatcher = c.valPattern.matcher(tag.value);
-                        if (valMatcher.matches()) {
-                            tag.addParams(valMatcher, "v");
-                        } else {
-                            matchingTag = false;
+                    for (String value : valuesFn.apply(key)) {
+                        MatchingTag tag = new MatchingTag(key, value, idPrefix);
+                        tag.addParams(keyMatcher, "k");
+                        boolean matchingTag = true;
+                        if (c.valPattern != null) {
+                            Matcher valMatcher = c.valPattern.matcher(tag.value);
+                            if (valMatcher.matches()) {
+                                tag.addParams(valMatcher, "v");
+                            } else {
+                                matchingTag = false;
+                            }
                         }
-                    }
-                    if (matchingTag) {
-                        result.matchingTags.add(tag);
+                        if (matchingTag) {
+                            result.matchingTags.add(tag);
+                        }
                     }
                 }
@@ -111,21 +111,20 @@
         return result;
     }
-    
+
     public EvalResult evaluates(IPrimitive p) {
-        return evaluates(p.getKeys());
+        return evaluates(p.keySet(), key -> singleton(p.get(key)));
     }
 
     public EvalResult evaluates(Tag tag) {
-        Map<String, String> map = new HashMap<>();
-        map.put(tag.getKey(), tag.getValue());
-        return evaluates(map);
+        return evaluates(singleton(tag.getKey()), x -> singleton(tag.getValue()));
     }
 
-    /* (non-Javadoc)
-     * @see java.lang.Object#toString()
-     */
+    public EvalResult evaluates(Tags tags) {
+        return evaluates(singleton(tags.getKey()), x -> tags.getValues());
+    }
+
     @Override
     public String toString() {
-        return "Rule [conditions=" + conditions + ", links=" + links + "]";
+        return "Rule [conditions=" + conditions + ", links=" + links + ']';
     }
 }
Index: applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/data/Source.java
===================================================================
--- applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/data/Source.java	(revision 35133)
+++ applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/data/Source.java	(revision 35134)
@@ -43,7 +43,4 @@
     }
 
-    /* (non-Javadoc)
-     * @see java.lang.Object#toString()
-     */
     @Override
     public String toString() {
Index: applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/listeners/PropertyPopupListener.java
===================================================================
--- applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/listeners/PropertyPopupListener.java	(revision 35133)
+++ applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/listeners/PropertyPopupListener.java	(revision 35134)
@@ -19,5 +19,5 @@
 import javax.swing.event.PopupMenuEvent;
 
-import org.openstreetmap.josm.data.osm.Tag;
+import org.openstreetmap.josm.data.osm.Tags;
 import org.openstreetmap.josm.gui.MapFrame;
 import org.openstreetmap.josm.plugins.tag2link.Tag2LinkRuleChecker;
@@ -32,8 +32,8 @@
     @Override
     public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
-        Tag tag = frame.propertiesDialog.getSelectedProperty();
-        if (tag != null) {
+        Tags tags = frame.propertiesDialog.getSelectedProperties();
+        if (tags != null) {
             JPopupMenu popup = (JPopupMenu) e.getSource();
-            for (Link link : Tag2LinkRuleChecker.getLinks(tag)) {
+            for (Link link : Tag2LinkRuleChecker.getLinks(tags)) {
                 addLink(popup, link);
             }
