Index: src/org/openstreetmap/josm/Main.java
===================================================================
--- src/org/openstreetmap/josm/Main.java	(revision 158)
+++ src/org/openstreetmap/josm/Main.java	(revision 159)
@@ -7,5 +7,4 @@
 import java.awt.Rectangle;
 import java.awt.Toolkit;
-import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
 import java.io.File;
@@ -21,12 +20,7 @@
 import java.util.regex.Pattern;
 
-import javax.swing.AbstractAction;
-import javax.swing.Action;
 import javax.swing.JComponent;
-import javax.swing.JMenu;
-import javax.swing.JMenuBar;
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
-import javax.swing.JSeparator;
 import javax.swing.JToolBar;
 import javax.swing.KeyStroke;
@@ -34,18 +28,5 @@
 
 import org.openstreetmap.josm.actions.AboutAction;
-import org.openstreetmap.josm.actions.AlignInCircleAction;
 import org.openstreetmap.josm.actions.DownloadAction;
-import org.openstreetmap.josm.actions.ExitAction;
-import org.openstreetmap.josm.actions.ExternalToolsAction;
-import org.openstreetmap.josm.actions.GpxExportAction;
-import org.openstreetmap.josm.actions.HelpAction;
-import org.openstreetmap.josm.actions.OpenAction;
-import org.openstreetmap.josm.actions.PreferencesAction;
-import org.openstreetmap.josm.actions.RedoAction;
-import org.openstreetmap.josm.actions.ReverseSegmentAction;
-import org.openstreetmap.josm.actions.SaveAction;
-import org.openstreetmap.josm.actions.SaveAsAction;
-import org.openstreetmap.josm.actions.UndoAction;
-import org.openstreetmap.josm.actions.UploadAction;
 import org.openstreetmap.josm.actions.DownloadAction.DownloadTask;
 import org.openstreetmap.josm.actions.mapmode.MapMode;
@@ -55,8 +36,8 @@
 import org.openstreetmap.josm.data.projection.Epsg4326;
 import org.openstreetmap.josm.data.projection.Projection;
+import org.openstreetmap.josm.gui.MainMenu;
 import org.openstreetmap.josm.gui.MapFrame;
 import org.openstreetmap.josm.gui.PleaseWaitDialog;
 import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
-import org.openstreetmap.josm.gui.annotation.AnnotationTester;
 import org.openstreetmap.josm.gui.dialogs.SelectionListDialog;
 import org.openstreetmap.josm.gui.layer.Layer;
@@ -107,8 +88,10 @@
 	 */
 	public static PleaseWaitDialog pleaseWaitDlg;
-	/**
-	 * The access to the help subsystem
-	 */
-	public HelpAction help;
+
+
+	/**
+	 * The main menu bar at top of screen.
+	 */
+	public final MainMenu menu;
 
 
@@ -153,10 +136,10 @@
 	public final void setLayerMenu(Component[] entries) {
 		if (entries == null || entries.length == 0)
-			layerMenu.setVisible(false);
+			menu.layerMenu.setVisible(false);
 		else {
-			layerMenu.removeAll();
+			menu.layerMenu.removeAll();
 			for (Component c : entries)
-				layerMenu.add(c);
-			layerMenu.setVisible(true);
+				menu.layerMenu.add(c);
+			menu.layerMenu.setVisible(true);
 		}
 	}
@@ -177,94 +160,24 @@
 		main = this;
 		contentPane.add(panel, BorderLayout.CENTER);
-
-		final Action annotationTesterAction = new AbstractAction(){
-			public void actionPerformed(ActionEvent e) {
-				String annotationSources = pref.get("annotation.sources");
-				if (annotationSources.equals("")) {
-					JOptionPane.showMessageDialog(Main.parent, tr("You have to specify annotation sources in the preferences first."));
-					return;
-				}
-				String[] args = annotationSources.split(";");
-				new AnnotationTester(args);
-			}
-		};
-		annotationTesterAction.putValue(Action.NAME, tr("Annotation Preset Tester"));
-		annotationTesterAction.putValue(Action.SMALL_ICON, ImageProvider.get("annotation-tester"));
-		final Action reverseSegmentAction = new ReverseSegmentAction();
-		final Action alignInCircleAction = new AlignInCircleAction();
-		final Action uploadAction = new UploadAction();
-		final Action saveAction = new SaveAction();
-		final Action saveAsAction = new SaveAsAction();
-		final Action gpxExportAction = new GpxExportAction(null);
-		final Action exitAction = new ExitAction();
-		final Action preferencesAction = new PreferencesAction();
-		help = new HelpAction();
-		final Action aboutAction = new AboutAction();
-
-		final JMenu fileMenu = new JMenu(tr("Files"));
-		fileMenu.setMnemonic('F');
-		fileMenu.add(openAction);
-		fileMenu.add(saveAction);
-		fileMenu.add(saveAsAction);
-		fileMenu.add(gpxExportAction);
-		fileMenu.addSeparator();
-		fileMenu.add(exitAction);
-		mainMenu.add(fileMenu);
-
-
-		final JMenu connectionMenu = new JMenu(tr("Connection"));
-		connectionMenu.setMnemonic('C');
-		connectionMenu.add(downloadAction);
-		//connectionMenu.add(new DownloadIncompleteAction());
-		connectionMenu.add(uploadAction);
-		mainMenu.add(connectionMenu);
-
-		layerMenu = new JMenu(tr("Layer"));
-		layerMenu.setMnemonic('L');
-		mainMenu.add(layerMenu);
-		layerMenu.setVisible(false);
-
-		final JMenu editMenu = new JMenu(tr("Edit"));
-		editMenu.setMnemonic('E');
-		editMenu.add(undoAction);
-		editMenu.add(redoAction);
-		editMenu.addSeparator();
-		editMenu.add(reverseSegmentAction);
-		editMenu.add(alignInCircleAction);
-		editMenu.addSeparator();
-		editMenu.add(preferencesAction);
-		mainMenu.add(editMenu);
-
-		JMenu externalMenu = ExternalToolsAction.buildMenu();
-		if (externalMenu != null)
-			mainMenu.add(externalMenu);
-
-		mainMenu.add(new JSeparator());
-		final JMenu helpMenu = new JMenu(tr("Help"));
-		helpMenu.setMnemonic('H');
-		helpMenu.add(help);
-		helpMenu.add(aboutAction);
-		helpMenu.addSeparator();
-		helpMenu.add(annotationTesterAction);
-		mainMenu.add(helpMenu);
+		menu = new MainMenu();
 
 		// creating toolbar
 		final JToolBar toolBar = new JToolBar();
 		toolBar.setFloatable(false);
