More work on i18n - changed Messages to string constants instead of enums, new strings must be translated into the messages_en.properties file

This commit is contained in:
fullwall 2012-09-30 17:55:51 +08:00
parent 3d5612cbf9
commit 55bb5adef7
13 changed files with 134 additions and 80 deletions

View File

@ -77,6 +77,7 @@
<directory>${basedir}/src/main/resources</directory>
<includes>
<include>plugin.yml</include>
<include>*_en.properties</include>
</includes>
</resource>
</resources>

View File

@ -185,7 +185,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
npcRegistry = null;
}
Messaging.logF("v%s disabled.", getDescription().getVersion());
Messaging.logTr(Messages.CITIZENS_DISABLED, getDescription().getVersion());
}
@Override
@ -194,8 +194,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
String mcVersion = ((CraftServer) getServer()).getServer().getVersion();
compatible = mcVersion.startsWith(COMPATIBLE_MC_VERSION);
if (!compatible) {
Messaging.severeF("v%s is not compatible with Minecraft v%s. Disabling.", getDescription()
.getVersion(), mcVersion);
Messaging.severeTr(Messages.CITIZENS_INCOMPATIBLE, getDescription().getVersion(), mcVersion);
getServer().getPluginManager().disablePlugin(this);
return;
}
@ -222,7 +221,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
registerCommands();
enableSubPlugins();
Messaging.logF("v%s enabled.", getDescription().getVersion());
Messaging.logTr(Messages.CITIZENS_ENABLED, getDescription().getVersion());
// Setup NPCs after all plugins have been enabled (allows for multiworld
// support and for NPCs to properly register external settings)

View File

@ -20,6 +20,8 @@ import net.citizensnpcs.api.trait.trait.Owner;
import net.citizensnpcs.editor.Editor;
import net.citizensnpcs.npc.entity.EntityHumanNPC;
import net.citizensnpcs.trait.CurrentLocation;
import net.citizensnpcs.util.Messages;
import net.citizensnpcs.util.Messaging;
import net.citizensnpcs.util.NMS;
import net.minecraft.server.EntityPlayer;
@ -209,7 +211,7 @@ public class EventListen implements Listener {
int wouldOwn = owned + 1;
if (wouldOwn >= limit) {
event.setCancelled(true);
event.setCancelReason(String.format("Over the NPC limit of %d.", limit));
event.setCancelReason(Messaging.tr(Messages.OVER_NPC_LIMIT, limit));
}
}

View File

@ -13,6 +13,7 @@ import net.citizensnpcs.api.util.Storage;
import net.citizensnpcs.api.util.YamlStorage;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.CitizensNPCRegistry;
import net.citizensnpcs.util.Messages;
import net.citizensnpcs.util.Messaging;
import org.bukkit.entity.EntityType;
@ -29,7 +30,7 @@ public class NPCDataStore {
for (DataKey key : root.getKey("npc").getIntegerSubKeys()) {
int id = Integer.parseInt(key.name());
if (!key.keyExists("name")) {
Messaging.logF("Could not find a name for ID '%s'.", id);
Messaging.logTr(Messages.LOAD_NAME_NOT_FOUND, id);
continue;
}
String unparsedEntityType = key.getString("traits.type", "PLAYER");
@ -38,8 +39,7 @@ public class NPCDataStore {
try {
type = EntityType.valueOf(unparsedEntityType);
} catch (IllegalArgumentException ex) {
Messaging.logF("NPC type '%s' was not recognized. Did you spell it correctly?",
unparsedEntityType);
Messaging.logTr(Messages.LOAD_UNKNOWN_NPC_TYPE, unparsedEntityType);
continue;
}
}
@ -50,7 +50,7 @@ public class NPCDataStore {
if (npc.isSpawned())
spawned++;
}
Messaging.logF("Loaded %d NPCs (%d spawned).", created, spawned);
Messaging.logTr(Messages.NUM_LOADED_NOTIFICATION, created, spawned);
}
public void remove(NPC npc) {
@ -89,7 +89,7 @@ public class NPCDataStore {
Setting.DATABASE_PASSWORD.asString());
} catch (SQLException e) {
e.printStackTrace();
Messaging.log("Unable to connect to database, falling back to YAML");
Messaging.logTr(Messages.DATABASE_CONNECTION_FAILED);
}
} else if (type.equalsIgnoreCase("nbt")) {
saves = new NBTStorage(folder + File.separator + Setting.STORAGE_FILE.asString(),
@ -99,7 +99,7 @@ public class NPCDataStore {
saves = new YamlStorage(new File(folder, Setting.STORAGE_FILE.asString()), "Citizens NPC Storage");
if (!saves.load())
return null;
Messaging.logF("Save method set to %s.", saves.toString());
Messaging.logTr(Messages.SAVE_METHOD_SET_NOTIFICATION, saves.toString());
return new NPCDataStore(saves);
}
}

View File

@ -2,6 +2,7 @@ package net.citizensnpcs;
import net.citizensnpcs.Settings.Setting;
import net.citizensnpcs.api.event.PlayerCreateNPCEvent;
import net.citizensnpcs.util.Messages;
import net.citizensnpcs.util.Messaging;
import net.citizensnpcs.util.StringHelper;
import net.milkbowl.vault.economy.Economy;
@ -28,13 +29,14 @@ public class PaymentListener implements Listener {
return;
double cost = Setting.NPC_COST.asDouble();
boolean hasEnough = provider.has(name, cost);
String formattedCost = provider.format(cost);
if (!hasEnough) {
event.setCancelled(true);
event.setCancelReason(String.format("Need at least %s.", provider.format(cost)));
event.setCancelReason(Messaging.tr(Messages.MINIMUM_COST_REQUIRED, formattedCost));
return;
}
provider.withdrawPlayer(name, cost);
Messaging.sendF(event.getCreator(), ChatColor.GREEN + "Withdrew %s for your NPC.",
StringHelper.wrap(provider.format(cost)));
String message = Messaging.tr(Messages.MONEY_WITHDRAWN, StringHelper.wrap(formattedCost));
Messaging.send(event.getCreator(), ChatColor.GREEN + message);
}
}

