Promote Translator to API, move to Colorizer

This commit is contained in:
fullwall 2013-01-23 22:35:29 +08:00
parent f58bac5cd0
commit 1dc12ccf9b
6 changed files with 56 additions and 344 deletions

View File

@ -3,6 +3,7 @@ package net.citizensnpcs;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.Locale;
import net.citizensnpcs.Settings.Setting;
import net.citizensnpcs.api.CitizensAPI;
@ -19,6 +20,7 @@ import net.citizensnpcs.api.scripting.ObjectProvider;
import net.citizensnpcs.api.scripting.ScriptCompiler;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.trait.TraitFactory;
import net.citizensnpcs.api.util.Translator;
import net.citizensnpcs.command.CommandContext;
import net.citizensnpcs.command.CommandManager;
import net.citizensnpcs.command.CommandManager.CommandInfo;
@ -173,6 +175,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
@Override
public void onEnable() {
setupTranslator();
CitizensAPI.setImplementation(this);
// Disable if the server is not using the compatible Minecraft version
String mcVersion = Util.getMinecraftVersion();
@ -289,6 +292,28 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
}
}
private void setupTranslator() {
Locale locale = Locale.getDefault();
String setting = Setting.LOCALE.asString();
if (!setting.isEmpty()) {
String[] parts = setting.split("[\\._]");
switch (parts.length) {
case 1:
locale = new Locale(parts[0]);
break;
case 2:
locale = new Locale(parts[0], parts[1]);
break;
case 3:
locale = new Locale(parts[0], parts[1], parts[2]);
break;
default:
break;
}
}
Translator.setInstance(new File(getDataFolder(), "lang"), locale);
}
private void startMetrics() {
try {
Metrics metrics = new Metrics(Citizens.this);

View File

@ -17,6 +17,7 @@ import net.citizensnpcs.api.trait.trait.MobType;
import net.citizensnpcs.api.trait.trait.Owner;
import net.citizensnpcs.api.trait.trait.Spawned;
import net.citizensnpcs.api.trait.trait.Speech;
import net.citizensnpcs.api.util.Colorizer;
import net.citizensnpcs.api.util.DataKey;
import net.citizensnpcs.api.util.MemoryDataKey;
import net.citizensnpcs.command.Command;
@ -274,7 +275,7 @@ public class NPCCommands {
permission = "npc.create")
@Requirements
public void create(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
String name = StringHelper.parseColors(args.getJoinedStrings(1));
String name = Colorizer.parseColors(args.getJoinedStrings(1));
if (name.length() > 16) {
Messaging.sendErrorTr(sender, Messages.NPC_NAME_TOO_LONG);
name = name.substring(0, 15);
@ -966,9 +967,8 @@ public class NPCCommands {
min = 2,
permission = "npc.speak")
public void speak(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
String type = npc.getTrait(Speech.class).getDefaultVocalChord();
String message = StringHelper.parseColors(args.getJoinedStrings(1));
String message = Colorizer.parseColors(args.getJoinedStrings(1));
if (message.length() <= 0) {
Messaging.send(sender, "Default Vocal Chord for " + npc.getName() + ": "

View File

@ -3,9 +3,9 @@ package net.citizensnpcs.npc.entity;
import net.citizensnpcs.Settings.Setting;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.util.Colorizer;
import net.citizensnpcs.npc.AbstractEntityController;
import net.citizensnpcs.util.NMS;
import net.citizensnpcs.util.StringHelper;
import net.minecraft.server.v1_4_R1.PlayerInteractManager;
import net.minecraft.server.v1_4_R1.WorldServer;
@ -19,7 +19,7 @@ public class HumanController extends AbstractEntityController {
@Override
protected LivingEntity createEntity(final Location at, final NPC npc) {
WorldServer ws = ((CraftWorld) at.getWorld()).getHandle();
final EntityHumanNPC handle = new EntityHumanNPC(ws.getServer().getServer(), ws, StringHelper.parseColors(npc
final EntityHumanNPC handle = new EntityHumanNPC(ws.getServer().getServer(), ws, Colorizer.parseColors(npc
.getFullName()), new PlayerInteractManager(ws), npc);
handle.getBukkitEntity().teleport(at);
Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() {

View File

@ -6,6 +6,8 @@ import java.util.regex.Pattern;
import net.citizensnpcs.Settings.Setting;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.trait.trait.Owner;
import net.citizensnpcs.api.util.Colorizer;
import net.citizensnpcs.api.util.Translator;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
@ -37,6 +39,24 @@ public class Messaging {
log(Level.INFO, Translator.translate(key, msg));
}
private static String prettify(String message) {
String trimmed = message.trim();
String messageColour = Colorizer.parseColors(Setting.MESSAGE_COLOUR.asString());
if (!trimmed.isEmpty()) {
if (trimmed.charAt(0) == ChatColor.COLOR_CHAR) {
ChatColor test = ChatColor.getByChar(trimmed.substring(1, 2));
if (test == null) {
message = messageColour + message;
} else
messageColour = test.toString();
} else
message = messageColour + message;
}
message = message.replace("[[", Colorizer.parseColors(Setting.HIGHLIGHT_COLOUR.asString()));
message = message.replace("]]", messageColour);
return message;
}
public static void send(CommandSender sender, Object... msg) {
sendMessageTo(sender, SPACE.join(msg));
}
@ -50,23 +70,9 @@ public class Messaging {
}
private static void sendMessageTo(CommandSender sender, String rawMessage) {
rawMessage = StringHelper.parseColors(rawMessage);
rawMessage = Colorizer.parseColors(rawMessage);
for (String message : CHAT_NEWLINE_SPLITTER.split(rawMessage)) {
String trimmed = message.trim();
String messageColour = StringHelper.parseColors(Setting.MESSAGE_COLOUR.asString());
if (!trimmed.isEmpty()) {
if (trimmed.charAt(0) == ChatColor.COLOR_CHAR) {
ChatColor test = ChatColor.getByChar(trimmed.substring(1, 2));
if (test == null) {
message = messageColour + message;
} else
messageColour = test.toString();
} else
message = messageColour + message;
}
message = message.replace("[[", StringHelper.parseColors(Setting.HIGHLIGHT_COLOUR.asString()));
message = message.replace("]]", messageColour);
sender.sendMessage(message);
sender.sendMessage(prettify(message));
}
}
@ -98,22 +104,7 @@ public class Messaging {
}
public static String tr(String key, Object... messages) {
String message = Translator.translate(key, messages);
String trimmed = message.trim();
String messageColour = StringHelper.parseColors(Setting.MESSAGE_COLOUR.asString());
if (!trimmed.isEmpty()) {
if (trimmed.charAt(0) == ChatColor.COLOR_CHAR) {
ChatColor test = ChatColor.getByChar(trimmed.substring(1, 2));
if (test == null) {
message = messageColour + message;
} else
messageColour = test.toString();
} else
message = messageColour + message;
}
message = message.replace("[[", StringHelper.parseColors(Setting.HIGHLIGHT_COLOUR.asString()));
message = message.replace("]]", messageColour);
return message;
return prettify(Translator.translate(key, messages));
}
public static String tryTranslate(Object possible) {

View File

@ -1,16 +1,11 @@
package net.citizensnpcs.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.citizensnpcs.Settings.Setting;
import net.citizensnpcs.api.util.Colorizer;
import org.bukkit.ChatColor;
public class StringHelper {
private static Pattern COLOR_MATCHER;
private static String GROUP = ChatColor.COLOR_CHAR + "$1";
public static String capitalize(Object string) {
String capitalize = string.toString();
@ -67,13 +62,8 @@ public class StringHelper {
return p[n];
}
public static String parseColors(String parsed) {
Matcher matcher = COLOR_MATCHER.matcher(ChatColor.translateAlternateColorCodes('&', parsed));
return matcher.replaceAll(GROUP);
}
public static String wrap(Object string) {
return wrap(string, parseColors(Setting.MESSAGE_COLOUR.asString()));
return wrap(string, Colorizer.parseColors(Setting.MESSAGE_COLOUR.asString()));
}
public static String wrap(Object string, ChatColor colour) {
@ -81,18 +71,11 @@ public class StringHelper {
}
public static String wrap(Object string, String colour) {
return parseColors(Setting.HIGHLIGHT_COLOUR.asString()) + string.toString() + colour;
return Colorizer.parseColors(Setting.HIGHLIGHT_COLOUR.asString()) + string.toString() + colour;
}
public static String wrapHeader(Object string) {
String highlight = Setting.HIGHLIGHT_COLOUR.asString();
return highlight + "=====[ " + string.toString() + highlight + " ]=====";
}
static {
String colors = "";
for (ChatColor color : ChatColor.values())
colors += color.getChar();
COLOR_MATCHER = Pattern.compile("\\<([COLORS])\\>".replace("COLORS", colors), Pattern.CASE_INSENSITIVE);
}
}

View File

@ -1,287 +0,0 @@
package net.citizensnpcs.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.MessageFormat;
import java.util.ListResourceBundle;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.MissingResourceException;
import java.util.Properties;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
import net.citizensnpcs.Settings.Setting;
import net.citizensnpcs.api.CitizensAPI;
import com.google.common.collect.Maps;
import com.google.common.io.Closeables;
import com.google.common.io.Files;
import com.google.common.io.InputSupplier;
public class Translator {
private final Locale defaultLocale;
private final Map<String, MessageFormat> messageFormatCache = Maps.newHashMap();
private ResourceBundle preferredBundle;
private final File resourceFile;
private Translator(File resourceFile, Locale locale) {
this.resourceFile = resourceFile;
this.defaultLocale = locale;
try {
preferredBundle = ResourceBundle.getBundle(PREFIX, defaultLocale,
new FileClassLoader(Translator.class.getClassLoader(), resourceFile));
} catch (MissingResourceException e) {
preferredBundle = getDefaultBundle();
Messaging.log(translate(Messages.MISSING_TRANSLATIONS, locale));
}
}
private String format(String key, Locale locale, Object... msg) {
String unreplaced = translate(key, locale);
MessageFormat formatter = getFormatter(unreplaced);
return formatter.format(msg);
}
private ResourceBundle getBundle(Locale locale) {
try {
ResourceBundle bundle = ResourceBundle.getBundle(PREFIX, locale,
new FileClassLoader(Translator.class.getClassLoader(), resourceFile));
return bundle == null ? preferredBundle : bundle;
} catch (MissingResourceException e) {
return preferredBundle;
}
}
private ResourceBundle getDefaultBundle() {
return getDefaultResourceBundle(resourceFile, PREFIX + "_en.properties");
}
private MessageFormat getFormatter(String unreplaced) {
MessageFormat formatter = messageFormatCache.get(unreplaced);
if (formatter == null)
messageFormatCache.put(unreplaced, formatter = new MessageFormat(unreplaced));
return formatter;
}
private String translate(String key, Locale locale) {
ResourceBundle bundle = preferredBundle;
if (locale != defaultLocale)
bundle = getBundle(locale);
try {
return bundle.getString(key);
} catch (MissingResourceException e) {
try {
return getDefaultBundle().getString(key);
} catch (MissingResourceException ex) {
return "?" + key + "?";
}
}
}
private static class FileClassLoader extends ClassLoader {
private final File folder;
public FileClassLoader(ClassLoader classLoader, File folder) {
super(classLoader);
this.folder = folder;
}
@Override
public URL getResource(String string) {
File file = new File(folder, string);
if (file.exists()) {
try {
return file.toURI().toURL();
} catch (MalformedURLException ex) {
}
} else {
string = string.replaceFirst("/", "");
URL test = Translator.class.getResource('/' + string);
if (test != null)
return test;
}
return super.getResource(string);
}
@Override
public InputStream getResourceAsStream(String string) {
File file = new File(folder, string);
if (file.exists()) {
try {
return new FileInputStream(file);
} catch (FileNotFoundException ex) {
}
} else {
string = string.replaceFirst("/", "");
InputStream stream = Translator.class.getResourceAsStream('/' + string);
if (stream != null) {
new Thread(new SaveResourceThread(folder, string)).start();
return stream;
}
}
return super.getResourceAsStream(string);
}
}
private static class SaveResourceThread implements Runnable {
private final String fileName;
private final File rootFolder;
private SaveResourceThread(File rootFolder, String fileName) {
this.rootFolder = rootFolder;
this.fileName = fileName;
}
@Override
public void run() {
File file = new File(rootFolder, fileName);
if (file.exists())
return;
final InputStream stream = Translator.class.getResourceAsStream('/' + fileName);
if (stream == null)
return;
InputSupplier<InputStream> in = new InputSupplier<InputStream>() {
@Override
public InputStream getInput() throws IOException {
return stream;
}
};
try {
rootFolder.mkdirs();
File to = File.createTempFile(fileName, null, rootFolder);
to.deleteOnExit();
Files.copy(in, to);
if (!file.exists())
to.renameTo(file);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static ResourceBundle defaultBundle;
private static Translator instance;
public static final String PREFIX = "messages";
private static void createInstance() {
Locale locale = Locale.getDefault();
String setting = Setting.LOCALE.asString();
if (!setting.isEmpty()) {
String[] parts = setting.split("[\\._]");
switch (parts.length) {
case 1:
locale = new Locale(parts[0]);
break;
case 2:
locale = new Locale(parts[0], parts[1]);
break;
case 3:
locale = new Locale(parts[0], parts[1], parts[2]);
break;
default:
break;
}
}
instance = new Translator(new File(CitizensAPI.getDataFolder(), "lang"), locale);
Messaging.logTr(Messages.LOCALE_NOTIFICATION, locale);
}
private static Properties getDefaultBundleProperties() {
Properties defaults = new Properties();
InputStream in = null;
try {
in = Messages.class.getResourceAsStream("/" + PREFIX + "_en.properties");
defaults.load(in);
} catch (IOException e) {
} finally {
Closeables.closeQuietly(in);
}
return defaults;
}
private static ResourceBundle getDefaultResourceBundle(File resourceDirectory, String fileName) {
if (Translator.defaultBundle != null)
return Translator.defaultBundle;
resourceDirectory.mkdirs();
File bundleFile = new File(resourceDirectory, fileName);
if (!bundleFile.exists()) {
try {
bundleFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
Translator.populateDefaults(bundleFile);
FileInputStream stream = null;
try {
stream = new FileInputStream(bundleFile);
Translator.defaultBundle = new PropertyResourceBundle(stream);
} catch (Exception e) {
e.printStackTrace();
Translator.defaultBundle = Translator.getFallbackResourceBundle();
} finally {
Closeables.closeQuietly(stream);
}
return Translator.defaultBundle;
}
private static ResourceBundle getFallbackResourceBundle() {
return new ListResourceBundle() {
@Override
protected Object[][] getContents() {
return new Object[0][0];
}
};
}
private static void populateDefaults(File bundleFile) {
Properties properties = new Properties();
InputStream in = null;
try {
in = new FileInputStream(bundleFile);
properties.load(in);
} catch (IOException e) {
} finally {
Closeables.closeQuietly(in);
}
Properties defaults = getDefaultBundleProperties();
for (Entry<Object, Object> entry : defaults.entrySet()) {
if (!properties.containsKey(entry.getKey()))
properties.put(entry.getKey(), entry.getValue());
}
OutputStream stream = null;
try {
stream = new FileOutputStream(bundleFile);
properties.store(stream, "");
} catch (Exception e) {
e.printStackTrace();
} finally {
Closeables.closeQuietly(stream);
}
}
public static String translate(String key, Locale preferredLocale, Object... msg) {
if (instance == null)
createInstance();
return StringHelper.parseColors(msg.length == 0 ? instance.translate(key, preferredLocale) : instance.format(
key, preferredLocale, msg));
}
public static String translate(String key, Object... msg) {
if (instance == null)
createInstance();
return translate(key, instance.defaultLocale, msg);
}
}