From b7f591781f4bd2e3c94596a2b1f2cf73cdc0d7cd Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Thu, 13 Oct 2011 17:01:51 -0400
Subject: [PATCH] Localized RPC client using server's resource file.

---
 src/com/gitblit/client/GitblitClientLauncher.java |    7 
 src/com/gitblit/client/JPalette.java              |   11 +
 src/com/gitblit/wicket/GitBlitWebApp.properties   |   16 ++
 src/com/gitblit/client/GitblitClient.java         |   24 +-
 src/com/gitblit/client/IndicatorsRenderer.java    |   49 +++++-
 src/com/gitblit/client/Translation.java           |   57 ++++++++
 src/com/gitblit/client/GitblitPanel.java          |   61 ++++----
 build.xml                                         |    1 
 src/com/gitblit/client/EditRepositoryDialog.java  |  130 +++++++++++++++---
 src/com/gitblit/client/RepositoriesModel.java     |   20 ++
 src/com/gitblit/client/EditUserDialog.java        |   30 ++--
 src/com/gitblit/build/Build.java                  |    8 +
 12 files changed, 309 insertions(+), 105 deletions(-)

diff --git a/build.xml b/build.xml
index 96da02d..97df46c 100644
--- a/build.xml
+++ b/build.xml
@@ -434,6 +434,7 @@
 			<resource file="${basedir}/resources/book_16x16.png" />
 			<resource file="${basedir}/resources/bug_16x16.png" />
 			<resource file="${basedir}/resources/blank.png" />
+			<resource file="${basedir}/src/com/gitblit/wicket/GitBlitWebApp.properties" />
 				
 			<class name="com.gitblit.client.GitblitClientLauncher" />
 			<classfilter>
diff --git a/src/com/gitblit/build/Build.java b/src/com/gitblit/build/Build.java
index 5589c5f..1f6642d 100644
--- a/src/com/gitblit/build/Build.java
+++ b/src/com/gitblit/build/Build.java
@@ -139,6 +139,8 @@
 		downloadListener = listener;
 		downloadFromApache(MavenObject.GSON, BuildType.RUNTIME);
 		downloadFromApache(MavenObject.JSCH, BuildType.RUNTIME);
+		downloadFromApache(MavenObject.SLF4JAPI, BuildType.RUNTIME);
+		downloadFromApache(MavenObject.SLF4JNOP, BuildType.RUNTIME);
 		
 		downloadFromEclipse(MavenObject.JGIT, BuildType.RUNTIME);
 	}
@@ -389,6 +391,12 @@
 				"46a386136c901748e6a3af67ebde6c22bc6b4524",
 				"e223571d77769cdafde59040da235842f3326453");
 
