From 411c66f768ff7c5d2d8c087cc3c3beb2d01dab4d Mon Sep 17 00:00:00 2001 From: Crafter_Y <71288761+Crafter-Y@users.noreply.github.com> Date: Tue, 11 Jul 2023 16:10:28 +0200 Subject: [PATCH] Internationalisation (i18) (#2) * i18n APIs * finished i18n * readme update --- README.md | 5 +- annotations/build.gradle | 3 + .../CraftingAnnotationProcessor.java | 185 ++++++++++++++++++ .../annotation/annotations/I18nDef.java | 12 ++ .../annotation/annotations/I18nSource.java | 12 ++ .../javax.annotation.processing.Processor | 1 + .../src/main/groovy/craftinghomes.java.gradle | 3 + .../craftinghomes/BukkitPlatform.java | 11 +- .../craftinghomes/impl/ConfigrationImpl.java | 43 +++- bukkit/src/main/resources/config.yml | 3 + common/build.gradle | 3 + .../craftinghomes/common/AbstractCommand.java | 6 + .../craftinghomes/common/Platform.java | 7 + .../craftinghomes/common/ServerEntry.java | 1 + .../common/api/ConfigurationI.java | 2 + .../common/i18n/BaseI18nProvider.java | 46 +++++ .../craftinghomes/common/i18n/Messages.java | 23 +++ .../craftery/craftinghomes/CraftingHomes.java | 4 + .../commands/DelhomeCommand.java | 6 +- .../craftinghomes/commands/HomeCommand.java | 6 +- .../craftinghomes/commands/HomesCommand.java | 6 +- .../commands/SethomeCommand.java | 4 +- gradle.properties | 2 +- settings.gradle | 3 +- 24 files changed, 377 insertions(+), 20 deletions(-) create mode 100644 annotations/build.gradle create mode 100644 annotations/src/main/java/de/craftery/craftinghomes/annotation/CraftingAnnotationProcessor.java create mode 100644 annotations/src/main/java/de/craftery/craftinghomes/annotation/annotations/I18nDef.java create mode 100644 annotations/src/main/java/de/craftery/craftinghomes/annotation/annotations/I18nSource.java create mode 100644 annotations/src/main/resources/META-INF/services/javax.annotation.processing.Processor create mode 100644 common/src/main/java/de/craftery/craftinghomes/common/i18n/BaseI18nProvider.java create mode 100644 common/src/main/java/de/craftery/craftinghomes/common/i18n/Messages.java diff --git a/README.md b/README.md index 13dc8c5..d48e9a0 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,14 @@ plugin (for now) that has the basic commands `/home`, `/homes`, Several things can be configured in the `config.yml` file. - maxHomes: The maximum amount of homes a player can have, default: 3 +- language: The language to use, default: en + +You can add your own language by creating a new file your_language.lang.yml ## Roadmap - [x] Persistent Data Storage - [x] Configurable Homes per player - [x] reflection for command discovery - [x] abstract command definition syntax (with annotations) -- [ ] i18n +- [x] configurable i18n - [ ] other implementations like fabric or forge diff --git a/annotations/build.gradle b/annotations/build.gradle new file mode 100644 index 0000000..5e2d27c --- /dev/null +++ b/annotations/build.gradle @@ -0,0 +1,3 @@ +plugins { + id("craftinghomes.java") +} \ No newline at end of file diff --git a/annotations/src/main/java/de/craftery/craftinghomes/annotation/CraftingAnnotationProcessor.java b/annotations/src/main/java/de/craftery/craftinghomes/annotation/CraftingAnnotationProcessor.java new file mode 100644 index 0000000..841ea10 --- /dev/null +++ b/annotations/src/main/java/de/craftery/craftinghomes/annotation/CraftingAnnotationProcessor.java @@ -0,0 +1,185 @@ +package de.craftery.craftinghomes.annotation; + +import de.craftery.craftinghomes.annotation.annotations.I18nDef; +import de.craftery.craftinghomes.annotation.annotations.I18nSource; + +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.annotation.processing.SupportedSourceVersion; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.*; +import javax.tools.Diagnostic; +import javax.tools.JavaFileObject; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.*; + +@SupportedAnnotationTypes("de.craftery.craftinghomes.annotation.annotations.*") +@SupportedSourceVersion(SourceVersion.RELEASE_17) +public class CraftingAnnotationProcessor extends AbstractProcessor { + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + return processI18nAnnotations(roundEnv); + } + + private boolean processI18nAnnotations(RoundEnvironment roundEnv) { + Set elements = roundEnv.getElementsAnnotatedWith(I18nSource.class); + if (elements.size() > 1) { + error("There can only be one I18nSource per project for now!"); + return false; + } + if (elements.isEmpty()) { + return false; + } + + Element providerElement = elements.iterator().next(); + if (!(providerElement instanceof TypeElement providerClass)) { + error("Entry element must be a interface!"); + return false; + } + + if (providerClass.getKind() != ElementKind.INTERFACE) { + error("Entry element must be a interface!"); + return false; + } + + Map translations = new HashMap<>(); + Map> parameters = new HashMap<>(); + + for (Element type : providerClass.getEnclosedElements()) { + if (type.getKind() != ElementKind.METHOD) { + error("Each entry in this interface must be a method!"); + return false; + } + ExecutableElement method = (ExecutableElement) type; + + if (!method.getReturnType().toString().equals("java.lang.String")) { + error("Each entry in this interface must return a String! Got: " + method.getReturnType().toString()); + return false; + } + if (type.getAnnotation(I18nDef.class) == null) { + error("Each entry in this interface must be annotated with @I18nDef!"); + return false; + } + + Map methodParameters = new HashMap<>(); + for (VariableElement parameter : method.getParameters()) { + String paramType; + switch (parameter.asType().toString()) { + case "java.lang.String" -> paramType = "String"; + case "java.lang.Integer" -> paramType = "Integer"; + default -> { + error("Unimplemented parameter type: " + parameter.asType().toString() + " in method " + method.getSimpleName().toString()); + return false; + } + } + methodParameters.put(parameter.getSimpleName().toString(), paramType); + } + + String def = type.getAnnotation(I18nDef.class).def(); + translations.put(type.getSimpleName().toString(), def); + parameters.put(type.getSimpleName().toString(), methodParameters); + } + + String providerPath = providerClass.getQualifiedName().toString(); + String providerName = providerClass.getAnnotation(I18nSource.class).name(); + + String packageName = null; + int lastDot = providerPath.lastIndexOf('.'); + if (lastDot > 0) { + packageName = providerPath.substring(0, lastDot); + } + String generatedClassName = packageName + "." + providerName; + + try { + JavaFileObject builderFile = processingEnv.getFiler() + .createSourceFile(generatedClassName); + + try (PrintWriter out = new PrintWriter(builderFile.openWriter())) { + // class header + if (packageName != null) { + out.print("package "); + out.print(packageName); + out.println(";"); + out.println(); + } + + out.print("public class "); + out.print(providerName); + out.print(" extends BaseI18nProvider implements "); + out.print(providerPath); + out.println(" {"); + + // adding all translations to outer object + out.println(" @Override"); + out.println(" protected void addAllTranslations() {"); + + for (Map.Entry implementation : translations.entrySet()) { + out.print(" this.defTranslations.put(\""); + out.print(implementation.getKey()); + out.print("\", \""); + out.print(implementation.getValue()); + out.println("\");"); + } + + out.println(" }"); + + // implement all methods of interface + for (Map.Entry implementation : translations.entrySet()) { + out.println(); + out.println(" @Override"); + out.print(" public String "); + out.print(implementation.getKey()); + out.print("("); + + List paramTypes = parameters.get(implementation.getKey()).entrySet().stream() + .map(el -> el.getValue() + " " + el.getKey()).toList(); + out.print(String.join(", ", paramTypes)); + + out.println(") {"); + out.print(" String translation = this.getTranslation(\""); + out.print(implementation.getKey()); + out.println("\");"); + + for (Map.Entry parameter : parameters.get(implementation.getKey()).entrySet()) { + String replaceMethod; + switch (parameter.getValue()) { + case "String" -> replaceMethod = "replaceString"; + case "Integer" -> replaceMethod = "replaceInteger"; + default -> { + error("Unimplemented parameter type: " + parameter.getValue()); + return false; + } + } + + out.print(" translation = this."); + out.print(replaceMethod); + out.print("(translation, \"${"); + out.print(parameter.getKey()); + out.print("}\", "); + out.print(parameter.getKey()); + out.println(");"); + + } + + out.println(" return translation;"); + + out.println(" }"); + } + + out.println(); + out.println("}"); + } + } catch (IOException e) { + error("Failed to create file: " + e.getMessage()); + return false; + } + + return true; + } + + private void error(String message) { + this.processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, message); + } +} diff --git a/annotations/src/main/java/de/craftery/craftinghomes/annotation/annotations/I18nDef.java b/annotations/src/main/java/de/craftery/craftinghomes/annotation/annotations/I18nDef.java new file mode 100644 index 0000000..67d7d1e --- /dev/null +++ b/annotations/src/main/java/de/craftery/craftinghomes/annotation/annotations/I18nDef.java @@ -0,0 +1,12 @@ +package de.craftery.craftinghomes.annotation.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.SOURCE) +@Target(ElementType.METHOD) +public @interface I18nDef { + String def(); +} diff --git a/annotations/src/main/java/de/craftery/craftinghomes/annotation/annotations/I18nSource.java b/annotations/src/main/java/de/craftery/craftinghomes/annotation/annotations/I18nSource.java new file mode 100644 index 0000000..10b914b --- /dev/null +++ b/annotations/src/main/java/de/craftery/craftinghomes/annotation/annotations/I18nSource.java @@ -0,0 +1,12 @@ +package de.craftery.craftinghomes.annotation.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.SOURCE) +@Target(ElementType.TYPE) +public @interface I18nSource { + String name(); +} diff --git a/annotations/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/annotations/src/main/resources/META-INF/services/javax.annotation.processing.Processor new file mode 100644 index 0000000..25fcb54 --- /dev/null +++ b/annotations/src/main/resources/META-INF/services/javax.annotation.processing.Processor @@ -0,0 +1 @@ +de.craftery.craftinghomes.annotation.CraftingAnnotationProcessor \ No newline at end of file diff --git a/build-logic/src/main/groovy/craftinghomes.java.gradle b/build-logic/src/main/groovy/craftinghomes.java.gradle index ec651a7..80d01ab 100644 --- a/build-logic/src/main/groovy/craftinghomes.java.gradle +++ b/build-logic/src/main/groovy/craftinghomes.java.gradle @@ -6,6 +6,9 @@ plugins { group = 'de.craftery' version = findProperty('version') +compileJava.options.encoding = "UTF-8" +compileTestJava.options.encoding = "UTF-8" + repositories { mavenCentral() maven { diff --git a/bukkit/src/main/java/de/craftery/craftinghomes/BukkitPlatform.java b/bukkit/src/main/java/de/craftery/craftinghomes/BukkitPlatform.java index f61f171..84331a4 100644 --- a/bukkit/src/main/java/de/craftery/craftinghomes/BukkitPlatform.java +++ b/bukkit/src/main/java/de/craftery/craftinghomes/BukkitPlatform.java @@ -66,10 +66,15 @@ public void registerCommand(AbstractCommand command) { @Override public ConfigurationI getConfiguration() { - return new ConfigrationImpl(this.getConfig()); + return new ConfigrationImpl(this.getDataFolder()); } - public static void saveConfiguration() { - instance.saveConfig(); + @Override + public ConfigurationI getConfiguration(String configFileName) { + return new ConfigrationImpl(this.getDataFolder(), configFileName); + } + + public static BukkitPlatform getInstance() { + return instance; } } diff --git a/bukkit/src/main/java/de/craftery/craftinghomes/impl/ConfigrationImpl.java b/bukkit/src/main/java/de/craftery/craftinghomes/impl/ConfigrationImpl.java index 7be3c8d..509eb14 100644 --- a/bukkit/src/main/java/de/craftery/craftinghomes/impl/ConfigrationImpl.java +++ b/bukkit/src/main/java/de/craftery/craftinghomes/impl/ConfigrationImpl.java @@ -1,18 +1,39 @@ package de.craftery.craftinghomes.impl; +import com.google.common.base.Charsets; import de.craftery.craftinghomes.BukkitPlatform; import de.craftery.craftinghomes.common.api.ConfigurationI; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import java.io.File; +import java.io.InputStream; +import java.io.InputStreamReader; import java.util.HashSet; import java.util.Set; public class ConfigrationImpl implements ConfigurationI { private final FileConfiguration config; + private final File configFile; - public ConfigrationImpl(FileConfiguration config) { - this.config = config; + public ConfigrationImpl(File configDirectory) { + this(configDirectory, "config.yml"); + } + + public ConfigrationImpl (File configDirectory, String configName) { + this.configFile = new File(configDirectory, configName); + this.config = YamlConfiguration.loadConfiguration(configFile); + this.tryLoadDefaults(this.config, configName); + } + + private void tryLoadDefaults(FileConfiguration config, String configName) { + InputStream defConfigStream = BukkitPlatform.getInstance().getResource(configName); + if (defConfigStream == null) { + return; + } + + config.setDefaults(YamlConfiguration.loadConfiguration(new InputStreamReader(defConfigStream, Charsets.UTF_8))); } @Override @@ -49,6 +70,22 @@ public Set getKeys(String path) { @Override public void saveConfig() { - BukkitPlatform.saveConfiguration(); + try { + this.config.save(this.configFile); + } catch (Exception e) { + throw new RuntimeException("Could not save config file!", e); + } + + } + + @Override + public void addDefault(String path, Object value) { + this.config.addDefault(path, value); + } + + @Override + public void applyDefaults() { + this.config.options().copyDefaults(true); + this.saveConfig(); } } diff --git a/bukkit/src/main/resources/config.yml b/bukkit/src/main/resources/config.yml index 530538d..2618b41 100644 --- a/bukkit/src/main/resources/config.yml +++ b/bukkit/src/main/resources/config.yml @@ -1,5 +1,8 @@ # The maximum amount of homes a player can have maxHomes: 3 +# The language to use. All language files must be in format language.lang.yml e.g. en.lang.yml +language: en + # This is the location where homes get saved by default homes: \ No newline at end of file diff --git a/common/build.gradle b/common/build.gradle index 97d6e05..31a9a33 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -5,6 +5,9 @@ plugins { dependencies { shadow 'org.apache.commons:commons-io:1.3.2' implementation 'org.jetbrains:annotations:24.0.1' + + implementation(project(":annotations")) + annotationProcessor(project(":annotations")) } tasks { diff --git a/common/src/main/java/de/craftery/craftinghomes/common/AbstractCommand.java b/common/src/main/java/de/craftery/craftinghomes/common/AbstractCommand.java index ec35bcb..283cb15 100644 --- a/common/src/main/java/de/craftery/craftinghomes/common/AbstractCommand.java +++ b/common/src/main/java/de/craftery/craftinghomes/common/AbstractCommand.java @@ -1,11 +1,13 @@ package de.craftery.craftinghomes.common; import de.craftery.craftinghomes.common.api.CommandSenderI; +import de.craftery.craftinghomes.common.i18n.I18n; import java.util.List; public abstract class AbstractCommand { private final String name; + protected I18n i18n; public AbstractCommand(String name) { this.name = name; @@ -15,6 +17,10 @@ public String getName() { return this.name; } + public void setI18n(I18n i18n) { + this.i18n = i18n; + } + public abstract boolean onCommand(CommandSenderI sender, String[] args); public abstract List onTabComplete(CommandSenderI sender, String[] args); } diff --git a/common/src/main/java/de/craftery/craftinghomes/common/Platform.java b/common/src/main/java/de/craftery/craftinghomes/common/Platform.java index 1f9ffb6..163e592 100644 --- a/common/src/main/java/de/craftery/craftinghomes/common/Platform.java +++ b/common/src/main/java/de/craftery/craftinghomes/common/Platform.java @@ -1,14 +1,21 @@ package de.craftery.craftinghomes.common; +import de.craftery.craftinghomes.common.i18n.I18n; + public class Platform { private static ServerEntry server; + private static final I18n i18n = new I18n(); public static void onEnable(ServerEntry entry) { server = entry; server.log("CraftingHomes is starting up!"); + server.log("Registering i18n!"); + i18n.register(); + for (AbstractCommand command : ReflectionUtil.getCommands()) { server.log("Registering command " + command.getName()); + command.setI18n(i18n); server.registerCommand(command); } } diff --git a/common/src/main/java/de/craftery/craftinghomes/common/ServerEntry.java b/common/src/main/java/de/craftery/craftinghomes/common/ServerEntry.java index ad583e1..ef5d322 100644 --- a/common/src/main/java/de/craftery/craftinghomes/common/ServerEntry.java +++ b/common/src/main/java/de/craftery/craftinghomes/common/ServerEntry.java @@ -6,4 +6,5 @@ public interface ServerEntry { void log(String message); void registerCommand(AbstractCommand command); ConfigurationI getConfiguration(); + ConfigurationI getConfiguration(String configFileName); } diff --git a/common/src/main/java/de/craftery/craftinghomes/common/api/ConfigurationI.java b/common/src/main/java/de/craftery/craftinghomes/common/api/ConfigurationI.java index c2eb972..b415c05 100644 --- a/common/src/main/java/de/craftery/craftinghomes/common/api/ConfigurationI.java +++ b/common/src/main/java/de/craftery/craftinghomes/common/api/ConfigurationI.java @@ -10,4 +10,6 @@ public interface ConfigurationI { boolean exists(String path); Set getKeys(String path); void saveConfig(); + void addDefault(String path, Object value); + void applyDefaults(); } diff --git a/common/src/main/java/de/craftery/craftinghomes/common/i18n/BaseI18nProvider.java b/common/src/main/java/de/craftery/craftinghomes/common/i18n/BaseI18nProvider.java new file mode 100644 index 0000000..ea9644f --- /dev/null +++ b/common/src/main/java/de/craftery/craftinghomes/common/i18n/BaseI18nProvider.java @@ -0,0 +1,46 @@ +package de.craftery.craftinghomes.common.i18n; + +import de.craftery.craftinghomes.common.Platform; +import de.craftery.craftinghomes.common.api.ConfigurationI; + +import java.util.HashMap; +import java.util.Map; + +public abstract class BaseI18nProvider { + protected final Map defTranslations = new HashMap<>(); + private ConfigurationI loadedTranslations; + + protected abstract void addAllTranslations(); + + public void register() { + this.addAllTranslations(); + + String language = Platform.getServer().getConfiguration().getString("language", "en"); + + loadedTranslations = Platform.getServer().getConfiguration(language + ".lang.yml"); + + for (Map.Entry entry : defTranslations.entrySet()) { + loadedTranslations.addDefault(entry.getKey(), entry.getValue()); + } + + loadedTranslations.applyDefaults(); + } + + protected String getTranslation(String key) { + if (loadedTranslations.exists(key)) { + return loadedTranslations.getString(key, "Not found: " + key); + } + return defTranslations.getOrDefault(key, "Not found: " + key); + } + + protected String replaceString(String input, String needle, String replacement) { + while (input.contains(needle)) { + input = input.replace(needle, replacement); + } + return input; + } + + protected String replaceInteger(String input, String needle, Integer replacement) { + return this.replaceString(input, needle, replacement.toString()); + } +} diff --git a/common/src/main/java/de/craftery/craftinghomes/common/i18n/Messages.java b/common/src/main/java/de/craftery/craftinghomes/common/i18n/Messages.java new file mode 100644 index 0000000..900dd16 --- /dev/null +++ b/common/src/main/java/de/craftery/craftinghomes/common/i18n/Messages.java @@ -0,0 +1,23 @@ +package de.craftery.craftinghomes.common.i18n; + +import de.craftery.craftinghomes.annotation.annotations.I18nDef; +import de.craftery.craftinghomes.annotation.annotations.I18nSource; + +@I18nSource(name = "I18n") +public interface Messages { + @I18nDef(def = "&cYou must be a player to use this command!") + String senderNotPlayer(); + @I18nDef(def = "&cHome with the name &b${homeName} &cdoes not exist!") + String homeNotExisting(String homeName); + @I18nDef(def = "&aHome &b${homeName} &adeleted!") + String homeDeleted(String homeName); + @I18nDef(def = "&aYou have been teleported to your home &b${homeName}&a!") + String teleportedToHome(String homeName); + @I18nDef(def = "&cYou don't have any homes!") + String noHomes(); + @I18nDef(def = "&aYour homes: &b${homeNames}") + String yourHomes(String homeNames); + @I18nDef(def = "&cYou can only have ${maxHomes} homes!") + String maxHomesReached(Integer maxHomes); + +} diff --git a/craftinghomes/src/main/java/de/craftery/craftinghomes/CraftingHomes.java b/craftinghomes/src/main/java/de/craftery/craftinghomes/CraftingHomes.java index bc68ca1..0037f8c 100644 --- a/craftinghomes/src/main/java/de/craftery/craftinghomes/CraftingHomes.java +++ b/craftinghomes/src/main/java/de/craftery/craftinghomes/CraftingHomes.java @@ -64,6 +64,10 @@ public static void addHome(PlayerI player, Home home) { String homeSection = playerSection + "." + name; + if (!config.exists(homeSection)) { + return null; + } + return new Home(name, new CraftingLocation( config.getString(homeSection + ".world", "world"), config.getDouble(homeSection + ".x"), diff --git a/craftinghomes/src/main/java/de/craftery/craftinghomes/commands/DelhomeCommand.java b/craftinghomes/src/main/java/de/craftery/craftinghomes/commands/DelhomeCommand.java index 91ca457..dbc6b76 100644 --- a/craftinghomes/src/main/java/de/craftery/craftinghomes/commands/DelhomeCommand.java +++ b/craftinghomes/src/main/java/de/craftery/craftinghomes/commands/DelhomeCommand.java @@ -20,7 +20,7 @@ public DelhomeCommand() { @Override public boolean onCommand(CommandSenderI sender, String[] args) { if (!(sender instanceof PlayerI player)) { - sender.sendMessage("&cYou must be a player to use this command!"); + sender.sendMessage(this.i18n.senderNotPlayer()); return true; } @@ -33,12 +33,12 @@ public boolean onCommand(CommandSenderI sender, String[] args) { Home home = CraftingHomes.getHome(player, homeName); if (home == null) { - player.sendMessage("&cHome with the name &b" + homeName + " &cdoes not exist!"); + player.sendMessage(this.i18n.homeNotExisting(homeName)); return true; } CraftingHomes.deleteHome(player, home); - player.sendMessage("&aHome &b" + homeName +" &adeleted!"); + player.sendMessage(this.i18n.homeDeleted(homeName)); return true; } diff --git a/craftinghomes/src/main/java/de/craftery/craftinghomes/commands/HomeCommand.java b/craftinghomes/src/main/java/de/craftery/craftinghomes/commands/HomeCommand.java index 1e76103..ca2db65 100644 --- a/craftinghomes/src/main/java/de/craftery/craftinghomes/commands/HomeCommand.java +++ b/craftinghomes/src/main/java/de/craftery/craftinghomes/commands/HomeCommand.java @@ -20,7 +20,7 @@ public HomeCommand() { @Override public boolean onCommand(CommandSenderI sender, String[] args) { if (!sender.isPlayer()) { - sender.sendMessage("&cYou must be a player to use this command!"); + sender.sendMessage(this.i18n.senderNotPlayer()); return true; } PlayerI player = sender.getPlayer(); @@ -34,12 +34,12 @@ public boolean onCommand(CommandSenderI sender, String[] args) { Home home = CraftingHomes.getHome(player, homeName); if (home == null) { - player.sendMessage("&cHome with the name &b" + homeName + "&c does not exist!"); + player.sendMessage(this.i18n.homeNotExisting(homeName)); return true; } player.teleport(home.location()); - player.sendMessage("&aYou have been teleported to your home &b" + homeName + "&a!"); + player.sendMessage(this.i18n.teleportedToHome(homeName)); return true; } diff --git a/craftinghomes/src/main/java/de/craftery/craftinghomes/commands/HomesCommand.java b/craftinghomes/src/main/java/de/craftery/craftinghomes/commands/HomesCommand.java index 4d89c10..6d27f35 100644 --- a/craftinghomes/src/main/java/de/craftery/craftinghomes/commands/HomesCommand.java +++ b/craftinghomes/src/main/java/de/craftery/craftinghomes/commands/HomesCommand.java @@ -20,18 +20,18 @@ public HomesCommand() { @Override public boolean onCommand(CommandSenderI sender, String[] args) { if (!(sender instanceof PlayerI player)) { - sender.sendMessage("&cYou must be a player to use this command!"); + sender.sendMessage(this.i18n.senderNotPlayer()); return true; } List homes = CraftingHomes.getHomes(player); if (homes.isEmpty()) { - player.sendMessage("&cYou don't have any homes!"); + player.sendMessage(this.i18n.noHomes()); return true; } String homeNames = String.join(", ", homes.stream().map(Home::name).toList()); - player.sendMessage("&aYour homes: &b" + homeNames); + player.sendMessage(this.i18n.yourHomes(homeNames)); return true; } diff --git a/craftinghomes/src/main/java/de/craftery/craftinghomes/commands/SethomeCommand.java b/craftinghomes/src/main/java/de/craftery/craftinghomes/commands/SethomeCommand.java index 1352e5d..a51c9c1 100644 --- a/craftinghomes/src/main/java/de/craftery/craftinghomes/commands/SethomeCommand.java +++ b/craftinghomes/src/main/java/de/craftery/craftinghomes/commands/SethomeCommand.java @@ -20,7 +20,7 @@ public SethomeCommand() { @Override public boolean onCommand(CommandSenderI sender, String[] args) { if (!(sender instanceof PlayerI player)) { - sender.sendMessage("&cYou must be a player to use this command!"); + sender.sendMessage(this.i18n.senderNotPlayer()); return true; } @@ -37,7 +37,7 @@ public boolean onCommand(CommandSenderI sender, String[] args) { } if (CraftingHomes.getHomes(player).size() >= CraftingHomes.getMaxHomes()) { - player.sendMessage("&cYou can only have "+ CraftingHomes.getMaxHomes() +" homes!"); + player.sendMessage(this.i18n.maxHomesReached(CraftingHomes.getMaxHomes())); return true; } diff --git a/gradle.properties b/gradle.properties index e64b2c3..9aa5d5e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,4 +4,4 @@ javaVersion=17 latestMinecraftVersion=1.20.1 -runPaperMinecraftVersion=1.8.8 \ No newline at end of file +runPaperMinecraftVersion=1.20.1 \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index d677aa2..92a3104 100644 --- a/settings.gradle +++ b/settings.gradle @@ -6,4 +6,5 @@ rootProject.name = 'CraftingHomes' include ":bukkit" include ":common" -include ":craftinghomes" \ No newline at end of file +include ":craftinghomes" +include ":annotations" \ No newline at end of file