Cleanup, imported i18n support from I2P and GNU gettext.
Imported high res/svg version of itoopie from dr|zed.
This commit is contained in:
@ -1,10 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project basedir="." default="all" name="desktopgui">
|
<project basedir="." default="all" name="itoopie">
|
||||||
|
|
||||||
<property name="src" value="src"/>
|
<property name="src" value="src"/>
|
||||||
<property name="build" value="build"/>
|
<property name="build" value="build"/>
|
||||||
<property name="dist" location="dist"/>
|
<property name="dist" location="dist"/>
|
||||||
<property name="jar" value="desktopgui.jar"/>
|
<property name="jar" value="itoopie.jar"/>
|
||||||
<property name="resources" value="resources"/>
|
<property name="resources" value="resources"/>
|
||||||
<property name="javadoc" value="javadoc"/>
|
<property name="javadoc" value="javadoc"/>
|
||||||
|
|
||||||
@ -33,7 +33,7 @@
|
|||||||
<pathelement location="../../router/java/build/router.jar" />
|
<pathelement location="../../router/java/build/router.jar" />
|
||||||
</classpath>
|
</classpath>
|
||||||
</javac>
|
</javac>
|
||||||
<copy todir="${build}/desktopgui/${resources}">
|
<copy todir="${build}/itoopie/${resources}">
|
||||||
<fileset dir="${resources}" />
|
<fileset dir="${resources}" />
|
||||||
</copy>
|
</copy>
|
||||||
</target>
|
</target>
|
||||||
@ -48,7 +48,7 @@
|
|||||||
|
|
||||||
<jar basedir="${build}" destfile="${dist}/${jar}">
|
<jar basedir="${build}" destfile="${dist}/${jar}">
|
||||||
<manifest>
|
<manifest>
|
||||||
<attribute name="Main-Class" value="net.i2p.desktopgui.Main"/>
|
<attribute name="Main-Class" value="net.i2p.itoopie.Main"/>
|
||||||
</manifest>
|
</manifest>
|
||||||
</jar>
|
</jar>
|
||||||
</target>
|
</target>
|
||||||
@ -61,7 +61,7 @@
|
|||||||
packagenames="*"
|
packagenames="*"
|
||||||
use="true"
|
use="true"
|
||||||
splitindex="true"
|
splitindex="true"
|
||||||
windowtitle="Desktopgui">
|
windowtitle="itoopie">
|
||||||
<classpath>
|
<classpath>
|
||||||
<pathelement location="../../router/java/build/router.jar" />
|
<pathelement location="../../router/java/build/router.jar" />
|
||||||
<pathelement location="../../core/java/build/i2p.jar" />
|
<pathelement location="../../core/java/build/i2p.jar" />
|
||||||
@ -69,7 +69,8 @@
|
|||||||
</javadoc>
|
</javadoc>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="poupdate">
|
<target name="poupdate" depends="init">
|
||||||
|
|
||||||
<exec executable="sh" osfamily="unix" failifexecutionfails="true" >
|
<exec executable="sh" osfamily="unix" failifexecutionfails="true" >
|
||||||
<arg value="./bundle-messages.sh" />
|
<arg value="./bundle-messages.sh" />
|
||||||
<arg value="-p" />
|
<arg value="-p" />
|
||||||
|
@ -9,8 +9,9 @@
|
|||||||
#
|
#
|
||||||
# zzz - public domain
|
# zzz - public domain
|
||||||
# Mathiasdm - modifications for desktopgui
|
# Mathiasdm - modifications for desktopgui
|
||||||
|
# hottuna - modifications for itoopie
|
||||||
#
|
#
|
||||||
CLASS=net.i2p.desktopgui.messages
|
CLASS=net.i2p.itoopie.messages
|
||||||
TMPFILE=build/javafiles.txt
|
TMPFILE=build/javafiles.txt
|
||||||
export TZ=UTC
|
export TZ=UTC
|
||||||
|
|
||||||
@ -19,7 +20,7 @@ then
|
|||||||
POUPDATE=1
|
POUPDATE=1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# add ../java/ so the refs will work in the po file
|
# add ../src/ so the refs will work in the po file
|
||||||
JPATHS="src"
|
JPATHS="src"
|
||||||
for i in locale/messages_*.po
|
for i in locale/messages_*.po
|
||||||
do
|
do
|
||||||
@ -34,8 +35,8 @@ do
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo $LG
|
echo $LG
|
||||||
if [ -s build/net/i2p/desktopgui/messages_$LG.class -a \
|
if [ -s build/net/i2p/itoopie/messages_$LG.class -a \
|
||||||
build/net/i2p/desktopgui/messages_$LG.class -nt $i -a \
|
build/net/i2p/itoopie/messages_$LG.class -nt $i -a \
|
||||||
! -s $TMPFILE ]
|
! -s $TMPFILE ]
|
||||||
then
|
then
|
||||||
continue
|
continue
|
||||||
@ -57,10 +58,10 @@ do
|
|||||||
# To start a new translation, copy the header from an old translation to the new .po file,
|
# To start a new translation, copy the header from an old translation to the new .po file,
|
||||||
# then ant distclean updater.
|
# then ant distclean updater.
|
||||||
find $JPATHS -name *.java > $TMPFILE
|
find $JPATHS -name *.java > $TMPFILE
|
||||||
xgettext -f $TMPFILE -F -L java --from-code=UTF-8 --add-comments\
|
xgettext -f $TMPFILE -F -L java --verbose --from-code=UTF-8 --add-comments\
|
||||||
--keyword=_ --keyword=_x --keyword=intl._ --keyword=intl.title \
|
--keyword=_ --keyword=_x --keyword=intl._ --keyword=intl.title \
|
||||||
--keyword=handler._ --keyword=formhandler._ \
|
--keyword=handler._ --keyword=formhandler._ \
|
||||||
--keyword=net.i2p.router.web.Messages.getString \
|
--keyword=net.i2p.itoopie.i18n.ItoopieTranslator.getString \
|
||||||
-o ${i}t
|
-o ${i}t
|
||||||
if [ $? -ne 0 ]
|
if [ $? -ne 0 ]
|
||||||
then
|
then
|
||||||
|
269
apps/itoopie/src/gnu/gettext/GettextResource.java
Normal file
269
apps/itoopie/src/gnu/gettext/GettextResource.java
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
/* GNU gettext for Java
|
||||||
|
* Copyright (C) 2001, 2007 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Library General Public License as published
|
||||||
|
* by the Free Software Foundation; either version 2, 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
* USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package gnu.gettext;
|
||||||
|
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class implements the main GNU libintl functions in Java.
|
||||||
|
* <P>
|
||||||
|
* Using the GNU gettext approach, compiled message catalogs are normal
|
||||||
|
* Java ResourceBundle classes and are thus interoperable with standard
|
||||||
|
* ResourceBundle based code.
|
||||||
|
* <P>
|
||||||
|
* The main differences between the Sun ResourceBundle approach and the
|
||||||
|
* GNU gettext approach are:
|
||||||
|
* <UL>
|
||||||
|
* <LI>In the Sun approach, the keys are abstract textual shortcuts.
|
||||||
|
* In the GNU gettext approach, the keys are the English/ASCII version
|
||||||
|
* of the messages.
|
||||||
|
* <LI>In the Sun approach, the translation files are called
|
||||||
|
* "<VAR>Resource</VAR>_<VAR>locale</VAR>.properties" and have non-ASCII
|
||||||
|
* characters encoded in the Java
|
||||||
|
* <CODE>\</CODE><CODE>u<VAR>nnnn</VAR></CODE> syntax. Very few editors
|
||||||
|
* can natively display international characters in this format. In the
|
||||||
|
* GNU gettext approach, the translation files are called
|
||||||
|
* "<VAR>Resource</VAR>.<VAR>locale</VAR>.po"
|
||||||
|
* and are in the encoding the translator has chosen. Many editors
|
||||||
|
* can be used. There are at least three GUI translating tools
|
||||||
|
* (Emacs PO mode, KDE KBabel, GNOME gtranslator).
|
||||||
|
* <LI>In the Sun approach, the function
|
||||||
|
* <CODE>ResourceBundle.getString</CODE> throws a
|
||||||
|
* <CODE>MissingResourceException</CODE> when no translation is found.
|
||||||
|
* In the GNU gettext approach, the <CODE>gettext</CODE> function
|
||||||
|
* returns the (English) message key in that case.
|
||||||
|
* <LI>In the Sun approach, there is no support for plural handling.
|
||||||
|
* Even the most elaborate MessageFormat strings cannot provide decent
|
||||||
|
* plural handling. In the GNU gettext approach, we have the
|
||||||
|
* <CODE>ngettext</CODE> function.
|
||||||
|
* </UL>
|
||||||
|
* <P>
|
||||||
|
* To compile GNU gettext message catalogs into Java ResourceBundle classes,
|
||||||
|
* the <CODE>msgfmt</CODE> program can be used.
|
||||||
|
*
|
||||||
|
* @author Bruno Haible
|
||||||
|
*/
|
||||||
|
public abstract class GettextResource extends ResourceBundle {
|
||||||
|
|
||||||
|
public static boolean verbose = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like gettext(catalog,msgid), except that it returns <CODE>null</CODE>
|
||||||
|
* when no translation was found.
|
||||||
|
*/
|
||||||
|
private static String gettextnull (ResourceBundle catalog, String msgid) {
|
||||||
|
try {
|
||||||
|
return (String)catalog.getObject(msgid);
|
||||||
|
} catch (MissingResourceException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the translation of <VAR>msgid</VAR>.
|
||||||
|
* @param catalog a ResourceBundle
|
||||||
|
* @param msgid the key string to be translated, an ASCII string
|
||||||
|
* @return the translation of <VAR>msgid</VAR>, or <VAR>msgid</VAR> if
|
||||||
|
* none is found
|
||||||
|
*/
|
||||||
|
public static String gettext (ResourceBundle catalog, String msgid) {
|
||||||
|
String result = gettextnull(catalog,msgid);
|
||||||
|
if (result != null)
|
||||||
|
return result;
|
||||||
|
return msgid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like ngettext(catalog,msgid,msgid_plural,n), except that it returns
|
||||||
|
* <CODE>null</CODE> when no translation was found.
|
||||||
|
*/
|
||||||
|
private static String ngettextnull (ResourceBundle catalog, String msgid, long n) {
|
||||||
|
// The reason why we use so many reflective API calls instead of letting
|
||||||
|
// the GNU gettext generated ResourceBundles implement some interface,
|
||||||
|
// is that we want the generated ResourceBundles to be completely
|
||||||
|
// standalone, so that migration from the Sun approach to the GNU gettext
|
||||||
|
// approach (without use of plurals) is as straightforward as possible.
|
||||||
|
ResourceBundle origCatalog = catalog;
|
||||||
|
do {
|
||||||
|
// Try catalog itself.
|
||||||
|
if (verbose)
|
||||||
|
System.out.println("ngettext on "+catalog);
|
||||||
|
Method handleGetObjectMethod = null;
|
||||||
|
Method getParentMethod = null;
|
||||||
|
try {
|
||||||
|
handleGetObjectMethod = catalog.getClass().getMethod("handleGetObject", new Class[] { java.lang.String.class });
|
||||||
|
getParentMethod = catalog.getClass().getMethod("getParent", new Class[0]);
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
}
|
||||||
|
if (verbose)
|
||||||
|
System.out.println("handleGetObject = "+(handleGetObjectMethod!=null)+", getParent = "+(getParentMethod!=null));
|
||||||
|
if (handleGetObjectMethod != null
|
||||||
|
&& Modifier.isPublic(handleGetObjectMethod.getModifiers())
|
||||||
|
&& getParentMethod != null) {
|
||||||
|
// A GNU gettext created class.
|
||||||
|
Method lookupMethod = null;
|
||||||
|
Method pluralEvalMethod = null;
|
||||||
|
try {
|
||||||
|
lookupMethod = catalog.getClass().getMethod("lookup", new Class[] { java.lang.String.class });
|
||||||
|
pluralEvalMethod = catalog.getClass().getMethod("pluralEval", new Class[] { Long.TYPE });
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
}
|
||||||
|
if (verbose)
|
||||||
|
System.out.println("lookup = "+(lookupMethod!=null)+", pluralEval = "+(pluralEvalMethod!=null));
|
||||||
|
if (lookupMethod != null && pluralEvalMethod != null) {
|
||||||
|
// A GNU gettext created class with plural handling.
|
||||||
|
Object localValue = null;
|
||||||
|
try {
|
||||||
|
localValue = lookupMethod.invoke(catalog, new Object[] { msgid });
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
e.getTargetException().printStackTrace();
|
||||||
|
}
|
||||||
|
if (localValue != null) {
|
||||||
|
if (verbose)
|
||||||
|
System.out.println("localValue = "+localValue);
|
||||||
|
if (localValue instanceof String)
|
||||||
|
// Found the value. It doesn't depend on n in this case.
|
||||||
|
return (String)localValue;
|
||||||
|
else {
|
||||||
|
String[] pluralforms = (String[])localValue;
|
||||||
|
long i = 0;
|
||||||
|
try {
|
||||||
|
i = ((Long) pluralEvalMethod.invoke(catalog, new Object[] { new Long(n) })).longValue();
|
||||||
|
if (!(i >= 0 && i < pluralforms.length))
|
||||||
|
i = 0;
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
e.getTargetException().printStackTrace();
|
||||||
|
}
|
||||||
|
return pluralforms[(int)i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// A GNU gettext created class without plural handling.
|
||||||
|
Object localValue = null;
|
||||||
|
try {
|
||||||
|
localValue = handleGetObjectMethod.invoke(catalog, new Object[] { msgid });
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
e.getTargetException().printStackTrace();
|
||||||
|
}
|
||||||
|
if (localValue != null) {
|
||||||
|
// Found the value. It doesn't depend on n in this case.
|
||||||
|
if (verbose)
|
||||||
|
System.out.println("localValue = "+localValue);
|
||||||
|
return (String)localValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Object parentCatalog = catalog;
|
||||||
|
try {
|
||||||
|
parentCatalog = getParentMethod.invoke(catalog, new Object[0]);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
e.getTargetException().printStackTrace();
|
||||||
|
}
|
||||||
|
if (parentCatalog != catalog)
|
||||||
|
catalog = (ResourceBundle)parentCatalog;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
} else
|
||||||
|
// Not a GNU gettext created class.
|
||||||
|
break;
|
||||||
|
} while (catalog != null);
|
||||||
|
// The end of chain of GNU gettext ResourceBundles is reached.
|
||||||
|
if (catalog != null) {
|
||||||
|
// For a non-GNU ResourceBundle we cannot access 'parent' and
|
||||||
|
// 'handleGetObject', so make a single call to catalog and all
|
||||||
|
// its parent catalogs at once.
|
||||||
|
Object value;
|
||||||
|
try {
|
||||||
|
value = catalog.getObject(msgid);
|
||||||
|
} catch (MissingResourceException e) {
|
||||||
|
value = null;
|
||||||
|
}
|
||||||
|
if (value != null)
|
||||||
|
// Found the value. It doesn't depend on n in this case.
|
||||||
|
return (String)value;
|
||||||
|
}
|
||||||
|
// Default: null.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the plural form for <VAR>n</VAR> of the translation of
|
||||||
|
* <VAR>msgid</VAR>.
|
||||||
|
* @param catalog a ResourceBundle
|
||||||
|
* @param msgid the key string to be translated, an ASCII string
|
||||||
|
* @param msgid_plural its English plural form
|
||||||
|
* @return the translation of <VAR>msgid</VAR> depending on <VAR>n</VAR>,
|
||||||
|
* or <VAR>msgid</VAR> or <VAR>msgid_plural</VAR> if none is found
|
||||||
|
*/
|
||||||
|
public static String ngettext (ResourceBundle catalog, String msgid, String msgid_plural, long n) {
|
||||||
|
String result = ngettextnull(catalog,msgid,n);
|
||||||
|
if (result != null)
|
||||||
|
return result;
|
||||||
|
// Default: English strings and Germanic plural rule.
|
||||||
|
return (n != 1 ? msgid_plural : msgid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The separator between msgctxt and msgid. */
|
||||||
|
private static final String CONTEXT_GLUE = "\u0004";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the translation of <VAR>msgid</VAR> in the context of
|
||||||
|
* <VAR>msgctxt</VAR>.
|
||||||
|
* @param catalog a ResourceBundle
|
||||||
|
* @param msgctxt the context for the key string, an ASCII string
|
||||||
|
* @param msgid the key string to be translated, an ASCII string
|
||||||
|
* @return the translation of <VAR>msgid</VAR>, or <VAR>msgid</VAR> if
|
||||||
|
* none is found
|
||||||
|
*/
|
||||||
|
public static String pgettext (ResourceBundle catalog, String msgctxt, String msgid) {
|
||||||
|
String result = gettextnull(catalog,msgctxt+CONTEXT_GLUE+msgid);
|
||||||
|
if (result != null)
|
||||||
|
return result;
|
||||||
|
return msgid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the plural form for <VAR>n</VAR> of the translation of
|
||||||
|
* <VAR>msgid</VAR> in the context of <VAR>msgctxt</VAR>.
|
||||||
|
* @param catalog a ResourceBundle
|
||||||
|
* @param msgctxt the context for the key string, an ASCII string
|
||||||
|
* @param msgid the key string to be translated, an ASCII string
|
||||||
|
* @param msgid_plural its English plural form
|
||||||
|
* @return the translation of <VAR>msgid</VAR> depending on <VAR>n</VAR>,
|
||||||
|
* or <VAR>msgid</VAR> or <VAR>msgid_plural</VAR> if none is found
|
||||||
|
*/
|
||||||
|
public static String npgettext (ResourceBundle catalog, String msgctxt, String msgid, String msgid_plural, long n) {
|
||||||
|
String result = ngettextnull(catalog,msgctxt+CONTEXT_GLUE+msgid,n);
|
||||||
|
if (result != null)
|
||||||
|
return result;
|
||||||
|
// Default: English strings and Germanic plural rule.
|
||||||
|
return (n != 1 ? msgid_plural : msgid);
|
||||||
|
}
|
||||||
|
}
|
@ -1,52 +0,0 @@
|
|||||||
package net.i2p.desktopgui;
|
|
||||||
|
|
||||||
import java.awt.MenuItem;
|
|
||||||
import java.awt.PopupMenu;
|
|
||||||
import java.awt.TrayIcon;
|
|
||||||
import java.awt.event.ActionEvent;
|
|
||||||
import java.awt.event.ActionListener;
|
|
||||||
|
|
||||||
import javax.swing.SwingWorker;
|
|
||||||
|
|
||||||
import net.i2p.desktopgui.router.RouterManager;
|
|
||||||
import net.i2p.util.Log;
|
|
||||||
|
|
||||||
public class ExternalTrayManager extends TrayManager {
|
|
||||||
|
|
||||||
private final static Log log = new Log(ExternalTrayManager.class);
|
|
||||||
|
|
||||||
protected ExternalTrayManager() {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PopupMenu getMainMenu() {
|
|
||||||
PopupMenu popup = new PopupMenu();
|
|
||||||
MenuItem startItem = new MenuItem(_("Start I2P"));
|
|
||||||
startItem.addActionListener(new ActionListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent arg0) {
|
|
||||||
new SwingWorker<Object, Object>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Object doInBackground() throws Exception {
|
|
||||||
RouterManager.start();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void done() {
|
|
||||||
trayIcon.displayMessage(_("Starting"), _("I2P is starting!"), TrayIcon.MessageType.INFO);
|
|
||||||
//Hide the tray icon.
|
|
||||||
//We cannot stop the desktopgui program entirely,
|
|
||||||
//since that risks killing the I2P process as well.
|
|
||||||
tray.remove(trayIcon);
|
|
||||||
}
|
|
||||||
|
|
||||||
}.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
popup.add(startItem);
|
|
||||||
return popup;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,97 +0,0 @@
|
|||||||
package net.i2p.desktopgui;
|
|
||||||
|
|
||||||
import java.awt.AWTException;
|
|
||||||
import java.awt.Desktop;
|
|
||||||
import java.awt.Image;
|
|
||||||
import java.awt.MenuItem;
|
|
||||||
import java.awt.PopupMenu;
|
|
||||||
import java.awt.SystemTray;
|
|
||||||
import java.awt.Toolkit;
|
|
||||||
import java.awt.TrayIcon;
|
|
||||||
import java.awt.Desktop.Action;
|
|
||||||
import java.awt.event.ActionEvent;
|
|
||||||
import java.awt.event.ActionListener;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.net.URL;
|
|
||||||
|
|
||||||
import javax.swing.SwingWorker;
|
|
||||||
|
|
||||||
import net.i2p.desktopgui.i18n.DesktopguiTranslator;
|
|
||||||
import net.i2p.desktopgui.router.RouterManager;
|
|
||||||
import net.i2p.desktopgui.util.BrowseException;
|
|
||||||
import net.i2p.desktopgui.util.ConfigurationManager;
|
|
||||||
import net.i2p.desktopgui.util.I2PDesktop;
|
|
||||||
import net.i2p.util.Log;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manages the tray icon life.
|
|
||||||
*/
|
|
||||||
public abstract class TrayManager {
|
|
||||||
|
|
||||||
private static TrayManager instance = null;
|
|
||||||
///The tray area, or null if unsupported
|
|
||||||
protected SystemTray tray = null;
|
|
||||||
///Our tray icon, or null if unsupported
|
|
||||||
protected TrayIcon trayIcon = null;
|
|
||||||
private final static Log log = new Log(TrayManager.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiate tray manager.
|
|
||||||
*/
|
|
||||||
protected TrayManager() {}
|
|
||||||
|
|
||||||
protected static TrayManager getInstance() {
|
|
||||||
if(instance == null) {
|
|
||||||
boolean inI2P = RouterManager.inI2P();
|
|
||||||
if(inI2P) {
|
|
||||||
instance = new InternalTrayManager();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
instance = new ExternalTrayManager();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add the tray icon to the system tray and start everything up.
|
|
||||||
*/
|
|
||||||
protected void startManager() {
|
|
||||||
if(SystemTray.isSupported()) {
|
|
||||||
tray = SystemTray.getSystemTray();
|
|
||||||
trayIcon = new TrayIcon(getTrayImage(), "I2P", getMainMenu());
|
|
||||||
trayIcon.setImageAutoSize(true); //Resize image to fit the system tray
|
|
||||||
try {
|
|
||||||
tray.add(trayIcon);
|
|
||||||
} catch (AWTException e) {
|
|
||||||
log.log(Log.WARN, "Problem creating system tray icon!", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void languageChanged() {
|
|
||||||
trayIcon.setPopupMenu(getMainMenu());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build a popup menu, adding callbacks to the different items.
|
|
||||||
* @return popup menu
|
|
||||||
*/
|
|
||||||
protected abstract PopupMenu getMainMenu();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get tray icon image from the desktopgui resources in the jar file.
|
|
||||||
* @return image used for the tray icon
|
|
||||||
*/
|
|
||||||
private Image getTrayImage() {
|
|
||||||
URL url = getClass().getResource("/desktopgui/resources/images/logo.png");
|
|
||||||
Image image = Toolkit.getDefaultToolkit().getImage(url);
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static String _(String s) {
|
|
||||||
return DesktopguiTranslator._(s);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
package net.i2p.desktopgui.i18n;
|
|
||||||
|
|
||||||
import net.i2p.I2PAppContext;
|
|
||||||
import net.i2p.util.Translate;
|
|
||||||
|
|
||||||
public class DesktopguiTranslator {
|
|
||||||
|
|
||||||
private static final String BUNDLE_NAME = "net.i2p.desktopgui.messages";
|
|
||||||
|
|
||||||
private static I2PAppContext ctx;
|
|
||||||
|
|
||||||
private static I2PAppContext getRouterContext() {
|
|
||||||
if(ctx == null) {
|
|
||||||
ctx = I2PAppContext.getCurrentContext();
|
|
||||||
}
|
|
||||||
return ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String _(String s) {
|
|
||||||
return Translate.getString(s, getRouterContext(), BUNDLE_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String _(String s, Object o) {
|
|
||||||
return Translate.getString(s, o, getRouterContext(), BUNDLE_NAME);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
<html>
|
|
||||||
<body>
|
|
||||||
<p>Desktopgui is a graphical interface to I2P that allows managing the lifecycle of I2P from the system tray.</p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,98 +0,0 @@
|
|||||||
package net.i2p.desktopgui.router;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.tanukisoftware.wrapper.WrapperManager;
|
|
||||||
|
|
||||||
import net.i2p.I2PAppContext;
|
|
||||||
import net.i2p.desktopgui.i18n.DesktopguiTranslator;
|
|
||||||
import net.i2p.desktopgui.util.ConfigurationManager;
|
|
||||||
import net.i2p.router.Router;
|
|
||||||
import net.i2p.router.RouterContext;
|
|
||||||
import net.i2p.util.Log;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle communications with the router instance.
|
|
||||||
* @author mathias
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class RouterManager {
|
|
||||||
|
|
||||||
private final static Log log = new Log(RouterManager.class);
|
|
||||||
private static I2PAppContext context = I2PAppContext.getCurrentContext();
|
|
||||||
|
|
||||||
public static I2PAppContext getAppContext() {
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static RouterContext getRouterContext() throws Exception {
|
|
||||||
if(context.isRouterContext()) {
|
|
||||||
return (RouterContext) context;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new Exception("No RouterContext available!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Router getRouter() {
|
|
||||||
try {
|
|
||||||
return getRouterContext().router();
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Failed to get router. Why did we request it if no RouterContext is available?", e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start an I2P router instance.
|
|
||||||
* This method has limited knowledge
|
|
||||||
* (there is no I2P instance running to collect information from).
|
|
||||||
*
|
|
||||||
* It determines the I2P location using the I2PAppContext.
|
|
||||||
*/
|
|
||||||
public static void start() {
|
|
||||||
try {
|
|
||||||
//TODO: set/get PID
|
|
||||||
String separator = System.getProperty("file.separator");
|
|
||||||
String location = getAppContext().getBaseDir().getAbsolutePath();
|
|
||||||
|
|
||||||
Runtime.getRuntime().exec(location + separator + "i2psvc " + location + separator + "wrapper.config");
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.log(Log.WARN, "Failed to start I2P", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Restart the running I2P instance.
|
|
||||||
*/
|
|
||||||
public static void restart() {
|
|
||||||
if(inI2P()) {
|
|
||||||
getRouter().restart();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop the running I2P instance.
|
|
||||||
*/
|
|
||||||
public static void shutDown() {
|
|
||||||
if(inI2P()) {
|
|
||||||
Thread t = new Thread(new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
WrapperManager.signalStopped(Router.EXIT_HARD);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
t.start();
|
|
||||||
getRouter().shutdown(Router.EXIT_HARD);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if we are running inside I2P.
|
|
||||||
*/
|
|
||||||
public static boolean inI2P() {
|
|
||||||
return context.isRouterContext();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
package net.i2p.desktopgui;
|
package net.i2p.itoopie;
|
||||||
|
|
||||||
import java.awt.MenuItem;
|
import java.awt.MenuItem;
|
||||||
import java.awt.PopupMenu;
|
import java.awt.PopupMenu;
|
||||||
@ -7,14 +7,11 @@ import java.awt.event.ActionListener;
|
|||||||
|
|
||||||
import javax.swing.SwingWorker;
|
import javax.swing.SwingWorker;
|
||||||
|
|
||||||
import net.i2p.desktopgui.router.RouterManager;
|
import net.i2p.itoopie.util.BrowseException;
|
||||||
import net.i2p.desktopgui.util.BrowseException;
|
import net.i2p.itoopie.util.I2PDesktop;
|
||||||
import net.i2p.desktopgui.util.I2PDesktop;
|
|
||||||
import net.i2p.util.Log;
|
|
||||||
|
|
||||||
public class InternalTrayManager extends TrayManager {
|
public class InternalTrayManager extends TrayManager {
|
||||||
|
|
||||||
private final static Log log = new Log(InternalTrayManager.class);
|
|
||||||
|
|
||||||
protected InternalTrayManager() {}
|
protected InternalTrayManager() {}
|
||||||
|
|
||||||
@ -39,7 +36,7 @@ public class InternalTrayManager extends TrayManager {
|
|||||||
try {
|
try {
|
||||||
I2PDesktop.browse("http://localhost:7657");
|
I2PDesktop.browse("http://localhost:7657");
|
||||||
} catch (BrowseException e1) {
|
} catch (BrowseException e1) {
|
||||||
log.log(Log.WARN, "Failed to open browser!", e1);
|
//log.log(Log.WARN, "Failed to open browser!", e1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,7 +52,7 @@ public class InternalTrayManager extends TrayManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object doInBackground() throws Exception {
|
protected Object doInBackground() throws Exception {
|
||||||
RouterManager.restart();
|
//RouterManager.restart();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +70,7 @@ public class InternalTrayManager extends TrayManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object doInBackground() throws Exception {
|
protected Object doInBackground() throws Exception {
|
||||||
RouterManager.shutDown();
|
//RouterManager.shutDown();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package net.i2p.desktopgui;
|
package net.i2p.itoopie;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Main.java
|
* Main.java
|
||||||
@ -8,13 +8,6 @@ import javax.swing.SwingUtilities;
|
|||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.UnsupportedLookAndFeelException;
|
import javax.swing.UnsupportedLookAndFeelException;
|
||||||
|
|
||||||
import net.i2p.I2PAppContext;
|
|
||||||
import net.i2p.desktopgui.router.RouterManager;
|
|
||||||
import net.i2p.desktopgui.util.*;
|
|
||||||
import net.i2p.util.Log;
|
|
||||||
import net.i2p.util.Translate;
|
|
||||||
import net.i2p.util.I2PProperties.I2PPropertyCallback;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main class of the application.
|
* The main class of the application.
|
||||||
*/
|
*/
|
||||||
@ -22,7 +15,6 @@ public class Main {
|
|||||||
|
|
||||||
///Manages the lifetime of the tray icon.
|
///Manages the lifetime of the tray icon.
|
||||||
private TrayManager trayManager = null;
|
private TrayManager trayManager = null;
|
||||||
private final static Log log = new Log(Main.class);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start the tray icon code (loads tray icon in the tray area).
|
* Start the tray icon code (loads tray icon in the tray area).
|
||||||
@ -31,7 +23,7 @@ public class Main {
|
|||||||
public void startUp() throws Exception {
|
public void startUp() throws Exception {
|
||||||
trayManager = TrayManager.getInstance();
|
trayManager = TrayManager.getInstance();
|
||||||
trayManager.startManager();
|
trayManager.startManager();
|
||||||
|
/*
|
||||||
if(RouterManager.inI2P()) {
|
if(RouterManager.inI2P()) {
|
||||||
RouterManager.getRouterContext().addPropertyCallback(new I2PPropertyCallback() {
|
RouterManager.getRouterContext().addPropertyCallback(new I2PPropertyCallback() {
|
||||||
|
|
||||||
@ -44,6 +36,7 @@ public class Main {
|
|||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
@ -58,16 +51,16 @@ public class Main {
|
|||||||
try {
|
try {
|
||||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||||
} catch (ClassNotFoundException ex) {
|
} catch (ClassNotFoundException ex) {
|
||||||
log.log(Log.ERROR, null, ex);
|
//log.log(Log.ERROR, null, ex);
|
||||||
} catch (InstantiationException ex) {
|
} catch (InstantiationException ex) {
|
||||||
log.log(Log.ERROR, null, ex);
|
//log.log(Log.ERROR, null, ex);
|
||||||
} catch (IllegalAccessException ex) {
|
} catch (IllegalAccessException ex) {
|
||||||
log.log(Log.ERROR, null, ex);
|
//log.log(Log.ERROR, null, ex);
|
||||||
} catch (UnsupportedLookAndFeelException ex) {
|
} catch (UnsupportedLookAndFeelException ex) {
|
||||||
log.log(Log.ERROR, null, ex);
|
//log.log(Log.ERROR, null, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigurationManager.getInstance().loadArguments(args);
|
//ConfigurationManager.getInstance().loadArguments(args);
|
||||||
|
|
||||||
final Main main = new Main();
|
final Main main = new Main();
|
||||||
|
|
||||||
@ -81,7 +74,7 @@ public class Main {
|
|||||||
main.startUp();
|
main.startUp();
|
||||||
}
|
}
|
||||||
catch(Exception e) {
|
catch(Exception e) {
|
||||||
log.error("Failed while running desktopgui!", e);
|
//log.error("Failed while running desktopgui!", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
159
apps/itoopie/src/net/i2p/itoopie/TrayManager.java
Normal file
159
apps/itoopie/src/net/i2p/itoopie/TrayManager.java
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
package net.i2p.itoopie;
|
||||||
|
|
||||||
|
import java.awt.AWTException;
|
||||||
|
import java.awt.Desktop;
|
||||||
|
import java.awt.Image;
|
||||||
|
import java.awt.MenuItem;
|
||||||
|
import java.awt.PopupMenu;
|
||||||
|
import java.awt.SystemTray;
|
||||||
|
import java.awt.Toolkit;
|
||||||
|
import java.awt.TrayIcon;
|
||||||
|
import java.awt.Desktop.Action;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import javax.swing.SwingWorker;
|
||||||
|
|
||||||
|
import net.i2p.itoopie.i18n.ItoopieTranslator;
|
||||||
|
import net.i2p.itoopie.util.BrowseException;
|
||||||
|
import net.i2p.itoopie.util.ConfigurationManager;
|
||||||
|
import net.i2p.itoopie.util.I2PDesktop;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages the tray icon life.
|
||||||
|
*/
|
||||||
|
public abstract class TrayManager {
|
||||||
|
|
||||||
|
private static TrayManager instance = null;
|
||||||
|
///The tray area, or null if unsupported
|
||||||
|
protected SystemTray tray = null;
|
||||||
|
///Our tray icon, or null if unsupported
|
||||||
|
protected TrayIcon trayIcon = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate tray manager.
|
||||||
|
*/
|
||||||
|
protected TrayManager() {}
|
||||||
|
|
||||||
|
protected static synchronized TrayManager getInstance() {
|
||||||
|
if(instance == null) {
|
||||||
|
instance = new InternalTrayManager();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the tray icon to the system tray and start everything up.
|
||||||
|
*/
|
||||||
|
protected void startManager() {
|
||||||
|
if(SystemTray.isSupported()) {
|
||||||
|
tray = SystemTray.getSystemTray();
|
||||||
|
trayIcon = new TrayIcon(getTrayImage(), "I2P", getMainMenu());
|
||||||
|
trayIcon.setImageAutoSize(true); //Resize image to fit the system tray
|
||||||
|
try {
|
||||||
|
tray.add(trayIcon);
|
||||||
|
} catch (AWTException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void languageChanged() {
|
||||||
|
trayIcon.setPopupMenu(getMainMenu());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get tray icon image from the itoopie resources in the jar file.
|
||||||
|
* @return image used for the tray icon
|
||||||
|
*/
|
||||||
|
private Image getTrayImage() {
|
||||||
|
URL url = getClass().getResource("/itoopie/resources/images/itoopie-logo.png");
|
||||||
|
Image image = Toolkit.getDefaultToolkit().getImage(url);
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static String _(String s) {
|
||||||
|
return ItoopieTranslator._(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a popup menu, adding callbacks to the different items.
|
||||||
|
* @return popup menu
|
||||||
|
*/
|
||||||
|
public PopupMenu getMainMenu() {
|
||||||
|
PopupMenu popup = new PopupMenu();
|
||||||
|
|
||||||
|
MenuItem browserLauncher = new MenuItem(_("Launch I2P Browser"));
|
||||||
|
browserLauncher.addActionListener(new ActionListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent arg0) {
|
||||||
|
new SwingWorker<Object, Object>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object doInBackground() throws Exception {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void done() {
|
||||||
|
try {
|
||||||
|
I2PDesktop.browse("http://localhost:7657");
|
||||||
|
} catch (BrowseException e1) {
|
||||||
|
//log.log(Log.WARN, "Failed to open browser!", e1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}.execute();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
MenuItem restartItem = new MenuItem(_("Restart I2P"));
|
||||||
|
restartItem.addActionListener(new ActionListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent arg0) {
|
||||||
|
new SwingWorker<Object, Object>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object doInBackground() throws Exception {
|
||||||
|
//RouterManager.restart();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}.execute();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
MenuItem stopItem = new MenuItem(_("Stop I2P"));
|
||||||
|
stopItem.addActionListener(new ActionListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent arg0) {
|
||||||
|
new SwingWorker<Object, Object>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object doInBackground() throws Exception {
|
||||||
|
//RouterManager.shutDown();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}.execute();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
popup.add(browserLauncher);
|
||||||
|
popup.addSeparator();
|
||||||
|
popup.add(restartItem);
|
||||||
|
popup.add(stopItem);
|
||||||
|
|
||||||
|
return popup;
|
||||||
|
}
|
||||||
|
}
|
21
apps/itoopie/src/net/i2p/itoopie/i18n/ItoopieTranslator.java
Normal file
21
apps/itoopie/src/net/i2p/itoopie/i18n/ItoopieTranslator.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package net.i2p.itoopie.i18n;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
import net.i2p.itoopie.i18n.UTF8Control;
|
||||||
|
|
||||||
|
|
||||||
|
public class ItoopieTranslator {
|
||||||
|
|
||||||
|
private static final String BUNDLE_NAME = "net.i2p.itoopie.messages";
|
||||||
|
|
||||||
|
|
||||||
|
public static String _(String s) {
|
||||||
|
return Translate.getString(s, BUNDLE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String _(String s, Object o) {
|
||||||
|
return Translate.getString(s, o, BUNDLE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
169
apps/itoopie/src/net/i2p/itoopie/i18n/Translate.java
Normal file
169
apps/itoopie/src/net/i2p/itoopie/i18n/Translate.java
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
package net.i2p.itoopie.i18n;
|
||||||
|
|
||||||
|
import gnu.gettext.GettextResource;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.MissingResourceException;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translate strings efficiently.
|
||||||
|
* We don't include an English or default ResourceBundle, we simply check
|
||||||
|
* for "en" and return the original string.
|
||||||
|
* Support real-time language changing with the routerconsole.lang property.
|
||||||
|
*
|
||||||
|
* @author zzz, from a base generated by eclipse.
|
||||||
|
* @since 0.7.9
|
||||||
|
*/
|
||||||
|
public abstract class Translate {
|
||||||
|
public static final String PROP_LANG = "routerconsole.lang";
|
||||||
|
private static final String _localeLang = Locale.getDefault().getLanguage();
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static final Map<String, ResourceBundle> _bundles = new ConcurrentHashMap(2);
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static final ConcurrentHashMap<String,Boolean> _missing = new ConcurrentHashMap(2);
|
||||||
|
/** use to look for untagged strings */
|
||||||
|
private static final String TEST_LANG = "xx";
|
||||||
|
private static final String TEST_STRING = "XXXX";
|
||||||
|
|
||||||
|
/** lang in routerconsole.lang property, else current locale */
|
||||||
|
public static String getString(String key, String bun) {
|
||||||
|
String lang = Locale.getDefault().getLanguage();
|
||||||
|
if (lang.equals("en"))
|
||||||
|
return key;
|
||||||
|
else if (lang.equals(TEST_LANG))
|
||||||
|
return TEST_STRING;
|
||||||
|
// shouldnt happen but dont dump the po headers if it does
|
||||||
|
if (key.equals(""))
|
||||||
|
return key;
|
||||||
|
ResourceBundle bundle = findBundle(bun, lang);
|
||||||
|
if (bundle == null)
|
||||||
|
return key;
|
||||||
|
try {
|
||||||
|
return bundle.getString(key);
|
||||||
|
} catch (MissingResourceException e) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* translate a string with a parameter
|
||||||
|
* This is a lot more expensive than getString(s, ctx), so use sparingly.
|
||||||
|
*
|
||||||
|
* @param s string to be translated containing {0}
|
||||||
|
* The {0} will be replaced by the parameter.
|
||||||
|
* Single quotes must be doubled, i.e. ' -> '' in the string.
|
||||||
|
* @param o parameter, not translated.
|
||||||
|
* To tranlslate parameter also, use _("foo {0} bar", _("baz"))
|
||||||
|
* Do not double the single quotes in the parameter.
|
||||||
|
* Use autoboxing to call with ints, longs, floats, etc.
|
||||||
|
*/
|
||||||
|
public static String getString(String s, Object o, String bun) {
|
||||||
|
String lang = Locale.getDefault().getLanguage();
|
||||||
|
if (lang.equals(TEST_LANG))
|
||||||
|
return TEST_STRING + '(' + o + ')' + TEST_STRING;
|
||||||
|
String x = getString(s, bun);
|
||||||
|
Object[] oArray = new Object[1];
|
||||||
|
oArray[0] = o;
|
||||||
|
try {
|
||||||
|
MessageFormat fmt = new MessageFormat(x, new Locale(lang));
|
||||||
|
return fmt.format(oArray, new StringBuffer(), null).toString();
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
System.err.println("Bad format: orig: \"" + s +
|
||||||
|
"\" trans: \"" + x +
|
||||||
|
"\" param: \"" + o +
|
||||||
|
"\" lang: " + lang);
|
||||||
|
return "FIXME: " + x + ' ' + o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** for {0} and {1} */
|
||||||
|
public static String getString(String s, Object o, Object o2, String bun) {
|
||||||
|
String lang = Locale.getDefault().getLanguage();
|
||||||
|
if (lang.equals(TEST_LANG))
|
||||||
|
return TEST_STRING + '(' + o + ',' + o2 + ')' + TEST_STRING;
|
||||||
|
String x = getString(s, bun);
|
||||||
|
Object[] oArray = new Object[2];
|
||||||
|
oArray[0] = o;
|
||||||
|
oArray[1] = o2;
|
||||||
|
try {
|
||||||
|
MessageFormat fmt = new MessageFormat(x, new Locale(lang));
|
||||||
|
return fmt.format(oArray, new StringBuffer(), null).toString();
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
System.err.println("Bad format: orig: \"" + s +
|
||||||
|
"\" trans: \"" + x +
|
||||||
|
"\" param1: \"" + o +
|
||||||
|
"\" param2: \"" + o2 +
|
||||||
|
"\" lang: " + lang);
|
||||||
|
return "FIXME: " + x + ' ' + o + ',' + o2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use GNU ngettext
|
||||||
|
* For .po file format see http://www.gnu.org/software/gettext/manual/gettext.html.gz#Translating-plural-forms
|
||||||
|
*
|
||||||
|
* @param n how many
|
||||||
|
* @param s singluar string, optionally with {0} e.g. "one tunnel"
|
||||||
|
* @param p plural string optionally with {0} e.g. "{0} tunnels"
|
||||||
|
* @since 0.7.14
|
||||||
|
*/
|
||||||
|
public static String getString(int n, String s, String p, String bun) {
|
||||||
|
String lang = Locale.getDefault().getLanguage();
|
||||||
|
if (lang.equals(TEST_LANG))
|
||||||
|
return TEST_STRING + '(' + n + ')' + TEST_STRING;
|
||||||
|
ResourceBundle bundle = null;
|
||||||
|
if (!lang.equals("en"))
|
||||||
|
bundle = findBundle(bun, lang);
|
||||||
|
String x;
|
||||||
|
if (bundle == null)
|
||||||
|
x = n == 1 ? s : p;
|
||||||
|
else
|
||||||
|
x = GettextResource.ngettext(bundle, s, p, n);
|
||||||
|
Object[] oArray = new Object[1];
|
||||||
|
oArray[0] = Integer.valueOf(n);
|
||||||
|
try {
|
||||||
|
MessageFormat fmt = new MessageFormat(x, new Locale(lang));
|
||||||
|
return fmt.format(oArray, new StringBuffer(), null).toString();
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
System.err.println("Bad format: sing: \"" + s +
|
||||||
|
"\" plural: \"" + p +
|
||||||
|
"\" lang: " + lang);
|
||||||
|
return "FIXME: " + s + ' ' + p + ',' + n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** cache both found and not found for speed */
|
||||||
|
private static ResourceBundle findBundle(String bun, String lang) {
|
||||||
|
String key = bun + '-' + lang;
|
||||||
|
ResourceBundle rv = _bundles.get(key);
|
||||||
|
if (rv == null && !_missing.containsKey(key)) {
|
||||||
|
try {
|
||||||
|
// We must specify the class loader so that a webapp can find the bundle in the .war
|
||||||
|
rv = ResourceBundle.getBundle(bun, new Locale(lang), Thread.currentThread().getContextClassLoader());
|
||||||
|
if (rv != null)
|
||||||
|
_bundles.put(key, rv);
|
||||||
|
} catch (MissingResourceException e) {
|
||||||
|
_missing.put(key, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the cache.
|
||||||
|
* Call this after adding new bundles to the classpath.
|
||||||
|
* @since 0.7.12
|
||||||
|
*/
|
||||||
|
public static void clearCache() {
|
||||||
|
_missing.clear();
|
||||||
|
}
|
||||||
|
}
|
5
apps/itoopie/src/net/i2p/itoopie/package.html
Normal file
5
apps/itoopie/src/net/i2p/itoopie/package.html
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<p>itoopie is a graphical interface to I2P that allows managing and monitoring most aspects of I2P.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -1,4 +1,4 @@
|
|||||||
package net.i2p.desktopgui.util;
|
package net.i2p.itoopie.util;
|
||||||
|
|
||||||
public class BrowseException extends Exception {
|
public class BrowseException extends Exception {
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package net.i2p.desktopgui.util;
|
package net.i2p.itoopie.util;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
@ -1,4 +1,4 @@
|
|||||||
package net.i2p.desktopgui.util;
|
package net.i2p.itoopie.util;
|
||||||
|
|
||||||
import java.awt.Desktop;
|
import java.awt.Desktop;
|
||||||
import java.awt.TrayIcon;
|
import java.awt.TrayIcon;
|
||||||
@ -7,12 +7,9 @@ import java.io.IOException;
|
|||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
import net.i2p.desktopgui.router.RouterManager;
|
|
||||||
import net.i2p.util.Log;
|
|
||||||
|
|
||||||
public class I2PDesktop {
|
public class I2PDesktop {
|
||||||
|
|
||||||
private final static Log log = new Log(I2PDesktop.class);
|
|
||||||
|
|
||||||
public static void browse(String url) throws BrowseException {
|
public static void browse(String url) throws BrowseException {
|
||||||
if(Desktop.isDesktopSupported()) {
|
if(Desktop.isDesktopSupported()) {
|
Reference in New Issue
Block a user