Index: src/org/openstreetmap/josm/Main.java
===================================================================
--- src/org/openstreetmap/josm/Main.java	(revision 103)
+++ src/org/openstreetmap/josm/Main.java	(revision 104)
@@ -1,3 +1,4 @@
 package org.openstreetmap.josm;
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.BorderLayout;
@@ -149,5 +150,5 @@
 		final Action aboutAction = new AboutAction();
 
-		final JMenu fileMenu = new JMenu("Files");
+		final JMenu fileMenu = new JMenu(tr("Files"));
 		fileMenu.setMnemonic('F');
 		fileMenu.add(openAction);
@@ -159,16 +160,17 @@
 
 
-		final JMenu connectionMenu = new JMenu("Connection");
+		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("Layer");
+		layerMenu = new JMenu(tr("Layer"));
 		layerMenu.setMnemonic('L');
 		mainMenu.add(layerMenu);
 		layerMenu.setVisible(false);
 		
-		final JMenu editMenu = new JMenu("Edit");
+		final JMenu editMenu = new JMenu(tr("Edit"));
 		editMenu.setMnemonic('E');
 		editMenu.add(undoAction);
@@ -179,5 +181,5 @@
 
 		mainMenu.add(new JSeparator());
-		final JMenu helpMenu = new JMenu("Help");
+		final JMenu helpMenu = new JMenu(tr("Help"));
 		helpMenu.setMnemonic('H');
 		helpMenu.add(aboutAction);
@@ -220,5 +222,5 @@
 	public final OsmDataLayer editLayer() {
 		if (map == null || map.mapView.editLayer == null)
-			addLayer(new OsmDataLayer(ds, "unnamed", false));
+			addLayer(new OsmDataLayer(ds, tr("unnamed"), false));
 		return map.mapView.editLayer;
 	}
@@ -270,5 +272,6 @@
 		} catch (final IOException e1) {
 			e1.printStackTrace();
-			errMsg = "Preferences could not be loaded. Write default preference file to '"+pref.getPreferencesDir()+"preferences'.";
+			errMsg = tr("Preferences could not be loaded. Write default preference file to '{0}'.",
+                    pref.getPreferencesDir() + "preferences");
 			Main.pref.resetToDefault();
 		}
@@ -280,5 +283,5 @@
 		} catch (final Exception e) {
 			e.printStackTrace();
-			JOptionPane.showMessageDialog(null, "The projection could not be read from preferences. Using EPSG:4263.");
+			JOptionPane.showMessageDialog(null, tr("The projection could not be read from preferences. Using EPSG:4263."));
 			Main.proj = new Epsg4326();
 		}
@@ -336,5 +339,5 @@
 			final Bounds b = DownloadAction.osmurl2bounds(s);
 			if (b == null)
-				JOptionPane.showMessageDialog(Main.parent, "Ignoring malformed url: '"+s+"'");
+				JOptionPane.showMessageDialog(Main.parent, tr("Ignoring malformed url: '{0}'", s));
 			else
 				main.downloadAction.download(false, b.min.lat(), b.min.lon(), b.max.lat(), b.max.lon());
@@ -346,5 +349,5 @@
 				main.openAction.openFile(new File(new URI(s)));
 			} catch (URISyntaxException e) {
-				JOptionPane.showMessageDialog(Main.parent, "Ignoring malformed file url: '"+s+"'");
+				JOptionPane.showMessageDialog(Main.parent, tr("Ignoring malformed file url: '{0}", s));
 			}
 			return;
Index: src/org/openstreetmap/josm/actions/AboutAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/AboutAction.java	(revision 103)
+++ src/org/openstreetmap/josm/actions/AboutAction.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.Dimension;
@@ -34,7 +36,7 @@
  */
 public class AboutAction extends JosmAction {
-	
+
 	public AboutAction() {
-		super("About", "about", "Display the about screen.", KeyEvent.VK_A);
+		super(tr("About"), "about",tr("Display the about screen."), KeyEvent.VK_A);
 	}
 	
@@ -54,18 +56,20 @@
 		
 		JPanel info = new JPanel(new GridBagLayout());
-		info.add(new JLabel("Java OpenStreetMap Editor Version "+version), GBC.eop());
-		info.add(new JLabel("last change at "+time), GBC.eop());
-		info.add(new JLabel("Homepage"), GBC.std().insets(0,0,10,0));
+		info.add(new JLabel(tr("Java OpenStreetMap Editor Version {0}",version)), GBC.eop());
+		info.add(new JLabel(tr("last change at {0}",time)), GBC.eop());
+		info.add(new JLabel(tr("Homepage")), GBC.std().insets(0,0,10,0));
 		info.add(new UrlLabel("http://wiki.eigenheimstrasse.de/wiki/JOSM"), GBC.eol());
+		info.add(new JLabel(tr("Bug Reports")), GBC.std().insets(0,0,10,0));
+		info.add(new UrlLabel("http://trac.openstreetmap.org"), GBC.eol());
 		
 		
 		
-		about.addTab("Info", info);
-		about.addTab("Readme", new JScrollPane(readme));
-		about.addTab("Revision", new JScrollPane(revision));
+		about.addTab(tr("Info"), info);
+		about.addTab(tr("Readme"), new JScrollPane(readme));
+		about.addTab(tr("Revision"), new JScrollPane(revision));
 		
 		about.setPreferredSize(new Dimension(500,300));
 		
-		JOptionPane.showMessageDialog(Main.parent, about, "About JOSM...",
+		JOptionPane.showMessageDialog(Main.parent, about, tr("About JOSM..."),
 				JOptionPane.INFORMATION_MESSAGE, ImageProvider.get("logo"));
 	}
@@ -77,5 +81,5 @@
 	 */
 	private JTextArea loadFile(URL resource) {
-		JTextArea area = new JTextArea("File could not be found.");
+		JTextArea area = new JTextArea(tr("File could not be found."));
 		area.setEditable(false);
 		Font font = Font.getFont("monospaced");
Index: src/org/openstreetmap/josm/actions/AutoScaleAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/AutoScaleAction.java	(revision 103)
+++ src/org/openstreetmap/josm/actions/AutoScaleAction.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.event.ActionEvent;
@@ -30,6 +32,6 @@
 		private final AutoScaleMode mode;
 		public Action(AutoScaleMode mode) {
-			super("Auto Scale: "+mode, ImageProvider.get("dialogs/autoscale/"+mode));
-			putValue(SHORT_DESCRIPTION, "Auto zoom the view to "+mode+". Disabled if the view is moved.");
+			super(tr("Auto Scale"+": "+tr(mode.toString())), ImageProvider.get("dialogs/autoscale/"+mode));
+			putValue(SHORT_DESCRIPTION, tr("Auto zoom the view")+tr("(to "+mode+")")+tr(". Disabled if the view is moved."));
 			this.mode = mode;
 		}
Index: src/org/openstreetmap/josm/actions/DiskAccessAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/DiskAccessAction.java	(revision 103)
+++ src/org/openstreetmap/josm/actions/DiskAccessAction.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.io.File;
@@ -54,5 +56,5 @@
 			File file = fc.getSelectedFile();
 			if (file == null || (file.exists() && JOptionPane.YES_OPTION != 
-					JOptionPane.showConfirmDialog(Main.parent, "File exists. Overwrite?", "Overwrite", JOptionPane.YES_NO_OPTION)))
+					JOptionPane.showConfirmDialog(Main.parent, tr("File exists. Overwrite?"), tr("Overwrite"), JOptionPane.YES_NO_OPTION)))
 				return null;
 		}
Index: src/org/openstreetmap/josm/actions/DownloadAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/DownloadAction.java	(revision 103)
+++ src/org/openstreetmap/josm/actions/DownloadAction.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.Dimension;
@@ -42,5 +44,5 @@
 import org.openstreetmap.josm.gui.layer.RawGpsLayer;
 import org.openstreetmap.josm.gui.layer.RawGpsLayer.GpsPoint;
-import org.openstreetmap.josm.io.OsmServerReader;
+import org.openstreetmap.josm.io.BoundingBoxDownloader;
 import org.openstreetmap.josm.tools.GBC;
 import org.xml.sax.SAXException;
