From: plaa Date: Fri, 25 Mar 2011 18:04:49 +0000 (+0000) Subject: l10n updates X-Git-Tag: upstream/1.1.5~1^2~3 X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=424a07d5cbc413d027326205edea23dd828d79b6;p=debian%2Fopenrocket l10n updates git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk@123 180e2498-e6e9-4542-8430-84ac67f01cd8 --- diff --git a/pix-src/icon/icon-large-close.xcf.gz b/pix-src/icon/icon-large-close.xcf.gz new file mode 100644 index 00000000..9ed11293 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 index 00000000..b4212dc9 --- /dev/null +++ b/src/net/sf/openrocket/l10n/ClassBasedTranslator.java @@ -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 + */ +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 index 00000000..a4cedc05 --- /dev/null +++ b/src/net/sf/openrocket/l10n/ExceptionSuppressingTranslator.java @@ -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 + */ +public class ExceptionSuppressingTranslator implements Translator { + + private static final Set errors = new HashSet(); + // 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); + } + } + +} diff --git a/src/net/sf/openrocket/l10n/ResourceBundleTranslator.java b/src/net/sf/openrocket/l10n/ResourceBundleTranslator.java index 5bfdbd28..241ecefc 100644 --- a/src/net/sf/openrocket/l10n/ResourceBundleTranslator.java +++ b/src/net/sf/openrocket/l10n/ResourceBundleTranslator.java @@ -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. - *

- * If a message is not found in any resource bundle, an error is logged and the key itself - * is returned. * * @author Sampo Niskanen */ 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); } } diff --git a/src/net/sf/openrocket/l10n/Translator.java b/src/net/sf/openrocket/l10n/Translator.java index c95d7bec..9eed2cdf 100644 --- a/src/net/sf/openrocket/l10n/Translator.java +++ b/src/net/sf/openrocket/l10n/Translator.java @@ -1,5 +1,7 @@ package net.sf.openrocket.l10n; +import java.util.MissingResourceException; + /** * An interface for obtaining translations from logical keys. *

@@ -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); diff --git a/src/net/sf/openrocket/startup/Application.java b/src/net/sf/openrocket/startup/Application.java index 020d714e..78d2941a 100644 --- a/src/net/sf/openrocket/startup/Application.java +++ b/src/net/sf/openrocket/startup/Application.java @@ -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; } diff --git a/src/net/sf/openrocket/startup/Startup.java b/src/net/sf/openrocket/startup/Startup.java index 802bdcc7..f1c4aa4d 100644 --- a/src/net/sf/openrocket/startup/Startup.java +++ b/src/net/sf/openrocket/startup/Startup.java @@ -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 index 00000000..94909b0c --- /dev/null +++ b/test/net/sf/openrocket/l10n/TestClassBasedTranslator.java @@ -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 index 00000000..62a1ca7c --- /dev/null +++ b/test/net/sf/openrocket/l10n/TestExceptionSuppressingTranslator.java @@ -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); + } + + +} diff --git a/web/html/menubg.png b/web/html/menubg.png index c527097f..535ef97d 100644 Binary files a/web/html/menubg.png and b/web/html/menubg.png differ