View File

@ -7,6 +7,7 @@ import java.util.List;
import net.citizensnpcs.api.util.DataKey;
import net.citizensnpcs.api.util.Storage;
import net.citizensnpcs.api.util.YamlStorage;
import net.citizensnpcs.util.Messages;
import net.citizensnpcs.util.Messaging;
import com.google.common.collect.Lists;
@ -22,7 +23,7 @@ public class Settings {
config.load();
for (Setting setting : Setting.values()) {
if (!root.keyExists(setting.path)) {
Messaging.logF("Writing default setting: '%s'", setting.path);
Messaging.logTr(Messages.WRITING_DEFAULT_SETTING, setting.path);
setting.setAtKey(root);
} else
setting.loadFromKey(root);

View File

@ -5,7 +5,6 @@ import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Command {
String[] aliases();
String desc();

View File

@ -26,6 +26,8 @@ import net.citizensnpcs.command.exception.RequirementMissingException;
import net.citizensnpcs.command.exception.ServerCommandException;
import net.citizensnpcs.command.exception.UnhandledCommandException;
import net.citizensnpcs.command.exception.WrappedCommandException;
import net.citizensnpcs.util.Messages;
import net.citizensnpcs.util.Messaging;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
@ -120,11 +122,12 @@ public class CommandManager {
if (cmdRequirements.selected()) {
boolean canRedefineSelected = context.hasValueFlag("id")
&& sender.hasPermission("npc.select");
String error = "You must have an NPC selected to execute that command.";
String error = Messaging.tr(Messages.COMMAND_MUST_HAVE_SELECTED);
if (canRedefineSelected) {
npc = CitizensAPI.getNPCRegistry().getById(context.getFlagInteger("id"));
if (npc == null)
error += " Couldn't find any NPC with ID " + context.getFlagInteger("id") + ".";
error += ' ' + Messaging.tr(Messages.COMMAND_ID_NOT_FOUND,
context.getFlagInteger("id"));
}
if (npc == null)
throw new RequirementMissingException(error);
@ -132,8 +135,7 @@ public class CommandManager {
if (cmdRequirements.ownership() && npc != null && !sender.hasPermission("citizens.admin")
&& !npc.getTrait(Owner.class).isOwnedBy(sender))
throw new RequirementMissingException(
"You must be the owner of this NPC to execute that command.");
throw new RequirementMissingException(Messaging.tr(Messages.COMMAND_MUST_BE_OWNER));
if (npc != null) {
Set<EntityType> types = Sets.newEnumSet(Arrays.asList(cmdRequirements.types()),
@ -144,8 +146,8 @@ public class CommandManager {
EntityType type = npc.getTrait(MobType.class).getType();
if (!types.contains(type)) {
throw new RequirementMissingException("The NPC cannot be the mob type '" + type.getName()
+ "' to use that command.");
throw new RequirementMissingException(Messaging.tr(Messages.COMMAND_INVALID_MOB_TYPE,
type.getName()));
}
}
}

View File

@ -4,55 +4,73 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ListResourceBundle;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
import com.google.common.io.Closeables;
public enum Messages {
CITIZENS_IMPLEMENTATION_DISABLED("citizens.changed-implementation",
"Citizens implementation changed, disabling plugin."),
COMMAND_INVALID_NUMBER("citizens.commands.invalid-number", "That is not a valid number."),
COMMAND_MUST_BE_INGAME("citizens.commands.must-be-ingame", "You must be ingame to use that command."),
COMMAND_REPORT_ERROR("citizens.commands.console-error", "Please report this error: [See console]"),
ERROR_INITALISING_SUB_PLUGIN("citizens.sub-plugins.error-on-load", "{0} initializing {1}"),
ERROR_LOADING_ECONOMY("citizens.economy.error-loading",
"Unable to use economy handling. Has Vault been enabled?"),
FAILED_LOAD_SAVES("citizens.saves.load-failed", "Unable to load saves, disabling..."),
LOAD_TASK_NOT_SCHEDULED("citizens.load-task-error", "NPC load task couldn't be scheduled - disabling..."),
LOADING_SUB_PLUGIN("citizens.sub-plugins.load", "Loading {0}"),
LOCALE_NOTIFICATION("citizens.notifications.locale", "Using locale {0}."),
METRICS_ERROR_NOTIFICATION("citizens.notifications.metrics-load-error", "Unable to start metrics: {0}."),
METRICS_NOTIFICATION("citizens.notifications.metrics-started", "Metrics started."),
UNKNOWN_COMMAND("citizens.commands.unknown-command", "Unknown command. Did you mean:");
private String defaultTranslation;
private String key;
Messages(String key, String defaultTranslation) {
this.key = key;
this.defaultTranslation = defaultTranslation;
}
public String getKey() {
return key;
}
public class Messages {
public static final String CITIZENS_DISABLED = "citizens.notifications.disabled";
public static final String CITIZENS_ENABLED = "citizens.notifications.enabled";
public static final String CITIZENS_IMPLEMENTATION_DISABLED = "citizens.changed-implementation";
public static final String CITIZENS_INCOMPATIBLE = "citizens.notifications.incompatible-version";
public static final String COMMAND_ID_NOT_FOUND = "citizens.commands.id-not-found";
public static final String COMMAND_INVALID_MOB_TYPE = "citizens.commands.disallowed-mobtype";
public static final String COMMAND_INVALID_NUMBER = "citizens.commands.invalid-number";
public static final String COMMAND_MUST_BE_INGAME = "citizens.commands.must-be-ingame";
public static final String COMMAND_MUST_BE_OWNER = "citizens.commands.must-be-owner";
public static final String COMMAND_MUST_HAVE_SELECTED = "citizens.commands.must-have-selected";
public static final String COMMAND_REPORT_ERROR = "citizens.commands.console-error";
public static final String DATABASE_CONNECTION_FAILED = "citizens.notifications.database-connection-failed";
private static ResourceBundle defaultBundle;
public static final String ERROR_INITALISING_SUB_PLUGIN = "citizens.sub-plugins.error-on-load";
public static final String ERROR_LOADING_ECONOMY = "citizens.economy.error-loading";
public static final String FAILED_LOAD_SAVES = "citizens.saves.load-failed";
public static final String LOAD_NAME_NOT_FOUND = "citizens.notifications.npc-name-not-found";
public static final String LOAD_TASK_NOT_SCHEDULED = "citizens.load-task-error";
public static final String LOAD_UNKNOWN_NPC_TYPE = "citizens.notifications.unknown-npc-type";
public static final String LOADING_SUB_PLUGIN = "citizens.sub-plugins.load";
public static final String LOCALE_NOTIFICATION = "citizens.notifications.locale";
public static final String METRICS_ERROR_NOTIFICATION = "citizens.notifications.metrics-load-error";
public static final String METRICS_NOTIFICATION = "citizens.notifications.metrics-started";
public static final String MINIMUM_COST_REQUIRED = "citizens.economy.minimum-cost-required-message";
public static final String MONEY_WITHDRAWN = "citizens.economy.money-withdrawn";
public static final String NUM_LOADED_NOTIFICATION = "citizens.notifications.npcs-loaded";
public static final String OVER_NPC_LIMIT = "citizens.limits.over-npc-limit";
public static final String SAVE_METHOD_SET_NOTIFICATION = "citizens.notifications.save-method-set";
public static final String UNKNOWN_COMMAND = "citizens.commands.unknown-command";
public static final String WRITING_DEFAULT_SETTING = "citizens.settings.writing-default";
private static Properties getDefaultBundleProperties() {
Properties defaults = new Properties();
InputStream in = null;
try {
in = Messages.class.getResourceAsStream("/" + Translator.PREFIX + "_en.properties");
defaults.load(in);
} catch (IOException e) {
} finally {
Closeables.closeQuietly(in);
}
return defaults;
}
public static ResourceBundle getDefaultResourceBundle(File resourceDirectory, String fileName) {
if (defaultBundle == null) {
resourceDirectory.mkdirs();
File bundleFile = new File(resourceDirectory, fileName);
if (!bundleFile.exists())
if (!bundleFile.exists()) {
try {
bundleFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
populateDefaults(bundleFile);
FileInputStream stream = null;
try {
@ -72,20 +90,14 @@ public enum Messages {
return new ListResourceBundle() {
@Override
protected Object[][] getContents() {
Messages[] values = values();
Object[][] contents = new Object[values.length][2];
for (int i = 0; i < values.length; i++) {
Messages message = values[i];
contents[i] = new Object[] { message.key, message.defaultTranslation };
}
return contents;
return new Object[0][0];
}
};
}
private static void populateDefaults(File bundleFile) {
Properties properties = new Properties();
FileInputStream in = null;
InputStream in = null;
try {
in = new FileInputStream(bundleFile);
properties.load(in);
@ -93,13 +105,15 @@ public enum Messages {
} finally {
Closeables.closeQuietly(in);
}
for (Messages message : values()) {
if (!properties.containsKey(message.key))
properties.put(message.key, message.defaultTranslation);
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 {
properties.store(stream = new FileOutputStream(bundleFile), "");
stream = new FileOutputStream(bundleFile);
properties.store(stream, "");
} catch (Exception e) {
e.printStackTrace();
} finally {

View File

@ -46,7 +46,7 @@ public class Messaging {
log(getFormatted(msg));
}
public static void logTr(Messages key, Object... msg) {
public static void logTr(String key, Object... msg) {
log(Level.INFO, Translator.tr(key, msg));
}
@ -62,7 +62,7 @@ public class Messaging {
sendF(sender, ChatColor.RED.toString() + SPACE.join(msg));
}
public static void sendErrorTr(CommandSender sender, Messages key, Object... msg) {
public static void sendErrorTr(CommandSender sender, String key, Object... msg) {
sendMessageTo(sender, ChatColor.RED + Translator.tr(key, msg));
}
@ -75,7 +75,7 @@ public class Messaging {
sender.sendMessage(msg);
}
public static void sendTr(CommandSender sender, Messages key, Object... msg) {
public static void sendTr(CommandSender sender, String key, Object... msg) {
sendMessageTo(sender, Translator.tr(key, msg));
}
@ -102,7 +102,11 @@ public class Messaging {
log(Level.SEVERE, getFormatted(messages));
}
public static void severeTr(Messages key, Object... messages) {
public static void severeTr(String key, Object... messages) {
log(Level.SEVERE, Translator.tr(key, messages));
}
public static String tr(String key, Object... messages) {
return Translator.tr(key, messages);
}
}

View File

@ -42,6 +42,7 @@ public class NMS {
private static Field PATHFINDING_RANGE;
private static Field SPEED_FIELD;
private static Field THREAD_STOPPER;
public static void attack(EntityLiving handle, EntityLiving target) {
handle.k(target);
}
@ -54,6 +55,7 @@ public class NMS {
List<?> list = (List<?>) NMS.GOAL_FIELD.get(selector);
list.clear();
} catch (Exception e) {
Messaging.logF("Could not clear goals: %s", e.getMessage());
}
}
}
@ -76,6 +78,7 @@ public class NMS {
f = clazz.getDeclaredField(field);
f.setAccessible(true);
} catch (Exception e) {
Messaging.logF("Could not fetch field %s: %s.", field, e.getMessage());
}
return f;
}
@ -134,8 +137,8 @@ public class NMS {
return;
try {
LAND_SPEED_MODIFIER_FIELD.setFloat(handle, speed);
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
} catch (Exception e) {
Messaging.logF("Could not update land speed modifier: %s.", e.getMessage());
}
}
@ -147,7 +150,7 @@ public class NMS {
Constructor<? extends Entity> constructor = getCustomEntityConstructor(clazz, type);
entity = constructor.newInstance(handle);
} catch (Exception e) {
e.printStackTrace();
Messaging.logF("Could not spawn custom entity: %s.", e.getMessage());
return null;
}
handle.addEntity(entity);
@ -161,6 +164,7 @@ public class NMS {
try {
THREAD_STOPPER.set(manager, false);
} catch (Exception e) {
Messaging.logF("Could not stop network threads: %s.", e.getMessage());
}
}
@ -179,6 +183,7 @@ public class NMS {
try {
NAVIGATION_WORLD_FIELD.set(handle.getNavigation(), worldHandle);
} catch (Exception e) {
Messaging.logF("Could not update navigation world: %s.", e.getMessage());
}
}
@ -188,8 +193,8 @@ public class NMS {
Navigation navigation = npc.getHandle().getNavigation();
try {
PATHFINDING_RANGE.set(navigation, pathfindingRange);
} catch (Exception ex) {
Messaging.logF("Could not update pathfinding range: %s.", ex.getMessage());
} catch (Exception e) {
Messaging.logF("Could not update pathfinding range: %s.", e.getMessage());
}
}
@ -218,12 +223,11 @@ public class NMS {
try {
Field field = getField(EntityTypes.class, "d");
field.setAccessible(true);
ENTITY_INT_TO_CLASS = (Map<Integer, Class<? extends Entity>>) field.get(null);
field = getField(EntityTypes.class, "e");
field.setAccessible(true);
ENTITY_CLASS_TO_INT = (Map<Class<? extends Entity>, Integer>) field.get(null);
} catch (Exception e) {
Messaging.logF("Could not fetch entity id mapping fields: %s", e.getMessage());
}
}
}

View File

@ -94,16 +94,13 @@ public class Translator {
private static Translator instance;
public static final String PREFIX = "messages";
public static void setInstance(File resourceFile, Locale locale) {
instance = new Translator(resourceFile, locale);
}
public static String tr(Messages key) {
return tr(key.getKey());
}
public static String tr(Messages key, Object... msg) {
return tr(key.getKey(), msg);
public static String tr(String key) {
return tr(key);
}
public static String tr(String key, Object... msg) {

View File

@ -0,0 +1,29 @@
citizens.changed-implementation=Citizens implementation changed=disabling plugin.
citizens.commands.console-error=Please report this error: [See console]
citizens.commands.invalid-number=That is not a valid number.
citizens.commands.must-be-ingame=You must be ingame to use that command.
citizens.commands.unknown-command=Unknown command. Did you mean:
citizens.commands.id-not-found=Couldn't find any NPC with ID {0}.
citizens.commands.disallowed-mobtype=The NPC cannot be the mob type '{0}' to use that command.
citizens.commands.must-have-selected=You must have an NPC selected to execute that command.
citizens.commands.must-be-owner=You must be the owner of this NPC to execute that command.
citizens.economy.error-loading=Unable to use economy handling. Has Vault been enabled?
citizens.economy.minimum-cost-required-message=Need at least {0}.
citizens.economy.money-withdrawn=Withdrew {0} for your NPC.
citizens.limits.over-npc-limt=Over the NPC limit of {0}.
citizens.load-task-error=NPC load task couldn't be scheduled - disabling...
citizens.saves.load-failed=Unable to load saves=disabling...
citizens.sub-plugins.load=Loading {0}
citizens.sub-plugins.error-on-load={0} initializing {1}
citizens.settings.writing-default=Writing default setting: '{0}'
citizens.notifications.enabled=v{0} enabled.
citizens.notifications.disabled=v{0} disabled.
citizens.notifications.incompatible-version=v{0} is not compatible with Minecraft v{1}. Disabling.
citizens.notifications.locale=Using locale {0}.
citizens.notifications.metrics-load-error=Unable to start metrics: {0}.
citizens.notifications.metrics-started=Metrics started.
citizens.notifications.npc-name-not-found=Could not find a name for ID '{0}'.
citizens.notifications.npc-loaded=Loaded {0} NPCs ({1} spawned).
citizens.notifications.save-method-set=Save method set to {0}.
citizens.notifications.database-connection-failed=Unable to connect to database, falling back to YAML
citizens.notifications.unknown-npc-type=NPC type '{0}' was not recognized. Did you spell it correctly?