add language menu
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sat, 5 Apr 2008 18:25:37 +0000 (18:25 +0000)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sat, 5 Apr 2008 18:25:37 +0000 (18:25 +0000)
git-svn-id: http://trooper/svn/projects/jSite/trunk@612 c3eda9e8-030b-0410-8277-bc7414b0a119

src/net/pterodactylus/jsite/gui/I18nMenu.java [new file with mode: 0644]
src/net/pterodactylus/jsite/gui/MainWindow.java
src/net/pterodactylus/jsite/gui/SwingInterface.java
src/net/pterodactylus/jsite/i18n/I18n.java
src/net/pterodactylus/jsite/i18n/jSite.properties
src/net/pterodactylus/jsite/i18n/jSite_de.properties [new file with mode: 0644]

diff --git a/src/net/pterodactylus/jsite/gui/I18nMenu.java b/src/net/pterodactylus/jsite/gui/I18nMenu.java
new file mode 100644 (file)
index 0000000..2b64211
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * jSite2 - I18nMenu.java -
+ * Copyright © 2008 David Roden
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+package net.pterodactylus.jsite.gui;
+
+import javax.swing.JMenu;
+
+import net.pterodactylus.jsite.i18n.I18n;
+import net.pterodactylus.jsite.i18n.I18nable;
+
+/**
+ * Menu that receives its properties from {@link I18n}.
+ * 
+ * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
+ * @version $Id$
+ */
+public class I18nMenu extends JMenu implements I18nable {
+
+       /** The {@link I18n} basename. */
+       private final String i18nBasename;
+
+       /**
+        * Creates a new menu with the given {@link I18n} basename.
+        * 
+        * @param i18nBasename
+        *            The basename of the {@link I18n} properties
+        */
+       public I18nMenu(String i18nBasename) {
+               this.i18nBasename = i18nBasename;
+               updateI18n();
+       }
+
+       //
+       // INTERFACE I18nable
+       //
+
+       /**
+        * {@inheritDoc}
+        */
+       public void updateI18n() {
+               setText(I18n.get(i18nBasename + ".name"));
+               setMnemonic(I18n.getKey(i18nBasename + ".mnemonic"));
+       }
+
+}
index 1142818..97b9fe5 100644 (file)
@@ -24,7 +24,6 @@ import java.awt.Container;
 import java.awt.Dimension;
 
 import javax.swing.JFrame;
-import javax.swing.JMenu;
 import javax.swing.JMenuBar;
 import javax.swing.JPanel;
 import javax.swing.JToolBar;
