For people who want to allow their users to change any message and not have their messages hard coded, I have made an enum for easily implementing custom messages. Here is the Lang enum, add this enum to your plugin. Code:java package your.package; import org.bukkit.ChatColor;import org.bukkit.configuration.file.YamlConfiguration; /*** An enum for requesting strings from the language file.* @author gomeow*/public enum Lang { TITLE("title-name", "&4[&fAWSMPLUGIN&4]:"), PLAYER_IS_COOL("player-is-cool", "&f%p is cool."), INVALID_ARGS("invalid-args", "&cInvalid args!"), PLAYER_ONLY("player-only", "Sorry but that can only be run by a player!"), MUST_BE_NUMBER("must-be-number", "&cYou need to specify a number, not a word."), NO_PERMS("no-permissions", "&cYou don''t have permission for that!"); private String path; private String def; private static YamlConfiguration LANG; /** * Lang enum constructor. * @param path The string path. * @param start The default string. */ Lang(String path, String start) { this.path = path; this.def = start; } /** * Set the {@code YamlConfiguration} to use. * @param config The config to set. */ public static void setFile(YamlConfiguration config) { LANG = config; } @Override public String toString() { if (this == TITLE) return ChatColor.translateAlternateColorCodes('&', LANG.getString(this.path, def)) + " "; return ChatColor.translateAlternateColorCodes('&', LANG.getString(this.path, def)); } /** * Get the default value of the path. * @return The default value of the path. */ public String getDefault() { return this.def; } /** * Get the path to the string. * @return The path to the string. */ public String getPath() { return this.path; }} For the actual enum values, the first parameter is the path to it in the yaml config, and the second is the default value. First, add these fields to your main class: Code:java public static YamlConfiguration LANG;public static File LANG_FILE; Next, you must call this method in your onEnable: Code:java /** * Load the lang.yml file. * @return The lang.yml config. */public void loadLang() { File lang = new File(getDataFolder(), "lang.yml"); if (!lang.exists()) { try { getDataFolder().mkdir(); lang.createNewFile(); InputStream defConfigStream = this.getResource("lang.yml"); if (defConfigStream != null) { YamlConfiguration defConfig = YamlConfiguration.loadConfiguration(defConfigStream); defConfig.save(lang); Lang.setFile(defConfig); return defConfig; } } catch(IOException e) { e.printStackTrace(); // So they notice log.severe("[PluginName] Couldn't create language file."); log.severe("[PluginName] This is a fatal error. Now disabling"); this.setEnabled(false); // Without it loaded, we can't send them messages } } YamlConfiguration conf = YamlConfiguration.loadConfiguration(lang); for(Lang item:Lang.values()) { if (conf.getString(item.getPath()) == null) { conf.set(item.getPath(), item.getDefault()); } } Lang.setFile(conf); MainClass.LANG = conf; MainClass.LANG_FILE = lang; try { conf.save(getLangFile()); } catch(IOException e) { log.log(Level.WARNING, "PluginName: Failed to save lang.yml."); log.log(Level.WARNING, "PluginName: Report this stack trace to <your name>."); e.printStackTrace(); }} This will load the lang.yml, by copying the default one from the jar, then it will set the yaml file in the Lang enum. This will allow that enum to use the lang.yml to get the user defined messages. Also, add these methods to your main class: Code:java /*** Gets the lang.yml config.* @return The lang.yml config.*/public YamlConfiguration getLang() { return LANG;} /*** Get the lang.yml file.* @return The lang.yml file.*/public File getLangFile() { return LANG_FILE;} Next, make a file next to your config.yml like this: Code: # Use & for color codes. # %p is where the player name will get inserted. title-name: "&4[&PluginName&4]:" player-is-cool: "&f%p is cool." player-only: "Sorry but that can only be run by a player!" must-be-number: "&cYou need to specify a number, not a word." invalid-args: "&cInvalid args!" no-permissions: "&cYou don't have permission for that!" Lastly, to use it say, if a player does not have permission to do something, we would use it like this: Code: player.sendMessage(Lang.TITLE.toString() + Lang.NO_PERMS); Now if you have messages that vary depending on some variable, say you wanted to say some player is cool, you would use it like this: Code: Bukkit.broadcastMessage(Lang.TITLE.toString() + Lang.PLAYER_IS_COOL.toString().replace("%p", player.getName())); I hope it helps you As seen in action: https://github.com/drtshock/PlayerV...java/com/drtshock/playervaults/util/Lang.java drtshock helped sorta kinda
Awesome. People should definitely use this for their plugins instead of hard coding messages. Makes things so much easier
Doing this makes localization much simpler and I recommend everyone to use it or adopt their own way of externalizing strings! Eclipse actually has this built in under Source > Externalize Strings.
You might want to force UTF-8 encoding for the language file to allow all special characters from the individual languages that are also usable in minecraft.
TheE How would one force UTF-8 encoding? I've had this problem with my language files for a long time. (Have I missed a constructor of YamlConfiguration ?)
Unfortunately you cannot use bukkit's configuration API here, because it always uses the encoding of the operation system it runs on. I have no idea why anybody could think (and still thinks!) this would be a great idea, but anyway... You will need to write your own YamlConfiguration implementation using the snackyaml-library bundled with bukkit and implement encoding support, or just force UTF-8 completely. As far as I remember, sk89q has done exactly that for worldedit, so you could just use his code if your project is licensed under GPL. If you do not need or want yaml, you just need to make sure that you set the encoding correctly when reading the files (InputStreamReader can be initialized with the file's encoding). You may have a look at the LanguageManager I wrote for MyWarp, although I strongly want to move to Yaml soon. Something that has not been stressed yet is that java actually has its own standards for localisations, RessourceBundles. I have not really looked into them until now, but I recently discovered that aumgn has written a yaml-version for BukkitUtils, so this might be worth a look too. Edit: According to Wolvereness they have implemented encoding somehow, but I have no idea how and where. There is nothing to be found in the docs of file-configuration and yaml-configuration.
gomeow I implemented this into my plugin the other day, and after doing some testing with it today, I realised there is a problem, idk if it is just me or what. everything works fine upon the first load. but when I shut the server down and restart it, everything in my config file is loaded without quotations Example, I save like this Code: NoPermission: "Sorry, you don't have permission to run this command." but after restarting the server it loads like this Code: NoPermission: Sorry, you don't have permission to run this command. this is causing problems with some of my wordings that use apostrophe... is this an error on me or with this code?
Try combining this with http://forums.bukkit.org/threads/get-a-players-minecraft-language.172468/ for an awesome user experience
Hello. Is there option to make .toString().replace("%points" getPlayerPoints(hero))) acceptable for int data type (getPlayerPoints(hero) returns int, not string, I mustn't change that)?
I'd recommend a *.xml-File for Language Files. In my opinion it's more efficient and you've got more possibilities with it. Might be different to every plugin, but as soon as your plugin gets bigger it would be the best way to use *.xml. You can figure it out with some methodes in which you use the APIs JavaX and W3C.Dom. My LanguageHandler contains 2 important methods: getRawMessage(String language, String element, String messageKey) getColoredMessage(String langugae, String messageKey) The first method does search for the language file in a specified format - like "lang_<shortcut>.xml". The element means which XML-element you'll use. Code: <language> <info key="name" value="English"> <info key="shortcut" value="en_US"> ... <messages> <message key="noperm" value="Insufficient permissions!" /> .. </messages> </language> So, if you want to get the shortcut for example, you have to use the element "info" with the messageKey "shortcut". The second method simply colors the raw message, for example in my plugin: Code: public String getColoredMessage(String lang, String messageKey) { return ChatColor.translateAlternateColorCodes('@', getRawMessage(lang, "message", messageKey)); } That's the usage of XML. gz PS: Sorry for my English, not my main language
When you say create a file next to your Config.yml, what do we name it? And how exactly do we create it? I'm sorry for the beginner question, I'm new to using configs :3
I copy and paste everything written there, but this shows error.. Code:java return defConfig; Void methods cannot return a value Did I missed Anything?[/quote] Plus how to add other Language? EDIT by Moderator: merged posts, please use the edit button instead of double posting.
Name it whatever you want, just make sure it is the same in the code. (The example uses lang.yml). Create the same way you create the plugin.yml Sounds like you need to check the method declaration. You edit the Lang file. Or you can supply your users with multiple files, and they can switch them out