* Translation: Move code from routerconsole to core,
to support translation of other webapps
This commit is contained in:
@ -1,65 +1,17 @@
|
|||||||
package net.i2p.router.web;
|
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.I2PAppContext;
|
||||||
import net.i2p.util.ConcurrentHashSet;
|
import net.i2p.util.Translate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translate strings efficiently.
|
* Translate strings for this package.
|
||||||
* 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 class Messages {
|
public class Messages extends Translate {
|
||||||
public static final String PROP_LANG = "routerconsole.lang";
|
|
||||||
private static final String BUNDLE_NAME = "net.i2p.router.web.messages";
|
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 */
|
/** lang in routerconsole.lang property, else current locale */
|
||||||
public static String getString(String key, I2PAppContext ctx) {
|
public static String getString(String key, I2PAppContext ctx) {
|
||||||
String lang = getLanguage(ctx);
|
return Translate.getString(key, ctx, BUNDLE_NAME);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,45 +27,6 @@ public class Messages {
|
|||||||
* Use autoboxing to call with ints, longs, floats, etc.
|
* Use autoboxing to call with ints, longs, floats, etc.
|
||||||
*/
|
*/
|
||||||
public static String getString(String s, Object o, I2PAppContext ctx) {
|
public static String getString(String s, Object o, I2PAppContext ctx) {
|
||||||
String lang = getLanguage(ctx);
|
return Translate.getString(s, o, ctx, BUNDLE_NAME);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
104
core/java/src/net/i2p/util/Translate.java
Normal file
104
core/java/src/net/i2p/util/Translate.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user