@@ -52,6 +51,12 @@ public class MainWindow extends JFrame implements I18nable {
        /** The content pane. */
        private JPanel contentPane = new JPanel();
 
+       /** The node menu. */
+       private I18nMenu nodeMenu;
+
+       /** The language menu. */
+       private I18nMenu languageMenu;
+
        /**
         * Creates a new main window that redirects all actions to the given swing
         * interface.
@@ -94,15 +99,21 @@ public class MainWindow extends JFrame implements I18nable {
        private void initWindow() {
                JMenuBar menuBar = new JMenuBar();
 
-               final JMenu nodeMenu = new JMenu(I18n.get("mainWindow.menu.node.name"));
+               nodeMenu = new I18nMenu("mainWindow.menu.node");
                menuBar.add(nodeMenu);
-               nodeMenu.setMnemonic(I18n.get("mainWindow.menu.node.mnemonic").charAt(0));
 
                nodeMenu.add(swingInterface.getManageNodesAction());
                nodeMenu.addSeparator();
                nodeMenu.add(swingInterface.getNodeConnectAction());
                nodeMenu.add(swingInterface.getNodeDisconnectAction());
 
+               languageMenu = new I18nMenu("mainWindow.menu.language");
+               menuBar.add(languageMenu);
+
+               for (I18nAction languageAction: swingInterface.getLanguageActions()) {
+                       languageMenu.add(languageAction);
+               }
+
                setJMenuBar(menuBar);
 
                JToolBar toolBar = new JToolBar(I18n.get("mainWindow.toolbar.name"));
@@ -142,6 +153,9 @@ public class MainWindow extends JFrame implements I18nable {
                swingInterface.getManageNodesAction().updateI18n();
                swingInterface.getNodeConnectAction().updateI18n();
                swingInterface.getNodeDisconnectAction().updateI18n();
+               nodeMenu.updateI18n();
+               languageMenu.updateI18n();
+               getJMenuBar().revalidate();
                SwingUtils.repackCentered(this);
        }
 
index 4a0c97f..91e4a58 100644 (file)
 package net.pterodactylus.jsite.gui;
 
 import java.awt.event.ActionEvent;
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Locale;
 
 import net.pterodactylus.jsite.core.Core;
 import net.pterodactylus.jsite.core.CoreListener;
 import net.pterodactylus.jsite.core.Node;
+import net.pterodactylus.jsite.i18n.I18n;
 
 /**
  * TODO
@@ -52,6 +55,9 @@ public class SwingInterface implements CoreListener {
        /** The node manager dialog. */
        private ManageNodesDialog manageNodesDialog;
 
+       /** All lanugage menu items. */
+       private List<I18nAction> languageActions = new ArrayList<I18nAction>();
+
        /** The list of all defined nodes. */
        private List<Node> nodeList;
 
@@ -63,6 +69,7 @@ public class SwingInterface implements CoreListener {
         */
        public SwingInterface(Core core) {
                this.core = core;
+               I18n.setLocale(Locale.ENGLISH); /* TODO - load config */
                initActions();
                initDialogs();
        }
@@ -116,6 +123,15 @@ public class SwingInterface implements CoreListener {
                return nodeDisconnectAction;
        }
 
+       /**
+        * Returns all language actions.
+        * 
+        * @return All language actions
+        */
+       List<I18nAction> getLanguageActions() {
+               return languageActions;
+       }
+
        //
        // ACTIONS
        //
@@ -167,6 +183,25 @@ public class SwingInterface implements CoreListener {
                                nodeDisconnect();
                        }
                };
+               List<Locale> availableLanguages = I18n.findAvailableLanguages();
+               for (final Locale locale: availableLanguages) {
+                       System.out.println("adding locale “" + locale.getLanguage() + "”");
+                       I18nAction languageAction = new I18nAction("general.language." + locale.getLanguage()) {
+
+                               @SuppressWarnings("synthetic-access")
+                               public void actionPerformed(ActionEvent e) {
+                                       System.out.println("changing locale to: " + locale);
+                                       changeLanguage(locale, this);
+                               }
+
+                       };
+                       System.out.println("locale: " + locale + ", i18n: " + I18n.getLocale());
+                       if (I18n.getLocale().getLanguage().equals(locale.getLanguage())) {
+                               languageAction.setEnabled(false);
+                       }
+                       languageActions.add(languageAction);
+               }
+
        }
 
        /**
@@ -176,6 +211,10 @@ public class SwingInterface implements CoreListener {
                manageNodesDialog = new ManageNodesDialog(this);
        }
 
+       //
+       // PRIVATE ACTIONS
+       //
+
        /**
         * Pops up the “manage nodes” dialog.
         */