-		toolBar.add(downloadAction);
-		toolBar.add(uploadAction);
+		toolBar.add(menu.download);
+		toolBar.add(menu.upload);
 		toolBar.addSeparator();
-		toolBar.add(openAction);
-		toolBar.add(saveAction);
-		toolBar.add(gpxExportAction);
+		toolBar.add(menu.open);
+		toolBar.add(menu.save);
+		toolBar.add(menu.gpxExport);
 		toolBar.addSeparator();
-		toolBar.add(undoAction);
-		toolBar.add(redoAction);
+		toolBar.add(menu.undo);
+		toolBar.add(menu.redo);
 		toolBar.addSeparator();
-		toolBar.add(preferencesAction);
+		toolBar.add(menu.preferences);
 		contentPane.add(toolBar, BorderLayout.NORTH);
 
         contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0), "Help");
-        contentPane.getActionMap().put("Help", help);
+        contentPane.getActionMap().put("Help", menu.help);
 
 		contentPane.updateUI();
@@ -280,7 +193,10 @@
 				try {
 					File pluginFile = new File(pref.getPreferencesDir()+"plugins/"+pluginName+".jar");
-					if (pluginFile.exists())
-						plugins.add(new PluginInformation(pluginFile).load());
-					else
+					if (pluginFile.exists()) {
+						PluginInformation info = new PluginInformation(pluginFile);
+						Class<?> klass = info.loadClass();
+						ImageProvider.sources.add(0, klass);
+						plugins.add(info.load(klass));
+					} else
 						JOptionPane.showMessageDialog(Main.parent, tr("Plugin not found: {0}.", pluginName));
 				} catch (PluginException e) {
@@ -327,22 +243,15 @@
 	////////////////////////////////////////////////////////////////////////////////////////
 
-
 	public static JPanel panel = new JPanel(new BorderLayout());
 
-	public final JMenuBar mainMenu = new JMenuBar();
 	protected static Rectangle bounds;
 
-	public final UndoAction undoAction = new UndoAction();
-	public final RedoAction redoAction = new RedoAction();
-	public final OpenAction openAction = new OpenAction();
-	public final DownloadAction downloadAction = new DownloadAction();
 
 	private final CommandQueueListener redoUndoListener = new CommandQueueListener(){
 		public void commandChanged(final int queueSize, final int redoSize) {
-			undoAction.setEnabled(queueSize > 0);
-			redoAction.setEnabled(redoSize > 0);
+			menu.undo.setEnabled(queueSize > 0);
+			menu.redo.setEnabled(redoSize > 0);
 		}
 	};
-	private JMenu layerMenu;
 
 	/**
@@ -420,6 +329,6 @@
 				JOptionPane.showMessageDialog(Main.parent, tr("Ignoring malformed url: \"{0}\"", s));
 			else {
-				DownloadTask osmTask = main.downloadAction.downloadTasks.get(0);
-				osmTask.download(main.downloadAction, b.min.lat(), b.min.lon(), b.max.lat(), b.max.lon());
+				DownloadTask osmTask = main.menu.download.downloadTasks.get(0);
+				osmTask.download(main.menu.download, b.min.lat(), b.min.lon(), b.max.lat(), b.max.lon());
 			}
 			return;
@@ -428,5 +337,5 @@
 		if (s.startsWith("file:")) {
 			try {
-				main.openAction.openFile(new File(new URI(s)));
+				main.menu.open.openFile(new File(new URI(s)));
 			} catch (URISyntaxException e) {
 				JOptionPane.showMessageDialog(Main.parent, tr("Ignoring malformed file url: \"{0}\"", s));
@@ -438,6 +347,6 @@
 		if (st.countTokens() == 4) {
 			try {
-				DownloadTask task = main.downloadAction.downloadTasks.get(rawGps ? 1 : 0);
-				task.download(main.downloadAction, Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()));
+				DownloadTask task = main.menu.download.downloadTasks.get(rawGps ? 1 : 0);
+				task.download(main.menu.download, Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()));
 				return;
 			} catch (final NumberFormatException e) {
@@ -445,5 +354,5 @@
 		}
 
-		main.openAction.openFile(new File(s));
+		main.menu.open.openFile(new File(s));
 	}
 }
Index: src/org/openstreetmap/josm/data/osm/OsmPrimitive.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(revision 158)
+++ src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(revision 159)
@@ -88,10 +88,19 @@
 
 	/**
-	 * Return the id as hashcode or supers hashcode if 0.
+	 * Return the id plus the class type encoded as hashcode or supers hashcode if id is 0.
 	 * 
 	 * An primitive has the same hashcode as its incomplete counter part.
 	 */
 	@Override public final int hashCode() {
-		return id == 0 ? super.hashCode() : (int)id;
+		if (id == 0)
+			return super.hashCode();
+		final int[] ret = new int[1];
+		Visitor v = new Visitor(){
+			public void visit(Node n) { ret[0] = 1; }
+			public void visit(Segment s) { ret[0] = 2; }
+			public void visit(Way w) { ret[0] = 3; }
+		};
+		visit(v);
+		return id == 0 ? super.hashCode() : (int)(id<<3)+ret[0];
 	}
 
Index: src/org/openstreetmap/josm/data/osm/visitor/AllNodesVisitor.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/visitor/AllNodesVisitor.java	(revision 158)
+++ src/org/openstreetmap/josm/data/osm/visitor/AllNodesVisitor.java	(revision 159)
@@ -41,6 +41,6 @@
 	 * Ways have all nodes from their segments.
 	 */
-	public void visit(Way t) {
-		for (Segment ls : t.segments)
+	public void visit(Way w) {
+		for (Segment ls : w.segments)
 			visit(ls);
 	}
Index: src/org/openstreetmap/josm/data/osm/visitor/BoundingXYVisitor.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/visitor/BoundingXYVisitor.java	(revision 158)
+++ src/org/openstreetmap/josm/data/osm/visitor/BoundingXYVisitor.java	(revision 159)
@@ -28,6 +28,6 @@
 	}
 
-	public void visit(Way t) {
-		for (Segment ls : t.segments)
+	public void visit(Way w) {
+		for (Segment ls : w.segments)
 			visit(ls);
 	}
Index: src/org/openstreetmap/josm/data/osm/visitor/CollectBackReferencesVisitor.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/visitor/CollectBackReferencesVisitor.java	(revision 158)
+++ src/org/openstreetmap/josm/data/osm/visitor/CollectBackReferencesVisitor.java	(revision 159)
@@ -57,11 +57,11 @@
 	}
 	public void visit(Segment ls) {
-		for (Way t : ds.ways) {
-			if (t.deleted)
+		for (Way w : ds.ways) {
+			if (w.deleted)
 				continue;
-			if (t.segments.contains(ls))
-				data.add(t);
+			if (w.segments.contains(ls))
+				data.add(w);
 		}
 	}
-	public void visit(Way t) {}
+	public void visit(Way w) {}
 }
Index: src/org/openstreetmap/josm/data/osm/visitor/DeleteVisitor.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/visitor/DeleteVisitor.java	(revision 158)
+++ src/org/openstreetmap/josm/data/osm/visitor/DeleteVisitor.java	(revision 159)
@@ -29,6 +29,6 @@
 		ds.segments.remove(ls);
 	}
