* Translation: Move code from routerconsole to core,

to support translation of other webapps
This commit is contained in:
zzz
2009-12-09 14:07:16 +00:00
parent 1e32170df2
commit c22b7568b1
2 changed files with 109 additions and 92 deletions

View File

@ -1,65 +1,17 @@
package net.i2p.router.web;
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;
import net.i2p.I2PAppContext;
import net.i2p.util.ConcurrentHashSet;
import net.i2p.util.Translate;
/**
* 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.
* Translate strings for this package.
*/
public class Messages {
public static final String PROP_LANG = "routerconsole.lang";
public class Messages extends Translate {
private static final String BUNDLE_NAME = "net.i2p.router.web.messages";
private static final String _localeLang = Locale.getDefault().getLanguage();
private static final Map<String, ResourceBundle> _bundles = new ConcurrentHashMap(2);
private static final Set<String> _missing = new ConcurrentHashSet(2);
/** use to look for untagged strings */
private static final String TEST_LANG = "xx";
private static final String TEST_STRING = "XXXX";
/** current locale **/
/* unused
public static String getString(String key) {
if (_localeLang.equals("en"))
return key;
ResourceBundle bundle = findBundle(_localeLang);
if (bundle == null)
return key;
try {
return bundle.getString(key);
} catch (MissingResourceException e) {
return key;
}
}
*/
/** lang in routerconsole.lang property, else current locale */
public static String getString(String key, I2PAppContext ctx) {
String lang = getLanguage(ctx);
if (lang.equals("en"))
return key;
else if (lang.equals(TEST_LANG))
return TEST_STRING;
ResourceBundle bundle = findBundle(lang);
if (bundle == null)
return key;
try {
return bundle.getString(key);
} catch (MissingResourceException e) {
return key;
}
return Translate.getString(key, ctx, BUNDLE_NAME);
}
/**
@ -75,45 +27,6 @@ public class Messages {
* Use autoboxing to call with ints, longs, floats, etc.
*/
public static String getString(String s, Object o, I2PAppContext ctx) {
String lang = getLanguage(ctx);
if (lang.equals(TEST_LANG))
return TEST_STRING + '(' + o + ')' + TEST_STRING;
String x = getString(s, ctx);
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;
}
}
public static String getLanguage(I2PAppContext ctx) {
String lang = ctx.getProperty(PROP_LANG);
if (lang == null || lang.length() <= 0)
lang = _localeLang;
return lang;
}
/** cache both found and not found for speed */
private static ResourceBundle findBundle(String lang) {
ResourceBundle rv = _bundles.get(lang);
if (rv == null && !_missing.contains(lang)) {
try {
// Would it be faster to specify a class loader?
// No matter we only do this once per lang.
rv = ResourceBundle.getBundle(BUNDLE_NAME, new Locale(lang));
if (rv != null)
_bundles.put(lang, rv);
} catch (MissingResourceException e) {
_missing.add(lang);
}
}
return rv;
return Translate.getString(s, o, ctx, BUNDLE_NAME);
}
}

View File

@ -0,0 +1,104 @@
package net.i2p.util;
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;
import net.i2p.I2PAppContext;
import net.i2p.util.ConcurrentHashSet;
/**
* 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.
*/
public abstract class Translate {
public static final String PROP_LANG = "routerconsole.lang";
private static final String _localeLang = Locale.getDefault().getLanguage();
private static final Map<String, ResourceBundle> _bundles = new ConcurrentHashMap(2);
private static final Set<String> _missing = new ConcurrentHashSet(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, I2PAppContext ctx, String bun) {
String lang = getLanguage(ctx);
if (lang.equals("en"))
return key;
else if (lang.equals(TEST_LANG))
return TEST_STRING;
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, I2PAppContext ctx, String bun) {
String lang = getLanguage(ctx);
if (lang.equals(TEST_LANG))
return TEST_STRING + '(' + o + ')' + TEST_STRING;
String x = getString(s, ctx, 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;
}
}
/** @return lang in routerconsole.lang property, else current locale */
public static String getLanguage(I2PAppContext ctx) {
String lang = ctx.getProperty(PROP_LANG);
if (lang == null || lang.length() <= 0)
lang = _localeLang;
return lang;
}
/** 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.contains(key)) {
try {
// Would it be faster to specify a class loader?
// No matter we only do this once per lang.
rv = ResourceBundle.getBundle(bun, new Locale(lang));
if (rv != null)
_bundles.put(key, rv);
} catch (MissingResourceException e) {
_missing.add(key);
}
}
return rv;
}
}