@@ -197,6 +236,22 @@ public class SwingInterface implements CoreListener {
        private void nodeDisconnect() {
        }
 
+       /**
+        * Changes the language of the interface. This method also disables the
+        * action for the newly set language and enables all others.
+        * 
+        * @param newLocale
+        *            The new language
+        * @param languageAction
+        *            The action that triggered the change
+        */
+       private void changeLanguage(Locale newLocale, I18nAction languageAction) {
+               for (I18nAction i18nAction: languageActions) {
+                       i18nAction.setEnabled(i18nAction != languageAction);
+               }
+               I18n.setLocale(newLocale);
+       }
+
        //
        // INTERFACE CoreListener
        //
index 0acdced..504dc88 100644 (file)
@@ -44,6 +44,9 @@ import net.pterodactylus.util.io.Closer;
  */
 public class I18n {
 
+       /** List of I18nables that are notified when the language changes. */
+       private static final List<I18nable> i18nables = new ArrayList<I18nable>();
+
        /** The current locale. */
        private static Locale currentLocale;
 
@@ -64,12 +67,9 @@ public class I18n {
                } catch (IOException e) {
                        /* something is fucked. */
                }
-               setLocale(Locale.getDefault());
+               setLocale(Locale.getDefault(), false);
        }
 
-       /** List of I18nables that are notified when the language changes. */
-       private static final List<I18nable> i18nables = new ArrayList<I18nable>();
-
        /**
         * Returns the translated value for a key. The translated values may contain
         * placeholders that are replaced with the given parameters.
@@ -105,7 +105,10 @@ public class I18n {
         * @return The keycode
         */
        public static int getKey(String key) {
-               String value = get(key);
+               String value = currentLanguage.getProperty(key);
+               if (value == null) {
+                       return -1;
+               }
                if (value.startsWith("VK_")) {
                        try {
                                Field field = KeyEvent.class.getField(value);
@@ -132,7 +135,7 @@ public class I18n {
         *         created from the translated value
         */
        public static KeyStroke getKeyStroke(String key) {
-               String value = get(key);
+               String value = currentLanguage.getProperty(key);
                if (value == null) {
                        return null;
                }
@@ -174,14 +177,35 @@ public class I18n {
         *            The new locale to use
         */
        public static void setLocale(Locale newLocale) {
+               setLocale(newLocale, true);
+       }
+
+       /**
+        * Sets the current locale.
+        * 
+        * @param newLocale
+        *            The new locale to use
+        * @param notify
+        *            <code>true</code> to notify registered {@link I18nable}s
+        *            after the language was changed
+        */
+       private static void setLocale(Locale newLocale, boolean notify) {
                currentLocale = newLocale;
                InputStream inputStream = null;
                try {
                        currentLanguage = new Properties(defaultLanguage);
-                       inputStream = I18n.class.getResourceAsStream("jSite_" + currentLocale.toString() + ".properties");
+                       if (newLocale == Locale.ENGLISH) {
+                               if (notify) {
+                                       notifyI18nables();
+                               }
+                               return;
+                       }
+                       inputStream = I18n.class.getResourceAsStream("jSite_" + newLocale.getLanguage() + ".properties");
                        if (inputStream != null) {
                                currentLanguage.load(inputStream);
-                               notifyI18nables();
+                               if (notify) {
+                                       notifyI18nables();
+                               }
                        }
                } catch (MissingResourceException mre1) {
                        currentLocale = Locale.ENGLISH;
@@ -193,6 +217,27 @@ public class I18n {
        }
 
        /**
+        * Returns the current locale.
+        * 
+        * @return The current locale
+        */
+       public static Locale getLocale() {
+               return currentLocale;
+       }
+
+       /**
+        * Finds all available locales.
+        * 
+        * @return All available locales
+        */
+       public static List<Locale> findAvailableLanguages() {
+               List<Locale> availableLanguages = new ArrayList<Locale>();
+               availableLanguages.add(Locale.ENGLISH);
+               availableLanguages.add(Locale.GERMAN);
+               return availableLanguages;
+       }
+
+       /**
         * Registers the given I18nable to be updated when the language is changed.
         * 
         * @param i18nable
index 2459687..728aeba 100644 (file)
@@ -18,12 +18,21 @@ general.button.cancel.accelerator: VK_ESCAPE
 general.button.cancel.shortDescription: Cancel
 general.button.cancel.longDescription: Don\u2019t Save Node Settings and Close Dialog
 
+general.language.en.name: English
+general.language.en.mnemonic: VK_E
+
+general.language.de.name: German
+general.language.de.mnemonic: VK_G
+
 # main window
 mainWindow.toolbar.name: jSite Toolbar
 
 # main menus
 mainWindow.menu.node.name: Node
-mainWindow.menu.node.mnemonic: n
+mainWindow.menu.node.mnemonic: VK_N
+
+mainWindow.menu.language.name: Languages
+mainWindow.menu.language.mnemonic: VK_L
 
 #
 # the node menu
diff --git a/src/net/pterodactylus/jsite/i18n/jSite_de.properties b/src/net/pterodactylus/jsite/i18n/jSite_de.properties
new file mode 100644 (file)
index 0000000..9cfac1f
--- /dev/null
@@ -0,0 +1,115 @@
+# jSite i18n data, English
+#
+# this file should be in US-ASCII format, with unicode characters outside
+# US-ASCII range encoded with the java-typical \u notation.
+
+# use small letters for mnemonics, use large letters for accelerators.
+
+# general gui components
+general.button.okay.name: OK
+general.button.okay.mnemonic: VK_O
+general.button.okay.accelerator: Ctrl-VK_O
+general.button.okay.shortDescription: \u00c4nderungen akzeptieren
+general.button.okay.longDescription: Dialog schlie\u00dfen und \u00c4nderungen akzeptieren
+
+general.button.cancel.name: Abbrechen
+general.button.cancel.mnemonic: VK_B
+general.button.cancel.accelerator: VK_ESCAPE
+general.button.cancel.shortDescription: Abbrechen
+general.button.cancel.longDescription: Dialog schlie\u00dfen und \u00c4nderungen verwerfen
+
+general.language.en.name: Englisch
+general.language.en.mnemonic: VK_E
+
+general.language.de.name: Deutsch
+general.language.de.mnemonic: VK_D
+
+# main window
+mainWindow.toolbar.name: jSite Toolbar
+
+# main menus
+mainWindow.menu.node.name: Node
+mainWindow.menu.node.mnemonic: VK_N
+
+mainWindow.menu.languages.name: Sprachen
+mainWindow.menu.languages.mnemonic: VK_S
+
+#
+# the node menu
+#
+
+#manage nodes
+mainWindow.menu.node.item.manageNodes.name: Nodes verwalten
+mainWindow.menu.node.item.manageNodes.mnemonic: VK_N
+mainWindow.menu.node.item.manageNodes.accelerator: Ctrl-VK_N
+mainWindow.menu.node.item.manageNodes.shortDescription: Nodes verwalten
+mainWindow.menu.node.item.manageNodes.longDescription: Nodes verwalten
+
+# connect to node
+mainWindow.menu.node.item.connect.name: Verbinden
+mainWindow.menu.node.item.connect.mnemonic: VK_V
+mainWindow.menu.node.item.connect.accelerator: Ctrl-VK_V
+mainWindow.menu.node.item.connect.shortDescription: Mit Node verbinden
+mainWindow.menu.node.item.connect.longDescription: Verbindung zum Node herstellen
+
+#disconnect from node
+mainWindow.menu.node.item.disconnect.name: Verbindung trennen
+mainWindow.menu.node.item.disconnect.mnemonic: VK_T
+mainWindow.menu.node.item.disconnect.accelerator: Ctrl-VK_T
+mainWindow.menu.node.item.disconnect.shortDescription: Von Node trennen 
+mainWindow.menu.node.item.disconnect.longDescription: Verbindung zum Node trennen
+
+#
+# the "manage nodes" dialog
+#
+
+manageNodesDialog.title: Nodes verwalten
+
+manageNodesDialog.button.addNode.name: Node hinzuf\u00fcgen
+manageNodesDialog.button.addNode.mnemonic: VK_H
+manageNodesDialog.button.addNode.accelerator: Ctrl-VK_H
+manageNodesDialog.button.addNode.shortDescription: Node hinzuf\u00fcgen
+manageNodesDialog.button.addNode.longDescription: Einen Node hinzuf\u00fcgen
+
+manageNodesDialog.button.editNode.name: Edit Node
+manageNodesDialog.button.editNode.mnemonic: e
+manageNodesDialog.button.editNode.accelerator: Ctrl-VK_E
+manageNodesDialog.button.editNode.shortDescription: Edit Selected Node
+
+manageNodesDialog.button.deleteNode.name: Delete Node
+manageNodesDialog.button.deleteNode.mnemonic: d
+manageNodesDialog.button.deleteNode.accelerator: Ctrl-VK_D
+manageNodesDialog.button.deleteNode.shortDescription: Delete Selected Node(s)
+
+manageNodesDialog.error.nodeListEmpty.title: Node List Empty
+manageNodesDialog.error.nodeListEmpty.message: The node list is empty.
+
+manageNodesDialog.error.nodeConnected.title: Node Is Connected
+manageNodesDialog.error.nodeConnected.message: The Node \u201c{0}\u201d is still connected. Do you really want to delete it?
+
+# the "edit node" dialog
+editNodeDialog.title: Edit Node
+
+editNodeDialog.label.name.name: Name
+editNodeDialog.label.name.mnemonic: n
+
+editNodeDialog.label.hostname.name: Hostname
+editNodeDialog.label.hostname.mnemonic: h
+
+editNodeDialog.label.port.name: Port
+editNodeDialog.label.port.mnemonic: p
+
+editNodeDialog.checkbox.sameMachine.name: Node on the same machine
+editNodeDialog.checkbox.sameMachine.mnemonic: s
+editNodeDialog.checkbox.sameMachine.accelerator: Alt-VK_S
+editNodeDialog.checkbox.sameMachine.shortDescription: Node is on the same machine
+editNodeDialog.checkbox.sameMachine.longDescription: The node is on the same machine as jSite and some optimizations can be used
+
+editNodeDialog.error.name.title: Wrong Node Name
+editNodeDialog.error.name.message: The name of the node is empty.
+
+editNodeDialog.error.hostname.title: Wrong Hostname
+editNodeDialog.error.hostname.message: The hostname is invalid.
+
+editNodeDialog.error.port.title: Wrong Port Number
+editNodeDialog.error.port.message: The port number is invalid.