-	public void visit(Way t) {
-		ds.ways.remove(t);
+	public void visit(Way w) {
+		ds.ways.remove(w);
 	}
 }
Index: src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java	(revision 158)
+++ src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java	(revision 159)
@@ -147,7 +147,7 @@
 
 		Way my = null;
-		for (Way t : ds.ways) {
-			if (match(other, t)) {
-				my = t;
+		for (Way w : ds.ways) {
+			if (match(other, w)) {
+				my = w;
 				break;
 			}
@@ -211,8 +211,8 @@
 	}
 
-	private void fixWay(Way t) {
+	private void fixWay(Way w) {
 	    boolean replacedSomething = false;
 	    LinkedList<Segment> newSegments = new LinkedList<Segment>();
-	    for (Segment ls : t.segments) {
+	    for (Segment ls : w.segments) {
 	    	Segment otherLs = mergedSegments.get(ls);
 	    	newSegments.add(otherLs == null ? ls : otherLs);
@@ -221,8 +221,8 @@
 	    }
 	    if (replacedSomething) {
-	    	t.segments.clear();
-	    	t.segments.addAll(newSegments);
+	    	w.segments.clear();
+	    	w.segments.addAll(newSegments);
 	    }
-	    for (Segment ls : t.segments)
+	    for (Segment ls : w.segments)
 	    	fixSegment(ls);
     }
@@ -258,15 +258,15 @@
 	 * @return Whether the ways matches (in sense of "be mergable").
 	 */
-	private boolean match(Way t1, Way t2) {
-		if (t1.id == 0 || t2.id == 0) {
-			if (t1.segments.size() != t2.segments.size())
+	private boolean match(Way w1, Way w2) {
+		if (w1.id == 0 || w2.id == 0) {
+			if (w1.segments.size() != w2.segments.size())
 				return false;
-			Iterator<Segment> it = t1.segments.iterator();
-			for (Segment ls : t2.segments)
+			Iterator<Segment> it = w1.segments.iterator();
+			for (Segment ls : w2.segments)
 				if (!match(ls, it.next()))
 					return false;
 			return true;
 		}
-		return t1.id == t2.id;
+		return w1.id == w2.id;
 	}
 
Index: src/org/openstreetmap/josm/gui/MainApplet.java
===================================================================
--- src/org/openstreetmap/josm/gui/MainApplet.java	(revision 158)
+++ src/org/openstreetmap/josm/gui/MainApplet.java	(revision 159)
@@ -26,5 +26,5 @@
 		private MainCaller() {
 			setContentPane(contentPane);
-			setJMenuBar(mainMenu);
+			setJMenuBar(menu);
 			setBounds(bounds);
 		}
Index: src/org/openstreetmap/josm/gui/MainApplication.java
===================================================================
--- src/org/openstreetmap/josm/gui/MainApplication.java	(revision 158)
+++ src/org/openstreetmap/josm/gui/MainApplication.java	(revision 159)
@@ -14,5 +14,4 @@
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Locale;
 import java.util.Map;
 
@@ -23,5 +22,8 @@
 import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.plugins.PluginException;
+import org.openstreetmap.josm.plugins.PluginInformation;
 import org.openstreetmap.josm.tools.BugReportExceptionHandler;
+import org.openstreetmap.josm.tools.ImageProvider;
 /**
  * Main window class application.
@@ -36,5 +38,5 @@
 	public MainApplication(JFrame mainFrame) {
 		mainFrame.setContentPane(contentPane);
-		mainFrame.setJMenuBar(mainMenu);
+		mainFrame.setJMenuBar(menu);
 		mainFrame.setBounds(bounds);
 		mainFrame.addWindowListener(new WindowAdapter(){
@@ -73,7 +75,7 @@
 		/////////////////////////////////////////////////////////////////////////
 		// Do not translate the early strings below until the locale is set up.
+		// (By the eager loaded plugins)
+		//
 		// These strings cannot be translated. That's live. Really. Sorry.
-		//
-		// The next one sending me a patch translating these strings owe me a beer!
 		//
 		//                                                                 Imi.
@@ -118,26 +120,24 @@
 		}
 
-		// setup the locale
-		if (args.containsKey("language") && !args.get("language").isEmpty() && args.get("language").iterator().next().length() >= 2) {
-			String s = args.get("language").iterator().next();
-			Locale l = null;
-			if (s.length() <= 2 || s.charAt(2) != '_')
-				l = new Locale(s);
-			else if (s.length() <= 5 || s.charAt(5) != '.')
-				l = new Locale(s.substring(0,2), s.substring(3));
-			else
-				l = new Locale(s.substring(0,2), s.substring(3,5), s.substring(6));
-			Locale.setDefault(l);
-		} else if (!Main.pref.get("language").equals("")) {
-			String lang = Main.pref.get("language");
-			for (Locale l : Locale.getAvailableLocales()) {
-				if (l.toString().equals(lang)) {
-					Locale.setDefault(l);
-					break;
+		// load the early plugins
+	    if (Main.pref.hasKey("plugins")) {
+			for (String pluginName : Main.pref.get("plugins").split(",")) {
+				try {
+					File pluginFile = new File(pref.getPreferencesDir()+"plugins/"+pluginName+".jar");
+					if (pluginFile.exists()) {
+						PluginInformation info = new PluginInformation(pluginFile);
+						if (!info.early)
+							continue;
+						Class<?> klass = info.loadClass();
+						ImageProvider.sources.add(0, klass);
+						Main.plugins.add(info.load(klass));
+					} else
+						System.out.println("Plugin not found: "+pluginName);
+				} catch (PluginException e) {
+					System.out.println("Could not load plugin "+pluginName);
+					e.printStackTrace();
 				}
 			}
 		}
-
-		// Locale is set. From now on, tr(), trn() and trc() may be called.
 
 		if (argList.contains("--help") || argList.contains("-?") || argList.contains("-h")) {
Index: src/org/openstreetmap/josm/gui/MainMenu.java
===================================================================
--- src/org/openstreetmap/josm/gui/MainMenu.java	(revision 159)
+++ src/org/openstreetmap/josm/gui/MainMenu.java	(revision 159)
@@ -0,0 +1,101 @@
+package org.openstreetmap.josm.gui;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import javax.swing.Action;
+import javax.swing.Box;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+
+import org.openstreetmap.josm.actions.AboutAction;
+import org.openstreetmap.josm.actions.AlignInCircleAction;
+import org.openstreetmap.josm.actions.DownloadAction;
+import org.openstreetmap.josm.actions.ExitAction;
+import org.openstreetmap.josm.actions.ExternalToolsAction;
+import org.openstreetmap.josm.actions.GpxExportAction;
+import org.openstreetmap.josm.actions.HelpAction;
+import org.openstreetmap.josm.actions.OpenAction;
+import org.openstreetmap.josm.actions.PreferencesAction;
+import org.openstreetmap.josm.actions.RedoAction;
+import org.openstreetmap.josm.actions.ReverseSegmentAction;
+import org.openstreetmap.josm.actions.SaveAction;
+import org.openstreetmap.josm.actions.SaveAsAction;
+import org.openstreetmap.josm.actions.UndoAction;
+import org.openstreetmap.josm.actions.UploadAction;
+
+/**
+ * This is the JOSM main menu bar. It is overwritten to initialize itself and provide
+ * all menu entries as member variables (sort of collect them).
+ * 
+ * It also provides possibilities to attach new menu entries (used by plugins).
+ * 
+ * @author Immanuel.Scholz
+ */
+public class MainMenu extends JMenuBar {
+
+	public final UndoAction undo = new UndoAction();
+	public final RedoAction redo = new RedoAction();
+	public final OpenAction open = new OpenAction();
+	public final DownloadAction download = new DownloadAction();
+	public final Action reverseSegment = new ReverseSegmentAction();
+	public final Action alignInCircle = new AlignInCircleAction();
+	public final Action upload = new UploadAction();
+	public final Action save = new SaveAction();
+	public final Action saveAs = new SaveAsAction();
+	public final Action gpxExport = new GpxExportAction(null);
+	public final Action exit = new ExitAction();
+	public final Action preferences = new PreferencesAction();
+	public final HelpAction help = new HelpAction();
+	public final Action about = new AboutAction();
+	
+	public final JMenu layerMenu = new JMenu(tr("Layer"));
+	public final JMenu editMenu = new JMenu(tr("Edit"));
+	public final JMenu externalMenu = ExternalToolsAction.buildMenu();
+	public final JMenu helpMenu = new JMenu(tr("Help"));
+	public final JMenu fileMenu = new JMenu(tr("Files"));
+	public final JMenu connectionMenu = new JMenu(tr("Connection"));
+
+
+	
+	public MainMenu() {
+		fileMenu.setMnemonic('F');
+		fileMenu.add(open);
+		fileMenu.add(save);
+		fileMenu.add(saveAs);
+		fileMenu.add(gpxExport);
+		fileMenu.addSeparator();
+		fileMenu.add(exit);
+		add(fileMenu);
+
+		editMenu.setMnemonic('E');
+		editMenu.add(undo);
+		editMenu.add(redo);
+		editMenu.addSeparator();
+		editMenu.add(reverseSegment);
+		editMenu.add(alignInCircle);
+		editMenu.addSeparator();
+		editMenu.add(preferences);
+		add(editMenu);
+
+		connectionMenu.setMnemonic('C');
+		connectionMenu.add(download);
+		//connectionMenu.add(new DownloadIncompleteAction());
+		connectionMenu.add(upload);
+		add(connectionMenu);
+
+		layerMenu.setMnemonic('L');
+		add(layerMenu);
+		layerMenu.setVisible(false);
+
+
+		if (externalMenu != null)
+			add(externalMenu);
+
+		add(Box.createHorizontalGlue());
+		
+		helpMenu.setMnemonic('H');
+		helpMenu.add(help);
+		helpMenu.add(about);
+		add(helpMenu);
+    }
+}
Index: src/org/openstreetmap/josm/gui/NavigatableComponent.java
===================================================================
--- src/org/openstreetmap/josm/gui/NavigatableComponent.java	(revision 158)
+++ src/org/openstreetmap/josm/gui/NavigatableComponent.java	(revision 159)
@@ -267,10 +267,10 @@
 		}
 		if (osm instanceof Node || osm instanceof Segment) {
-			for (Way t : Main.ds.ways) {
-				if (t.deleted)
+			for (Way w : Main.ds.ways) {
+				if (w.deleted)
 					continue;
-				for (Segment ls : t.segments) {
+				for (Segment ls : w.segments) {
 					if (!ls.deleted && !ls.incomplete && c.contains(ls)) {
-						c.add(t);
+						c.add(w);
 						break;
 					}
Index: src/org/openstreetmap/josm/gui/PreferenceDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/PreferenceDialog.java	(revision 158)
+++ src/org/openstreetmap/josm/gui/PreferenceDialog.java	(revision 159)
@@ -14,6 +14,5 @@
 import java.util.Collection;
 import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Locale;
+import java.util.LinkedList;
 import java.util.Map;
 import java.util.StringTokenizer;
@@ -85,5 +84,4 @@
 		public void actionPerformed(ActionEvent e) {
 			Main.pref.put("laf", ((LookAndFeelInfo)lafCombo.getSelectedItem()).getClassName());
-			Main.pref.put("language", languages.getSelectedItem().toString());
 			Main.pref.put("projection", projectionCombo.getSelectedItem().getClass().getName());
 			Main.pref.put("osm-server.url", osmDataServer.getText());
@@ -156,10 +154,4 @@
 	 */
 	private JComboBox lafCombo = new JComboBox(UIManager.getInstalledLookAndFeels());
-	private JComboBox languages = new JComboBox(new Locale[]{
-			new Locale("en", "US"),
-			new Locale("en", "GB"),
-			Locale.GERMAN,
-			Locale.FRENCH,
-			new Locale("ro", "RO")});
 	/**
 	 * The main tab panel.
@@ -232,19 +224,4 @@
 		});
 		lafCombo.addActionListener(requireRestartAction);
-
-		// language
-		String lang = Main.pref.get("language");
-		for (int i = 0; i < languages.getItemCount(); ++i) {
-			if (languages.getItemAt(i).toString().equals(lang)) {
-				languages.setSelectedIndex(i);
-				break;
-			}
-		}
-		languages.setRenderer(new DefaultListCellRenderer(){
-			@Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
-				return super.getListCellRendererComponent(list, ((Locale)value).getDisplayName(), index, isSelected, cellHasFocus);
-			}
-		});
-		languages.addActionListener(requireRestartAction);
 
 		// projection combo box
@@ -285,10 +262,12 @@
 
 		Box pluginPanel = Box.createVerticalBox();
-		Collection<PluginInformation> availablePlugins = new HashSet<PluginInformation>();
+		Collection<PluginInformation> availablePlugins = new LinkedList<PluginInformation>();
 		File[] pluginFiles = new File(Main.pref.getPreferencesDir()+"plugins").listFiles();
-		if (pluginFiles != null)
+		if (pluginFiles != null) {
+			Arrays.sort(pluginFiles);
 			for (File f : pluginFiles)
 				if (f.isFile() && f.getName().endsWith(".jar"))
 					availablePlugins.add(new PluginInformation(f));
+		}
 
 		Collection<String> enabledPlugins = Arrays.asList(Main.pref.get("plugins").split(","));
@@ -320,5 +299,5 @@
 		for (Entry<String,String> e : allColors.entrySet()) {
 			Vector<Object> row = new Vector<Object>(2);
-			row.add(tr(e.getKey().substring("color.".length())));
+			row.add(e.getKey().substring("color.".length()));
 			row.add(ColorHelper.html2color(e.getValue()));
 			rows.add(row);
@@ -342,5 +321,5 @@
 					return l;
 				}
-				return oldColorsRenderer.getTableCellRendererComponent(t,o,selected,focus,row,column);
+				return oldColorsRenderer.getTableCellRendererComponent(t,tr(o.toString()),selected,focus,row,column);
 			}
 		});
@@ -429,7 +408,4 @@
 		display.add(GBC.glue(5,0), GBC.std().fill(GBC.HORIZONTAL));
 		display.add(lafCombo, GBC.eol().fill(GBC.HORIZONTAL));
-		display.add(new JLabel(tr("Language")), GBC.std());
-		display.add(GBC.glue(5,0), GBC.std().fill(GBC.HORIZONTAL));
-		display.add(languages, GBC.eol().fill(GBC.HORIZONTAL));
 		display.add(drawRawGpsLines, GBC.eol().insets(20,0,0,0));
 		display.add(forceRawGpsLines, GBC.eop().insets(40,0,0,0));
@@ -487,5 +463,5 @@
 		plugin.add(pluginPane, GBC.eol().fill(GBC.BOTH));
 		plugin.add(GBC.glue(0,10), GBC.eol());
-		plugin.add(new UrlLabel("http://josm.eigenheimstrasse.de/wiki/Plugins", "Get more plugins"), GBC.std().fill(GBC.HORIZONTAL));
+		plugin.add(new UrlLabel("http://josm.eigenheimstrasse.de/wiki/Plugins", tr("Get more plugins")), GBC.std().fill(GBC.HORIZONTAL));
 
 		tabPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
@@ -505,4 +481,8 @@
 		setModal(true);
 		pack();
+		if (getHeight() > 400)
+			setSize(getWidth(), 400);
+		if (getWidth() > 600)
+			setSize(600, getHeight());
 		setLocationRelativeTo(Main.parent);
 	}
Index: src/org/openstreetmap/josm/gui/annotation/AnnotationTester.java
===================================================================
--- src/org/openstreetmap/josm/gui/annotation/AnnotationTester.java	(revision 158)
+++ 	(revision )
@@ -1,106 +1,0 @@
-package org.openstreetmap.josm.gui.annotation;
-
-import java.awt.BorderLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.Vector;
-
-import javax.swing.BorderFactory;
-import javax.swing.DefaultComboBoxModel;
-import javax.swing.JButton;
-import javax.swing.JComboBox;
-import javax.swing.JFrame;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-
-import org.xml.sax.SAXException;
-
-public class AnnotationTester extends JFrame {
-
-	private JComboBox annotationPresets;
-	private final String[] args;
-	private JPanel annotationPanel = new JPanel(new BorderLayout());
-	private JPanel panel = new JPanel(new BorderLayout());
-
-	public void reload() {
-		Vector<AnnotationPreset> allPresets = new Vector<AnnotationPreset>();
-		for (String source : args) {
-			InputStream in = null;
-			try {
-				if (source.startsWith("http") || source.startsWith("ftp") || source.startsWith("file"))
-					in = new URL(source).openStream();
-				else if (source.startsWith("resource://"))
-					in = AnnotationTester.class.getResourceAsStream(source.substring("resource:/".length()));
-				else
-					in = new FileInputStream(source);
-				allPresets.addAll(AnnotationPreset.readAll(in));
-			} catch (IOException e) {
-				e.printStackTrace();
-				JOptionPane.showMessageDialog(null, "Could not read annotation preset source: "+source);
-			} catch (SAXException e) {
-				e.printStackTrace();
-				JOptionPane.showMessageDialog(null, "Error parsing "+source+": "+e.getMessage());
-			}
-
-			try {
-	            if (in != null)
-	            	in.close();
-            } catch (IOException e) {
-            }
-		}
-		annotationPresets.setModel(new DefaultComboBoxModel(allPresets));
-	}
-
-	public void reselect() {
-		annotationPanel.removeAll();
-		AnnotationPreset preset = (AnnotationPreset)annotationPresets.getSelectedItem();
-		if (preset == null)
-			return;
-		JPanel p = preset.createPanel();
-		p.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
-		if (p != null)
-			annotationPanel.add(p, BorderLayout.NORTH);
-		panel.validate();
-		panel.repaint();
-	}
-	
-	public AnnotationTester(String[] args) {
-		super("Annotation Preset Tester");
-		this.args = args;
-		annotationPresets = new JComboBox();
-		annotationPresets.setRenderer(new AnnotationCellRenderer());
-		reload();
-
-		panel.add(annotationPresets, BorderLayout.NORTH);
-		panel.add(annotationPanel, BorderLayout.CENTER);
-		annotationPresets.addActionListener(new ActionListener(){
-			public void actionPerformed(ActionEvent e) {
-				reselect();
-			}
-		});
-		reselect();
-
-		JButton b = new JButton("Reload");
-		b.addActionListener(new ActionListener(){
-			public void actionPerformed(ActionEvent e) {
-				int i = annotationPresets.getSelectedIndex();
-				reload();
-				annotationPresets.setSelectedIndex(i);
-			}
-		});
-		panel.add(b, BorderLayout.SOUTH);
-
-		setContentPane(panel);
-		setSize(300,500);
-		setVisible(true);
-	}
-
-	public static void main(String[] args) {
-		JFrame f = new AnnotationTester(args);
-		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
-	}
-}
Index: src/org/openstreetmap/josm/plugins/Plugin.java
===================================================================
--- src/org/openstreetmap/josm/plugins/Plugin.java	(revision 158)
+++ src/org/openstreetmap/josm/plugins/Plugin.java	(revision 159)
@@ -1,4 +1,5 @@
 package org.openstreetmap.josm.plugins;
 
+import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
@@ -71,4 +72,7 @@
 	 */
 	public void copy(String from, String to) throws FileNotFoundException, IOException {
+		File pluginDir = new File(getPluginDir());
+		if (!pluginDir.exists())
+			pluginDir.mkdirs();
     	FileOutputStream out = new FileOutputStream(getPluginDir()+to);
     	InputStream in = getClass().getResourceAsStream(from);
Index: src/org/openstreetmap/josm/plugins/PluginInformation.java
===================================================================
--- src/org/openstreetmap/josm/plugins/PluginInformation.java	(revision 158)
+++ src/org/openstreetmap/josm/plugins/PluginInformation.java	(revision 159)
@@ -6,4 +6,7 @@
 import java.net.URL;
 import java.net.URLClassLoader;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.jar.Attributes;
 import java.util.jar.JarInputStream;
 import java.util.jar.Manifest;
@@ -20,4 +23,8 @@
 	public final String className;
 	public final String description;
+	public final boolean early;
+	public final String author;
+
+	public final Map<String, String> attr = new TreeMap<String, String>();
 
 	public PluginInformation(File file) {
@@ -25,24 +32,40 @@
 		name = file.getName().substring(0, file.getName().length()-4);
 		try {
-	        JarInputStream jar = new JarInputStream(new FileInputStream(file));
-	        Manifest manifest = jar.getManifest();
-	        className = manifest.getMainAttributes().getValue("Plugin-Class");
-	        description = manifest.getMainAttributes().getValue("Plugin-Description");
-	        jar.close();
-        } catch (IOException e) {
-        	throw new PluginException(null, name, e);
-        }
-    }
+			JarInputStream jar = new JarInputStream(new FileInputStream(file));
+			Manifest manifest = jar.getManifest();
+			Attributes attr = manifest.getMainAttributes();
+			className = attr.getValue("Plugin-Class");
+			description = attr.getValue("Plugin-Description");
+			early = Boolean.parseBoolean(attr.getValue("Plugin-Early"));
+			author = attr.getValue("Author");
+			for (Object o : attr.keySet())
+				this.attr.put(o.toString(), attr.getValue(o.toString()));
+			jar.close();
+		} catch (IOException e) {
+			throw new PluginException(null, name, e);
+		}
+	}
 
 	/**
 	 * Load and instantiate the plugin
 	 */
-	public PluginProxy load() {
+	public PluginProxy load(Class<?> klass) {
+		try {
+			return new PluginProxy(klass.newInstance(), this);
+		} catch (Exception e) {
+			throw new PluginException(null, name, e);
+		}
+	}
+
+	/**
+	 * Load the class of the plugin
+	 */
+	public Class<?> loadClass() {
 		try {
 			ClassLoader loader = URLClassLoader.newInstance(
 					new URL[]{new URL(getURLString())},
 					getClass().getClassLoader());
-			Object plugin = Class.forName(className, true, loader).newInstance();
-			return new PluginProxy(plugin, this);
+			Class<?> realClass = Class.forName(className, true, loader);
+			return realClass;
 		} catch (Exception e) {
 			throw new PluginException(null, name, e);
@@ -54,4 +77,4 @@
 			return "file:/"+file.getAbsolutePath();
 		return "file://"+file.getAbsolutePath();
-    }
+	}
 }
Index: src/org/openstreetmap/josm/tools/I18n.java
===================================================================
--- src/org/openstreetmap/josm/tools/I18n.java	(revision 158)
+++ src/org/openstreetmap/josm/tools/I18n.java	(revision 159)
@@ -1,13 +1,5 @@
 package org.openstreetmap.josm.tools;
 
-import java.io.File;
-import java.net.URL;
-import java.net.URLClassLoader;
 import java.text.MessageFormat;
-import java.util.Locale;
-import java.util.MissingResourceException;
-
-import org.openstreetmap.josm.Main;
-import org.xnap.commons.i18n.I18nFactory;
 
 /**
@@ -17,29 +9,9 @@
  */
 public class I18n {
-	private static org.xnap.commons.i18n.I18n i18n;
-
-	static {
-		String localeFile = Main.pref.getPreferencesDir()+"lang/"+Locale.getDefault()+".jar";
-		Class<?> klass = Main.class;
-		if (new File(localeFile).exists()) {
-			try {
-				String url = localeFile.replace('\\','/');
-				if (System.getProperty("os.name").startsWith("Windows"))
-					url = "file:/"+url;
-				else
-					url = "file://"+url;
-		        URLClassLoader loader = new URLClassLoader(new URL[]{new URL(url)});
-		        klass = Class.forName("org.openstreetmap.josm.Translation_"+Locale.getDefault(), true, loader);
-	        } catch (Exception e) {
-	        	System.out.println("Couldn't load locale file "+localeFile);
-	        	e.printStackTrace();
-	        }
-		}
-		try {
-			i18n = I18nFactory.getI18n(klass);
-		} catch (MissingResourceException e) {
-			System.out.println("Locale '"+Locale.getDefault()+"' not found. Using default.");
-		}
-	}
+	/**
+	 * Set by MainApplication. Changes here later will probably mess up everything, because
+	 * many strings are already loaded.
+	 */
+	public static org.xnap.commons.i18n.I18n i18n;
 
 	public static String tr(String text, Object... objects) {
Index: src/org/openstreetmap/josm/tools/ImageProvider.java
===================================================================
--- src/org/openstreetmap/josm/tools/ImageProvider.java	(revision 158)
+++ src/org/openstreetmap/josm/tools/ImageProvider.java	(revision 159)
@@ -12,4 +12,6 @@
 import java.net.URL;
 import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 
@@ -37,4 +39,10 @@
 
 	/**
+	 * Add here all ClassLoader whose ressource should be searched.
+	 * Plugin's class loaders are added by main.
+	 */
+	public static final List<Class<?>> sources = new LinkedList<Class<?>>();
+
+	/**
 	 * Return an image from the specified location.
 	 *
@@ -47,5 +55,10 @@
 			subdir += "/";
 		String ext = name.indexOf('.') != -1 ? "" : ".png";
-		URL path = Main.class.getResource("/images/"+subdir+name+ext);
+		URL path = null;
+		for (Class<?> source : sources) {
+			path = source.getResource("/images/"+subdir+name+ext);
+			if (path != null)
+				break;
+		}
 		if (path == null)
 			throw new NullPointerException("/images/"+subdir+name+ext+" not found");
@@ -108,3 +121,7 @@
 		return new ImageIcon(img);
 	}
+
+	static {
+		sources.add(Main.class);
+	}
 }
Index: src/org/openstreetmap/josm/tools/UrlLabel.java
===================================================================
--- src/org/openstreetmap/josm/tools/UrlLabel.java	(revision 158)
+++ src/org/openstreetmap/josm/tools/UrlLabel.java	(revision 159)
@@ -21,4 +21,5 @@
 		setContentType("text/html");
 		setText("<html><a href=\""+url+"\">"+description+"</a></html>");
+		setToolTipText(url);
 		setEditable(false);
 		setOpaque(false);