@@ -55,5 +57,4 @@
  */
 public class DownloadAction extends JosmAction {
-
 	/**
 	 * Open the download dialog and download the data.
@@ -61,9 +62,9 @@
 	 */
 	private final class DownloadOsmTask extends PleaseWaitRunnable {
-		private final OsmServerReader reader;
+		private final BoundingBoxDownloader reader;
 		private DataSet dataSet;
 
-		private DownloadOsmTask(OsmServerReader reader) {
-			super("Downloading data");
+		private DownloadOsmTask(BoundingBoxDownloader reader) {
+			super(tr("Downloading data"));
 			this.reader = reader;
 			reader.setProgressInformation(currentAction, progress);
@@ -77,7 +78,7 @@
 			if (dataSet == null)
 				return; // user cancelled download or error occoured
-			if (dataSet.nodes.isEmpty())
-				errorMessage = "No data imported.";
-			Main.main.addLayer(new OsmDataLayer(dataSet, "Data Layer", false));
+			if (dataSet.allPrimitives().isEmpty())
+				errorMessage = tr("No data imported.");
+			Main.main.addLayer(new OsmDataLayer(dataSet, tr("Data Layer"), false));
 		}
 
@@ -89,9 +90,9 @@
 
 	private final class DownloadGpsTask extends PleaseWaitRunnable {
-		private final OsmServerReader reader;
+		private final BoundingBoxDownloader reader;
 		private Collection<Collection<GpsPoint>> rawData;
 
-		private DownloadGpsTask(OsmServerReader reader) {
-			super("Downloading GPS data");
+		private DownloadGpsTask(BoundingBoxDownloader reader) {
+			super(tr("Downloading GPS data"));
 			this.reader = reader;
 			reader.setProgressInformation(currentAction, progress);
@@ -123,8 +124,8 @@
 			new JTextField(9),
 			new JTextField(9)};
-	JCheckBox rawGps = new JCheckBox("Open as raw gps data", false);
+	JCheckBox rawGps = new JCheckBox(tr("Open as raw gps data"), false);
 
 	public DownloadAction() {
-		super("Download from OSM", "download", "Download map data from the OSM server.", "Ctrl-Shift-D", 
+		super(tr("Download from OSM"), "download", tr("Download map data from the OSM server."), tr("Ctrl-Shift-D"), 
 				KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK));
 		// TODO remove when bug in Java6 is fixed
@@ -139,15 +140,15 @@
 		WorldChooser wc = new WorldChooser();
 		dlg.add(wc, GBC.eop());
-		wc.setToolTipText("Move and zoom the image like the main map. Select an area to download by dragging.");
+		wc.setToolTipText(tr("Move and zoom the image like the main map. Select an area to download by dragging."));
 
 		// Bounding box edits
-		dlg.add(new JLabel("Bounding box"), GBC.eol());
-		dlg.add(new JLabel("min lat"), GBC.std().insets(10,0,5,0));
+		dlg.add(new JLabel(tr("Bounding box")), GBC.eol());
+		dlg.add(new JLabel(tr("min lat")), GBC.std().insets(10,0,5,0));
 		dlg.add(latlon[0], GBC.std());
-		dlg.add(new JLabel("min lon"), GBC.std().insets(10,0,5,0));
+		dlg.add(new JLabel(tr("min lon")), GBC.std().insets(10,0,5,0));
 		dlg.add(latlon[1], GBC.eol());
-		dlg.add(new JLabel("max lat"), GBC.std().insets(10,0,5,0));
+		dlg.add(new JLabel(tr("max lat")), GBC.std().insets(10,0,5,0));
 		dlg.add(latlon[2], GBC.std());
-		dlg.add(new JLabel("max lon"), GBC.std().insets(10,0,5,0));
+		dlg.add(new JLabel(tr("max lon")), GBC.std().insets(10,0,5,0));
 		dlg.add(latlon[3], GBC.eol());
 		if (Main.map != null) {
@@ -161,5 +162,5 @@
 
 		// OSM url edit
-		dlg.add(new JLabel("URL from www.openstreetmap.org"), GBC.eol());
+		dlg.add(new JLabel(tr("URL from www.openstreetmap.org")), GBC.eol());
 		final JTextField osmUrl = new JTextField();
 		dlg.add(osmUrl, GBC.eop().fill(GBC.HORIZONTAL));
@@ -214,5 +215,5 @@
 
 		// Bookmarks
-		dlg.add(new JLabel("Bookmarks"), GBC.eol());
+		dlg.add(new JLabel(tr("Bookmarks")), GBC.eol());
 		final BookmarkList bookmarks = new BookmarkList();
 		bookmarks.getSelectionModel().addListSelectionListener(new ListSelectionListener(){
@@ -231,13 +232,13 @@
 
 		JPanel buttons = new JPanel(new GridLayout(1,2));
-		JButton add = new JButton("Add");
+		JButton add = new JButton(tr("Add"));
 		add.addActionListener(new ActionListener(){
 			public void actionPerformed(ActionEvent e) {
 				Bookmark b = readBookmark();
 				if (b == null) {
-					JOptionPane.showMessageDialog(Main.parent, "Please enter the desired coordinates first.");
+					JOptionPane.showMessageDialog(Main.parent, tr("Please enter the desired coordinates first."));
 					return;
 				}
-				b.name = JOptionPane.showInputDialog(Main.parent, "Please enter a name for the location.");
+				b.name = JOptionPane.showInputDialog(Main.parent,tr("Please enter a name for the location."));
 				if (b.name != null && !b.name.equals("")) {
 					((DefaultListModel)bookmarks.getModel()).addElement(b);
@@ -247,10 +248,10 @@
 		});
 		buttons.add(add);
-		JButton remove = new JButton("Remove");
+		JButton remove = new JButton(tr("Remove"));
 		remove.addActionListener(new ActionListener(){
 			public void actionPerformed(ActionEvent e) {
 				Object sel = bookmarks.getSelectedValue();
 				if (sel == null) {
-					JOptionPane.showMessageDialog(Main.parent, "Select a bookmark first.");
+					JOptionPane.showMessageDialog(Main.parent,tr("Select a bookmark first."));
 					return;
 				}
@@ -270,5 +271,5 @@
 		do {
 			final JOptionPane pane = new JOptionPane(dlg, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION);
-			final JDialog panedlg = pane.createDialog(Main.parent, "Choose an area");
+			final JDialog panedlg = pane.createDialog(Main.parent, tr("Choose an area"));
 			bookmarks.addMouseListener(new MouseAdapter(){
 				@Override public void mouseClicked(MouseEvent e) {
@@ -285,5 +286,5 @@
 			b = readBookmark();
 			if (b == null)
-				JOptionPane.showMessageDialog(Main.parent, "Please enter the desired coordinates or click on a bookmark.");
+				JOptionPane.showMessageDialog(Main.parent,tr("Please enter the desired coordinates or click on a bookmark."));
 		} while (b == null);
 
@@ -365,5 +366,5 @@
 	 */
 	public void download(boolean rawGps, double minlat, double minlon, double maxlat, double maxlon) {
-		OsmServerReader reader = new OsmServerReader(minlat, minlon, maxlat, maxlon);
+		BoundingBoxDownloader reader = new BoundingBoxDownloader(minlat, minlon, maxlat, maxlon);
 		PleaseWaitRunnable task = rawGps ? new DownloadGpsTask(reader) : new DownloadOsmTask(reader);
 		Main.worker.execute(task);
Index: src/org/openstreetmap/josm/actions/DownloadIncompleteAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/DownloadIncompleteAction.java	(revision 104)
+++ src/org/openstreetmap/josm/actions/DownloadIncompleteAction.java	(revision 104)
@@ -0,0 +1,110 @@
+package org.openstreetmap.josm.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+
+import javax.swing.JOptionPane;
+import javax.swing.KeyStroke;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Segment;
+import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.gui.PleaseWaitRunnable;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.io.ObjectListDownloader;
+import org.xml.sax.SAXException;
+
+/**
+ * Action that opens a connection to the osm server and download map data.
+ * 
+ * An dialog is displayed asking the user to specify a rectangle to grab.
+ * The url and account settings from the preferences are used.
+ *  
+ * @author imi
+ */
+public class DownloadIncompleteAction extends JosmAction {
+
+	/**
+	 * Open the download dialog and download the data.
+	 * Run in the worker thread.
+	 */
+	private final class DownloadTask extends PleaseWaitRunnable {
+		private ObjectListDownloader reader;
+		private DataSet dataSet;
+		private boolean nodesLoaded = false;
+
+		private DownloadTask(Collection<OsmPrimitive> toDownload) {
+			super(tr("Downloading {0} segments", toDownload.size()));
+			reader = new ObjectListDownloader(toDownload);
+			reader.setProgressInformation(currentAction, progress);
+		}
+
+		@Override public void realRun() throws IOException, SAXException {
+			dataSet = reader.parse();
+		}
+
+		@Override protected void finish() {
+			if (dataSet == null)
+				return; // user cancelled download or error occoured
+			if (dataSet.allPrimitives().isEmpty())
+				errorMessage = tr("No data imported.");
+			if (errorMessage == null && nodesLoaded == false)
+				startDownloadNodes();
+			else if (errorMessage == null)
+				Main.main.addLayer(new OsmDataLayer(dataSet, tr("Data Layer"), false));
+		}
+
+		private void startDownloadNodes() {
+			Collection<OsmPrimitive> nodes = new HashSet<OsmPrimitive>();
+			for (Segment s : dataSet.segments) {
+				nodes.add(s.from);
+				nodes.add(s.to);
+			}
+			reader = new ObjectListDownloader(nodes);
+			reader.setProgressInformation(currentAction, progress);
+			nodesLoaded = true;
+			Main.worker.execute(this);
+			pleaseWaitDlg.setVisible(true);
+		}
+
+		@Override protected void cancel() {
+			reader.cancel();
+		}
+	}
+
+	public DownloadIncompleteAction() {
+		super(tr("Download incomplete objects"), "downloadincomplete", tr("Download all (selected) incomplete ways from the OSM server."), tr("Ctrl-Shift-Alt-D"), 
+				KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK | InputEvent.ALT_DOWN_MASK));
+	}
+
+	public void actionPerformed(ActionEvent e) {
+		Collection<Way> ways = new HashSet<Way>();
+		boolean sel = false;
+		for (Way w : Main.ds.ways) {
+			if (w.isIncomplete())
+				ways.add(w);
+			sel = sel || w.selected;
+		}
+		if (sel)
+			for (Iterator<Way> it = ways.iterator(); it.hasNext();)
+				if (!it.next().selected)
+					it.remove();
+		Collection<OsmPrimitive> toDownload = new HashSet<OsmPrimitive>();
+		for (Way w : ways)
+			toDownload.addAll(w.segments);
+		if (JOptionPane.YES_OPTION != JOptionPane.showConfirmDialog(Main.parent, tr("Download {0} ways containing a total of {1} segments?", ways.size(), toDownload.size()), tr("Download?"), JOptionPane.YES_NO_OPTION))
+			return;
+		PleaseWaitRunnable task = new DownloadTask(toDownload);
+		Main.worker.execute(task);
+		task.pleaseWaitDlg.setVisible(true);
+	}
+}
Index: src/org/openstreetmap/josm/actions/ExitAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/ExitAction.java	(revision 103)
+++ src/org/openstreetmap/josm/actions/ExitAction.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.event.ActionEvent;
@@ -10,16 +12,13 @@
  */
 public class ExitAction extends JosmAction {
-
 	/**
 	 * Construct the action with "Exit" as label
 	 */
 	public ExitAction() {
-		super("Exit", "exit", "Exit the application.", KeyEvent.VK_X);
+		super(tr("Exit"), "exit", tr("Exit the application."), KeyEvent.VK_X);
 	}
 	
 	public void actionPerformed(ActionEvent e) {
-		// todo: check for modified windows before exiting
 		System.exit(0);
 	}
-
 }
Index: src/org/openstreetmap/josm/actions/ExtensionFileFilter.java
===================================================================
--- src/org/openstreetmap/josm/actions/ExtensionFileFilter.java	(revision 103)
+++ src/org/openstreetmap/josm/actions/ExtensionFileFilter.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.io.File;
@@ -12,5 +14,4 @@
  */
 public class ExtensionFileFilter extends FileFilter {
-	
 	private final String extension;
 	private final String description;
@@ -22,7 +23,7 @@
 	
 	public static ExtensionFileFilter[] filters = {
-		new ExtensionFileFilter("osm,xml", "osm", "OSM Server Version 0.2 (.osm .xml)"),
-		new ExtensionFileFilter("gpx", "gpx", "GPX Files Version 0.1 (.gpx)"),
-		new ExtensionFileFilter("csv,txt", "csv", "CSV Files Version 0.1 (.csv .txt)"),
+		new ExtensionFileFilter("osm,xml", "osm", tr("OSM Server Files (.osm .xml)")),
+		new ExtensionFileFilter("gpx", "gpx", tr("GPX Files (.gpx)")),
+		new ExtensionFileFilter("csv,txt", "csv", tr("CSV Files (.csv .txt)")),
 	};
 
Index: src/org/openstreetmap/josm/actions/GpxExportAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/GpxExportAction.java	(revision 103)
+++ src/org/openstreetmap/josm/actions/GpxExportAction.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.GridBagLayout;
@@ -36,10 +38,10 @@
 public class GpxExportAction extends DiskAccessAction {
 
-	private final static String warningGpl = "<html><font color='red' size='-2'>Note: GPL is not compatible to the OSM license. Do not upload GPL licensed tracks</html>";
+	private final static String warningGpl = tr("<html><font color='red' size='-2'>Note: GPL is not compatible to the OSM license. Do not upload GPL licensed tracks</html>");
 
 	private final Layer layer;
 
 	public GpxExportAction(Layer layer) {
-		super("Export to GPX", "exportgpx", "Export the data to GPX file.", "Ctrl-E", KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.CTRL_DOWN_MASK));
+		super(tr("Export to GPX"), "exportgpx", tr("Export the data to GPX file."), tr("Ctrl-E"), KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.CTRL_DOWN_MASK));
 		this.layer = layer;
 	}
@@ -47,5 +49,5 @@
 	public void actionPerformed(ActionEvent e) {
 		if (layer == null && Main.map == null) {
-			JOptionPane.showMessageDialog(Main.parent, "Nothing to export. Get some data first.");
+			JOptionPane.showMessageDialog(Main.parent, tr("Nothing to export. Get some data first."));
 			return;
 		}
@@ -71,5 +73,5 @@
 		JPanel p = new JPanel(new GridBagLayout());
 
-		p.add(new JLabel("gps track description"), GBC.eol());
+		p.add(new JLabel(tr("gps track description")), GBC.eol());
 		JTextArea desc = new JTextArea(3,40);
 		desc.setWrapStyleWord(true);
@@ -77,22 +79,22 @@
 		p.add(new JScrollPane(desc), GBC.eop().fill(GBC.BOTH));
 		
-		JCheckBox author = new JCheckBox("Add author information", Main.pref.getBoolean("lastAddAuthor", true));
+		JCheckBox author = new JCheckBox(tr("Add author information"), Main.pref.getBoolean("lastAddAuthor", true));
 		author.setSelected(true);
 		p.add(author, GBC.eol());
-		JLabel nameLabel = new JLabel("Real name");
+		JLabel nameLabel = new JLabel(tr("Real name"));
 		p.add(nameLabel, GBC.std().insets(10,0,5,0));
 		JTextField authorName = new JTextField(Main.pref.get("lastAuthorName"));
 		p.add(authorName, GBC.eol().fill(GBC.HORIZONTAL));
-		JLabel emailLabel = new JLabel("Email");
+		JLabel emailLabel = new JLabel(tr("Email"));
 		p.add(emailLabel, GBC.std().insets(10,0,5,0));
 		JTextField email = new JTextField(Main.pref.get("osm-server.username"));
 		p.add(email, GBC.eol().fill(GBC.HORIZONTAL));
-		JLabel copyrightLabel = new JLabel("Copyright (URL)");
+		JLabel copyrightLabel = new JLabel(tr("Copyright (URL)"));
 		p.add(copyrightLabel, GBC.std().insets(10,0,5,0));
 		JTextField copyright = new JTextField();
 		p.add(copyright, GBC.std().fill(GBC.HORIZONTAL));
-		JButton predefined = new JButton("Predefined");
+		JButton predefined = new JButton(tr("Predefined"));
 		p.add(predefined, GBC.eol().insets(5,0,0,0));
-		JLabel copyrightYearLabel = new JLabel("Copyright year");
+		JLabel copyrightYearLabel = new JLabel(tr("Copyright year"));
 		p.add(copyrightYearLabel, GBC.std().insets(10,0,5,5));
 		JTextField copyrightYear = new JTextField("");
@@ -102,9 +104,9 @@
 		addDependencies(author, authorName, email, copyright, predefined, copyrightYear, nameLabel, emailLabel, copyrightLabel, copyrightYearLabel, warning);
 		
-		p.add(new JLabel("Keywords"), GBC.eol());
+		p.add(new JLabel(tr("Keywords")), GBC.eol());
 		JTextField keywords = new JTextField();
 		p.add(keywords, GBC.eop().fill(GBC.HORIZONTAL));
 
-		int answer = JOptionPane.showConfirmDialog(Main.parent, p, "Export options", JOptionPane.OK_CANCEL_OPTION);
+		int answer = JOptionPane.showConfirmDialog(Main.parent, p, tr("Export options"), JOptionPane.OK_CANCEL_OPTION);
 		if (answer != JOptionPane.OK_OPTION)
 			return;
@@ -127,5 +129,5 @@
 		} catch (IOException x) {
 			x.printStackTrace();
-			JOptionPane.showMessageDialog(Main.parent, "Error while exporting "+fn+":\n"+x.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
+			JOptionPane.showMessageDialog(Main.parent, tr("Error while exporting {0}", fn)+":\n"+x.getMessage(), tr("Error"), JOptionPane.ERROR_MESSAGE);
 		}		
 	}
@@ -178,8 +180,8 @@
 		predefined.addActionListener(new ActionListener(){
 			public void actionPerformed(ActionEvent e) {
-				JList l = new JList(new String[]{"Creative Commons By-SA", "public domain", "GNU Lesser Public License (LGPL)", "BSD License (same as MIT/X11)"});
+				JList l = new JList(new String[]{"Creative Commons By-SA", "public domain", "GNU Lesser Public License (LGPL)", "BSD License (MIT/X11)"});
 				l.setVisibleRowCount(4);
 				l.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
-				int answer = JOptionPane.showConfirmDialog(Main.parent, new JScrollPane(l), "Choose a predefined license", JOptionPane.OK_CANCEL_OPTION);
+				int answer = JOptionPane.showConfirmDialog(Main.parent, new JScrollPane(l),tr("Choose a predefined license"), JOptionPane.OK_CANCEL_OPTION);
 				if (answer != JOptionPane.OK_OPTION || l.getSelectedIndex() == -1)
 					return;
Index: src/org/openstreetmap/josm/actions/OpenAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/OpenAction.java	(revision 103)
+++ src/org/openstreetmap/josm/actions/OpenAction.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.event.ActionEvent;
@@ -32,10 +34,10 @@
  */
 public class OpenAction extends DiskAccessAction {
-
+	
 	/**
 	 * Create an open action. The name is "Open a file".
 	 */
 	public OpenAction() {
-		super("Open", "open", "Open a file.", "Ctrl-O", KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_DOWN_MASK));
+		super(tr("Open"), "open", tr("Open a file."), tr("Ctrl-O"), KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_DOWN_MASK));
 	}
 
@@ -70,18 +72,18 @@
 					dataSet = OsmReader.parseDataSet(new FileInputStream(filename), null, null);
 				} else if (ExtensionFileFilter.filters[ExtensionFileFilter.CSV].acceptName(fn)) {
-					JOptionPane.showMessageDialog(Main.parent, fn+": CSV Data import for non-GPS data is not implemented yet.");
+					JOptionPane.showMessageDialog(Main.parent, fn+": "+tr("CSV Data import for non-GPS data is not implemented yet."));
 					return;
 				} else {
-					JOptionPane.showMessageDialog(Main.parent, fn+": Unknown file extension: "+fn.substring(filename.getName().lastIndexOf('.')+1));
+					JOptionPane.showMessageDialog(Main.parent, fn+": "+tr("Unknown file extension: {0}", fn.substring(filename.getName().lastIndexOf('.')+1)));
 					return;
 				}
-				Main.main.addLayer(new OsmDataLayer(dataSet, "Data Layer", true));
+				Main.main.addLayer(new OsmDataLayer(dataSet, tr("Data Layer"), true));
 			}
 		} catch (SAXException x) {
 			x.printStackTrace();
-			JOptionPane.showMessageDialog(Main.parent, "Error while parsing "+fn+": "+x.getMessage());
+			JOptionPane.showMessageDialog(Main.parent, tr("Error while parsing {0}",fn)+": "+x.getMessage());
 		} catch (IOException x) {
 			x.printStackTrace();
-			JOptionPane.showMessageDialog(Main.parent, "Could not read '"+fn+"'\n"+x.getMessage());
+			JOptionPane.showMessageDialog(Main.parent, tr("Could not read '{0}'",fn)+"\n"+x.getMessage());
 		}
 	}
Index: src/org/openstreetmap/josm/actions/PreferencesAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/PreferencesAction.java	(revision 103)
+++ src/org/openstreetmap/josm/actions/PreferencesAction.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.event.ActionEvent;
@@ -19,5 +21,5 @@
 	 */
 	public PreferencesAction() {
-		super("Preferences", "preference", "Open a preferences page for global settings.", "F12", KeyStroke.getKeyStroke(KeyEvent.VK_F12, 0));
+		super(tr("Preferences"), "preference", tr("Open a preferences page for global settings."), tr("F12"), KeyStroke.getKeyStroke(KeyEvent.VK_F12, 0));
 	}
 
Index: src/org/openstreetmap/josm/actions/RedoAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/RedoAction.java	(revision 103)
+++ src/org/openstreetmap/josm/actions/RedoAction.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.event.ActionEvent;
@@ -21,5 +23,5 @@
 	 */
 	public RedoAction() {
-		super("Redo", "redo", "Redo the last undone action.", "Ctrl-Shift-Z", KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK));
+		super(tr("Redo"), "redo", tr("Redo the last undone action."), tr("Ctrl-Shift-Z"), KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK));
 		setEnabled(false);
 	}
Index: src/org/openstreetmap/josm/actions/SaveAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/SaveAction.java	(revision 103)
+++ src/org/openstreetmap/josm/actions/SaveAction.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.event.ActionEvent;
@@ -22,5 +24,5 @@
  */
 public class SaveAction extends DiskAccessAction {
-
+    
 	/**
 	 * Construct the action with "Save" as label.
@@ -29,17 +31,17 @@
 	 */
 	public SaveAction() {
-		super("Save", "save", "Save the current data.", "Ctrl-S", KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK));
+		super(tr("Save"), "save", tr("Save the current data."), tr("Ctrl-S"), KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK));
 	}
 	
 	public void actionPerformed(ActionEvent event) {
 		if (Main.map == null) {
-			JOptionPane.showMessageDialog(Main.parent, "No document open so nothing to save.");
+			JOptionPane.showMessageDialog(Main.parent, tr("No document open so nothing to save."));
 			return;
 		}
-		if (isDataSetEmpty() && JOptionPane.NO_OPTION == JOptionPane.showConfirmDialog(Main.parent, "The document contains no data. Save anyway?", "Empty document", JOptionPane.YES_NO_OPTION))
+		if (isDataSetEmpty() && JOptionPane.NO_OPTION == JOptionPane.showConfirmDialog(Main.parent,tr("The document contains no data. Save anyway?"), tr("Empty document"), JOptionPane.YES_NO_OPTION))
 			return;
 		if (!Main.map.conflictDialog.conflicts.isEmpty()) {
 			int answer = JOptionPane.showConfirmDialog(Main.parent, 
-					"There are unresolved conflicts. Conflicts will not be saved and handled as if you rejected all. Continue?", "Conflicts", JOptionPane.YES_NO_OPTION);
+					tr("There are unresolved conflicts. Conflicts will not be saved and handled as if you rejected all. Continue?"),tr("Conflicts"), JOptionPane.YES_NO_OPTION);
 			if (answer != JOptionPane.YES_OPTION)
 				return;
@@ -70,13 +72,13 @@
 				Main.main.editLayer().cleanData(null, false);
 			} else if (ExtensionFileFilter.filters[ExtensionFileFilter.CSV].acceptName(fn)) {
-				JOptionPane.showMessageDialog(Main.parent, "CSV output not supported yet.");
+				JOptionPane.showMessageDialog(Main.parent, tr("CSV output not supported yet."));
 				return;
 			} else {
-				JOptionPane.showMessageDialog(Main.parent, "Unknown file extension.");
+				JOptionPane.showMessageDialog(Main.parent, tr("Unknown file extension."));
 				return;
 			}
 		} catch (IOException e) {
 			e.printStackTrace();
-			JOptionPane.showMessageDialog(Main.parent, "An error occoured while saving.\n"+e.getMessage());
+			JOptionPane.showMessageDialog(Main.parent, tr("An error occoured while saving.")+"\n"+e.getMessage());
 		}
 	}
Index: src/org/openstreetmap/josm/actions/UndoAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/UndoAction.java	(revision 103)
+++ src/org/openstreetmap/josm/actions/UndoAction.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.event.ActionEvent;
@@ -21,5 +23,5 @@
 	 */
 	public UndoAction() {
-		super("Undo", "undo", "Undo the last action.", "Ctrl-Z", KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_DOWN_MASK));
+		super(tr("Undo"), "undo", tr("Undo the last action."), tr("Ctrl-Z"), KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_DOWN_MASK));
 		setEnabled(false);
 	}
Index: src/org/openstreetmap/josm/actions/UploadAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/UploadAction.java	(revision 103)
+++ src/org/openstreetmap/josm/actions/UploadAction.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.GridBagLayout;
@@ -32,7 +34,6 @@
  */
 public class UploadAction extends JosmAction {
-
 	public UploadAction() {
-		super("Upload to OSM", "upload", "Upload all changes to the OSM server.", "Ctrl-Shift-U", 
+		super(tr("Upload to OSM"), "upload", tr("Upload all changes to the OSM server."), tr("Ctrl-Shift-U"), 
 				KeyStroke.getKeyStroke(KeyEvent.VK_U, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK));
 	}
@@ -40,10 +41,10 @@
 	public void actionPerformed(ActionEvent e) {
 		if (Main.map == null) {
-			JOptionPane.showMessageDialog(Main.parent, "Nothing to upload. Get some data first.");
+			JOptionPane.showMessageDialog(Main.parent,tr("Nothing to upload. Get some data first."));
 			return;
 		}
 		
 		if (!Main.map.conflictDialog.conflicts.isEmpty()) {
-			JOptionPane.showMessageDialog(Main.parent, "There are unresolved conflicts. You have to resolve these first.");
+			JOptionPane.showMessageDialog(Main.parent,tr("There are unresolved conflicts. You have to resolve these first."));
 			Main.map.conflictDialog.action.button.setSelected(true);
 			Main.map.conflictDialog.action.actionPerformed(null);
@@ -72,5 +73,5 @@
 		all.addAll(delete);
 
-		PleaseWaitRunnable uploadTask = new PleaseWaitRunnable("Uploading data"){
+		PleaseWaitRunnable uploadTask = new PleaseWaitRunnable(tr("Uploading data")){
 			@Override protected void realRun() throws SAXException {
 				server.setProgressInformation(currentAction, progress);
@@ -96,5 +97,5 @@
 	private boolean displayUploadScreen(Collection<OsmPrimitive> add, Collection<OsmPrimitive> update, Collection<OsmPrimitive> delete) {
 		if (add.isEmpty() && update.isEmpty() && delete.isEmpty()) {
-			JOptionPane.showMessageDialog(Main.parent, "No changes to upload.");
+			JOptionPane.showMessageDialog(Main.parent,tr("No changes to upload."));
 			return false;
 		}
@@ -105,5 +106,5 @@
 
 		if (!add.isEmpty()) {
-			p.add(new JLabel("Objects to add:"), GBC.eol());
+			p.add(new JLabel(tr("Objects to add:")), GBC.eol());
 			JList l = new JList(add.toArray());
 			l.setCellRenderer(renderer);
@@ -113,5 +114,5 @@
 
 		if (!update.isEmpty()) {
-			p.add(new JLabel("Objects to modify:"), GBC.eol());
+			p.add(new JLabel(tr("Objects to modify:")), GBC.eol());
 			JList l = new JList(update.toArray());
 			l.setCellRenderer(renderer);
@@ -121,5 +122,5 @@
 
 		if (!delete.isEmpty()) {
-			p.add(new JLabel("Objects to delete:"), GBC.eol());
+			p.add(new JLabel(tr("Objects to delete:")), GBC.eol());
 			JList l = new JList(delete.toArray());
 			l.setCellRenderer(renderer);
@@ -128,5 +129,5 @@
 		}
 
-		return JOptionPane.showConfirmDialog(Main.parent, p, "Upload this changes?", 
+		return JOptionPane.showConfirmDialog(Main.parent, p, tr("Upload this changes?"), 
 				JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION;
 	}
Index: src/org/openstreetmap/josm/actions/WmsServerAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/WmsServerAction.java	(revision 103)
+++ src/org/openstreetmap/josm/actions/WmsServerAction.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.event.ActionEvent;
@@ -11,9 +13,9 @@
 
     public WmsServerAction() {
-        super("Show background", "wmsserver", "Download and show landsat background images.", KeyEvent.VK_B);
+        super(tr("Show background"), "wmsserver", tr("Download and show landsat background images."), KeyEvent.VK_B);
     }
 
     public void actionPerformed(ActionEvent e) {
-    	JOptionPane.showMessageDialog(Main.parent, "Not implemented yet.");
+    	JOptionPane.showMessageDialog(Main.parent, tr("Not implemented yet."));
     }
 }
Index: src/org/openstreetmap/josm/actions/mapmode/AddNodeAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/AddNodeAction.java	(revision 103)
+++ src/org/openstreetmap/josm/actions/mapmode/AddNodeAction.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.actions.mapmode;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.Cursor;
@@ -42,6 +44,6 @@
 		public AddNodeGroup(MapFrame mf) {
 			super(KeyEvent.VK_N,0);
-			actions.add(new AddNodeAction(mf, "Add node", Mode.node, "Add a new node to the map"));
-			actions.add(new AddNodeAction(mf, "Add node into segment", Mode.nodesegment, "Add a node into an existing segment"));
+			actions.add(new AddNodeAction(mf,tr("Add node"), Mode.node, tr("Add a new node to the map")));
+			actions.add(new AddNodeAction(mf, tr("Add node into segment"), Mode.nodesegment,tr( "Add a node into an existing segment")));
 			setCurrent(0);
 		}
@@ -79,5 +81,5 @@
 		Node n = new Node(Main.map.mapView.getLatLon(e.getX(), e.getY()));
 		if (n.coor.isOutSideWorld()) {
-			JOptionPane.showMessageDialog(Main.parent, "Can not add a node outside of the world.");
+			JOptionPane.showMessageDialog(Main.parent,tr("Can not add a node outside of the world."));
 			return;
 		}
@@ -128,5 +130,5 @@
 			}
 
-			c = new SequenceCommand("Add Node into Segment", cmds);
+			c = new SequenceCommand(tr("Add Node into Segment"), cmds);
 		}
 		Main.main.editLayer().add(c);
Index: src/org/openstreetmap/josm/actions/mapmode/AddSegmentAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/AddSegmentAction.java	(revision 103)
+++ src/org/openstreetmap/josm/actions/mapmode/AddSegmentAction.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.actions.mapmode;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.Color;
@@ -11,7 +13,7 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.command.AddCommand;
-import org.openstreetmap.josm.data.osm.Segment;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Segment;
 import org.openstreetmap.josm.gui.MapFrame;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -47,7 +49,7 @@
 	 */
 	public AddSegmentAction(MapFrame mapFrame) {
-		super("Add segment", 
+		super(tr("Add segment"), 
 				"addsegment", 
-				"Add a segment between two nodes.", 
+				tr("Add a segment between two nodes."), 
 				"G", 
 				KeyEvent.VK_G, 
Index: src/org/openstreetmap/josm/actions/mapmode/AddWayAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/AddWayAction.java	(revision 103)
+++ src/org/openstreetmap/josm/actions/mapmode/AddWayAction.java	(revision 104)
@@ -1,3 +1,6 @@
 package org.openstreetmap.josm.actions.mapmode;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+import static org.openstreetmap.josm.tools.I18n.trn;
 
 import java.awt.event.KeyEvent;
@@ -48,5 +51,4 @@
  */
 public class AddWayAction extends MapMode implements SelectionChangedListener {
-
 	private Way way;
 
@@ -57,5 +59,5 @@
 	 */
 	public AddWayAction(MapFrame mapFrame) {
-		super("Add Way", "addway", "Add a new way to the data.", "W", KeyEvent.VK_W, mapFrame, ImageProvider.getCursor("normal", "way"));
+		super(tr("Add Way"), "addway", tr("Add a new way to the data."), "W", KeyEvent.VK_W, mapFrame, ImageProvider.getCursor("normal", "way"));
 		
 		Main.ds.addSelectionChangedListener(this);
@@ -91,5 +93,5 @@
 				for (Segment seg : way.segments) {
 					if (seg.incomplete) {
-						JOptionPane.showMessageDialog(Main.parent, "Warning: This way is incomplete. Try to download it, before adding segments.");
+						JOptionPane.showMessageDialog(Main.parent,tr("Warning: This way is incomplete. Try to download it, before adding segments."));
 						return;
 					}
@@ -139,5 +141,5 @@
 			for (Segment seg : way.segments) {
 				if (seg.incomplete) {
-					JOptionPane.showMessageDialog(Main.parent, "Warning: This way is incomplete. Try to download it, before adding segments.");
+					JOptionPane.showMessageDialog(Main.parent, tr("Warning: This way is incomplete. Try to download it, before adding segments."));
 					break;
 				}
@@ -158,7 +160,5 @@
 		boolean reordered = false;
 		if (numberOfSelectedWays > 0) {
-			String ways = "way" + (numberOfSelectedWays==1?" has":"s have");
-			int answer = JOptionPane.showConfirmDialog(Main.parent, numberOfSelectedWays+" "+ways+" been selected.\n" +
-					"Do you wish to select all segments belonging to the "+ways+" instead?", "Add segments from ways", JOptionPane.YES_NO_OPTION);
+			int answer = JOptionPane.showConfirmDialog(Main.parent,trn("{0} way has been selected.\nDo you wish to select all segments belonging to the way instead?","{0} ways have been selected.\nDo you wish to select all segments belonging to the ways instead?",numberOfSelectedWays,numberOfSelectedWays),tr("Add segments from ways"), JOptionPane.YES_NO_OPTION);
 			if (answer == JOptionPane.YES_OPTION) {
 				for (OsmPrimitive osm : selection)
@@ -166,10 +166,10 @@
 						segmentSet.addAll(((Way)osm).segments);
 			} else if (numberOfSelectedWays == 1) {
-				answer = JOptionPane.showConfirmDialog(Main.parent, "Do you want to add all other selected segments to the one selected way?", "Add segments to way?", JOptionPane.YES_NO_OPTION);
+				answer = JOptionPane.showConfirmDialog(Main.parent,tr("Do you want to add all other selected segments to the one selected way?"),tr("Add segments to way?"), JOptionPane.YES_NO_OPTION);
 				if (answer == JOptionPane.YES_OPTION) {
 					for (OsmPrimitive osm : selection) {
 						if (osm instanceof Way) {
 							wayToAdd = (Way)osm;
-							answer = JOptionPane.showConfirmDialog(Main.parent, "Reorder all line segments?", "Reorder?", JOptionPane.YES_NO_CANCEL_OPTION);
+							answer = JOptionPane.showConfirmDialog(Main.parent,tr("Reorder all line segments?"), tr("Reorder?"), JOptionPane.YES_NO_CANCEL_OPTION);
 							if (answer == JOptionPane.CANCEL_OPTION)
 								return wayToAdd;
@@ -230,5 +230,5 @@
 		}
 
-		if (JOptionPane.YES_OPTION != JOptionPane.showConfirmDialog(Main.parent, "Create a new way out of "+sortedSegments.size()+" segments?", "Create new way", JOptionPane.YES_NO_OPTION))
+		if (JOptionPane.YES_OPTION != JOptionPane.showConfirmDialog(Main.parent,trn("Create a new way out of {0} segment?","Create a new way out of {0} segments?",sortedSegments.size(),sortedSegments.size()), tr("Create new way"), JOptionPane.YES_NO_OPTION))
 			return null;
 
Index: src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java	(revision 103)
+++ src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.actions.mapmode;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.event.ActionEvent;
@@ -51,7 +53,7 @@
 	 */
 	public DeleteAction(MapFrame mapFrame) {
-		super("Delete", 
+		super(tr("Delete"), 
 				"delete", 
-				"Delete nodes, streets or segments.", 
+				tr("Delete nodes, streets or segments."), 
 				"D", 
 				KeyEvent.VK_D, 
@@ -146,9 +148,9 @@
 					String reason = deleteNodeAndJoinSegment((Node)osm);
 					if (reason != null && msgBox) {
-						JOptionPane.showMessageDialog(Main.parent, "Cannot delete node. "+reason);
+						JOptionPane.showMessageDialog(Main.parent,tr("Cannot delete node.")+" "+reason);
 						return;
 					}
 				} else if (msgBox) {
-					JOptionPane.showMessageDialog(Main.parent, "This object is in use.");
+					JOptionPane.showMessageDialog(Main.parent, tr("This object is in use."));
 					return;
 				}
@@ -167,10 +169,10 @@
 			if (!s.deleted && (s.from == n || s.to == n)) {
 				if (segs.size() > 1)
-					return "Used by more than two segments.";
+					return tr("Used by more than two segments.");
 				segs.add(s);
 			}
 		}
 		if (segs.size() != 2)
-			return "Used by only one segment.";
+			return tr("Used by only one segment.");
 		Segment seg1 = segs.get(0);
 		Segment seg2 = segs.get(1);
@@ -182,10 +184,10 @@
 		for (Way w : Main.ds.ways)
 			if (!w.deleted && (w.segments.contains(seg1) || w.segments.contains(seg2)))
-				return "Used in a way.";
+				return tr("Used in a way.");
 		if (seg1.from == seg2.from || seg1.to == seg2.to)
-			return "Wrong direction of segments.";
+			return tr("Wrong direction of segments.");
 		for (Entry<String, String> e : seg1.entrySet())
 			if (seg2.keySet().contains(e.getKey()) && !seg2.get(e.getKey()).equals(e.getValue()))
-				return "Conflicting keys";
+				return tr("Conflicting keys");
 		Segment s = new Segment(seg1);
 		s.to = seg2.to;
@@ -197,5 +199,5 @@
 			new ChangeCommand(seg1, s), 
 			new DeleteCommand(Arrays.asList(new OsmPrimitive[]{n, seg2}))};
-		Main.main.editLayer().add(new SequenceCommand("Delete Node", Arrays.asList(cmds)));
+		Main.main.editLayer().add(new SequenceCommand(tr("Delete Node"), Arrays.asList(cmds)));
 		return null;
     }
Index: src/org/openstreetmap/josm/actions/mapmode/MapMode.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/MapMode.java	(revision 103)
+++ src/org/openstreetmap/josm/actions/mapmode/MapMode.java	(revision 104)
@@ -23,5 +23,4 @@
  */
 abstract public class MapMode extends JosmAction implements MouseListener, MouseMotionListener {
-
 //	private final Cursor cursor;
 //	private Cursor oldCursor;
Index: src/org/openstreetmap/josm/actions/mapmode/MoveAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/MoveAction.java	(revision 103)
+++ src/org/openstreetmap/josm/actions/mapmode/MoveAction.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.actions.mapmode;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.Cursor;
@@ -18,5 +20,4 @@
 import org.openstreetmap.josm.gui.MapFrame;
 import org.openstreetmap.josm.tools.ImageProvider;
-
 /**
  * Move is an action that can move all kind of OsmPrimitives (except Keys for now).
@@ -29,5 +30,4 @@
  */
 public class MoveAction extends MapMode {
-
 	/**
 	 * The old cursor before the user pressed the mouse button.
@@ -49,7 +49,7 @@
 	 */
 	public MoveAction(MapFrame mapFrame) {
-		super("Move", 
+		super(tr("Move"), 
 				"move", 
-				"Move selected objects around.", 
+				tr("Move selected objects around."), 
 				"M", 
 				KeyEvent.VK_M, 
@@ -97,5 +97,5 @@
 		for (OsmPrimitive osm : affectedNodes) {
 			if (osm instanceof Node && ((Node)osm).coor.isOutSideWorld()) {
-				JOptionPane.showMessageDialog(Main.parent, "Cannot move objects outside of the world.");
+				JOptionPane.showMessageDialog(Main.parent,tr("Cannot move objects outside of the world."));
 				return;
 			}
Index: src/org/openstreetmap/josm/actions/mapmode/SelectionAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/SelectionAction.java	(revision 103)
+++ src/org/openstreetmap/josm/actions/mapmode/SelectionAction.java	(revision 104)
@@ -1,11 +1,20 @@
 package org.openstreetmap.josm.actions.mapmode;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.Rectangle;
 import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
 import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.LinkedList;
+import java.util.Map;
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.GroupAction;
+import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Segment;
 import org.openstreetmap.josm.gui.MapFrame;
 import org.openstreetmap.josm.gui.SelectionManager;
@@ -55,8 +64,28 @@
 public class SelectionAction extends MapMode implements SelectionEnded {
 
+	enum Mode {select, straight}
+	private final Mode mode;
+
+	public static class Group extends GroupAction {
+		public Group(MapFrame mf) {
+			super(KeyEvent.VK_S,0);
+			actions.add(new SelectionAction(mf, tr("Selection"), Mode.select, tr("Select objects by dragging or clicking.")));
+			actions.add(new SelectionAction(mf, tr("Straight line"), Mode.straight, tr("Select objects in a straight line.")));
+			setCurrent(0);
+		}
+	}
+
+
 	/**
 	 * The SelectionManager that manages the selection rectangle.
 	 */
 	private SelectionManager selectionManager;
+
+	private Node straightStart = null;
+	private Node lastEnd = null;
+	private Collection<OsmPrimitive> oldSelection = null;
+
+	//TODO: Implement reverse references into data objects and remove this
+	private final Map<Node, Collection<Segment>> reverseSegmentMap = new HashMap<Node, Collection<Segment>>();
 
 	/**
@@ -64,12 +93,7 @@
 	 * @param mapFrame The frame this action belongs to
 	 */
-	public SelectionAction(MapFrame mapFrame) {
-		super("Selection", 
-				"selection", 
-				"Select objects by dragging or clicking.", 
-				"S", 
-				KeyEvent.VK_S, 
-				mapFrame,
-				ImageProvider.getCursor("normal", "selection"));
+	public SelectionAction(MapFrame mapFrame, String name, Mode mode, String desc) {
+		super(name, "selection/"+mode, desc, "S", KeyEvent.VK_S, mapFrame, ImageProvider.getCursor("normal", "selection"));
+		this.mode = mode;
 		this.selectionManager = new SelectionManager(this, false, mapFrame.mapView);
 	}
@@ -77,10 +101,34 @@
 	@Override public void enterMode() {
 		super.enterMode();
-		selectionManager.register(Main.map.mapView);
+		if (mode == Mode.select)
+			selectionManager.register(Main.map.mapView);
+		else {
+			Main.map.mapView.addMouseMotionListener(this);
+			Main.map.mapView.addMouseListener(this);
+			for (Segment s : Main.ds.segments) {
+				addBackReference(s.from, s);
+				addBackReference(s.to, s);
+			}
+		}
+	}
+
+	private void addBackReference(Node n, Segment s) {
+		Collection<Segment> c = reverseSegmentMap.get(n);
+		if (c == null) {
+			c = new HashSet<Segment>();
+			reverseSegmentMap.put(n, c);
+		}
+		c.add(s);
 	}
 
 	@Override public void exitMode() {
 		super.exitMode();
-		selectionManager.unregister(Main.map.mapView);
+		if (mode == Mode.select)
+			selectionManager.unregister(Main.map.mapView);
+		else {
+			Main.map.mapView.removeMouseMotionListener(this);
+			Main.map.mapView.removeMouseListener(this);
+			reverseSegmentMap.clear();
+		}
 	}
 
@@ -108,3 +156,74 @@
 		Main.map.mapView.repaint();
 	}
+
+	@Override public void mouseDragged(MouseEvent e) {
+		Node old = lastEnd;
+		lastEnd = Main.map.mapView.getNearestNode(e.getPoint());
+		if (straightStart == null)
+			straightStart = lastEnd;
+		if (straightStart != null && lastEnd != null && straightStart != lastEnd && old != lastEnd) {
+			Collection<OsmPrimitive> path = new HashSet<OsmPrimitive>();
+			Collection<OsmPrimitive> sel = new HashSet<OsmPrimitive>();
+			path.add(straightStart);
+			calculateShortestPath(path, straightStart, lastEnd);
+			if ((e.getModifiers() & MouseEvent.CTRL_MASK) != 0) {
+				sel.addAll(oldSelection);
+				sel.removeAll(path);
+			} else if ((e.getModifiers() & MouseEvent.SHIFT_MASK) != 0) {
+				sel = path;
+				sel.addAll(oldSelection);
+			} else
+				sel = path;
+			Main.ds.setSelected(sel);
+		}
+	}
+
+	@Override public void mousePressed(MouseEvent e) {
+		straightStart = Main.map.mapView.getNearestNode(e.getPoint());
+		lastEnd = null;
+		oldSelection = Main.ds.getSelected();
+	}
+
+	@Override public void mouseReleased(MouseEvent e) {
+		straightStart = null;
+		lastEnd = null;
+		oldSelection = null;
+	}
+
+	/**
+	 * Get the shortest path by stepping through the node with a common segment with start 
+	 * and nearest to the end (greedy algorithm).
+	 */
+	private void calculateShortestPath(Collection<OsmPrimitive> path, Node start, Node end) {
+		for (Node pivot = start; pivot != null;)
+			pivot = addNearest(path, pivot, end);
+	}
+
+	private Node addNearest(Collection<OsmPrimitive> path, Node start, Node end) {
+		Collection<Segment> c = reverseSegmentMap.get(start);
+		double min = Double.MAX_VALUE;
+		Node next = null;
+		Segment seg = null;
+		for (Segment s : c) {
+			Node other = s.from == start ? s.to : s.from;
+			if (other == end) {
+				next = other;
+				seg = s;
+				min = 0;
+				break;
+			}
+			double distance = other.eastNorth.distance(end.eastNorth);
+			if (distance < min) {
+				min = distance;
+				next = other;
+				seg = s;
+			}
+		}
+		if (min < start.eastNorth.distance(end.eastNorth) && next != null) {
+			path.add(next);
+			path.add(seg);
+			return next;
+		}
+		return null;
+	}
 }
Index: src/org/openstreetmap/josm/actions/mapmode/ZoomAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/ZoomAction.java	(revision 103)
+++ src/org/openstreetmap/josm/actions/mapmode/ZoomAction.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.actions.mapmode;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.Rectangle;
@@ -42,5 +44,5 @@
 	 */
 	public ZoomAction(MapFrame mapFrame) {
-		super("Zoom", "zoom", "Zoom in by dragging. (Ctrl+up,left,down,right,+,-)", "Z", KeyEvent.VK_Z, mapFrame, ImageProvider.getCursor("normal", "zoom"));
+		super(tr("Zoom"), "zoom", tr("Zoom in by dragging. (Ctrl+up,left,down,right,+,-)"), "Z", KeyEvent.VK_Z, mapFrame, ImageProvider.getCursor("normal", "zoom"));
 		mv = mapFrame.mapView;
 		selectionManager = new SelectionManager(this, true, mv);
Index: src/org/openstreetmap/josm/command/AddCommand.java
===================================================================
--- src/org/openstreetmap/josm/command/AddCommand.java	(revision 103)
+++ src/org/openstreetmap/josm/command/AddCommand.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.command;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.util.Collection;
@@ -48,5 +50,5 @@
 		NameVisitor v = new NameVisitor();
 		osm.visit(v);
-		return new DefaultMutableTreeNode(new JLabel("Add "+v.className+" "+v.name, v.icon, JLabel.HORIZONTAL));
+		return new DefaultMutableTreeNode(new JLabel(tr("Add")+" "+v.className+" "+v.name, v.icon, JLabel.HORIZONTAL));
     }
 }
Index: src/org/openstreetmap/josm/command/ChangeCommand.java
===================================================================
--- src/org/openstreetmap/josm/command/ChangeCommand.java	(revision 103)
+++ src/org/openstreetmap/josm/command/ChangeCommand.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.command;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.util.Collection;
@@ -33,5 +35,5 @@
 		NameVisitor v = new NameVisitor();
 		osm.visit(v);
-		return new DefaultMutableTreeNode(new JLabel("Change "+v.className+" "+v.name, v.icon, JLabel.HORIZONTAL));
+		return new DefaultMutableTreeNode(new JLabel(tr("Change")+" "+v.className+" "+v.name, v.icon, JLabel.HORIZONTAL));
     }
 }
Index: src/org/openstreetmap/josm/command/ChangePropertyCommand.java
===================================================================
--- src/org/openstreetmap/josm/command/ChangePropertyCommand.java	(revision 103)
+++ src/org/openstreetmap/josm/command/ChangePropertyCommand.java	(revision 104)
@@ -1,3 +1,6 @@
 package org.openstreetmap.josm.command;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+import static org.openstreetmap.josm.tools.I18n.trn;
 
 import java.util.Collection;
@@ -20,5 +23,4 @@
  */
 public class ChangePropertyCommand extends Command {
-
 	/**
 	 * All primitives, that are affected with this command.
@@ -62,6 +64,5 @@
 
 	@Override public MutableTreeNode description() {
-		String text = value == null ? "Remove '"+key+"'" : "Set '"+key+"="+value+"'";
-		text += " for ";
+		String text = value == null ? tr( "Remove '{0}' for",key) : tr("Set {0}={1} for",key,value);
 		if (objects.size() == 1) {
 			NameVisitor v = new NameVisitor();
@@ -69,5 +70,5 @@
 			text += v.className+" "+v.name;
 		} else
-			text += objects.size()+" objects";
+			text += trn("{0} object","{0} objects",objects.size(),objects.size());
 		DefaultMutableTreeNode root = new DefaultMutableTreeNode(new JLabel(text, ImageProvider.get("data", "key"), JLabel.HORIZONTAL));
 		if (objects.size() == 1)
Index: src/org/openstreetmap/josm/command/ConflictResolveCommand.java
===================================================================
--- src/org/openstreetmap/josm/command/ConflictResolveCommand.java	(revision 103)
+++ src/org/openstreetmap/josm/command/ConflictResolveCommand.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.command;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.util.Collection;
@@ -73,5 +75,5 @@
 			if (c.resolution != null)
 				i++;
-		return new DefaultMutableTreeNode(new JLabel("Resolve "+i+" conflicts in "+resolved.size()+" objects", ImageProvider.get("data", "primitive"), JLabel.HORIZONTAL));
+		return new DefaultMutableTreeNode(new JLabel(tr("Resolve {0} conflicts in {1} objects",i,resolved.size()), ImageProvider.get("data", "primitive"), JLabel.HORIZONTAL));
     }
 }
Index: src/org/openstreetmap/josm/command/DeleteCommand.java
===================================================================
--- src/org/openstreetmap/josm/command/DeleteCommand.java	(revision 103)
+++ src/org/openstreetmap/josm/command/DeleteCommand.java	(revision 104)
@@ -1,3 +1,6 @@
 package org.openstreetmap.josm.command;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+import static org.openstreetmap.josm.tools.I18n.trn;
 
 import java.util.Collection;
@@ -41,5 +44,5 @@
 		if (data.size() == 1) {
 			data.iterator().next().visit(v);
-			return new DefaultMutableTreeNode(new JLabel("Delete "+v.className+" "+v.name, v.icon, JLabel.HORIZONTAL));
+			return new DefaultMutableTreeNode(new JLabel(tr("Delete"+" "+v.className+" "+v.name), v.icon, JLabel.HORIZONTAL));
 		}
 
@@ -52,5 +55,6 @@
 				cname = "primitive";
 		}
-		DefaultMutableTreeNode root = new DefaultMutableTreeNode(new JLabel("Delete "+data.size()+" "+cname+(data.size()==1?"":"s"), ImageProvider.get("data", cname), JLabel.HORIZONTAL));
+		DefaultMutableTreeNode root = new DefaultMutableTreeNode(new JLabel(
+				tr("Delete")+" "+data.size()+" "+trn(cname, cname+"s", data.size()), ImageProvider.get("data", cname), JLabel.HORIZONTAL));
 		for (OsmPrimitive osm : data) {
 			osm.visit(v);
Index: src/org/openstreetmap/josm/command/MoveCommand.java
===================================================================
--- src/org/openstreetmap/josm/command/MoveCommand.java	(revision 103)
+++ src/org/openstreetmap/josm/command/MoveCommand.java	(revision 104)
@@ -1,3 +1,6 @@
 package org.openstreetmap.josm.command;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+import static org.openstreetmap.josm.tools.I18n.trn;
 
 import java.util.Collection;
@@ -25,5 +28,4 @@
  */
 public class MoveCommand extends Command {
-
 	/**
 	 * The objects that should be moved.
@@ -113,5 +115,5 @@
 
 	@Override public MutableTreeNode description() {
-		return new DefaultMutableTreeNode(new JLabel("Move "+objects.size()+" Node"+(objects.size()==1?"":"s"), ImageProvider.get("data", "node"), JLabel.HORIZONTAL));
+		return new DefaultMutableTreeNode(new JLabel(tr("Move")+" "+objects.size()+" "+trn("node","nodes",objects.size()), ImageProvider.get("data", "node"), JLabel.HORIZONTAL));
     }
 }
Index: src/org/openstreetmap/josm/command/SequenceCommand.java
===================================================================
--- src/org/openstreetmap/josm/command/SequenceCommand.java	(revision 103)
+++ src/org/openstreetmap/josm/command/SequenceCommand.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.command;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.util.Collection;
@@ -47,5 +49,5 @@
 
 	@Override public MutableTreeNode description() {
-		DefaultMutableTreeNode root = new DefaultMutableTreeNode("Sequence: "+name);
+		DefaultMutableTreeNode root = new DefaultMutableTreeNode(tr("Sequence")+": "+name);
 		for (Command c : sequence)
 			root.add(c.description());
Index: src/org/openstreetmap/josm/data/conflict/ConflictItem.java
===================================================================
--- src/org/openstreetmap/josm/data/conflict/ConflictItem.java	(revision 103)
+++ src/org/openstreetmap/josm/data/conflict/ConflictItem.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.data.conflict;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.util.Collection;
@@ -29,5 +31,5 @@
 				value = v;
 			else if (!value.equals(v)) {
-				value = "<html><i>&lt;different&gt;</i></html>";
+				value = "<html><i>&lt;"+tr("different")+"&gt;</i></html>";
 				break;
 			}
Index: src/org/openstreetmap/josm/data/conflict/DeleteConflict.java
===================================================================
--- src/org/openstreetmap/josm/data/conflict/DeleteConflict.java	(revision 103)
+++ src/org/openstreetmap/josm/data/conflict/DeleteConflict.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.data.conflict;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
@@ -10,9 +12,9 @@
 
 	@Override public String key() {
-		return "deleted|deleted";
+		return "deleted|"+tr("deleted");
 	}
 
 	@Override protected String str(OsmPrimitive osm) {
-		return osm.deleted ? "true" : "false";
+		return osm.deleted ? tr("true") : tr("false");
 	}
 
Index: src/org/openstreetmap/josm/data/conflict/FromConflict.java
===================================================================
--- src/org/openstreetmap/josm/data/conflict/FromConflict.java	(revision 103)
+++ src/org/openstreetmap/josm/data/conflict/FromConflict.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.data.conflict;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
@@ -15,5 +17,5 @@
 	
 	@Override public String key() {
-		return "segment|from";
+		return "segment|"+tr("from");
 	}
 	
Index: src/org/openstreetmap/josm/data/conflict/PositionConflict.java
===================================================================
--- src/org/openstreetmap/josm/data/conflict/PositionConflict.java	(revision 103)
+++ src/org/openstreetmap/josm/data/conflict/PositionConflict.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.data.conflict;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import org.openstreetmap.josm.data.osm.Node;
@@ -15,5 +17,5 @@
 	
 	@Override public String key() {
-		return "node|position";
+		return "node|"+tr("position");
 	}
 	
Index: src/org/openstreetmap/josm/data/conflict/SegmentConflict.java
===================================================================
--- src/org/openstreetmap/josm/data/conflict/SegmentConflict.java	(revision 103)
+++ src/org/openstreetmap/josm/data/conflict/SegmentConflict.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.data.conflict;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
@@ -17,9 +19,9 @@
 		for (Segment ls : ((Way)osm).segments)
 			s += ls.id + ",";
-		return s.equals("") ? "<html><i>&lt;none&gt;</i></html>" : s.substring(0, s.length()-1);
+		return s.equals("") ? "<html><i>&lt;"+tr("none")+"&gt;</i></html>" : s.substring(0, s.length()-1);
 	}
 	
 	@Override public String key() {
-		return "way|segments";
+		return "way|"+tr("segments");
 	}
 	
Index: src/org/openstreetmap/josm/data/conflict/ToConflict.java
===================================================================
--- src/org/openstreetmap/josm/data/conflict/ToConflict.java	(revision 103)
+++ src/org/openstreetmap/josm/data/conflict/ToConflict.java	(revision 104)
@@ -1,6 +1,5 @@
-/**
- * 
- */
 package org.openstreetmap.josm.data.conflict;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
@@ -18,5 +17,5 @@
 
 	@Override public String key() {
-		return "segment|to";
+		return "segment|"+tr("to");
 	}
 	
Index: src/org/openstreetmap/josm/data/osm/Way.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/Way.java	(revision 103)
+++ src/org/openstreetmap/josm/data/osm/Way.java	(revision 104)
@@ -50,3 +50,10 @@
 	    return o instanceof Way ? Long.valueOf(id).compareTo(o.id) : -1;
     }
+	
+	public boolean isIncomplete() {
+		for (Segment s : segments)
+			if (s.incomplete)
+				return true;
+		return false;
+	}
 }
Index: src/org/openstreetmap/josm/data/osm/visitor/NameVisitor.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/visitor/NameVisitor.java	(revision 103)
+++ src/org/openstreetmap/josm/data/osm/visitor/NameVisitor.java	(revision 104)
@@ -1,4 +1,7 @@
 
 package org.openstreetmap.josm.data.osm.visitor;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+import static org.openstreetmap.josm.tools.I18n.trn;
 
 import java.util.HashSet;
@@ -8,6 +11,6 @@
 import javax.swing.JLabel;
 
+import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.Segment;
-import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -43,5 +46,5 @@
 		if (name == null) {
 			if (ls.incomplete)
-				name = ls.id == 0 ? "new" : ""+ls.id+" (unknown)";
+				name = ls.id == 0 ? tr("new") : tr("{0} (unknown)", ls.id);
 			else
 				name = (ls.id==0?"":ls.id+" ")+"("+ls.from.coor.lat()+","+ls.from.coor.lon()+") -> ("+ls.to.coor.lat()+","+ls.to.coor.lon()+")";
@@ -80,7 +83,7 @@
 					incomplete = true;
 			}
-			name = nodes.size()+" nodes";
+			name = trn("{0} node", "{0} nodes", nodes.size(), nodes.size());
 			if (incomplete)
-				name += " (incomplete)";
+				name += " ("+tr("incomplete")+")";
 		}
 		icon = ImageProvider.get("data", "way");
Index: src/org/openstreetmap/josm/gui/BookmarkList.java
===================================================================
--- src/org/openstreetmap/josm/gui/BookmarkList.java	(revision 103)
+++ src/org/openstreetmap/josm/gui/BookmarkList.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.gui;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.Component;
@@ -86,5 +88,5 @@
 			in.close();
 		} catch (IOException e) {
-			JOptionPane.showMessageDialog(Main.parent, "Could not read bookmarks.\n"+e.getMessage());
+			JOptionPane.showMessageDialog(Main.parent, tr("Could not read bookmarks.")+"\n"+e.getMessage());
 		}
 	}
@@ -110,5 +112,5 @@
 			out.close();
 		} catch (IOException e) {
-			JOptionPane.showMessageDialog(Main.parent, "Could not write bookmark.\n"+e.getMessage());
+			JOptionPane.showMessageDialog(Main.parent,tr("Could not write bookmark.")+"\n"+e.getMessage());
 		}
 	}
Index: src/org/openstreetmap/josm/gui/ConflictResolver.java
===================================================================
--- src/org/openstreetmap/josm/gui/ConflictResolver.java	(revision 103)
+++ src/org/openstreetmap/josm/gui/ConflictResolver.java	(revision 104)
@@ -1,3 +1,6 @@
 package org.openstreetmap.josm.gui;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+import static org.openstreetmap.josm.tools.I18n.trn;
 
 import java.awt.Component;
@@ -76,5 +79,5 @@
 		}
 
-		public String getColumnName(int columnIndex) {return columnIndex == 0 ? "Key" : "Value";}
+		public String getColumnName(int columnIndex) {return columnIndex == 0 ? tr("Key") : tr("Value");}
 		public int getColumnCount() {return 2;}
 		public boolean isCellEditable(int row, int column) {return false;}
@@ -158,5 +161,5 @@
 		
 		if (this.conflicts.isEmpty())
-			throw new RuntimeException("No conflicts but in conflict list:\n" + Arrays.toString(conflicts.entrySet().toArray()));
+			throw new RuntimeException(tr("No conflicts but in conflict list:\n{0}" , Arrays.toString(conflicts.entrySet().toArray())));
 
 		// have to initialize the JTables here and not in the declaration, because its constructor
@@ -227,8 +230,8 @@
 		resolveTable.addMouseListener(new DblClickListener(null));
 
-		add(new JLabel(conflicts.size()+" object"+(conflicts.size()==1?" has":"s have")+" conflicts:"), GBC.eol().insets(0,0,0,10));
+		add(new JLabel(trn("{0} object has conflicts:","{0} objects have conflicts:",conflicts.size(),conflicts.size())), GBC.eol().insets(0,0,0,10));
 
 		JPanel p = new JPanel(new GridBagLayout());
-		p.add(new JLabel("my version:"), GBC.eol());
+		p.add(new JLabel(tr("my version:")), GBC.eol());
 		p.add(new JScrollPane(myTable), GBC.eol().fill(GBC.BOTH));
 		p.add(new JButton(new ResolveAction("down", Resolution.MY)), GBC.eol().anchor(GBC.CENTER).insets(0,5,0,0));
@@ -236,5 +239,5 @@
 
 		p = new JPanel(new GridBagLayout());
-		p.add(new JLabel("their version:"), GBC.eol());
+		p.add(new JLabel(tr("their version:")), GBC.eol());
 		p.add(new JScrollPane(theirTable), GBC.eol().fill(GBC.BOTH));
 		p.add(new JButton(new ResolveAction("down", Resolution.THEIR)), GBC.eol().anchor(GBC.CENTER).insets(0,5,0,0));
@@ -242,5 +245,5 @@
 
 		add(new JButton(new ResolveAction("up", null)), GBC.eol().anchor(GBC.CENTER));
-		add(new JLabel("resolved version:"), GBC.eol().insets(0,5,0,0));
+		add(new JLabel(tr("resolved version:")), GBC.eol().insets(0,5,0,0));
 		add(new JScrollPane(resolveTable), GBC.eol().anchor(GBC.CENTER).fill(GBC.BOTH));
 	}
Index: src/org/openstreetmap/josm/gui/MainApplet.java
===================================================================
--- src/org/openstreetmap/josm/gui/MainApplet.java	(revision 103)
+++ src/org/openstreetmap/josm/gui/MainApplet.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.gui;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.GridBagLayout;
@@ -30,11 +32,11 @@
 
 	private final static String[][] paramInfo = {
-		{"username", "string", "Name of the user."},
-		{"password", "string", "OSM Password."},
-		{"geometry", "string", "Size the applet to the given geometry (format: WIDTHxHEIGHT)"},
-		{"download", "string;string;...", "Download each. Can be x1,y1,x2,y2 an url containing lat=y&lon=x&zoom=z or a filename"},
-		{"downloadgps", "string;string;...", "Download each as raw gps. Can be x1,y1,x2,y2 an url containing lat=y&lon=x&zoom=z or a filename"},
-		{"selection", "string;string;...", "Add each to the initial selection. Can be a google-like search string or an url which returns osm-xml"},
-		{"reset-preferences", "any", "If specified, reset the configuration instead of reading it."}
+		{"username", tr("string"), tr("Name of the user.")},
+		{"password", tr("string"), tr("OSM Password.")},
+		{"geometry", tr("string"), tr("Size the applet to the given geometry (format: WIDTHxHEIGHT)")},
+		{"download", tr("string;string;..."), tr("Download each. Can be x1,y1,x2,y2 an url containing lat=y&lon=x&zoom=z or a filename")},
+		{"downloadgps", tr("string;string;..."), tr("Download each as raw gps. Can be x1,y1,x2,y2 an url containing lat=y&lon=x&zoom=z or a filename")},
+		{"selection", tr("string;string;..."), tr("Add each to the initial selection. Can be a google-like search string or an url which returns osm-xml")},
+		{"reset-preferences", tr("any"),tr("If specified, reset the configuration instead of reading it.")}
 	};
 	
@@ -61,8 +63,8 @@
 		if (username == null || password == null) {
 			JPanel p = new JPanel(new GridBagLayout());
-			p.add(new JLabel("Username"), GBC.std().insets(0,0,20,0));
+			p.add(new JLabel(tr("Username")), GBC.std().insets(0,0,20,0));
 			JTextField user = new JTextField(username == null ? "" : username);
 			p.add(user, GBC.eol().fill(GBC.HORIZONTAL));
-			p.add(new JLabel("Password"), GBC.std().insets(0,0,20,0));
+			p.add(new JLabel(tr("Password")), GBC.std().insets(0,0,20,0));
 			JPasswordField pass = new JPasswordField(password == null ? "" : password);
 			p.add(pass, GBC.eol().fill(GBC.HORIZONTAL));
Index: src/org/openstreetmap/josm/gui/MainApplication.java
===================================================================
--- src/org/openstreetmap/josm/gui/MainApplication.java	(revision 103)
+++ src/org/openstreetmap/josm/gui/MainApplication.java	(revision 104)
@@ -1,4 +1,6 @@
 //Licence: GPL
 package org.openstreetmap.josm.gui;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.Toolkit;
@@ -20,5 +22,4 @@
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.BugReportExceptionHandler;
-
 /**
  * Main window class application.
@@ -27,5 +28,4 @@
  */
 public class MainApplication extends Main {
-
 	/**
 	 * Construct an main frame, ready sized and operating. Does not 
@@ -49,8 +49,8 @@
 					}
 					if (modified) {
-						final String msg = uploadedModified ? "\nHint: Some changes came from uploading new data to the server." : "";
+						final String msg = uploadedModified ? tr("\nHint: Some changes came from uploading new data to the server.") : "";
 						final int answer = JOptionPane.showConfirmDialog(
-								Main.parent, "There are unsaved changes. Really quit?"+msg,
-								"Unsaved Changes", JOptionPane.YES_NO_OPTION);
+								Main.parent, tr("There are unsaved changes. Really quit?")+msg,
+								tr("Unsaved Changes"), JOptionPane.YES_NO_OPTION);
 						if (answer != JOptionPane.YES_OPTION)
 							return;
@@ -72,30 +72,26 @@
 		List<String> argList = Arrays.asList(argArray);
 		if (argList.contains("--help") || argList.contains("-?") || argList.contains("-h")) {
-			System.out.println("Java OpenStreetMap Editor");
-			System.out.println();
-			System.out.println("usage:");
-			System.out.println("\tjava -jar josm.jar <option> <option> <option>...");
-			System.out.println();
-			System.out.println("options:");
-			System.out.println("\t--help|-?|-h                              Show this help");
-			System.out.println("\t--geometry=widthxheight(+|-)x(+|-)y       Standard unix geometry argument");
-			System.out.println("\t[--download=]minlat,minlon,maxlat,maxlon  Download the bounding box");
-			System.out.println("\t[--download=]<url>                        Download the location at the url (with lat=x&lon=y&zoom=z)");
-			System.out.println("\t[--download=]<filename>                   Open file (as raw gps, if .gpx or .csv)");
-			System.out.println("\t--downloadgps=minlat,minlon,maxlat,maxlon Download the bounding box as raw gps");
-			System.out.println("\t--selection=<searchstring>                Select with the given search");
-			System.out.println("\t--no-fullscreen                           Don't launch in fullscreen mode");
-			System.out.println("\t--reset-preferences                       Reset the preferences to default");
-			System.out.println();
-			System.out.println("examples:");
-			System.out.println("\tjava -jar josm.jar track1.gpx track2.gpx london.osm");
-			System.out.println("\tjava -jar josm.jar http://www.openstreetmap.org/index.html?lat=43.2&lon=11.1&zoom=13");
-			System.out.println("\tjava -jar josm.jar london.osm --selection=http://www.ostertag.name/osm/OSM_errors_node-duplicate.xml");
-			System.out.println("\tjava -jar josm.jar 43.2,11.1,43.4,11.4");
-			System.out.println();
-			System.out.println("Parameters are read in the order they are specified, so make sure you load");
-			System.out.println("some data before --selection");
-			System.out.println();
-			System.out.println("Instead of --download=<bbox> you may specify osm://<bbox>");
+			System.out.println(tr("Java OpenStreetMap Editor\n\n"+
+						   "usage:\n"+
+						   "\tjava -jar josm.jar <option> <option> <option>...\n\n"+
+						   "options:\n"+
+						   "\t--help|-?|-h                              Show this help\n"+
+						   "\t--geometry=widthxheight(+|-)x(+|-)y       Standard unix geometry argument\n"+
+						   "\t[--download=]minlat,minlon,maxlat,maxlon  Download the bounding box\n"+
+						   "\t[--download=]<url>                        Download the location at the url (with lat=x&lon=y&zoom=z)\n"+
+						   "\t[--download=]<filename>                   Open file (as raw gps, if .gpx or .csv)\n"+
+						   "\t--downloadgps=minlat,minlon,maxlat,maxlon Download the bounding box as raw gps\n"+
+						   "\t--selection=<searchstring>                Select with the given search\n"+
+						   "\t--no-fullscreen                           Don't launch in fullscreen mode\n"+
+						   "\t--reset-preferences                       Reset the preferences to default\n\n"+
+						   "examples:\n"+
+						   "\tjava -jar josm.jar track1.gpx track2.gpx london.osm\n"+
+						   "\tjava -jar josm.jar http://www.openstreetmap.org/index.html?lat=43.2&lon=11.1&zoom=13\n"+
+						   "\tjava -jar josm.jar london.osm --selection=http://www.ostertag.name/osm/OSM_errors_node-duplicate.xml\n"+
+						   "\tjava -jar josm.jar 43.2,11.1,43.4,11.4\n\n"+
+
+						   "Parameters are read in the order they are specified, so make sure you load\n"+
+						   "some data before --selection\n\n"+
+						   "Instead of --download=<bbox> you may specify osm://<bbox>\n"));
 			System.exit(0);
 		}
@@ -103,5 +99,5 @@
 		final File prefDir = new File(Main.pref.getPreferencesDir());
 		if (prefDir.exists() && !prefDir.isDirectory()) {
-			JOptionPane.showMessageDialog(null, "Cannot open preferences directory: "+Main.pref.getPreferencesDir());
+			JOptionPane.showMessageDialog(null, tr("Cannot open preferences directory: {0}",Main.pref.getPreferencesDir()));
 			return;
 		}
@@ -125,5 +121,5 @@
 
 		preConstructorInit(args);
-		JFrame mainFrame = new JFrame("Java Open Street Map - Editor");
+		JFrame mainFrame = new JFrame(tr("Java Open Street Map - Editor"));
 		Main.parent = mainFrame;
 		Main main = new MainApplication(mainFrame);
Index: src/org/openstreetmap/josm/gui/MapFrame.java
===================================================================
--- src/org/openstreetmap/josm/gui/MapFrame.java	(revision 103)
+++ src/org/openstreetmap/josm/gui/MapFrame.java	(revision 104)
@@ -78,5 +78,5 @@
 		toolBarActions.setFloatable(false);
 		toolBarActions.add(new IconToggleButton(new ZoomAction(this)));
-		final SelectionAction selectionAction = new SelectionAction(this);
+		final Action selectionAction = new SelectionAction.Group(this);
 		toolBarActions.add(new IconToggleButton(selectionAction));
 		toolBarActions.add(new IconToggleButton(new MoveAction(this)));
Index: src/org/openstreetmap/josm/gui/MapStatus.java
===================================================================
--- src/org/openstreetmap/josm/gui/MapStatus.java	(revision 103)
+++ src/org/openstreetmap/josm/gui/MapStatus.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.gui;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.AWTEvent;
@@ -203,4 +205,6 @@
 			}
 			public void mouseMoved(MouseEvent e) {
+				if (mv.center == null)
+					return;
 				// Do not update the view, if ctrl is pressed.
 				if ((e.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) == 0) {
@@ -215,7 +219,7 @@
 		setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
 		setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
-		add(new JLabel("Lat/Lon "));
+		add(new JLabel(tr("Lat/Lon ")));
 		add(positionText);
-		add(new JLabel(" Object "));
+		add(new JLabel(tr(" Object ")));
 		add(nameText);
 
Index: src/org/openstreetmap/josm/gui/MapView.java
===================================================================
--- src/org/openstreetmap/josm/gui/MapView.java	(revision 103)
+++ src/org/openstreetmap/josm/gui/MapView.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.gui;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.Color;
@@ -155,5 +157,5 @@
 			dataLayer.listenerModified.add(new ModifiedChangedListener(){
 				public void modifiedChanged(boolean value, OsmDataLayer source) {
-					JOptionPane.getFrameForComponent(Main.parent).setTitle((value?"*":"")+"Java Open Street Map - Editor");
+					JOptionPane.getFrameForComponent(Main.parent).setTitle(tr("{0}Java Open Street Map - Editor",(value?"*":"")));
 				}
 			});
@@ -193,5 +195,5 @@
 		int curLayerPos = layers.indexOf(layer);
 		if (curLayerPos == -1)
-			throw new IllegalArgumentException("layer not in list.");
+			throw new IllegalArgumentException(tr("layer not in list."));
 		if (pos == curLayerPos)
 			return; // already in place.
@@ -322,5 +324,5 @@
 	public void setActiveLayer(Layer layer) {
 		if (!layers.contains(layer))
-			throw new IllegalArgumentException("layer must be in layerlist");
+			throw new IllegalArgumentException(tr("layer must be in layerlist"));
 		Layer old = activeLayer;
 		activeLayer = layer;
Index: src/org/openstreetmap/josm/gui/NavigatableComponent.java
===================================================================
--- src/org/openstreetmap/josm/gui/NavigatableComponent.java	(revision 103)
+++ src/org/openstreetmap/josm/gui/NavigatableComponent.java	(revision 104)
@@ -23,4 +23,5 @@
  */
 public class NavigatableComponent extends JComponent {
+
 
 	public static final EastNorth world = Main.proj.latlon2eastNorth(new LatLon(Projection.MAX_LAT, Projection.MAX_LON));
Index: src/org/openstreetmap/josm/gui/PleaseWaitRunnable.java
===================================================================
--- src/org/openstreetmap/josm/gui/PleaseWaitRunnable.java	(revision 103)
+++ src/org/openstreetmap/josm/gui/PleaseWaitRunnable.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.gui;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.EventQueue;
@@ -30,4 +32,5 @@
  */
 public abstract class PleaseWaitRunnable implements Runnable {
+
 	public final JDialog pleaseWaitDlg;
 	public String errorMessage;
@@ -36,5 +39,5 @@
 	private boolean closeDialogCalled = false;
 
-	protected final JLabel currentAction = new JLabel("Contact OSM server...");
+	protected final JLabel currentAction = new JLabel(tr("Contact OSM server..."));
 	protected final BoundedRangeModel progress = progressBar.getModel();
 
@@ -49,5 +52,5 @@
 		pane.add(currentAction, GBC.eol().fill(GBC.HORIZONTAL));
 		pane.add(progressBar, GBC.eop().fill(GBC.HORIZONTAL));
-		JButton cancel = new JButton("Cancel");
+		JButton cancel = new JButton(tr(tr("Cancel")));
 		pane.add(cancel, GBC.eol().anchor(GBC.CENTER));
 		pleaseWaitDlg.setContentPane(pane);
@@ -75,8 +78,8 @@
 		} catch (SAXException x) {
 			x.printStackTrace();
-			errorMessage = "Error while parsing: "+x.getMessage();
+			errorMessage = tr("Error while parsing: ")+x.getMessage();
 		} catch (FileNotFoundException x) {
 			x.printStackTrace();
-			errorMessage = "Not found: " + x.getMessage();
+			errorMessage = tr("Not found: ") + x.getMessage();
 		} catch (IOException x) {
 			x.printStackTrace();
Index: src/org/openstreetmap/josm/gui/PreferenceDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/PreferenceDialog.java	(revision 103)
+++ src/org/openstreetmap/josm/gui/PreferenceDialog.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.gui;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.Color;
@@ -81,9 +83,9 @@
 				String name = (String)colors.getValueAt(i, 0);
 				Color col = (Color)colors.getValueAt(i, 1);
-				Main.pref.put("color."+name, ColorHelper.color2html(col));
+				Main.pref.put("color."+tr(name), ColorHelper.color2html(col));
 			}
 
 			if (requiresRestart)
-				JOptionPane.showMessageDialog(PreferenceDialog.this, "You have to restart JOSM for some settings to take effect.");
+				JOptionPane.showMessageDialog(PreferenceDialog.this,tr("You have to restart JOSM for some settings to take effect."));
 			Main.parent.repaint();
 			setVisible(false);
@@ -150,10 +152,10 @@
 	 * The checkbox stating whether nodes should be merged together.
 	 */
-	private JCheckBox drawRawGpsLines = new JCheckBox("Draw lines between raw gps points.");
+	private JCheckBox drawRawGpsLines = new JCheckBox(tr("Draw lines between raw gps points."));
 	/**
 	 * The checkbox stating whether raw gps lines should be forced.
 	 */
-	private JCheckBox forceRawGpsLines = new JCheckBox("Force lines if no segments imported.");
-	private JCheckBox directionHint = new JCheckBox("Draw Direction Arrows");
+	private JCheckBox forceRawGpsLines = new JCheckBox(tr("Force lines if no segments imported."));
+	private JCheckBox directionHint = new JCheckBox(tr("Draw Direction Arrows"));
 	private JTable colors;
 
@@ -166,5 +168,5 @@
 	 */
 	public PreferenceDialog() {
-		super(JOptionPane.getFrameForComponent(Main.parent), "Preferences");
+		super(JOptionPane.getFrameForComponent(Main.parent), tr("Preferences"));
 
 		// look and feel combo box
@@ -215,8 +217,8 @@
 		csvImportString.setText(Main.pref.get("csv.importstring"));
 		drawRawGpsLines.setSelected(Main.pref.getBoolean("draw.rawgps.lines"));
-		forceRawGpsLines.setToolTipText("Force drawing of lines if the imported data contain no line information.");
+		forceRawGpsLines.setToolTipText(tr("Force drawing of lines if the imported data contain no line information."));
 		forceRawGpsLines.setSelected(Main.pref.getBoolean("draw.rawgps.lines.force"));
 		forceRawGpsLines.setEnabled(drawRawGpsLines.isSelected());
-		directionHint.setToolTipText("Draw direction hints for all segments.");
+		directionHint.setToolTipText(tr("Draw direction hints for all segments."));
 		directionHint.setSelected(Main.pref.getBoolean("draw.segment.direction"));
 
@@ -255,14 +257,14 @@
 		colors.getColumnModel().getColumn(1).setWidth(100);
 
-		JButton colorEdit = new JButton("Choose");
+		JButton colorEdit = new JButton(tr("Choose"));
 		colorEdit.addActionListener(new ActionListener(){
 			public void actionPerformed(ActionEvent e) {
 				if (colors.getSelectedRowCount() == 0) {
-					JOptionPane.showMessageDialog(PreferenceDialog.this, "Please select a color.");
+					JOptionPane.showMessageDialog(PreferenceDialog.this, tr("Please select a color."));
 					return;
 				}
 				int sel = colors.getSelectedRow();
 				JColorChooser chooser = new JColorChooser((Color)colors.getValueAt(sel, 1));
-				int answer = JOptionPane.showConfirmDialog(PreferenceDialog.this, chooser, "Choose a color for "+colors.getValueAt(sel, 0), JOptionPane.OK_CANCEL_OPTION);
+				int answer = JOptionPane.showConfirmDialog(PreferenceDialog.this, chooser, tr("Choose a color for {0}", colors.getValueAt(sel, 0)), JOptionPane.OK_CANCEL_OPTION);
 				if (answer == JOptionPane.OK_OPTION)
 					colors.setValueAt(chooser.getColor(), sel, 1);
@@ -271,9 +273,9 @@
 
 		// setting tooltips
-		osmDataServer.setToolTipText("The base URL to the OSM server (REST API)");
-		osmDataUsername.setToolTipText("Login name (email) to the OSM account.");
-		osmDataPassword.setToolTipText("Login password to the OSM account. Leave blank to not store any password.");
-		wmsServerBaseUrl.setToolTipText("The base URL to the server retrieving WMS background pictures from.");
-		csvImportString.setToolTipText("<html>Import string specification. lat/lon and time are imported.<br>" +
+		osmDataServer.setToolTipText(tr("The base URL to the OSM server (REST API)"));
+		osmDataUsername.setToolTipText(tr("Login name (email) to the OSM account."));
+		osmDataPassword.setToolTipText(tr("Login password to the OSM account. Leave blank to not store any password."));
+		wmsServerBaseUrl.setToolTipText(tr("The base URL to the server retrieving WMS background pictures from."));
+		csvImportString.setToolTipText(tr("<html>Import string specification. lat/lon and time are imported.<br>" +
 				"<b>lat</b>: The latitude coordinate<br>" +
 				"<b>lon</b>: The longitude coordinate<br>" +
@@ -281,13 +283,13 @@
 				"<b>ignore</b>: Skip this field<br>" +
 				"An example: \"ignore ignore lat lon\" will use ' ' as delimiter, skip the first two values and read then lat/lon.<br>" +
-		"Other example: \"lat,lon\" will just read lat/lon values comma seperated.</html>");
-		drawRawGpsLines.setToolTipText("If your gps device draw to few lines, select this to draw lines along your way.");
-		colors.setToolTipText("Colors used by different objects in JOSM.");
+		"Other example: \"lat,lon\" will just read lat/lon values comma seperated.</html>"));
+		drawRawGpsLines.setToolTipText(tr("If your gps device draw to few lines, select this to draw lines along your way."));
+		colors.setToolTipText(tr("Colors used by different objects in JOSM."));
 
 		// creating the gui
 
 		// Display tab
-		JPanel display = createPreferenceTab("display", "Display Settings", "Various settings that influence the visual representation of the whole program.");
-		display.add(new JLabel("Look and Feel"), GBC.std());
+		JPanel display = createPreferenceTab("display", tr("Display Settings"), tr("Various settings that influence the visual representation of the whole program."));
+		display.add(new JLabel(tr("Look and Feel")), GBC.std());
 		display.add(GBC.glue(5,0), GBC.std().fill(GBC.HORIZONTAL));
 		display.add(lafCombo, GBC.eol().fill(GBC.HORIZONTAL));
@@ -295,5 +297,5 @@
 		display.add(forceRawGpsLines, GBC.eop().insets(40,0,0,0));
 		display.add(directionHint, GBC.eop().insets(20,0,0,0));
-		display.add(new JLabel("Colors"), GBC.eol());
+		display.add(new JLabel(tr("Colors")), GBC.eol());
 		colors.setPreferredScrollableViewportSize(new Dimension(100,112));
 		display.add(new JScrollPane(colors), GBC.eol().fill(GBC.BOTH));
@@ -302,15 +304,15 @@
 
 		// Connection tab
-		JPanel con = createPreferenceTab("connection", "Connection Settings", "Connection Settings to the OSM server.");
-		con.add(new JLabel("Base Server URL"), GBC.std());
+		JPanel con = createPreferenceTab("connection", tr("Connection Settings"), tr("Connection Settings to the OSM server."));
+		con.add(new JLabel(tr("Base Server URL")), GBC.std());
 		con.add(osmDataServer, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5));
-		con.add(new JLabel("OSM username (email)"), GBC.std());
+		con.add(new JLabel(tr("OSM username (email)")), GBC.std());
 		con.add(osmDataUsername, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5));
-		con.add(new JLabel("OSM password"), GBC.std());
+		con.add(new JLabel(tr("OSM password")), GBC.std());
 		con.add(osmDataPassword, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,0));
-		JLabel warning = new JLabel("<html>" +
+		JLabel warning = new JLabel(tr("<html>" +
 				"WARNING: The password is stored in plain text in the preferences file.<br>" +
 				"The password is transfered in plain text to the server, encoded in the url.<br>" +
-		"<b>Do not use a valuable Password.</b></html>");
+		"<b>Do not use a valuable Password.</b></html>"));
 		warning.setFont(warning.getFont().deriveFont(Font.ITALIC));
 		con.add(warning, GBC.eop().fill(GBC.HORIZONTAL));
@@ -318,11 +320,11 @@
 		//con.add(wmsServerBaseUrl, GBC.eop().fill(GBC.HORIZONTAL));
 		//con.add(Box.createVerticalGlue(), GBC.eol().fill(GBC.VERTICAL));
-		con.add(new JLabel("CSV import specification (empty: read from first line in data)"), GBC.eol());
+		con.add(new JLabel(tr("CSV import specification (empty: read from first line in data)")), GBC.eol());
 		con.add(csvImportString, GBC.eop().fill(GBC.HORIZONTAL));
 		con.add(Box.createVerticalGlue(), GBC.eol().fill(GBC.VERTICAL));
 
 		// Map tab
-		JPanel map = createPreferenceTab("map", "Map Settings", "Settings for the map projection and data interpretation.");
-		map.add(new JLabel("Projection method"), GBC.std());
+		JPanel map = createPreferenceTab("map", tr("Map Settings"), tr("Settings for the map projection and data interpretation."));
+		map.add(new JLabel(tr("Projection method")), GBC.std());
 		map.add(GBC.glue(5,0), GBC.std().fill(GBC.HORIZONTAL));
 		map.add(projectionCombo, GBC.eol().fill(GBC.HORIZONTAL).insets(0,0,0,5));
Index: src/org/openstreetmap/josm/gui/dialogs/CommandStackDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/CommandStackDialog.java	(revision 103)
+++ src/org/openstreetmap/josm/gui/dialogs/CommandStackDialog.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.gui.dialogs;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.BorderLayout;
@@ -28,5 +30,5 @@
 
 	public CommandStackDialog(final MapFrame mapFrame) {
-		super("Command Stack", "commandstack", "Open a list of all commands (undo buffer).", KeyEvent.VK_C);
+		super(tr("Command Stack"), "commandstack", tr("Open a list of all commands (undo buffer)."), KeyEvent.VK_C);
 		setPreferredSize(new Dimension(320,100));
 		mapFrame.mapView.addLayerChangeListener(new LayerChangeListener(){
Index: src/org/openstreetmap/josm/gui/dialogs/ConflictDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/ConflictDialog.java	(revision 103)
+++ src/org/openstreetmap/josm/gui/dialogs/ConflictDialog.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.gui.dialogs;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.BorderLayout;
@@ -47,5 +49,5 @@
 
 	public ConflictDialog() {
-		super("Conflict", "conflict", "Merging conflicts.", KeyEvent.VK_C);
+		super(tr("Conflict"), "conflict", tr("Merging conflicts."), KeyEvent.VK_C);
 		displaylist.setCellRenderer(new OsmPrimitivRenderer());
 		displaylist.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
@@ -59,6 +61,6 @@
 
 		JPanel buttonPanel = new JPanel(new GridLayout(1,2));
-		JButton button = new JButton("Resolve", ImageProvider.get("dialogs", "conflict"));
-		button.setToolTipText("Open a merge dialog of all selected items in the list above.");
+		JButton button = new JButton(tr("Resolve"), ImageProvider.get("dialogs", "conflict"));
+		button.setToolTipText(tr("Open a merge dialog of all selected items in the list above."));
 		button.addActionListener(new ActionListener(){
 			public void actionPerformed(ActionEvent e) {
@@ -68,6 +70,6 @@
 		buttonPanel.add(button);
 
-		button = new JButton("Select", ImageProvider.get("mapmode", "selection"));
-		button.setToolTipText("Set the selected elements on the map to the selected items in the list above.");
+		button = new JButton(tr("Select"), ImageProvider.get("mapmode/selection/select"));
+		button.setToolTipText(tr("Set the selected elements on the map to the selected items in the list above."));
 		button.addActionListener(new ActionListener(){
 			public void actionPerformed(ActionEvent e) {
@@ -102,5 +104,5 @@
 	private final void resolve() {
 		if (displaylist.getSelectedIndex() == -1) {
-			JOptionPane.showMessageDialog(Main.parent, "Please select something from the conflict list.");
+			JOptionPane.showMessageDialog(Main.parent,tr("Please select something from the conflict list."));
 			return;
 		}
@@ -111,5 +113,5 @@
 		}
 		ConflictResolver resolver = new ConflictResolver(sel);
-		int answer = JOptionPane.showConfirmDialog(Main.parent, resolver, "Resolve Conflicts", JOptionPane.OK_CANCEL_OPTION);
+		int answer = JOptionPane.showConfirmDialog(Main.parent, resolver, tr("Resolve Conflicts"), JOptionPane.OK_CANCEL_OPTION);
 		if (answer != JOptionPane.OK_OPTION)
 			return;
Index: src/org/openstreetmap/josm/gui/dialogs/LayerList.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/LayerList.java	(revision 103)
+++ src/org/openstreetmap/josm/gui/dialogs/LayerList.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.gui.dialogs;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.BorderLayout;
@@ -55,5 +57,5 @@
 		public DeleteLayerAction(Layer layer) {
 			super("Delete", ImageProvider.get("dialogs", "delete"));
-			putValue(SHORT_DESCRIPTION, "Delete the selected layer.");
+			putValue(SHORT_DESCRIPTION, tr("Delete the selected layer."));
 			this.layer = layer;
 		}
@@ -76,6 +78,6 @@
 
 		public ShowHideLayerAction(Layer layer) {
-			super("Show/Hide", ImageProvider.get("dialogs", "showhide"));
-			putValue(SHORT_DESCRIPTION, "Toggle visible state of the selected layer.");
+			super(tr("Show/Hide"), ImageProvider.get("dialogs", "showhide"));
+			putValue(SHORT_DESCRIPTION, tr("Toggle visible state of the selected layer."));
 			this.layer = layer;
 		}
@@ -115,5 +117,5 @@
 	 */
 	public LayerList(MapFrame mapFrame) {
-		super("Layers", "layerlist", "Open a list of all loaded layers.", KeyEvent.VK_L);
+		super(tr("Layers"), "layerlist", tr("Open a list of all loaded layers."), KeyEvent.VK_L);
 		instance = new JList(model);
 		setPreferredSize(new Dimension(320,100));
@@ -188,10 +190,10 @@
 		};
 
-		upButton.setToolTipText("Move the selected layer one row up.");
+		upButton.setToolTipText(tr("Move the selected layer one row up."));
 		upButton.addActionListener(upDown);
 		upButton.setActionCommand("up");
 		buttonPanel.add(upButton);
 
-		downButton.setToolTipText("Move the selected layer one row down.");
+		downButton.setToolTipText(tr("Move the selected layer one row down."));
 		downButton.addActionListener(upDown);
 		downButton.setActionCommand("down");
@@ -206,5 +208,5 @@
 		buttonPanel.add(deleteButton);
 
-		mergeButton.setToolTipText("Merge the selected layer into the layer directly below.");
+		mergeButton.setToolTipText(tr("Merge the selected layer into the layer directly below."));
 		mergeButton.addActionListener(new ActionListener(){
 			public void actionPerformed(ActionEvent e) {
Index: src/org/openstreetmap/josm/gui/dialogs/LayerListPopup.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/LayerListPopup.java	(revision 103)
+++ src/org/openstreetmap/josm/gui/dialogs/LayerListPopup.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.gui.dialogs;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.Component;
@@ -21,5 +23,5 @@
 	    private final Layer layer;
 	    public InfoAction(Layer layer) {
-	    	super("Info", ImageProvider.get("info"));
+	    	super(tr("Info"), ImageProvider.get("info"));
 		    this.layer = layer;
 	    }
Index: src/org/openstreetmap/josm/gui/dialogs/PropertiesDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/PropertiesDialog.java	(revision 103)
+++ src/org/openstreetmap/josm/gui/dialogs/PropertiesDialog.java	(revision 104)
@@ -1,3 +1,6 @@
 package org.openstreetmap.josm.gui.dialogs;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+import static org.openstreetmap.josm.tools.I18n.trn;
 
 import java.awt.BorderLayout;
@@ -83,9 +86,8 @@
 		String key = data.getValueAt(row, 0).toString();
 		Collection<OsmPrimitive> sel = Main.ds.getSelected();
-		String msg = "<html>This will change "+sel.size()+" object"+(sel.size()==1?"":"s")+".<br><br>"+
-		"Please select a new value for '"+key+"'.<br>(Empty string deletes the key.)";
+		String msg = "<html>"+trn("This will change {0} object.", "This will change {0} objects.", sel.size(), sel.size())+"<br><br> "+tr("Please select a new value for '{0}'.<br>(Empty string deletes the key.)</html>)", key);
 		final JComboBox combo = (JComboBox)data.getValueAt(row, 1);
 		JPanel p = new JPanel(new BorderLayout());
-		p.add(new JLabel(msg+"</html>"), BorderLayout.NORTH);
+		p.add(new JLabel(msg), BorderLayout.NORTH);
 		p.add(combo, BorderLayout.CENTER);
 
@@ -96,5 +98,5 @@
 			}
 		};
-		final JDialog dlg = optionPane.createDialog(Main.parent, "Change values?");
+		final JDialog dlg = optionPane.createDialog(Main.parent, tr("Change values?"));
 		combo.getEditor().addActionListener(new ActionListener(){
 			public void actionPerformed(ActionEvent e) {
@@ -114,5 +116,5 @@
 
 		String value = combo.getEditor().getItem().toString();
-		if (value.equals("<different>"))
+		if (value.equals(tr("<different>")))
 			return;
 		if (value.equals(""))
@@ -134,6 +136,8 @@
 
 		JPanel p = new JPanel(new BorderLayout());
-		p.add(new JLabel("<html>This will change "+sel.size()+" object"+(sel.size()==1?"":"s")+".<br><br>"+
-		"Please select a key"), BorderLayout.NORTH);
+		p.add(new JLabel(trn("<html>This will change {0} object.<br>br>Please select a key",
+				"<html>This will change {0} objects.<br>br>Please select a key",
+				sel.size(),sel.size())),
+				BorderLayout.NORTH);
 		TreeSet<String> allKeys = new TreeSet<String>();
 		for (OsmPrimitive osm : Main.ds.allNonDeletedPrimitives())
@@ -147,5 +151,5 @@
 		JPanel p2 = new JPanel(new BorderLayout());
 		p.add(p2, BorderLayout.SOUTH);
-		p2.add(new JLabel("Please select a value"), BorderLayout.NORTH);
+		p2.add(new JLabel(tr("Please select a value")), BorderLayout.NORTH);
 		final JTextField values = new JTextField();
 		p2.add(values, BorderLayout.CENTER);
@@ -156,5 +160,5 @@
 			}
 		};
-		pane.createDialog(Main.parent, "Change values?").setVisible(true);
+		pane.createDialog(Main.parent, tr("Change values?")).setVisible(true);
 		if (!Integer.valueOf(JOptionPane.OK_OPTION).equals(pane.getValue()))
 			return;
@@ -198,9 +202,9 @@
 	 */
 	public PropertiesDialog(MapFrame mapFrame) {
-		super("Properties", "propertiesdialog", "Property for selected objects.", KeyEvent.VK_P);
+		super(tr("Properties"), "propertiesdialog", tr("Property for selected objects."), KeyEvent.VK_P);
 
 		setPreferredSize(new Dimension(320,150));
 
-		data.setColumnIdentifiers(new String[]{"Key", "Value"});
+		data.setColumnIdentifiers(new String[]{tr("Key"),tr("Value")});
 		propertyTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
 		propertyTable.setDefaultRenderer(JComboBox.class, new DefaultTableCellRenderer(){
@@ -210,5 +214,5 @@
 					String str = ((JComboBox)value).getEditor().getItem().toString();
 					((JLabel)c).setText(str);
-					if (str.equals("<different>"))
+					if (str.equals(tr("<different>")))
 						c.setFont(c.getFont().deriveFont(Font.ITALIC));
 				}
@@ -231,14 +235,14 @@
 			public void actionPerformed(ActionEvent e) {
 				int sel = propertyTable.getSelectedRow();
-				if (e.getActionCommand().equals("Add"))
+				if (e.getActionCommand().equals(tr("Add")))
 					add();
-				else if (e.getActionCommand().equals("Edit")) {
+				else if (e.getActionCommand().equals(tr("Edit"))) {
 					if (sel == -1)
-						JOptionPane.showMessageDialog(Main.parent, "Please select the row to edit.");
+						JOptionPane.showMessageDialog(Main.parent, tr("Please select the row to edit."));
 					else
 						edit(sel);
-				} else if (e.getActionCommand().equals("Delete")) {
+				} else if (e.getActionCommand().equals(tr("Delete"))) {
 					if (sel == -1)
-						JOptionPane.showMessageDialog(Main.parent, "Please select the row to delete.");
+						JOptionPane.showMessageDialog(Main.parent, tr("Please select the row to delete."));
 					else
 						delete(sel);
@@ -246,7 +250,7 @@
 			}
 		};
-		buttonPanel.add(createButton("Add", "Add a new key/value pair to all objects", KeyEvent.VK_A, buttonAction));
-		buttonPanel.add(createButton("Edit", "Edit the value of the selected key for all objects", KeyEvent.VK_E, buttonAction));
-		buttonPanel.add(createButton("Delete", "Delete the selected key in all objects", KeyEvent.VK_D, buttonAction));
+		buttonPanel.add(createButton(tr("Add"),tr("Add a new key/value pair to all objects"), KeyEvent.VK_A, buttonAction));
+		buttonPanel.add(createButton(tr("Edit"),tr( "Edit the value of the selected key for all objects"), KeyEvent.VK_E, buttonAction));
+		buttonPanel.add(createButton(tr("Delete"),tr("Delete the selected key in all objects"), KeyEvent.VK_D, buttonAction));
 		add(buttonPanel, BorderLayout.SOUTH);
 	}
@@ -294,5 +298,5 @@
 			JComboBox value = new JComboBox(e.getValue().toArray());
 			value.setEditable(true);
-			value.getEditor().setItem(valueCount.get(e.getKey()) != newSelection.size() ? "<different>" : e.getValue().iterator().next());
+			value.getEditor().setItem(valueCount.get(e.getKey()) != newSelection.size() ? tr("<different>") : e.getValue().iterator().next());
 			data.addRow(new Object[]{e.getKey(), value});
 		}
Index: src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java	(revision 103)
+++ src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.gui.dialogs;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.BorderLayout;
@@ -53,5 +55,4 @@
  */
 public class SelectionListDialog extends ToggleDialog implements SelectionChangedListener {
-
 	public static enum SearchMode {replace, add, remove}
 
@@ -62,5 +63,5 @@
 		private OsmIdReader idReader = new OsmIdReader();
 		public SelectionWebsiteLoader(String urlStr, SearchMode mode) {
-	        super("Load Selection");
+	        super(tr("Load Selection"));
 	        this.mode = mode;
 	        URL u = null;
@@ -69,10 +70,10 @@
         }
 		@Override protected void realRun() {
-			currentAction.setText("Contact "+url.getHost()+"...");
+			currentAction.setText(tr("Contact {0}...", url.getHost()));
 			sel = mode != SearchMode.remove ? new LinkedList<OsmPrimitive>() : Main.ds.allNonDeletedPrimitives();
 			try {
 		        URLConnection con = url.openConnection();
 		        InputStream in = new ProgressReader(con, progress, currentAction);
-				currentAction.setText("Downloading...");
+				currentAction.setText(tr("Downloading..."));
 				Map<Long, String> ids = idReader.parseIds(in);
 		        for (OsmPrimitive osm : Main.ds.allNonDeletedPrimitives()) {
@@ -86,8 +87,8 @@
 	        } catch (IOException e) {
 		        e.printStackTrace();
-		        JOptionPane.showMessageDialog(Main.parent, "Could not read from url: '"+url+"'");
+		        JOptionPane.showMessageDialog(Main.parent, tr("Could not read from url: '{0}'",url));
 	        } catch (SAXException e) {
 		        e.printStackTrace();
-		        JOptionPane.showMessageDialog(Main.parent, "Parsing error in url: '"+url+"'");
+		        JOptionPane.showMessageDialog(Main.parent,tr("Parsing error in url: '{0}'",url));
 	        }
         }
@@ -116,5 +117,5 @@
 	 */
 	public SelectionListDialog(MapFrame mapFrame) {
-		super("Current Selection", "selectionlist", "Open a selection list window.", KeyEvent.VK_E);
+		super(tr("Current Selection"), "selectionlist", tr("Open a selection list window."), KeyEvent.VK_E);
 		setPreferredSize(new Dimension(320,150));
 		displaylist.setCellRenderer(new OsmPrimitivRenderer());
@@ -132,6 +133,6 @@
 		JPanel buttonPanel = new JPanel(new GridLayout(1,2));
 		
-		JButton button = new JButton("Select", ImageProvider.get("mapmode", "selection"));
-		button.setToolTipText("Set the selected elements on the map to the selected items in the list above.");
+		JButton button = new JButton(tr("Select"), ImageProvider.get("mapmode/selection/select"));
+		button.setToolTipText(tr("Set the selected elements on the map to the selected items in the list above."));
 		button.addActionListener(new ActionListener(){
 			public void actionPerformed(ActionEvent e) {
@@ -141,6 +142,6 @@
 		buttonPanel.add(button);
 
-		button = new JButton("Reload", ImageProvider.get("dialogs", "refresh"));
-		button.setToolTipText("Refresh the selection list.");
+		button = new JButton(tr("Reload"), ImageProvider.get("dialogs", "refresh"));
+		button.setToolTipText(tr("Refresh the selection list."));
 		button.addActionListener(new ActionListener(){
 			public void actionPerformed(ActionEvent e) {
@@ -150,12 +151,12 @@
 		buttonPanel.add(button);
 		
-		button = new JButton("Search", ImageProvider.get("dialogs", "search"));
-		button.setToolTipText("Search for objects.");
+		button = new JButton(tr("Search"), ImageProvider.get("dialogs", "search"));
+		button.setToolTipText(tr("Search for objects."));
 		button.addActionListener(new ActionListener(){
 			private String lastSearch = "";
 			public void actionPerformed(ActionEvent e) {
-				JLabel label = new JLabel("Please enter a search string.");
+				JLabel label = new JLabel(tr("Please enter a search string."));
 				final JTextField input = new JTextField(lastSearch);
-				input.setToolTipText("<html>Fulltext search.<ul>" +
+				input.setToolTipText(tr("<html>Fulltext search.<ul>" +
 						"<li><code>Baker Street</code>  - 'Baker' and 'Street' in any key or name.</li>" +
 						"<li><code>\"Baker Street\"</code>  - 'Baker Street' in any key or name.</li>" +
@@ -163,9 +164,9 @@
 						"<li><code>-name:Bak</code>  - not 'Bak' in the name.</li>" +
 						"<li><code>foot:</code>  - key=foot set to any value." +
-						"</ul></html>");
-
-				JRadioButton replace = new JRadioButton("replace selection", true);
-				JRadioButton add = new JRadioButton("add to selection", false);
-				JRadioButton remove = new JRadioButton("remove from selection", false);
+						"</ul></html>"));
+
+				JRadioButton replace = new JRadioButton(tr("replace selection"), true);
+				JRadioButton add = new JRadioButton(tr("add to selection"), false);
+				JRadioButton remove = new JRadioButton(tr("remove from selection"), false);
 				ButtonGroup bg = new ButtonGroup();
 				bg.add(replace);
@@ -184,5 +185,5 @@
                     }
 				};
-				pane.createDialog(Main.parent, "Search").setVisible(true);
+				pane.createDialog(Main.parent,tr("Search")).setVisible(true);
 				if (!Integer.valueOf(JOptionPane.OK_OPTION).equals(pane.getValue()))
 					return;
Index: src/org/openstreetmap/josm/gui/layer/GeoImageLayer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/GeoImageLayer.java	(revision 103)
+++ src/org/openstreetmap/josm/gui/layer/GeoImageLayer.java	(revision 104)
@@ -1,3 +1,6 @@
 package org.openstreetmap.josm.gui.layer;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+import static org.openstreetmap.josm.tools.I18n.trn;
 
 import java.awt.BorderLayout;
@@ -80,10 +83,10 @@
 		private final RawGpsLayer gpsLayer;
 		public Loader(Collection<File> files, RawGpsLayer gpsLayer) {
-			super("Images");
+			super(tr("Images"));
 			this.files = files;
 			this.gpsLayer = gpsLayer;
 		}
 		@Override protected void realRun() throws IOException {
-			currentAction.setText("Read GPS...");
+			currentAction.setText(tr("Read GPS..."));
 			LinkedList<TimedPoint> gps = new LinkedList<TimedPoint>();
 
@@ -95,12 +98,12 @@
 					for (GpsPoint p : c) {
 						if (p.time == null)
-							throw new IOException("No time for point "+p.latlon.lat()+","+p.latlon.lon());
+							throw new IOException(tr("No time for point {0},{1}",p.latlon.lat(),p.latlon.lon()));
 						Matcher m = reg.matcher(p.time);
 						if (!m.matches())
-							throw new IOException("Cannot read time from point "+p.latlon.lat()+","+p.latlon.lon());
+							throw new IOException(tr("Cannot read time from point {0},{1}",p.latlon.lat(),p.latlon.lon()));
 						Date d = DateParser.parse(m.group(1)+" "+m.group(2));
 						gps.add(new TimedPoint(d, p.eastNorth));
 						if (last != null && last.after(d))
-							throw new IOException("Time loop in gps data.");
+							throw new IOException(tr("Time loop in gps data."));
 						last = d;
 					}
@@ -108,9 +111,9 @@
 			} catch (ParseException e) {
 				e.printStackTrace();
-				throw new IOException("Incorrect date information");
+				throw new IOException(tr("Incorrect date information"));
 			}
 
 			if (gps.isEmpty()) {
-				errorMessage = "No images with readable timestamps found.";
+				errorMessage = tr("No images with readable timestamps found.");
 				return;
 			}
@@ -123,5 +126,5 @@
 				if (cancelled)
 					break;
-				currentAction.setText("Reading "+f.getName()+"...");
+				currentAction.setText(tr("Reading {0}...",f.getName()));
 				progress.setValue(i++);
 
@@ -183,5 +186,5 @@
 
 	private GeoImageLayer(final ArrayList<ImageEntry> data, LinkedList<TimedPoint> gps) {
-		super("Geotagged Images");
+		super(tr("Geotagged Images"));
 		this.data = data;
 		this.gps = gps;
@@ -250,9 +253,9 @@
 		p.add(new JLabel(getToolTipText()), GBC.eop());
 
-		p.add(new JLabel("GPS start: "+dateFormat.format(gps.getFirst().time)), GBC.eol());
-		p.add(new JLabel("GPS end: "+dateFormat.format(gps.getLast().time)), GBC.eop());
-
-		p.add(new JLabel("current delta: "+(delta/1000.0)+"s"), GBC.eol());
-		p.add(new JLabel("timezone difference: "+(gpstimezone>0?"+":"")+(gpstimezone/1000/60/60)), GBC.eop());
+		p.add(new JLabel(tr("GPS start: {0}",dateFormat.format(gps.getFirst().time))), GBC.eol());
+		p.add(new JLabel(tr("GPS end: {0}",dateFormat.format(gps.getLast().time))), GBC.eop());
+
+		p.add(new JLabel(tr("current delta: {0}s",(delta/1000.0))), GBC.eol());
+		p.add(new JLabel(tr("timezone difference: ")+(gpstimezone>0?"+":"")+(gpstimezone/1000/60/60)), GBC.eop());
 
 		JList img = new JList(data.toArray());
@@ -278,5 +281,5 @@
 			if (e.pos != null)
 				i++;
-		return data.size()+" images, "+i+" within the track.";
+		return trn("{0} image. {1} within the track.","{0} images. {1} within the track.",data.size(),data.size(),i);
 	}
 
@@ -316,5 +319,5 @@
 
 	@Override public Component[] getMenuEntries() {
-		JMenuItem sync = new JMenuItem("Sync clock", ImageProvider.get("clock"));
+		JMenuItem sync = new JMenuItem(tr("Sync clock"), ImageProvider.get("clock"));
 		sync.addActionListener(new ActionListener(){
 			public void actionPerformed(ActionEvent e) {
@@ -327,5 +330,5 @@
 					}
 					@Override public String getDescription() {
-						return "JPEG images (*.jpg)";
+						return tr("JPEG images (*.jpg)");
 					}
 				});
@@ -369,10 +372,10 @@
 		Date exifDate = ExifReader.readTime(f);
 		JPanel p = new JPanel(new GridBagLayout());
-		p.add(new JLabel("Image"), GBC.eol());
+		p.add(new JLabel(tr("Image")), GBC.eol());
 		p.add(new JLabel(loadScaledImage(f, 300)), GBC.eop());
-		p.add(new JLabel("Enter shown date (mm/dd/yyyy HH:MM:SS)"), GBC.eol());
+		p.add(new JLabel(tr("Enter shown date (mm/dd/yyyy HH:MM:SS)")), GBC.eol());
 		JTextField gpsText = new JTextField(dateFormat.format(new Date(exifDate.getTime()+delta)));
 		p.add(gpsText, GBC.eol().fill(GBC.HORIZONTAL));
-		p.add(new JLabel("GPS unit timezome (difference to photo)"), GBC.eol());
+		p.add(new JLabel(tr("GPS unit timezome (difference to photo)")), GBC.eol());
 		String t = Main.pref.get("tagimages.gpstimezone", "0");
 		if (t.charAt(0) != '-')
@@ -382,5 +385,5 @@
 
 		while (true) {
-			int answer = JOptionPane.showConfirmDialog(Main.parent, p, "Syncronize Time with GPS Unit", JOptionPane.OK_CANCEL_OPTION);
+			int answer = JOptionPane.showConfirmDialog(Main.parent, p, tr("Syncronize Time with GPS Unit"), JOptionPane.OK_CANCEL_OPTION);
 			if (answer != JOptionPane.OK_OPTION || gpsText.getText().equals(""))
 				return;
@@ -398,5 +401,5 @@
 				return;
 			} catch (ParseException x) {
-				JOptionPane.showMessageDialog(Main.parent, "Time entered could not be parsed.");
+				JOptionPane.showMessageDialog(Main.parent, tr("Time entered could not be parsed."));
 			}
 		}
Index: src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 103)
+++ src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 104)
@@ -1,3 +1,6 @@
 package org.openstreetmap.josm.gui.layer;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+import static org.openstreetmap.josm.tools.I18n.trn;
 
 import java.awt.Component;
@@ -148,7 +151,7 @@
 
 	@Override public String getToolTipText() {
-		return undeletedSize(data.nodes)+" nodes, "+
-		undeletedSize(data.segments)+" segments, "+
-		undeletedSize(data.ways)+" streets.";
+		return trn("{0} node", "{0} nodes", undeletedSize(data.nodes), undeletedSize(data.nodes))
+		+trn("{0} segment", "{0} segments", undeletedSize(data.segments), undeletedSize(data.segments))
+		+trn("{0} way", "{0} ways", undeletedSize(data.ways), undeletedSize(data.ways));
 	}
 
@@ -162,5 +165,5 @@
 		final ConflictDialog dlg = Main.map.conflictDialog;
 		dlg.add(visitor.conflicts);
-		JOptionPane.showMessageDialog(Main.parent, "There were conflicts during import.");
+		JOptionPane.showMessageDialog(Main.parent,tr("There were conflicts during import."));
 		if (!dlg.isVisible())
 			dlg.action.actionPerformed(new ActionEvent(this, 0, ""));
@@ -301,9 +304,9 @@
 			osm.visit(counter);
 		final JPanel p = new JPanel(new GridBagLayout());
-		p.add(new JLabel(name+" consists of:"), GBC.eol());
+		p.add(new JLabel(tr("{0} consists of:", name)), GBC.eol());
 		for (int i = 0; i < counter.normal.length; ++i) {
-			String s = counter.normal[i]+" "+counter.names[i]+(counter.normal[i] != 1 ?"s":"");
+			String s = counter.normal[i]+" "+trn(counter.names[i],counter.names[i]+"s",counter.normal[i]);
 			if (counter.deleted[i] > 0)
-				s += " ("+counter.deleted[i]+" deleted)";
+				s += tr(" ({0} deleted.)",counter.deleted[i]);
 			p.add(new JLabel(s, ImageProvider.get("data", counter.names[i]), JLabel.HORIZONTAL), GBC.eop().insets(15,0,0,0));
 		}
Index: src/org/openstreetmap/josm/gui/layer/RawGpsLayer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/RawGpsLayer.java	(revision 103)
+++ src/org/openstreetmap/josm/gui/layer/RawGpsLayer.java	(revision 104)
@@ -1,3 +1,6 @@
 package org.openstreetmap.josm.gui.layer;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+import static org.openstreetmap.josm.tools.I18n.trn;
 
 import java.awt.Color;
@@ -46,5 +49,5 @@
 	public class ConvertToDataLayerAction extends AbstractAction {
 		public ConvertToDataLayerAction() {
-			super("Convert to data layer", ImageProvider.get("converttoosm"));
+			super(tr("Convert to data layer"), ImageProvider.get("converttoosm"));
         }
 		public void actionPerformed(ActionEvent e) {
@@ -65,5 +68,5 @@
 				ds.ways.add(w);
 			}
-			Main.main.addLayer(new OsmDataLayer(ds, "Data Layer", true));
+			Main.main.addLayer(new OsmDataLayer(ds, tr("Data Layer"), true));
 			Main.main.removeLayer(RawGpsLayer.this);
         }
@@ -127,5 +130,6 @@
 		for (Collection<GpsPoint> c : data)
 			points += c.size();
-		return data.size()+" tracks, "+points+" points.";
+		return trn("{0} track", "{0} tracks", data.size(), data.size())
+		+" "+trn("{0} point", "{0} points", points, points);
 	}
 
@@ -149,19 +153,19 @@
 		int points = 0;
 		for (Collection<GpsPoint> c : data) {
-			b.append("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a track with "+c.size()+" points<br>");
+			b.append("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"+trn("a track with {0} point","a track with {0} points", c.size(), c.size())+"<br>");
 			points += c.size();
 		}
 		b.append("</html>");
-		return "<html>"+name+" consists of "+data.size()+" tracks ("+points+" points)<br>"+b.toString();
+		return "<html>"+tr("{0} consists of ")+trn("{0} track", "{0} tracks", data.size(), data.size())+" ("+trn("{0} point", "{0} points", points, points)+")<br>"+b.toString();
 	}
 
 	@Override public Component[] getMenuEntries() {
-		JMenuItem color = new JMenuItem("Customize Color", ImageProvider.get("colorchooser"));
+		JMenuItem color = new JMenuItem(tr("Customize Color"), ImageProvider.get("colorchooser"));
 		color.addActionListener(new ActionListener(){
 			public void actionPerformed(ActionEvent e) {
 				String col = Main.pref.get("color.layer "+name, Main.pref.get("color.gps point", ColorHelper.color2html(Color.gray)));
 				JColorChooser c = new JColorChooser(ColorHelper.html2color(col));
-				Object[] options = new Object[]{"OK", "Cancel", "Default"};
-				int answer = JOptionPane.showOptionDialog(Main.parent, c, "Choose a color", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, options[0]);
+				Object[] options = new Object[]{tr("OK"), tr("Cancel"), tr("Default")};
+				int answer = JOptionPane.showOptionDialog(Main.parent, c, tr("Choose a color"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, options[0]);
 				switch (answer) {
 				case 0:
@@ -178,5 +182,5 @@
 		});
 		
-		JMenuItem tagimage = new JMenuItem("Import images", ImageProvider.get("tagimages"));
+		JMenuItem tagimage = new JMenuItem(tr("Import images"), ImageProvider.get("tagimages"));
 		tagimage.addActionListener(new ActionListener(){
 			public void actionPerformed(ActionEvent e) {
@@ -190,5 +194,5 @@
 					}
 					@Override public String getDescription() {
-						return "JPEG images (*.jpg)";
+						return tr("JPEG images (*.jpg)");
 					}
 				});
Index: src/org/openstreetmap/josm/gui/layer/WmsServerLayer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/WmsServerLayer.java	(revision 103)
+++ src/org/openstreetmap/josm/gui/layer/WmsServerLayer.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.gui.layer;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.Component;
@@ -42,5 +44,5 @@
 		// unprojected scale.
 		if (Projection.MAX_LON != 180)
-			throw new IllegalArgumentException("Wrong longitude transformation for tile cache. Can't operate on "+Main.proj);
+			throw new IllegalArgumentException(tr("Wrong longitude transformation for tile cache. Can't operate on {0}",Main.proj));
 
 		this.url = url;
@@ -53,5 +55,5 @@
 
 	@Override public String getToolTipText() {
-		return "WMS layer: "+url;
+		return tr("WMS layer: {0}", url);
 	}
 
Index: src/org/openstreetmap/josm/io/BoundingBoxDownloader.java
===================================================================
--- src/org/openstreetmap/josm/io/BoundingBoxDownloader.java	(revision 104)
+++ src/org/openstreetmap/josm/io/BoundingBoxDownloader.java	(revision 104)
@@ -0,0 +1,107 @@
+package org.openstreetmap.josm.io;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collection;
+import java.util.LinkedList;
+
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.gui.layer.RawGpsLayer.GpsPoint;
+import org.xml.sax.SAXException;
+
+public class BoundingBoxDownloader extends OsmServerReader {
+
+	/**
+     * The boundings of the desired map data.
+     */
+    private final double lat1;
+	private final double lon1;
+	private final double lat2;
+	private final double lon2;
+
+	public BoundingBoxDownloader(double lat1, double lon1, double lat2, double lon2) {
+		this.lat1 = lat1;
+		this.lon1 = lon1;
+		this.lat2 = lat2;
+		this.lon2 = lon2;
+    }
+
+	/**
+     * Retrieve raw gps waypoints from the server API.
+     * @return A list of all primitives retrieved. Currently, the list of lists
+     * 		contain only one list, since the server cannot distinguish between
+     * 		ways.
+     */
+    public Collection<Collection<GpsPoint>> parseRawGps() throws IOException, SAXException {
+    	try {
+    		String url = "trackpoints?bbox="+lon1+","+lat1+","+lon2+","+lat2+"&page=";
+    		Collection<Collection<GpsPoint>> data = new LinkedList<Collection<GpsPoint>>();
+    		Collection<GpsPoint> list = new LinkedList<GpsPoint>();
+    
+    		for (int i = 0;;++i) {
+    			currentAction.setText(tr("Downloading points {0} to {1}...", i * 5000, ((i + 1) * 5000)));
+    			InputStream in = getInputStream(url+i);
+    			if (in == null)
+    				break;
+    			Collection<Collection<GpsPoint>> allWays = RawGpsReader.parse(in);
+    			boolean foundSomething = false;
+    			for (Collection<GpsPoint> t : allWays) {
+    				if (!t.isEmpty()) {
+    					foundSomething = true;
+    					list.addAll(t);
+    				}
+    			}
+    			if (!foundSomething)
+    				break;
+    			in.close();
+    			activeConnection = null;
+    		}
+    
+    		data.add(list);
+    		return data;
+    	} catch (IOException e) {
+    		if (cancel)
+    			return null;
+    		throw e;
+    	} catch (SAXException e) {
+    		throw e;
+    	} catch (Exception e) {
+    		if (cancel)
+    			return null;
+    		if (e instanceof RuntimeException)
+    			throw (RuntimeException)e;
+    		throw new RuntimeException(e);
+    	}
+    }
+
+	/**
+     * Read the data from the osm server address.
+     * @return A data set containing all data retrieved from that url
+     */
+    public DataSet parseOsm() throws SAXException, IOException {
+    	try {
+    		final InputStream in = getInputStream("map?bbox="+lon1+","+lat1+","+lon2+","+lat2);
+    		if (in == null)
+    			return null;
+    		currentAction.setText(tr("Downloading OSM data..."));
+    		final DataSet data = OsmReader.parseDataSet(in, currentAction, progress);
+    		in.close();
+    		activeConnection = null;
+    		return data;
+    	} catch (IOException e) {
+    		if (cancel)
+    			return null;
+    		throw e;
+    	} catch (SAXException e) {
+    		throw e;
+    	} catch (Exception e) {
+    		if (cancel)
+    			return null;
+    		if (e instanceof RuntimeException)
+    			throw (RuntimeException)e;
+    		throw new RuntimeException(e);
+    	}
+    }
+}
Index: src/org/openstreetmap/josm/io/ObjectListDownloader.java
===================================================================
--- src/org/openstreetmap/josm/io/ObjectListDownloader.java	(revision 104)
+++ src/org/openstreetmap/josm/io/ObjectListDownloader.java	(revision 104)
@@ -0,0 +1,69 @@
+package org.openstreetmap.josm.io;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collection;
+
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.visitor.MergeVisitor;
+import org.openstreetmap.josm.data.osm.visitor.NameVisitor;
+import org.xml.sax.SAXException;
+
+public class ObjectListDownloader extends OsmServerReader {
+
+	/**
+	 * All the objects to download (if not downloading bounding boxes instead)
+	 */
+	private final Collection<OsmPrimitive> toDownload;
+	private final DataSet ds = new DataSet();
+	private final MergeVisitor merger = new MergeVisitor(ds);
+
+	public ObjectListDownloader(Collection<OsmPrimitive> toDownload) {
+		this.toDownload = toDownload;
+	}
+
+	public DataSet parse() throws SAXException, IOException {
+		progress.setMaximum(toDownload.size());
+		progress.setValue(0);
+		try {
+			final NameVisitor namer = new NameVisitor();
+			for (OsmPrimitive osm : toDownload) {
+				osm.visit(namer);
+				download(namer.className, osm.id);
+				if (cancel)
+					break;
+			}
+			if (!merger.conflicts.isEmpty())
+				throw new RuntimeException(tr("Conflicts in disjunct objects"));
+			return ds;
+		} catch (IOException e) {
+			if (cancel)
+				return null;
+			throw e;
+		} catch (SAXException e) {
+			throw e;
+		} catch (Exception e) {
+			if (cancel)
+				return null;
+			if (e instanceof RuntimeException)
+				throw (RuntimeException)e;
+			throw new RuntimeException(e);
+		}
+	}
+
+	private void download(String className, long id) throws IOException, SAXException {
+		currentAction.setText(tr("Downloading {0} {1}", className, id));
+		InputStream in = getInputStream(className+"/"+id);
+		if (in == null)
+			return;
+		DataSet data = OsmReader.parseDataSet(in, null, null);
+		progress.setValue(progress.getValue()+1);
+		if (data.allPrimitives().size() > 1)
+			throw new SAXException(tr("Got more than one object when expecting only one."));
+		for (OsmPrimitive osm : data.allPrimitives())
+			osm.visit(merger);
+	}
+}
Index: src/org/openstreetmap/josm/io/OsmConnection.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmConnection.java	(revision 103)
+++ src/org/openstreetmap/josm/io/OsmConnection.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.io;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.Font;
@@ -66,19 +68,19 @@
 				JPanel p = new JPanel(new GridBagLayout());
 				if (!username.equals("") && !password.equals(""))
-					p.add(new JLabel("Incorrect password or username."), GBC.eop());
-				p.add(new JLabel("Username"), GBC.std().insets(0,0,10,0));
+					p.add(new JLabel(tr("Incorrect password or username.")), GBC.eop());
+				p.add(new JLabel(tr("Username")), GBC.std().insets(0,0,10,0));
 				JTextField usernameField = new JTextField(username, 20);
 				p.add(usernameField, GBC.eol());
-				p.add(new JLabel("Password"), GBC.std().insets(0,0,10,0));
+				p.add(new JLabel(tr("Password")), GBC.std().insets(0,0,10,0));
 				JPasswordField passwordField = new JPasswordField(password, 20);
 				p.add(passwordField, GBC.eol());
-				JLabel warning = new JLabel("Warning: The password is transferred unencrypted.");
+				JLabel warning = new JLabel(tr("Warning: The password is transferred unencrypted."));
 				warning.setFont(warning.getFont().deriveFont(Font.ITALIC));
 				p.add(warning, GBC.eop());
 
-				JCheckBox savePassword = new JCheckBox("Save user and password (unencrypted)", !username.equals("") && !password.equals(""));
+				JCheckBox savePassword = new JCheckBox(tr("Save user and password (unencrypted)"), !username.equals("") && !password.equals(""));
 				p.add(savePassword, GBC.eop());
 
-				int choice = JOptionPane.showConfirmDialog(Main.parent, p, "Enter Password", JOptionPane.OK_CANCEL_OPTION);
+				int choice = JOptionPane.showConfirmDialog(Main.parent, p, tr("Enter Password"), JOptionPane.OK_CANCEL_OPTION);
 				if (choice == JOptionPane.CANCEL_OPTION) {
 					authCancelled = true;
@@ -120,5 +122,5 @@
 
 	public void cancel() {
-		currentAction.setText("Aborting...");
+		currentAction.setText(tr("Aborting..."));
 		cancel = true;
 		if (activeConnection != null) {
Index: src/org/openstreetmap/josm/io/OsmIdReader.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmIdReader.java	(revision 103)
+++ src/org/openstreetmap/josm/io/OsmIdReader.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.io;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.io.IOException;
@@ -30,5 +32,5 @@
 			} catch (Exception e) {
 				e.printStackTrace();
-				throw new SAXException("Error during parse.");
+				throw new SAXException(tr("Error during parse."));
 			}
 		}
Index: src/org/openstreetmap/josm/io/OsmReader.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmReader.java	(revision 103)
+++ src/org/openstreetmap/josm/io/OsmReader.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.io;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.io.IOException;
@@ -93,7 +95,7 @@
 				if (qName.equals("osm")) {
 					if (atts == null)
-						throw new SAXException("Unknown version.");
+						throw new SAXException(tr("Unknown version."));
 					if (!"0.3".equals(atts.getValue("version")))
-						throw new SAXException("Unknown version "+atts.getValue("version"));
+						throw new SAXException(tr("Unknown version {0}",atts.getValue("version")));
 				} else if (qName.equals("node")) {
 					current = new Node(new LatLon(getDouble(atts, "lat"), getDouble(atts, "lon")));
@@ -111,8 +113,8 @@
 					Collection<Long> list = ways.get(current);
 					if (list == null)
-						throw new SAXException("Found <seg> tag on non-way.");
+						throw new SAXException(tr("Found <seg> tag on non-way."));
 					long id = getLong(atts, "id");
 					if (id == 0)
-						throw new SAXException("Incomplete segment with id=0");
+						throw new SAXException(tr("Incomplete segment with id=0"));
 					list.add(id);
 				} else if (qName.equals("tag"))
@@ -123,5 +125,5 @@
 			} catch (NullPointerException x) {
 				x.printStackTrace(); // SAXException does not chain correctly
-				throw new SAXException("NullPointerException. Possible some missing tags.", x);
+				throw new SAXException(tr("NullPointerException. Possible some missing tags."), x);
 			}
 		}
@@ -138,5 +140,5 @@
 		current.id = getLong(atts, "id");
 		if (current.id == 0)
-			throw new SAXException("Illegal object with id=0");
+			throw new SAXException(tr("Illegal object with id=0"));
 
 		String time = atts.getValue("timestamp");
@@ -147,5 +149,5 @@
 			} catch (ParseException e) {
 				e.printStackTrace();
-				throw new SAXException("Couldn't read time format '"+time+"'.");
+				throw new SAXException(tr("Couldn't read time format '{0}'.",time));
 			}
 		}
@@ -162,5 +164,5 @@
 		String s = atts.getValue(value);
 		if (s == null)
-			throw new SAXException("Missing required attirbute '"+value+"'");
+			throw new SAXException(tr("Missing required attirbute '{0}'.",value));
 		return Long.parseLong(s);
 	}
@@ -209,5 +211,5 @@
 			progress.setValue(0);
 		if (currentAction != null)
-			currentAction.setText("Preparing data...");
+			currentAction.setText(tr("Preparing data..."));
 		for (Node n : osm.nodes.values())
 			osm.adder.visit(n);
@@ -218,5 +220,5 @@
 		} catch (NumberFormatException e) {
 			e.printStackTrace();
-			throw new SAXException("Illformed Node id");
+			throw new SAXException(tr("Illformed Node id"));
 		}
 
Index: src/org/openstreetmap/josm/io/OsmServerReader.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmServerReader.java	(revision 103)
+++ src/org/openstreetmap/josm/io/OsmServerReader.java	(revision 104)
@@ -5,11 +5,6 @@
 import java.net.HttpURLConnection;
 import java.net.URL;
-import java.util.Collection;
-import java.util.LinkedList;
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.data.osm.DataSet;
-import org.openstreetmap.josm.gui.layer.RawGpsLayer.GpsPoint;
-import org.xml.sax.SAXException;
 
 /**
@@ -18,104 +13,5 @@
  * @author imi
  */
-public class OsmServerReader extends OsmConnection {
-
-	/**
-	 * The boundings of the desired map data.
-	 */
-	private final double lat1;
-	private final double lon1;
-	private final double lat2;
-	private final double lon2;
-
-	/**
-	 * Construct the reader and store the information for attaching
-	 */
-	public OsmServerReader(double lat1, double lon1, double lat2, double lon2) {
-		this.lon2 = lon2;
-		this.lat2 = lat2;
-		this.lon1 = lon1;
-		this.lat1 = lat1;
-	}
-
-
-	/**
-	 * Retrieve raw gps waypoints from the server API.
-	 * @return A list of all primitives retrieved. Currently, the list of lists
-	 * 		contain only one list, since the server cannot distinguish between
-	 * 		ways.
-	 */
-	public Collection<Collection<GpsPoint>> parseRawGps() throws IOException, SAXException {
-		try {
-			String url = Main.pref.get("osm-server.url")+"/0.3/trackpoints?bbox="+lon1+","+lat1+","+lon2+","+lat2+"&page=";
-			Collection<Collection<GpsPoint>> data = new LinkedList<Collection<GpsPoint>>();
-			Collection<GpsPoint> list = new LinkedList<GpsPoint>();
-
-			for (int i = 0;;++i) {
-				currentAction.setText("Downloading points "+(i*5000)+" to "+((i+1)*5000)+"...");
-				InputStream in = getInputStream(url+i);
-				if (in == null)
-					break;
-				Collection<Collection<GpsPoint>> allWays = RawGpsReader.parse(in);
-				boolean foundSomething = false;
-				for (Collection<GpsPoint> t : allWays) {
-					if (!t.isEmpty()) {
-						foundSomething = true;
-						list.addAll(t);
-					}
-				}
-				if (!foundSomething)
-					break;
-				in.close();
-				activeConnection = null;
-			}
-
-			data.add(list);
-			return data;
-		} catch (IOException e) {
-			if (cancel)
-				return null;
-			throw e;
-		} catch (SAXException e) {
-			throw e;
-		} catch (Exception e) {
-			if (cancel)
-				return null;
-			if (e instanceof RuntimeException)
-				throw (RuntimeException)e;
-			throw new RuntimeException(e);
-		}
-	}
-
-
-	/**
-	 * Read the data from the osm server address.
-	 * @return A data set containing all data retrieved from that url
-	 */
-	public DataSet parseOsm() throws SAXException, IOException {
-		try {
-			final InputStream in = getInputStream(Main.pref.get("osm-server.url")+"/0.3/map?bbox="+lon1+","+lat1+","+lon2+","+lat2);
-			if (in == null)
-				return null;
-			currentAction.setText("Downloading OSM data...");
-			final DataSet data = OsmReader.parseDataSet(in, currentAction, progress);
-			in.close();
-			activeConnection = null;
-			return data;
-		} catch (IOException e) {
-			if (cancel)
-				return null;
-			throw e;
-		} catch (SAXException e) {
-			throw e;
-		} catch (Exception e) {
-			if (cancel)
-				return null;
-			if (e instanceof RuntimeException)
-				throw (RuntimeException)e;
-			throw new RuntimeException(e);
-		}
-	}
-
-
+abstract class OsmServerReader extends OsmConnection {
 	/**
 	 * Open a connection to the given url and return a reader on the input stream
@@ -124,9 +20,11 @@
 	 * @return An reader reading the input stream (servers answer) or <code>null</code>.
 	 */
-	private InputStream getInputStream(String urlStr) throws IOException {
+	protected InputStream getInputStream(String urlStr) throws IOException {
+		urlStr = Main.pref.get("osm-server.url")+"/0.3/" + urlStr;
 		System.out.println("download: "+urlStr);
 		initAuthentication();
 		URL url = new URL(urlStr);
 		activeConnection = (HttpURLConnection)url.openConnection();
+		System.out.println("got return: "+activeConnection.getResponseCode());
 		activeConnection.setConnectTimeout(15000);
 		if (isAuthCancelled() && activeConnection.getResponseCode() == 401)
Index: src/org/openstreetmap/josm/io/OsmServerWriter.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmServerWriter.java	(revision 103)
+++ src/org/openstreetmap/josm/io/OsmServerWriter.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.io;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.io.BufferedReader;
@@ -67,5 +69,5 @@
 					return;
 				osm.visit(v);
-				currentAction.setText("Upload "+v.className+" "+v.name+" ("+osm.id+")...");
+				currentAction.setText(tr("Upload {0} {1} ({2})...", v.className, v.name, osm.id));
 				osm.visit(this);
 				progress.setValue(progress.getValue()+1);
@@ -152,5 +154,5 @@
 		try {
 			URL url = new URL(Main.pref.get("osm-server.url") + "/0.3/" + urlSuffix + "/" + osm.id);
-			System.out.println("upload to: "+url);
+			System.out.println(tr("upload to: {0}"));
 			activeConnection = (HttpURLConnection) url.openConnection();
 			activeConnection.setConnectTimeout(15000);
@@ -169,5 +171,5 @@
 			if (retCode == 200 && osm.id == 0)
 				osm.id = readId(activeConnection.getInputStream());
-			System.out.println("got return: "+retCode+" with id "+osm.id);
+			System.out.println(tr("got return: {0} with id {1}",retCode,osm.id));
 			String retMsg = activeConnection.getResponseMessage();
 			activeConnection.disconnect();
@@ -181,5 +183,5 @@
 			}
 		} catch (UnknownHostException e) {
-			throw new RuntimeException("Unknown host: "+e.getMessage(), e);
+			throw new RuntimeException(tr("Unknown host: ")+e.getMessage(), e);
 		} catch (Exception e) {
 			if (cancel)
Index: src/org/openstreetmap/josm/io/RawCsvReader.java
===================================================================
--- src/org/openstreetmap/josm/io/RawCsvReader.java	(revision 103)
+++ src/org/openstreetmap/josm/io/RawCsvReader.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.io;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.io.BufferedReader;
@@ -35,5 +37,5 @@
 			formatStr = in.readLine();
 		if (formatStr == null)
-			throw new SAXException("Could not detect data format string.");
+			throw new SAXException(tr("Could not detect data format string."));
 
 		// get delimiter
@@ -58,6 +60,6 @@
 		if (!format.contains("lat") || !format.contains("lon")) {
 			if (Main.pref.get("csv.importstring").equals(""))
-				throw new SAXException("Format string in data is incomplete or not found. Try setting an manual format string in Preferences.");
-			throw new SAXException("Format string is incomplete. Need at least 'lat' and 'lon' specification");
+				throw new SAXException(tr("Format string in data is incomplete or not found. Try setting an manual format string in Preferences."));
+			throw new SAXException(tr("Format string is incomplete. Need at least 'lat' and 'lon' specification"));
 		}
 
@@ -79,10 +81,10 @@
 						st.nextToken();
 					else
-						throw new SAXException("Unknown data type: '"+token+"'."+(Main.pref.get("csv.importstring").equals("") ? " Maybe add an format string in preferences." : ""));
+						throw new SAXException(tr("Unknown data type: '{0}'.{1}",token,(Main.pref.get("csv.importstring").equals("") ? (" "+tr("Maybe add an format string in preferences.")) : "")));
 				}
 				data.add(new GpsPoint(new LatLon(lat, lon), time));
 			}
 		} catch (RuntimeException e) {
-			throw new SAXException("Parsing error in line "+lineNo, e);
+			throw new SAXException(tr("Parsing error in line {0}",lineNo), e);
 		}
 		return data;
Index: src/org/openstreetmap/josm/io/RawGpsReader.java
===================================================================
--- src/org/openstreetmap/josm/io/RawGpsReader.java	(revision 103)
+++ src/org/openstreetmap/josm/io/RawGpsReader.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.io;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.io.IOException;
@@ -37,7 +39,7 @@
 	                double lon = Double.parseDouble(atts.getValue("lon"));
 	        		if (Math.abs(lat) > 90)
-	        			throw new SAXException("Data error: lat value '"+lat+"' is out of bound.");
+	        			throw new SAXException(tr("Data error: lat value '{0}' is out of bound.", lat));
 	        		if (Math.abs(lon) > 180)
-	        			throw new SAXException("Data error: lon value '"+lon+"' is out of bound.");
+	        			throw new SAXException(tr("Data error: lon value '{0}' is out of bound.", lon));
 	                currentLatLon = new LatLon(lat, lon);
                 } catch (NumberFormatException e) {
Index: src/org/openstreetmap/josm/tools/BugReportExceptionHandler.java
===================================================================
--- src/org/openstreetmap/josm/tools/BugReportExceptionHandler.java	(revision 103)
+++ src/org/openstreetmap/josm/tools/BugReportExceptionHandler.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.tools;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.GridBagLayout;
@@ -25,5 +27,6 @@
  * @author imi
  */
-public final class BugReportExceptionHandler implements Thread.UncaughtExceptionHandler {
+public final class BugReportExceptionHandler implements Thread.UncaughtExceptionHandler {        
+
 	public void uncaughtException(Thread t, Throwable e) {
 		e.printStackTrace();
@@ -34,9 +37,9 @@
 			}
 			
-			Object[] options = new String[]{"Do nothing", "Report Bug"};
-			int answer = JOptionPane.showOptionDialog(Main.parent, "An unexpected exception occoured.\n\n" +
+			Object[] options = new String[]{tr("Do nothing"), tr("Report Bug")};
+			int answer = JOptionPane.showOptionDialog(Main.parent, tr("An unexpected exception occoured.\n\n" +
 					"This is always a coding error. If you are running the latest\n" +
-					"version of JOSM, please consider be kind and file a bug report.",
-					"Unexpected Exception", JOptionPane.YES_NO_OPTION, JOptionPane.ERROR_MESSAGE,
+					"version of JOSM, please consider be kind and file a bug report."),
+					tr("Unexpected Exception"), JOptionPane.YES_NO_OPTION, JOptionPane.ERROR_MESSAGE,
 					null, options, options[0]);
 			if (answer == 1) {
Index: src/org/openstreetmap/josm/tools/DateParser.java
===================================================================
--- src/org/openstreetmap/josm/tools/DateParser.java	(revision 103)
+++ src/org/openstreetmap/josm/tools/DateParser.java	(revision 104)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.tools;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.text.ParseException;
@@ -25,5 +27,5 @@
 			try {return sdf.parse(d);} catch (ParseException pe) {}
 		}
-		throw new ParseException("No applicable parse format", 0);
+		throw new ParseException(tr("No applicable parse format"), 0);
 	}
 }
Index: src/org/openstreetmap/josm/tools/ExifReader.java
===================================================================
--- src/org/openstreetmap/josm/tools/ExifReader.java	(revision 103)
+++ src/org/openstreetmap/josm/tools/ExifReader.java	(revision 104)
@@ -2,5 +2,4 @@
 
 import java.io.File;
-import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.Iterator;
@@ -24,5 +23,5 @@
 	                Tag tag = tagIt.next();
 	                if (tag.getTagType() == 0x132 || tag.getTagType() == 0x9003 || tag.getTagType() == 0x9004)
-	                	return new SimpleDateFormat("yyyy:MM:dd HH:mm:ss").parse(tag.getDescription());
+	                	return DateParser.parse(tag.getDescription());
 	            }
 	        }
Index: src/org/openstreetmap/josm/tools/I18n.java
===================================================================
--- src/org/openstreetmap/josm/tools/I18n.java	(revision 104)
+++ src/org/openstreetmap/josm/tools/I18n.java	(revision 104)
@@ -0,0 +1,27 @@
+package org.openstreetmap.josm.tools;
+
+import java.text.MessageFormat;
+
+/**
+ * Internationalisation support.
+ * 
+ * @author Immanuel.Scholz
+ */
+public class I18n {
+	public static String tr(String text, Object... objects) {
+		MessageFormat mf = new MessageFormat(text);
+		return mf.format(objects);
+	}
+
+	public static String tr(String text) {
+		return text;
+	}
+
+	public static String trn(String text, String pluralText, long n, Object... objects) {
+		return n==1 ? tr(text,objects) : tr(pluralText,objects);
+	}
+
+	public static String trn(String text, String pluralText, long n) {
+		return n==1 ? text : pluralText;
+	}
+}
Index: src/org/openstreetmap/josm/tools/ShortCutLabel.java
===================================================================
--- src/org/openstreetmap/josm/tools/ShortCutLabel.java	(revision 103)
+++ src/org/openstreetmap/josm/tools/ShortCutLabel.java	(revision 104)
@@ -1,5 +1,8 @@
 package org.openstreetmap.josm.tools;
 
+import static org.openstreetmap.josm.tools.I18n.tr;
+
 import java.awt.event.KeyEvent;
+
 
 public class ShortCutLabel {
@@ -7,11 +10,11 @@
 		String s = "";
 		if ((modifiers & KeyEvent.CTRL_MASK) != 0)
-			s += "Ctrl-";
+			s += tr("Ctrl-");
 		if ((modifiers & KeyEvent.ALT_MASK) != 0)
-			s += "Alt-";
+			s += tr("Alt-");
 		if ((modifiers & KeyEvent.ALT_GRAPH_MASK) != 0)
-			s += "AltGr-";
+			s += tr("AltGr-");
 		if ((modifiers & KeyEvent.SHIFT_MASK) != 0)
-			s += "Shift-";
+			s += tr("Shift-");
 		s += Character.toUpperCase((char)shortCut);
 		return s;
Index: src/org/openstreetmap/josm/tools/UrlLabel.java
===================================================================
--- src/org/openstreetmap/josm/tools/UrlLabel.java	(revision 103)
+++ src/org/openstreetmap/josm/tools/UrlLabel.java	(revision 104)
@@ -11,5 +11,8 @@
 public class UrlLabel extends JEditorPane implements HyperlinkListener {
 
+	private final String url;
+
 	public UrlLabel(String url) {
+		this.url = url;
 		setContentType("text/html");
 		setText("<html><a href=\""+url+"\">"+url+"</a></html>");
@@ -21,5 +24,5 @@
 	public void hyperlinkUpdate(HyperlinkEvent e) {
 		if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
-			OpenBrowser.displayUrl("http://wiki.eigenheimstrasse.de/wiki/JOSM");
+			OpenBrowser.displayUrl(url);
 		}
 	}
