]> git.gag.com Git - debian/openrocket/commitdiff
l10n updates
authorplaa <plaa@180e2498-e6e9-4542-8430-84ac67f01cd8>
Fri, 25 Mar 2011 18:04:49 +0000 (18:04 +0000)
committerplaa <plaa@180e2498-e6e9-4542-8430-84ac67f01cd8>
Fri, 25 Mar 2011 18:04:49 +0000 (18:04 +0000)
git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk@123 180e2498-e6e9-4542-8430-84ac67f01cd8

pix-src/icon/icon-large-close.xcf.gz [new file with mode: 0644]
src/net/sf/openrocket/l10n/ClassBasedTranslator.java [new file with mode: 0644]
src/net/sf/openrocket/l10n/ExceptionSuppressingTranslator.java [new file with mode: 0644]
src/net/sf/openrocket/l10n/ResourceBundleTranslator.java
src/net/sf/openrocket/l10n/Translator.java
src/net/sf/openrocket/startup/Application.java
src/net/sf/openrocket/startup/Startup.java
test/net/sf/openrocket/l10n/TestClassBasedTranslator.java [new file with mode: 0644]
test/net/sf/openrocket/l10n/TestExceptionSuppressingTranslator.java [new file with mode: 0644]
web/html/menubg.png

diff --git a/pix-src/icon/icon-large-close.xcf.gz b/pix-src/icon/icon-large-close.xcf.gz
new file mode 100644 (file)
index 0000000..9ed1129
Binary files /dev/null and b/pix-src/icon/icon-large-close.xcf.gz differ
diff --git a/src/net/sf/openrocket/l10n/ClassBasedTranslator.java b/src/net/sf/openrocket/l10n/ClassBasedTranslator.java
new file mode 100644 (file)
index 0000000..b4212dc
--- /dev/null
@@ -0,0 +1,92 @@
+package net.sf.openrocket.l10n;
+
+import java.util.MissingResourceException;
+
+import net.sf.openrocket.logging.TraceException;
+import net.sf.openrocket.util.BugException;
+
+/**
+ * A translator that prepends a pre-defined class name in front of a translation key
+ * and retrieves the translator for that key, and only if that is missing reverts to
+ * the base key name.  The base class name can either be provided to the constructor
+ * or retrieved from the stack.
+ * 
+ * @author Sampo Niskanen <sampo.niskanen@iki.fi>
+ */
+public class ClassBasedTranslator implements Translator {
+       
+
+       private final Translator translator;
+       private final String className;
+       
+       /**
+        * Construct a translator using a specified class name.
+        * 
+        * @param translator    the translator from which to obtain the translations.
+        * @param className             the base class name to prepend.
+        */
+       public ClassBasedTranslator(Translator translator, String className) {
+               this.translator = translator;
+               this.className = className;
+       }
+       
+       /**
+        * Construct a translator by obtaining the base class name from the stack.
+        * 
+        * @param translator    the translator from which to obtain the translations.
+        * @param levels                the number of levels to move upwards in the stack from the point where this method is called.
+        */
+       public ClassBasedTranslator(Translator translator, int levels) {
+               this(translator, getStackClass(levels));
+       }
+       
+       
+
+       @Override
+       public String get(String key) {
+               String classKey = className + "." + key;
+               
+               try {
+                       return translator.get(classKey);
+               } catch (MissingResourceException e) {
+                       // Ignore
+               }
+               
+               try {
+                       return translator.get(key);
+               } catch (MissingResourceException e) {
+                       MissingResourceException mre = new MissingResourceException(
+                                       "Neither key '" + classKey + "' nor '" + key + "' could be found", e.getClassName(), key);
+                       mre.initCause(e);
+                       throw mre;
+               }
+       }
+       
+       
+
+       private static String getStackClass(int levels) {
+               TraceException trace = new TraceException();
+               StackTraceElement stack[] = trace.getStackTrace();
+               final int index = levels + 2;
+               if (stack.length <= index) {
+                       throw new BugException("Stack trace is too short, length=" + stack.length + ", expected=" + index, trace);
+               }
+               
+               StackTraceElement element = stack[index];
+               String cn = element.getClassName();
+               int pos = cn.lastIndexOf('.');
+               if (pos >= 0) {
+                       cn = cn.substring(pos + 1);
+               }
+               return cn;
+       }
+       
+       
+
+
+       // For unit testing purposes
+       String getClassName() {
+               return className;
+       }
+       
+}
diff --git a/src/net/sf/openrocket/l10n/ExceptionSuppressingTranslator.java b/src/net/sf/openrocket/l10n/ExceptionSuppressingTranslator.java
new file mode 100644 (file)
index 0000000..a4cedc0
--- /dev/null
@@ -0,0 +1,58 @@
+package net.sf.openrocket.l10n;
+
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.Set;
+
+import net.sf.openrocket.gui.main.ExceptionHandler;
+
+/**
+ * A translator that suppresses MissingResourceExceptions and handles them gracefully.
+ * For every missing key this class calls the exception handler exactly once, and
+ * returns the key itself as the translation.
+ * 
+ * @author Sampo Niskanen <sampo.niskanen@iki.fi>
+ */
+public class ExceptionSuppressingTranslator implements Translator {
+       
+       private static final Set<String> errors = new HashSet<String>();
+       // For unit testing:
+       static int failures = 0;
+       
+       private final Translator translator;
+       
+       
+
+       /**
+        * Sole constructor.
+        * 
+        * @param translator    the translator to use
+        */
+       public ExceptionSuppressingTranslator(Translator translator) {
+               this.translator = translator;
+       }
+       
+       
+
+       @Override
+       public String get(String key) {
+               try {
+                       return translator.get(key);
+               } catch (MissingResourceException e) {
+                       handleError(key, e);
+               }
+               
+               return key;
+       }
+       
+       
+
+       private static synchronized void handleError(String key, MissingResourceException e) {
+               if (errors.add(key)) {
+                       failures++;
+                       ExceptionHandler.handleErrorCondition("Can not find translation for '" + key + "' locale=" + Locale.getDefault(), e);
+               }
+       }
+       
+}
index 5bfdbd28d487cecf1abd761c4c04c9ba62543f2f..241ecefcfba93f62525c9f6bd0734cb2b6d3937e 100644 (file)
@@ -1,26 +1,16 @@
 package net.sf.openrocket.l10n;
 
 import java.util.Locale;