+		public static final MavenObject SLF4JNOP = new MavenObject("SLF4J NOP", "org/slf4j",
+				"slf4j-nop", "1.6.1", 4800, 4100, 32300,
+				"70249094d4e5653b6bdfea46f3a1a4165c1e1993",
+				"4a8e77f7bf6897a3c3b7fc3acb4c862dfb905baa",
+				"24b2b46f9025f2db53b5b32143f7832538fa3178");
+
 		public static final MavenObject SLF4LOG4J = new MavenObject("SLF4J LOG4J", "org/slf4j",
 				"slf4j-log4j12", "1.6.1", 9800, 9500, 52400,
 				"bd245d6746cdd4e6203e976e21d597a46f115802",
diff --git a/src/com/gitblit/client/EditRepositoryDialog.java b/src/com/gitblit/client/EditRepositoryDialog.java
index 756128a..49d9047 100644
--- a/src/com/gitblit/client/EditRepositoryDialog.java
+++ b/src/com/gitblit/client/EditRepositoryDialog.java
@@ -16,6 +16,7 @@
 package com.gitblit.client;
 
 import java.awt.BorderLayout;
+import java.awt.Component;
 import java.awt.Dimension;
 import java.awt.FlowLayout;
 import java.awt.Font;
@@ -32,9 +33,11 @@
 import javax.swing.JComponent;
 import javax.swing.JDialog;
 import javax.swing.JLabel;
+import javax.swing.JList;
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JTextField;
+import javax.swing.ListCellRenderer;
 
 import com.gitblit.Constants.AccessRestrictionType;
 import com.gitblit.Constants.FederationStrategy;
@@ -42,6 +45,11 @@
 import com.gitblit.models.UserModel;
 import com.gitblit.utils.StringUtils;
 
+/**
+ * Dialog to create/edit a repository.
+ * 
+ * @author James Moger
+ */
 public class EditRepositoryDialog extends JDialog {
 
 	private static final long serialVersionUID = 1L;
@@ -76,7 +84,7 @@
 
 	public EditRepositoryDialog(List<UserModel> allusers) {
 		this(new RepositoryModel(), allusers);
-		setTitle("Create Repository");
+		setTitle(Translation.get("gb.newRepository"));
 	}
 
 	public EditRepositoryDialog(RepositoryModel aRepository, List<UserModel> allUsers) {
@@ -84,7 +92,7 @@
 		this.repository = new RepositoryModel();
 		initialize(aRepository, allUsers);
 		setModal(true);
-		setTitle("Edit Repository: " + aRepository.name);
+		setTitle(Translation.get("gb.edit") + ": " + aRepository.name);
 		setIconImage(new ImageIcon(getClass().getResource("/gitblt-favicon.png")).getImage());
 	}
 
@@ -105,48 +113,56 @@
 			owner.setSelectedItem(currentOwner);
 		}
 
-		useTickets = new JCheckBox("distributed Ticgit issues", anRepository.useTickets);
-		useDocs = new JCheckBox("enumerates Markdown documentation in repository",
-				anRepository.useDocs);
-		showRemoteBranches = new JCheckBox("show remote branches", anRepository.showRemoteBranches);
-		showReadme = new JCheckBox("show a \"readme\" Markdown file on the summary page",
+		useTickets = new JCheckBox(Translation.get("gb.useTicketsDescription"),
+				anRepository.useTickets);
+		useDocs = new JCheckBox(Translation.get("gb.useDocsDescription"), anRepository.useDocs);
+		showRemoteBranches = new JCheckBox(Translation.get("gb.showRemoteBranchesDescription"),
+				anRepository.showRemoteBranches);
+		showReadme = new JCheckBox(Translation.get("gb.showReadmeDescription"),
 				anRepository.showReadme);
-		isFrozen = new JCheckBox("deny push operations", anRepository.isFrozen);
+		isFrozen = new JCheckBox(Translation.get("gb.isFrozenDescription"), anRepository.isFrozen);
 
 		accessRestriction = new JComboBox(AccessRestrictionType.values());
+		accessRestriction.setRenderer(new AccessRestrictionRenderer());
 		accessRestriction.setSelectedItem(anRepository.accessRestriction);
 
 		federationStrategy = new JComboBox(FederationStrategy.values());
+		federationStrategy.setRenderer(new FederationStrategyRenderer());
 		federationStrategy.setSelectedItem(anRepository.federationStrategy);
 
 		JPanel fieldsPanel = new JPanel(new GridLayout(0, 1));
-		fieldsPanel.add(newFieldPanel("name", nameField));
-		fieldsPanel.add(newFieldPanel("description", descriptionField));
-		fieldsPanel.add(newFieldPanel("owner", owner));
+		fieldsPanel.add(newFieldPanel(Translation.get("gb.name"), nameField));
+		fieldsPanel.add(newFieldPanel(Translation.get("gb.description"), descriptionField));
+		fieldsPanel.add(newFieldPanel(Translation.get("gb.owner"), owner));
 
-		fieldsPanel.add(newFieldPanel("enable tickets", useTickets));
-		fieldsPanel.add(newFieldPanel("enable docs", useDocs));
-		fieldsPanel.add(newFieldPanel("show remote branches", showRemoteBranches));
-		fieldsPanel.add(newFieldPanel("show readme", showReadme));
-		fieldsPanel.add(newFieldPanel("is frozen", isFrozen));
+		fieldsPanel.add(newFieldPanel(Translation.get("gb.enableTickets"), useTickets));
+		fieldsPanel.add(newFieldPanel(Translation.get("gb.enableDocs"), useDocs));
+		fieldsPanel
+				.add(newFieldPanel(Translation.get("gb.showRemoteBranches"), showRemoteBranches));
+		fieldsPanel.add(newFieldPanel(Translation.get("gb.showReadme"), showReadme));
+		fieldsPanel.add(newFieldPanel(Translation.get("gb.isFrozen"), isFrozen));
 
 		usersPalette = new JPalette<String>();
 		JPanel accessPanel = new JPanel(new BorderLayout(5, 5));
-		accessPanel.add(newFieldPanel("access restriction", accessRestriction), BorderLayout.NORTH);
-		accessPanel.add(newFieldPanel("permitted users", usersPalette), BorderLayout.CENTER);
+		accessPanel.add(newFieldPanel(Translation.get("gb.accessRestriction"), accessRestriction),
+				BorderLayout.NORTH);
+		accessPanel.add(newFieldPanel(Translation.get("gb.permittedUsers"), usersPalette),
+				BorderLayout.CENTER);
 
 		setsPalette = new JPalette<String>();
 		JPanel federationPanel = new JPanel(new BorderLayout(5, 5));
-		federationPanel.add(newFieldPanel("federation strategy", federationStrategy),
+		federationPanel.add(
+				newFieldPanel(Translation.get("gb.federationStrategy"), federationStrategy),
 				BorderLayout.NORTH);
-		federationPanel.add(newFieldPanel("federation sets", setsPalette), BorderLayout.CENTER);
+		federationPanel.add(newFieldPanel(Translation.get("gb.federationSets"), setsPalette),
+				BorderLayout.CENTER);
 
 		JPanel panel = new JPanel(new BorderLayout(5, 5));
 		panel.add(fieldsPanel, BorderLayout.NORTH);
 		panel.add(accessPanel, BorderLayout.CENTER);
 		panel.add(federationPanel, BorderLayout.SOUTH);
 
-		JButton createButton = new JButton("Save");
+		JButton createButton = new JButton(Translation.get("gb.save"));
 		createButton.addActionListener(new ActionListener() {
 			public void actionPerformed(ActionEvent event) {
 				if (validateFields()) {
@@ -156,7 +172,7 @@
 			}
 		});
 
-		JButton cancelButton = new JButton("Cancel");
+		JButton cancelButton = new JButton(Translation.get("gb.cancel"));
 		cancelButton.addActionListener(new ActionListener() {
 			public void actionPerformed(ActionEvent event) {
 				canceled = true;
@@ -203,8 +219,8 @@
 	}
 
 	private void showValidationError(String message) {
-		JOptionPane.showMessageDialog(EditRepositoryDialog.this, message, "Validation Error",
-				JOptionPane.ERROR_MESSAGE);
+		JOptionPane.showMessageDialog(EditRepositoryDialog.this, message,
+				Translation.get("gb.error"), JOptionPane.ERROR_MESSAGE);
 	}
 
 	public void setUsers(List<String> all, List<String> selected) {
@@ -221,4 +237,70 @@
 		}
 		return repository;
 	}
+
+	/**
+	 * ListCellRenderer to display descriptive text about the access
+	 * restriction.
+	 * 
+	 */
+	private class AccessRestrictionRenderer extends JLabel implements ListCellRenderer {
+
+		private static final long serialVersionUID = 1L;
+
+		@Override
+		public Component getListCellRendererComponent(JList list, Object value, int index,
+				boolean isSelected, boolean cellHasFocus) {
+			if (value instanceof AccessRestrictionType) {
+				AccessRestrictionType restriction = (AccessRestrictionType) value;
+				switch (restriction) {
+				case NONE:
+					setText(Translation.get("gb.notRestricted"));
+					break;
+				case PUSH:
+					setText(Translation.get("gb.pushRestricted"));
+					break;
+				case CLONE:
+					setText(Translation.get("gb.cloneRestricted"));
+					break;
+				case VIEW:
+					setText(Translation.get("gb.viewRestricted"));
+					break;
+				}
+			} else {
+				setText(value.toString());
+			}
+			return this;
+		}
+	}
+
+	/**
+	 * ListCellRenderer to display descriptive text about the federation
+	 * strategy.
+	 */
+	private class FederationStrategyRenderer extends JLabel implements ListCellRenderer {
+
+		private static final long serialVersionUID = 1L;
+
+		@Override
+		public Component getListCellRendererComponent(JList list, Object value, int index,
+				boolean isSelected, boolean cellHasFocus) {
+			if (value instanceof FederationStrategy) {
+				FederationStrategy strategy = (FederationStrategy) value;
+				switch (strategy) {
+				case EXCLUDE:
+					setText(Translation.get("gb.excludeFromFederation"));
+					break;
+				case FEDERATE_THIS:
+					setText(Translation.get("gb.federateThis"));
+					break;
+				case FEDERATE_ORIGIN:
+					setText(Translation.get("gb.federateOrigin"));
+					break;
+				}
+			} else {
+				setText(value.toString());
+			}
+			return this;
+		}
+	}
 }
diff --git a/src/com/gitblit/client/EditUserDialog.java b/src/com/gitblit/client/EditUserDialog.java
index 5fce8c5..e2f6417 100644
--- a/src/com/gitblit/client/EditUserDialog.java
+++ b/src/com/gitblit/client/EditUserDialog.java
@@ -70,7 +70,7 @@
 
 	public EditUserDialog(IStoredSettings settings) {
 		this(new UserModel(""), settings);
-		setTitle("Create User");
+		setTitle(Translation.get("gb.newUser"));
 	}
 
 	public EditUserDialog(UserModel anUser, IStoredSettings settings) {
@@ -79,7 +79,7 @@
 		this.settings = settings;
 		initialize(anUser);
 		setModal(true);
-		setTitle("Edit User: " + anUser.username);
+		setTitle(Translation.get("gb.edit") + ": " + anUser.username);
 		setIconImage(new ImageIcon(getClass().getResource("/gitblt-favicon.png")).getImage());
 	}
 
@@ -88,24 +88,26 @@
 		passwordField = new JPasswordField(anUser.password == null ? "" : anUser.password, 25);
 		confirmPasswordField = new JPasswordField(anUser.password == null ? "" : anUser.password,
 				25);
-		canAdminCheckbox = new JCheckBox("can administer Gitblit server", anUser.canAdmin);
+		canAdminCheckbox = new JCheckBox(Translation.get("gb.canAdminDescription"), anUser.canAdmin);
 		notFederatedCheckbox = new JCheckBox(
-				"block federated Gitblit instances from pulling this account",
+				Translation.get("gb.excludeFromFederationDescription"),
 				anUser.excludeFromFederation);
 
 		JPanel fieldsPanel = new JPanel(new GridLayout(0, 1));
-		fieldsPanel.add(newFieldPanel("username", usernameField));
-		fieldsPanel.add(newFieldPanel("password", passwordField));
-		fieldsPanel.add(newFieldPanel("confirm password", confirmPasswordField));
-		fieldsPanel.add(newFieldPanel("can admin", canAdminCheckbox));
-		fieldsPanel.add(newFieldPanel("exclude from federation", notFederatedCheckbox));
+		fieldsPanel.add(newFieldPanel(Translation.get("gb.username"), usernameField));
+		fieldsPanel.add(newFieldPanel(Translation.get("gb.password"), passwordField));
+		fieldsPanel.add(newFieldPanel(Translation.get("gb.confirmPassword"), confirmPasswordField));
+		fieldsPanel.add(newFieldPanel(Translation.get("gb.canAdmin"), canAdminCheckbox));
+		fieldsPanel.add(newFieldPanel(Translation.get("gb.excludeFromFederation"),
+				notFederatedCheckbox));
 
 		repositoryPalette = new JPalette<String>();
 		JPanel panel = new JPanel(new BorderLayout());
 		panel.add(fieldsPanel, BorderLayout.NORTH);
-		panel.add(newFieldPanel("restricted repositories", repositoryPalette), BorderLayout.CENTER);
+		panel.add(newFieldPanel(Translation.get("gb.restrictedRepositories"), repositoryPalette),
+				BorderLayout.CENTER);
 
-		JButton createButton = new JButton("Save");
+		JButton createButton = new JButton(Translation.get("gb.save"));
 		createButton.addActionListener(new ActionListener() {
 			public void actionPerformed(ActionEvent event) {
 				if (validateFields()) {
@@ -115,7 +117,7 @@
 			}
 		});
 
-		JButton cancelButton = new JButton("Cancel");
+		JButton cancelButton = new JButton(Translation.get("gb.cancel"));
 		cancelButton.addActionListener(new ActionListener() {
 			public void actionPerformed(ActionEvent event) {
 				canceled = true;
@@ -164,7 +166,7 @@
 		}
 
 		// TODO verify username uniqueness on create
-		
+
 		// if (isCreate) {
 		// UserModel model = GitBlit.self().getUserModel(username);
 		// if (model != null) {
@@ -210,7 +212,7 @@
 	}
 
 	private void showValidationError(String message) {
-		JOptionPane.showMessageDialog(EditUserDialog.this, message, "Validation Error",
+		JOptionPane.showMessageDialog(EditUserDialog.this, message, Translation.get("gb.error"),
 				JOptionPane.ERROR_MESSAGE);
 	}
 
diff --git a/src/com/gitblit/client/GitblitClient.java b/src/com/gitblit/client/GitblitClient.java
index 65a8c36..d66fdea 100644
--- a/src/com/gitblit/client/GitblitClient.java
+++ b/src/com/gitblit/client/GitblitClient.java
@@ -18,6 +18,7 @@
 import java.awt.BorderLayout;
 import java.awt.Dimension;
 import java.awt.EventQueue;
+import java.awt.Font;
 import java.awt.GridLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
@@ -92,11 +93,11 @@
 
 	private JMenuBar setupMenu() {
 		JMenuBar menuBar = new JMenuBar();
-		JMenu serversMenu = new JMenu("Servers");
+		JMenu serversMenu = new JMenu(Translation.get("gb.servers"));
 		menuBar.add(serversMenu);
-		recentMenu = new JMenu("Recent");
+		recentMenu = new JMenu(Translation.get("gb.recent"));
 		serversMenu.add(recentMenu);
-		JMenuItem login = new JMenuItem("Login...");
+		JMenuItem login = new JMenuItem(Translation.get("gb.login") + "...");
 		login.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_L, KeyEvent.CTRL_DOWN_MASK, false));
 		login.addActionListener(new ActionListener() {
 			public void actionPerformed(ActionEvent event) {
@@ -109,6 +110,7 @@
 
 	private JPanel newLabelPanel(String text, JTextField field) {
 		JLabel label = new JLabel(text);
+		label.setFont(label.getFont().deriveFont(Font.BOLD));
 		label.setPreferredSize(new Dimension(75, 10));
 		JPanel jpanel = new JPanel(new BorderLayout());
 		jpanel.add(label, BorderLayout.WEST);
@@ -132,13 +134,13 @@
 		JPasswordField passwordField = new JPasswordField(new String(reg.password));
 
 		JPanel panel = new JPanel(new GridLayout(0, 1, 5, 5));
-		panel.add(newLabelPanel("name", nameField));
-		panel.add(newLabelPanel("url", urlField));
-		panel.add(newLabelPanel("account", accountField));
-		panel.add(newLabelPanel("password", passwordField));
+		panel.add(newLabelPanel(Translation.get("gb.name"), nameField));
+		panel.add(newLabelPanel(Translation.get("gb.url"), urlField));
+		panel.add(newLabelPanel(Translation.get("gb.username"), accountField));
+		panel.add(newLabelPanel(Translation.get("gb.password"), passwordField));
 
-		int result = JOptionPane.showConfirmDialog(GitblitClient.this, panel, "Login",
-				JOptionPane.OK_CANCEL_OPTION);
+		int result = JOptionPane.showConfirmDialog(GitblitClient.this, panel,
+				Translation.get("gb.login"), JOptionPane.OK_CANCEL_OPTION);
 		if (result != JOptionPane.OK_OPTION) {
 			return false;
 		}
@@ -165,8 +167,8 @@
 					panel));
 			return true;
 		} catch (IOException e) {
-			JOptionPane.showMessageDialog(GitblitClient.this, e.getMessage(), "Error",
-					JOptionPane.ERROR_MESSAGE);
+			JOptionPane.showMessageDialog(GitblitClient.this, e.getMessage(),
+					Translation.get("gb.error"), JOptionPane.ERROR_MESSAGE);
 		}
 		return false;
 	}
diff --git a/src/com/gitblit/client/GitblitClientLauncher.java b/src/com/gitblit/client/GitblitClientLauncher.java
index 24832d1..463dc96 100644
--- a/src/com/gitblit/client/GitblitClientLauncher.java
+++ b/src/com/gitblit/client/GitblitClientLauncher.java
@@ -44,14 +44,13 @@
 		DownloadListener downloadListener = new DownloadListener() {
 			@Override
 			public void downloading(String name) {
-				updateSplash(splash, "Downloading " + name + "...");				
+				updateSplash(splash, Translation.get("gb.downloading") + " " + name + "...");				
 			}
 		};
 		
 		// download rpc client runtime dependencies
 		Build.rpcClient(downloadListener);
 
-		updateSplash(splash, "Scanning Library Folder...");
 		File libFolder = new File("ext");
 		List<File> jars = Launcher.findJars(libFolder.getAbsoluteFile());
 		
@@ -61,14 +60,14 @@
 		Collections.reverse(jars);
 		for (File jar : jars) {
 			try {
-				updateSplash(splash, "Loading " + jar.getName() + "...");
+				updateSplash(splash, Translation.get("gb.loading") + " " + jar.getName() + "...");
 				Launcher.addJarFile(jar);
 			} catch (IOException e) {
 
 			}
 		}
 		
-		updateSplash(splash, "Starting Gitblit RPC Client...");
+		updateSplash(splash, Translation.get("gb.starting") + " Gitblit RPC Client...");
 		GitblitClient.main(args);
 	}
 
diff --git a/src/com/gitblit/client/GitblitPanel.java b/src/com/gitblit/client/GitblitPanel.java
index d29f2a9..ec7385e 100644
--- a/src/com/gitblit/client/GitblitPanel.java
+++ b/src/com/gitblit/client/GitblitPanel.java
@@ -108,7 +108,7 @@
 
 	private NameRenderer nameRenderer;
 
-	private TypeRenderer typeRenderer;
+	private IndicatorsRenderer typeRenderer;
 
 	private DefaultTableCellRenderer ownerRenderer;
 
@@ -127,7 +127,7 @@
 		this.account = account;
 		this.password = password;
 
-		final JButton browseRepository = new JButton("Browse");
+		final JButton browseRepository = new JButton(Translation.get("gb.browse"));
 		browseRepository.setEnabled(false);
 		browseRepository.addActionListener(new ActionListener() {
 			public void actionPerformed(ActionEvent e) {
@@ -142,7 +142,7 @@
 			}
 		});
 
-		JButton refreshRepositories = new JButton("Refresh");
+		JButton refreshRepositories = new JButton(Translation.get("gb.refresh"));
 		refreshRepositories.addActionListener(new ActionListener() {
 			public void actionPerformed(ActionEvent e) {
 				try {
@@ -157,14 +157,14 @@
 			}
 		});
 
-		createRepository = new JButton("Create");
+		createRepository = new JButton(Translation.get("gb.create"));
 		createRepository.addActionListener(new ActionListener() {
 			public void actionPerformed(ActionEvent e) {
 				createRepository();
 			}
 		});
 
-		final JButton editRepository = new JButton("Edit");
+		final JButton editRepository = new JButton(Translation.get("gb.edit"));
 		editRepository.setEnabled(false);
 		editRepository.addActionListener(new ActionListener() {
 			public void actionPerformed(ActionEvent e) {
@@ -172,7 +172,7 @@
 			}
 		});
 
-		delRepository = new JButton("Delete");
+		delRepository = new JButton(Translation.get("gb.delete"));
 		delRepository.setEnabled(false);
 		delRepository.addActionListener(new ActionListener() {
 			public void actionPerformed(ActionEvent e) {
@@ -180,7 +180,7 @@
 			}
 		});
 
-		final JButton cloneRepository = new JButton("Clone");
+		final JButton cloneRepository = new JButton(Translation.get("gb.clone"));
 		cloneRepository.setEnabled(false);
 		cloneRepository.addActionListener(new ActionListener() {
 			public void actionPerformed(ActionEvent e) {
@@ -191,7 +191,7 @@
 		});
 
 		nameRenderer = new NameRenderer();
-		typeRenderer = new TypeRenderer();
+		typeRenderer = new IndicatorsRenderer();
 
 		sizeRenderer = new DefaultTableCellRenderer();
 		sizeRenderer.setHorizontalAlignment(SwingConstants.RIGHT);
@@ -216,7 +216,7 @@
 		repositoriesTable.setDefaultRenderer(Date.class,
 				new DateCellRenderer(null, Color.orange.darker()));
 		setRenderer(RepositoriesModel.Columns.Name, nameRenderer);
-		setRenderer(RepositoriesModel.Columns.Type, typeRenderer);
+		setRenderer(RepositoriesModel.Columns.Indicators, typeRenderer);
 		setRenderer(RepositoriesModel.Columns.Owner, ownerRenderer);
 		setRenderer(RepositoriesModel.Columns.Size, sizeRenderer);
 
@@ -252,7 +252,7 @@
 		});
 
 		JPanel filterPanel = new JPanel(new BorderLayout(margin, margin));
-		filterPanel.add(new JLabel("Filter"), BorderLayout.WEST);
+		filterPanel.add(new JLabel(Translation.get("gb.filter")), BorderLayout.WEST);
 		filterPanel.add(repositoryFilter, BorderLayout.CENTER);
 
 		JPanel tablePanel = new JPanel(new BorderLayout(margin, margin));
@@ -267,11 +267,12 @@
 		repositoryControls.add(delRepository);
 
 		JPanel repositoriesPanel = new JPanel(new BorderLayout(margin, margin));
-		repositoriesPanel.add(newHeaderLabel("Repositories"), BorderLayout.NORTH);
+		repositoriesPanel.add(newHeaderLabel(Translation.get("gb.repositories")),
+				BorderLayout.NORTH);
 		repositoriesPanel.add(tablePanel, BorderLayout.CENTER);
 		repositoriesPanel.add(repositoryControls, BorderLayout.SOUTH);
 
-		JButton refreshUsers = new JButton("Refresh");
+		JButton refreshUsers = new JButton(Translation.get("gb.refresh"));
 		refreshUsers.addActionListener(new ActionListener() {
 			public void actionPerformed(ActionEvent e) {
 				try {
@@ -286,14 +287,14 @@
 			}
 		});
 
-		JButton createUser = new JButton("Create");
+		JButton createUser = new JButton(Translation.get("gb.create"));
 		createUser.addActionListener(new ActionListener() {
 			public void actionPerformed(ActionEvent e) {
 				createUser();
 			}
 		});
 
-		final JButton editUser = new JButton("Edit");
+		final JButton editUser = new JButton(Translation.get("gb.edit"));
 		editUser.setEnabled(false);
 		editUser.addActionListener(new ActionListener() {
 			public void actionPerformed(ActionEvent e) {
@@ -301,7 +302,7 @@
 			}
 		});
 
-		final JButton delUser = new JButton("Delete");
+		final JButton delUser = new JButton(Translation.get("gb.delete"));
 		delUser.setEnabled(false);
 		delUser.addActionListener(new ActionListener() {
 			public void actionPerformed(ActionEvent e) {
@@ -331,7 +332,7 @@
 		userControls.add(delUser);
 
 		usersPanel = new JPanel(new BorderLayout(margin, margin));
-		usersPanel.add(newHeaderLabel("Users"), BorderLayout.NORTH);
+		usersPanel.add(newHeaderLabel(Translation.get("gb.users")), BorderLayout.NORTH);
 		usersPanel.add(new JScrollPane(usersList), BorderLayout.CENTER);
 		usersPanel.add(userControls, BorderLayout.SOUTH);
 
@@ -343,8 +344,8 @@
 		mainPanel.add(usersPanel, BorderLayout.EAST);
 
 		tabs = new JTabbedPane(JTabbedPane.BOTTOM);
-		tabs.addTab("Main", mainPanel);
-		tabs.addTab("Federation", new JPanel());
+		tabs.addTab(Translation.get("gb.repositories"), mainPanel);
+		tabs.addTab(Translation.get("gb.federation"), new JPanel());
 
 		setLayout(new BorderLayout());
 		add(tabs, BorderLayout.CENTER);
@@ -541,8 +542,8 @@
 						String msg = MessageFormat.format(
 								"Failed to execute request \"{0}\" for repository \"{1}\".",
 								request.name(), newRepository.name);
-						JOptionPane.showMessageDialog(GitblitPanel.this, msg, "Error!",
-								JOptionPane.ERROR_MESSAGE);
+						JOptionPane.showMessageDialog(GitblitPanel.this, msg,
+								Translation.get("gb.error"), JOptionPane.ERROR_MESSAGE);
 					}
 				} catch (ForbiddenException e) {
 					explainForbidden(request);
@@ -597,8 +598,8 @@
 						String msg = MessageFormat.format(
 								"Failed to execute request \"{0}\" for repository \"{1}\".",
 								request.name(), repository.name);
-						JOptionPane.showMessageDialog(GitblitPanel.this, msg, "Error!",
-								JOptionPane.ERROR_MESSAGE);
+						JOptionPane.showMessageDialog(GitblitPanel.this, msg,
+								Translation.get("gb.error"), JOptionPane.ERROR_MESSAGE);
 					}
 				} catch (ForbiddenException e) {
 					explainForbidden(request);
@@ -642,8 +643,8 @@
 							refreshRepositoriesTable();
 						} else {
 							String msg = "Failed to delete specified repositories!";
-							JOptionPane.showMessageDialog(GitblitPanel.this, msg, "Error!",
-									JOptionPane.ERROR_MESSAGE);
+							JOptionPane.showMessageDialog(GitblitPanel.this, msg,
+									Translation.get("gb.error"), JOptionPane.ERROR_MESSAGE);
 						}
 					} catch (ForbiddenException e) {
 						explainForbidden(request);
@@ -690,8 +691,8 @@
 						String msg = MessageFormat.format(
 								"Failed to execute request \"{0}\" for user \"{1}\".",
 								request.name(), newUser.username);
-						JOptionPane.showMessageDialog(GitblitPanel.this, msg, "Error!",
-								JOptionPane.ERROR_MESSAGE);
+						JOptionPane.showMessageDialog(GitblitPanel.this, msg,
+								Translation.get("gb.error"), JOptionPane.ERROR_MESSAGE);
 					}
 				} catch (ForbiddenException e) {
 					explainForbidden(request);
@@ -738,8 +739,8 @@
 						String msg = MessageFormat.format(
 								"Failed to execute request \"{0}\" for user \"{1}\".",
 								request.name(), user.username);
-						JOptionPane.showMessageDialog(GitblitPanel.this, msg, "Error!",
-								JOptionPane.ERROR_MESSAGE);
+						JOptionPane.showMessageDialog(GitblitPanel.this, msg,
+								Translation.get("gb.error"), JOptionPane.ERROR_MESSAGE);
 					}
 				} catch (ForbiddenException e) {
 					explainForbidden(request);
@@ -783,8 +784,8 @@
 							refreshUsersTable();
 						} else {
 							String msg = "Failed to delete specified users!";
-							JOptionPane.showMessageDialog(GitblitPanel.this, msg, "Error!",
-									JOptionPane.ERROR_MESSAGE);
+							JOptionPane.showMessageDialog(GitblitPanel.this, msg,
+									Translation.get("gb.error"), JOptionPane.ERROR_MESSAGE);
 						}
 					} catch (ForbiddenException e) {
 						explainForbidden(request);
diff --git a/src/com/gitblit/client/TypeRenderer.java b/src/com/gitblit/client/IndicatorsRenderer.java
similarity index 69%
rename from src/com/gitblit/client/TypeRenderer.java
rename to src/com/gitblit/client/IndicatorsRenderer.java
index 8f92dcf..8c13122 100644
--- a/src/com/gitblit/client/TypeRenderer.java
+++ b/src/com/gitblit/client/IndicatorsRenderer.java
@@ -34,7 +34,7 @@
  * @author James Moger
  * 
  */
-public class TypeRenderer extends JPanel implements TableCellRenderer, Serializable {
+public class IndicatorsRenderer extends JPanel implements TableCellRenderer, Serializable {
 
 	private static final long serialVersionUID = 1L;
 
@@ -54,7 +54,7 @@
 
 	private final ImageIcon federatedIcon;
 
-	public TypeRenderer() {
+	public IndicatorsRenderer() {
 		super(new GridLayout(1, 0, 1, 0));
 		blankIcon = new ImageIcon(getClass().getResource("/blank.png"));
 		pushIcon = new ImageIcon(getClass().getResource("/lock_go_16x16.png"));
@@ -75,44 +75,67 @@
 			setBackground(table.getBackground());
 		removeAll();
 		if (value instanceof RepositoryModel) {
+			StringBuilder tooltip = new StringBuilder();
 			RepositoryModel model = (RepositoryModel) value;
 			if (model.useTickets) {
-				add(new JLabel(tixIcon));
+				JLabel icon = new JLabel(tixIcon);
+				tooltip.append(Translation.get("gb.tickets")).append("<br/>");
+				add(icon);
 			} else {
 				add(new JLabel(blankIcon));
 			}
 			if (model.useDocs) {
-				add(new JLabel(doxIcon));
+				JLabel icon = new JLabel(doxIcon);
+				tooltip.append(Translation.get("gb.docs")).append("<br/>");
+				add(icon);
 			} else {
 				add(new JLabel(blankIcon));
 			}
 			if (model.isFrozen) {
-				add(new JLabel(frozenIcon));
+				JLabel icon = new JLabel(frozenIcon);
+				tooltip.append(Translation.get("gb.isFrozen")).append("<br/>");
+				add(icon);
 			} else {
 				add(new JLabel(blankIcon));
 			}
 			if (model.isFederated) {
-				add(new JLabel(federatedIcon));
+				JLabel icon = new JLabel(federatedIcon);
+				tooltip.append(Translation.get("gb.isFederated")).append("<br/>");
+				add(icon);
 			} else {
 				add(new JLabel(blankIcon));
 			}
 
 			switch (model.accessRestriction) {
-			case NONE:
+			case NONE: {
 				add(new JLabel(blankIcon));
 				break;
-			case PUSH:
-				add(new JLabel(pushIcon));
+			}
+			case PUSH: {
+				JLabel icon = new JLabel(pushIcon);
+				tooltip.append(Translation.get("gb.pushRestricted")).append("<br/>");
+				add(icon);
 				break;
-			case CLONE:
-				add(new JLabel(pullIcon));
+			}
+			case CLONE: {
+				JLabel icon = new JLabel(pullIcon);
+				tooltip.append(Translation.get("gb.pullRestricted")).append("<br/>");
+				add(icon);
 				break;
-			case VIEW:
-				add(new JLabel(viewIcon));
+			}
+			case VIEW: {
+				JLabel icon = new JLabel(viewIcon);
+				tooltip.append(Translation.get("gb.viewRestricted")).append("<br/>");
+				add(icon);
 				break;
+			}
 			default:
 				add(new JLabel(blankIcon));
 			}
+			if (tooltip.length() > 0) {
+				tooltip.insert(0, "<html><body>");
+				setToolTipText(tooltip.toString().trim());
+			}
 		}
 		return this;
 	}
diff --git a/src/com/gitblit/client/JPalette.java b/src/com/gitblit/client/JPalette.java
index 19456e1..eb445b4 100644
--- a/src/com/gitblit/client/JPalette.java
+++ b/src/com/gitblit/client/JPalette.java
@@ -18,6 +18,7 @@
 import java.awt.BorderLayout;
 import java.awt.Color;
 import java.awt.Dimension;
+import java.awt.Font;
 import java.awt.GridBagLayout;
 import java.awt.GridLayout;
 import java.awt.event.ActionEvent;
@@ -92,9 +93,9 @@
 		JPanel center = new JPanel(new GridBagLayout());
 		center.add(controls);
 
-		add(newListPanel("Available", available), BorderLayout.WEST);
+		add(newListPanel(Translation.get("gb.available"), available), BorderLayout.WEST);
 		add(center, BorderLayout.CENTER);
-		add(newListPanel("Selected", selected), BorderLayout.EAST);
+		add(newListPanel(Translation.get("gb.selected"), selected), BorderLayout.EAST);
 	}
 
 	private JPanel newListPanel(String label, JTable table) {
@@ -110,7 +111,9 @@
 		JScrollPane jsp = new JScrollPane(table);
 		jsp.setPreferredSize(new Dimension(225, 175));
 		JPanel panel = new JPanel(new BorderLayout());
-		panel.add(new JLabel(label), BorderLayout.NORTH);
+		JLabel jlabel = new JLabel(label);
+		jlabel.setFont(jlabel.getFont().deriveFont(Font.BOLD));
+		panel.add(jlabel, BorderLayout.NORTH);
 		panel.add(jsp, BorderLayout.CENTER);
 		return panel;
 	}
@@ -161,7 +164,7 @@
 
 		@Override
 		public String getColumnName(int column) {
-			return "Name";
+			return Translation.get("gb.name");
 		}
 
 		public Class<?> getColumnClass(int columnIndex) {
diff --git a/src/com/gitblit/client/RepositoriesModel.java b/src/com/gitblit/client/RepositoriesModel.java
index d8e448f..c1fead9 100644
--- a/src/com/gitblit/client/RepositoriesModel.java
+++ b/src/com/gitblit/client/RepositoriesModel.java
@@ -37,7 +37,7 @@
 	List<RepositoryModel> list;
 
 	enum Columns {
-		Name, Description, Owner, Type, Last_Change, Size;
+		Name, Description, Owner, Indicators, Last_Change, Size;
 
 		@Override
 		public String toString() {
@@ -67,7 +67,19 @@
 	@Override
 	public String getColumnName(int column) {
 		Columns col = Columns.values()[column];
-		return col.toString();
+		switch (col) {
+		case Name:
+			return Translation.get("gb.name");
+		case Description:
+			return Translation.get("gb.description");
+		case Owner:
+			return Translation.get("gb.owner");
+		case Last_Change:
+			return Translation.get("gb.lastChange");
+		case Size:
+			return Translation.get("gb.size");
+		}
+		return "";
 	}
 
 	/**
@@ -81,7 +93,7 @@
 		Columns col = Columns.values()[columnIndex];
 		switch (col) {
 		case Name:
-		case Type:
+		case Indicators:
 			return RepositoryModel.class;
 		case Last_Change:
 			return Date.class;
@@ -100,7 +112,7 @@
 			return model.description;
 		case Owner:
 			return model.owner;
-		case Type:
+		case Indicators:
 			return model;
 		case Last_Change:
 			return model.lastChange;
diff --git a/src/com/gitblit/client/Translation.java b/src/com/gitblit/client/Translation.java
new file mode 100644
index 0000000..cd5515b
--- /dev/null
+++ b/src/com/gitblit/client/Translation.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2011 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit.client;
+
+import java.io.InputStream;
+import java.util.Properties;
+
+public class Translation {
+
+	private final static Properties translation;
+
+	static {
+		translation = new Properties();
+		InputStream is = null;
+		try {
+			is = Translation.class.getResource("/com/gitblit/wicket/GitBlitWebApp.properties")
+					.openStream();
+		} catch (Throwable t) {
+			try {
+				is = Translation.class.getResource("/GitBlitWebApp.properties").openStream();
+			} catch (Throwable x) {
+			}
+		}
+		if (is != null) {
+			try {
+				translation.load(is);
+			} catch (Throwable t) {
+
+			} finally {
+				try {
+					is.close();
+				} catch (Throwable t) {
+				}
+			}
+		}
+	}
+
+	public static String get(String key) {
+		if (translation.containsKey(key)) {
+			return translation.getProperty(key).trim();
+		}
+		return key;
+	}
+}
diff --git a/src/com/gitblit/wicket/GitBlitWebApp.properties b/src/com/gitblit/wicket/GitBlitWebApp.properties
index 30fac60..c7ee6ce 100644
--- a/src/com/gitblit/wicket/GitBlitWebApp.properties
+++ b/src/com/gitblit/wicket/GitBlitWebApp.properties
@@ -140,4 +140,18 @@
 gb.destinationUrl = send to
 gb.destinationUrlDescription = the url of the Gitblit instance to send your proposal
 gb.users = users
-gb.federation = federation
\ No newline at end of file
+gb.federation = federation
+gb.error = error
+gb.refresh = refresh
+gb.browse = browse
+gb.clone = clone
+gb.filter = filter
+gb.create = create
+gb.servers = servers
+gb.recent = recent
+gb.available = available
+gb.selected = selected
+gb.size = size
+gb.downloading = downloading
+gb.loading = loading
+gb.starting = starting
\ No newline at end of file

--
Gitblit v1.9.1