-import java.util.MissingResourceException;
 import java.util.ResourceBundle;
 
-import net.sf.openrocket.logging.LogHelper;
-import net.sf.openrocket.startup.Application;
-
 /**
  * A translator that obtains translated strings from a resource bundle.
- * <p>
- * If a message is not found in any resource bundle, an error is logged and the key itself
- * is returned.
  * 
  * @author Sampo Niskanen <sampo.niskanen@iki.fi>
  */
 public class ResourceBundleTranslator implements Translator {
-       private static final LogHelper log = Application.getLogger();
        
        private final ResourceBundle bundle;
-       private final String baseName;
-       private final Locale locale;
        
        /**
         * Create a ResourceBundleTranslator using the default Locale.
@@ -39,8 +29,6 @@ public class ResourceBundleTranslator implements Translator {
         */
        public ResourceBundleTranslator(String baseName, Locale locale) {
                this.bundle = ResourceBundle.getBundle(baseName, locale);
-               this.baseName = baseName;
-               this.locale = locale;
        }
        
        
@@ -49,12 +37,7 @@ public class ResourceBundleTranslator implements Translator {
         */
        @Override
        public synchronized String get(String key) {
-               try {
-                       return bundle.getString(key);
-               } catch (MissingResourceException e) {
-                       log.error("String not found for key '" + key + "' in bundle '" + baseName + "' with locale " + locale, e);
-               }
-               return key;
+               return bundle.getString(key);
        }
        
 }
index c95d7becd932c337588f5420cbc9ac98ac1aeb87..9eed2cdfa51ada85ce290e1941df03676c1ccfb7 100644 (file)
@@ -1,5 +1,7 @@
 package net.sf.openrocket.l10n;
 
+import java.util.MissingResourceException;
+
 /**
  * An interface for obtaining translations from logical keys.
  * <p>
@@ -15,6 +17,7 @@ public interface Translator {
         * 
         * @param key   the logical string key.
         * @return              the translated string.
+        * @throws MissingResourceException if the translation corresponding to the key is not found.
         * @throws NullPointerException if key is null.
         */
        public String get(String key);
index 020d714e57abb13c7f48c5554d320520e72b637f..78d2941a7c3fa777c40ba57b983373a68d4a4e2a 100644 (file)
@@ -1,7 +1,9 @@
 package net.sf.openrocket.startup;
 
 import net.sf.openrocket.database.ThrustCurveMotorSetDatabase;
+import net.sf.openrocket.l10n.ClassBasedTranslator;
 import net.sf.openrocket.l10n.DebugTranslator;
+import net.sf.openrocket.l10n.ExceptionSuppressingTranslator;
 import net.sf.openrocket.l10n.Translator;
 import net.sf.openrocket.logging.LogHelper;
 import net.sf.openrocket.logging.LogLevel;
@@ -18,7 +20,7 @@ public final class Application {
        private static LogHelper logger;
        private static LogLevelBufferLogger logBuffer;
        
-       private static Translator translator = new DebugTranslator();
+       private static Translator baseTranslator = new DebugTranslator();
        
        private static ThrustCurveMotorSetDatabase motorSetDatabase;
        
@@ -87,15 +89,18 @@ public final class Application {
         * @return      a translator.
         */
        public static Translator getTranslator() {
-               return translator;
+               Translator t = baseTranslator;
+               t = new ClassBasedTranslator(t, 1);
+               t = new ExceptionSuppressingTranslator(t);
+               return t;
        }
        
        /**
         * Set the translator used in obtaining translated strings.
         * @param translator    the translator to set.
         */
-       public static void setTranslator(Translator translator) {
-               Application.translator = translator;
+       public static void setBaseTranslator(Translator translator) {
+               Application.baseTranslator = translator;
        }
        
        
index 802bdcc737673171c6ee9188715f05cffbf299b3..f1c4aa4d4e124196425fc216a9acd2c53d9e6255 100644 (file)
@@ -134,6 +134,7 @@ public class Startup {
                        } else {
                                l = new Locale(split[0], split[1], split[2]);
                        }
+                       log.info("Setting custom locale " + l);
                        Locale.setDefault(l);
                }
                
@@ -147,7 +148,7 @@ public class Startup {
                log.info("Set up translation for locale " + Locale.getDefault() +
                                ", debug.currentFile=" + t.get("debug.currentFile"));
                
-               Application.setTranslator(t);
+               Application.setBaseTranslator(t);
        }
        
        
diff --git a/test/net/sf/openrocket/l10n/TestClassBasedTranslator.java b/test/net/sf/openrocket/l10n/TestClassBasedTranslator.java
new file mode 100644 (file)
index 0000000..94909b0
--- /dev/null
@@ -0,0 +1,79 @@
+package net.sf.openrocket.l10n;
+
+import static org.junit.Assert.*;
+
+import java.util.MissingResourceException;
+
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.auto.Mock;
+import org.jmock.integration.junit4.JMock;
+import org.jmock.integration.junit4.JUnit4Mockery;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+@RunWith(JMock.class)
+public class TestClassBasedTranslator {
+       Mockery context = new JUnit4Mockery();
+       
+       @Mock
+       Translator translator;
+       
+       @Test
+       public void testClassName() {
+               ClassBasedTranslator cbt = new ClassBasedTranslator(null, 0);
+               assertEquals("TestClassBasedTranslator", cbt.getClassName());
+               
+               cbt = new ClassBasedTranslator(null, "foobar");
+               assertEquals("foobar", cbt.getClassName());
+       }
+       
+       @Test
+       public void testGetWithClassName() {
+               ClassBasedTranslator cbt = new ClassBasedTranslator(translator, 0);
+               
+               // @formatter:off
+               context.checking(new Expectations() {{
+                               oneOf(translator).get("TestClassBasedTranslator.fake.key"); will(returnValue("foobar")); 
+               }});
+               // @formatter:on
+               
+               assertEquals("foobar", cbt.get("fake.key"));
+       }
+       
+       
+       @Test
+       public void testGetWithoutClassName() {
+               ClassBasedTranslator cbt = new ClassBasedTranslator(translator, 0);
+               
+               // @formatter:off
+               context.checking(new Expectations() {{
+                       oneOf(translator).get("TestClassBasedTranslator.fake.key"); will(throwException(new MissingResourceException("a", "b", "c"))); 
+                       oneOf(translator).get("fake.key"); will(returnValue("barbaz")); 
+               }});
+               // @formatter:on
+               
+               assertEquals("barbaz", cbt.get("fake.key"));
+       }
+       
+       
+       @Test
+       public void testMissing() {
+               ClassBasedTranslator cbt = new ClassBasedTranslator(translator, 0);
+               
+               // @formatter:off
+               context.checking(new Expectations() {{
+                       oneOf(translator).get("TestClassBasedTranslator.fake.key"); will(throwException(new MissingResourceException("a", "b", "c"))); 
+                       oneOf(translator).get("fake.key"); will(throwException(new MissingResourceException("a", "b", "c"))); 
+               }});
+               // @formatter:on
+               
+               try {
+                       fail("Returned: " + cbt.get("fake.key"));
+               } catch (MissingResourceException e) {
+                       assertEquals("Neither key 'TestClassBasedTranslator.fake.key' nor 'fake.key' could be found", e.getMessage());
+               }
+               
+       }
+}
diff --git a/test/net/sf/openrocket/l10n/TestExceptionSuppressingTranslator.java b/test/net/sf/openrocket/l10n/TestExceptionSuppressingTranslator.java
new file mode 100644 (file)
index 0000000..62a1ca7
--- /dev/null
@@ -0,0 +1,64 @@
+package net.sf.openrocket.l10n;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.MissingResourceException;
+
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.auto.Mock;
+import org.jmock.integration.junit4.JMock;
+import org.jmock.integration.junit4.JUnit4Mockery;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(JMock.class)
+public class TestExceptionSuppressingTranslator {
+       Mockery context = new JUnit4Mockery();
+       
+       @Mock
+       Translator translator;
+       
+       @Test
+       public void testSuccessful() {
+               ExceptionSuppressingTranslator est = new ExceptionSuppressingTranslator(translator);
+               
+               // @formatter:off
+               context.checking(new Expectations() {{
+                               oneOf(translator).get("fake.key"); will(returnValue("foobar")); 
+               }});
+               // @formatter:on
+               
+               assertEquals("foobar", est.get("fake.key"));
+       }
+       
+       
+       @Test
+       public void testFailure() {
+               ExceptionSuppressingTranslator est = new ExceptionSuppressingTranslator(translator);
+               
+               assertEquals("Prerequisite failed", 0, ExceptionSuppressingTranslator.failures);
+               
+               // @formatter:off
+               context.checking(new Expectations() {{
+                       oneOf(translator).get("fake.key"); will(throwException(new MissingResourceException("a", "b", "c"))); 
+                       oneOf(translator).get("fake.key"); will(throwException(new MissingResourceException("a", "b", "c"))); 
+                       oneOf(translator).get("fake.key2"); will(throwException(new MissingResourceException("a", "b", "c"))); 
+               }});
+               // @formatter:on
+               
+               // Test first failure
+               assertEquals("fake.key", est.get("fake.key"));
+               assertEquals(1, ExceptionSuppressingTranslator.failures);
+               
+               // Test second failure
+               assertEquals("fake.key", est.get("fake.key"));
+               assertEquals(1, ExceptionSuppressingTranslator.failures);
+               
+               // Test failure with other key
+               assertEquals("fake.key2", est.get("fake.key"));
+               assertEquals(2, ExceptionSuppressingTranslator.failures);
+       }
+       
+
+}
index c527097f46d88b72833574fa909e384734b95e72..535ef97d360474040966c00c25c82112e2c90cdc 100644 (file)
Binary files a/web/html/menubg.png and b/web/html/menubg.png differ