From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Tue, 11 Aug 2020 19:17:46 +0200
Subject: [PATCH] Add methods to get translation keys

Co-authored-by: MeFisto94 <MeFisto94@users.noreply.github.com>

diff --git a/src/main/java/org/bukkit/Difficulty.java b/src/main/java/org/bukkit/Difficulty.java
index 3f6cbefc2b1414ba2dad709e79288013b3ef73be..122884098f08c9aa5e144876746b5ce4e8f1a4b6 100644
--- a/src/main/java/org/bukkit/Difficulty.java
+++ b/src/main/java/org/bukkit/Difficulty.java
@@ -7,7 +7,7 @@ import org.jetbrains.annotations.Nullable;
 /**
  * Represents the various difficulty levels that are available.
  */
-public enum Difficulty {
+public enum Difficulty implements net.kyori.adventure.translation.Translatable { // Paper - Adventure translations
     /**
      * Players regain health over time, hostile mobs don't spawn, the hunger
      * bar does not deplete.
@@ -51,6 +51,12 @@ public enum Difficulty {
         return value;
     }
 
+    // Paper start
+    @Override
+    public @org.jetbrains.annotations.NotNull String translationKey() {
+        return "options.difficulty." + this.name().toLowerCase(java.util.Locale.ENGLISH);
+    }
+    // Paper end
     /**
      * Gets the Difficulty represented by the specified value
      *
diff --git a/src/main/java/org/bukkit/FireworkEffect.java b/src/main/java/org/bukkit/FireworkEffect.java
index 4a97e73ce59c0eee77661967f1d3ac23508aae3e..d543b2b6aa131efec9b978d0b71a228f79a31f9a 100644
--- a/src/main/java/org/bukkit/FireworkEffect.java
+++ b/src/main/java/org/bukkit/FireworkEffect.java
@@ -18,28 +18,44 @@ public final class FireworkEffect implements ConfigurationSerializable {
     /**
      * The type or shape of the effect.
      */
-    public enum Type {
+    public enum Type implements net.kyori.adventure.translation.Translatable { // Paper - Adventure translations
         /**
          * A small ball effect.
          */
-        BALL,
+        BALL("small_ball"), // Paper - add name
         /**
          * A large ball effect.
          */
-        BALL_LARGE,
+        BALL_LARGE("large_ball"), // Paper - add name
         /**
          * A star-shaped effect.
          */
-        STAR,
+        STAR("star"), // Paper - add name
         /**
          * A burst effect.
          */
-        BURST,
+        BURST("burst"), // Paper - add name
         /**
          * A creeper-face effect.
          */
-        CREEPER,
+        CREEPER("creeper"), // Paper - add name
         ;
+        // Paper start
+        /**
+         * The name map.
+         */
+        public static final net.kyori.adventure.util.Index<String, org.bukkit.FireworkEffect.Type> NAMES = net.kyori.adventure.util.Index.create(Type.class, type -> type.name);
+        private final String name;
+
+        Type(final String name) {
+            this.name = name;
+        }
+
+        @Override
+        public @NotNull String translationKey() {
+            return "item.minecraft.firework_star.shape." + this.name;
+        }
+        // Paper end
     }
 
     /**
diff --git a/src/main/java/org/bukkit/GameRule.java b/src/main/java/org/bukkit/GameRule.java
index 442db40bc6ea2cfd2f724807544a080bb62bd8c5..d3365e44e64c2e72416d3a50be20ada79320ba2a 100644
--- a/src/main/java/org/bukkit/GameRule.java
+++ b/src/main/java/org/bukkit/GameRule.java
@@ -15,7 +15,7 @@ import org.jetbrains.annotations.Nullable;
  *
  * @param <T> type of rule (Boolean or Integer)
  */
-public final class GameRule<T> {
+public final class GameRule<T> implements net.kyori.adventure.translation.Translatable { // Paper - Adventure translations
 
     private static Map<String, GameRule<?>> gameRules = new HashMap<>();
     // Boolean rules
@@ -283,4 +283,11 @@ public final class GameRule<T> {
     public static GameRule<?>[] values() {
         return gameRules.values().toArray(new GameRule<?>[gameRules.size()]);
     }
+
+    // Paper start
+    @Override
+    public @NotNull String translationKey() {
+        return "gamerule." + this.name;
+    }
+    // Paper end
 }
diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java
index a8561434d56f7db7e4f52283759b282e9c2116a2..1d01bf9b193a031439343835bff07f2a0d26346f 100644
--- a/src/main/java/org/bukkit/Material.java
+++ b/src/main/java/org/bukkit/Material.java
@@ -104,7 +104,7 @@ import org.jetbrains.annotations.Nullable;
  * An enum of all material IDs accepted by the official server and client
  */
 @SuppressWarnings({"DeprecatedIsStillUsed", "deprecation"}) // Paper
-public enum Material implements Keyed {
+public enum Material implements Keyed, net.kyori.adventure.translation.Translatable { // Paper
     //<editor-fold desc="Materials" defaultstate="collapsed">
     AIR(9648, 0),
     STONE(22948),
@@ -3988,6 +3988,23 @@ public enum Material implements Keyed {
         }
         return false;
     }
+
+    /**
+     * Return the translation key for the Material, so the client can translate it into the active
+     * locale when using a TranslatableComponent.
+     * @return the translation key
+     * @deprecated use {@link #translationKey()}
+     */
+    @NotNull
+    @Deprecated
+    public String getTranslationKey() {
+        return this.translationKey();
+    }
+
+    @Override
+    public @NotNull String translationKey() {
+        return Bukkit.getUnsafe().getTranslationKey(this);
+    }
     // Paper end
 
     /**
diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java
index f9434c19c1bf355a734b3a1ddf32c81fb7abf9eb..580e73c3fc0e647ad128ab7d845c15fbe80484a3 100644
--- a/src/main/java/org/bukkit/UnsafeValues.java
+++ b/src/main/java/org/bukkit/UnsafeValues.java
@@ -111,5 +111,34 @@ public interface UnsafeValues {
     byte[] serializeItem(ItemStack item);
 
     ItemStack deserializeItem(byte[] data);
+
+    /**
+     * Return the translation key for the Material, so the client can translate it into the active
+     * locale when using a {@link net.kyori.adventure.text.TranslatableComponent}.
+     * @return the translation key
+     */
+    String getTranslationKey(Material mat);
+
+    /**
+     * Return the translation key for the Block, so the client can translate it into the active
+     * locale when using a {@link net.kyori.adventure.text.TranslatableComponent}.
+     * @return the translation key
+     */
+    String getTranslationKey(org.bukkit.block.Block block);
+
+    /**
+     * Return the translation key for the EntityType, so the client can translate it into the active
+     * locale when using a {@link net.kyori.adventure.text.TranslatableComponent}.<br>
+     * This is <code>null</code>, when the EntityType isn't known to NMS (custom entities)
+     * @return the translation key
+     */
+    String getTranslationKey(org.bukkit.entity.EntityType type);
+
+    /**
+     * Return the translation key for the ItemStack, so the client can translate it into the active
+     * locale when using a {@link net.kyori.adventure.text.TranslatableComponent}.<br>
+     * @return the translation key
+     */
+    String getTranslationKey(ItemStack itemStack);
     // Paper end
 }
diff --git a/src/main/java/org/bukkit/attribute/Attribute.java b/src/main/java/org/bukkit/attribute/Attribute.java
index 13eac9ad2c1672051635d1c35cc49239252e7a61..107e36ef02a9481954bd770ce9a55a0b1e84be7a 100644
--- a/src/main/java/org/bukkit/attribute/Attribute.java
+++ b/src/main/java/org/bukkit/attribute/Attribute.java
@@ -7,7 +7,7 @@ import org.jetbrains.annotations.NotNull;
 /**
  * Types of attributes which may be present on an {@link Attributable}.
  */
-public enum Attribute implements Keyed {
+public enum Attribute implements Keyed, net.kyori.adventure.translation.Translatable { // Paper - Adventure translations
 
     /**
      * Maximum health of an Entity.
@@ -73,4 +73,10 @@ public enum Attribute implements Keyed {
     public NamespacedKey getKey() {
         return key;
     }
+    // Paper start
+    @Override
+    public @NotNull String translationKey() {
+        return "attribute.name." + this.key.getKey();
+    }
+    // Paper end
 }
diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java
index c88c4223928c2e47f1a85b73165cf433806677df..7124f7134a0afb355c01cac9e0187164f9630bcd 100644
--- a/src/main/java/org/bukkit/block/Block.java
+++ b/src/main/java/org/bukkit/block/Block.java
@@ -31,7 +31,7 @@ import org.jetbrains.annotations.Nullable;
  * (i.e. lighting and power) may not be able to be safely accessed during world
  * generation when used in cases like BlockPhysicsEvent!!!!
  */
-public interface Block extends Metadatable {
+public interface Block extends Metadatable, net.kyori.adventure.translation.Translatable { // Paper - translatable
 
     /**
      * Gets the metadata for this block
@@ -637,5 +637,15 @@ public interface Block extends Metadatable {
      */
     @NotNull
     com.destroystokyo.paper.block.BlockSoundGroup getSoundGroup();
+
+    /**
+     * Return the translation key for the Block, so the client can translate it into the active
+     * locale when using a TranslatableComponent.
+     * @return the translation key
+     * @deprecated use {@link #translationKey()}
+     */
+    @NotNull
+    @Deprecated
+    String getTranslationKey();
     // Paper end
 }
diff --git a/src/main/java/org/bukkit/enchantments/Enchantment.java b/src/main/java/org/bukkit/enchantments/Enchantment.java
index 8eb0497c81744874809ebc4bc2e28b128e66a926..b277034fee2d4f38c40713842d14a8f6dde757aa 100644
--- a/src/main/java/org/bukkit/enchantments/Enchantment.java
+++ b/src/main/java/org/bukkit/enchantments/Enchantment.java
@@ -12,7 +12,7 @@ import org.jetbrains.annotations.Nullable;
 /**
  * The various type of enchantments that may be added to armour or weapons
  */
-public abstract class Enchantment implements Keyed {
+public abstract class Enchantment implements Keyed, net.kyori.adventure.translation.Translatable { // Paper - Adventure translations
     /**
      * Provides protection against environmental damage
      */
diff --git a/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java b/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java
index 4d5f0837bd0e02a30c943d8969fb6b13452322e0..a39f9c078f42451bd122f3e3729d10ca299bee5f 100644
--- a/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java
+++ b/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java
@@ -69,5 +69,10 @@ public class EnchantmentWrapper extends Enchantment {
     public net.kyori.adventure.text.Component displayName(int level) {
         return getEnchantment().displayName(level);
     }
+
+    @Override
+    public @NotNull String translationKey() {
+        return getEnchantment().translationKey();
+    }
     // Paper end
 }
diff --git a/src/main/java/org/bukkit/entity/EntityType.java b/src/main/java/org/bukkit/entity/EntityType.java
index 9be5371c7f398d0ec8241403661415ff40661067..d36d314383713bac3b11f18d95b0809dce3cd6e0 100644
--- a/src/main/java/org/bukkit/entity/EntityType.java
+++ b/src/main/java/org/bukkit/entity/EntityType.java
@@ -20,7 +20,7 @@ import org.jetbrains.annotations.Contract;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-public enum EntityType implements Keyed {
+public enum EntityType implements Keyed, net.kyori.adventure.translation.Translatable { // Paper - translatable
 
     // These strings MUST match the strings in nms.EntityTypes and are case sensitive.
     /**
@@ -419,4 +419,27 @@ public enum EntityType implements Keyed {
     public boolean isAlive() {
         return living;
     }
+    // Paper start
+    /**
+     * Return the translation key for the EntityType, so the client can translate it into the active
+     * locale when using a TranslatableComponent.<br>
+     * This is <code>null</code>, when the EntityType isn't known to NMS (custom entities)
+     * @return the translation key
+     * @deprecated use {@link #translationKey()}
+     */
+    @Deprecated
+    @Nullable
+    public String getTranslationKey() {
+        return org.bukkit.Bukkit.getUnsafe().getTranslationKey(this);
+    }
+
+    /**
+     * @throws IllegalArgumentException if the entity does not have a translation key (is probably a custom entity)
+     */
+    @Override
+    public @NotNull String translationKey() {
+        Preconditions.checkArgument(this != UNKNOWN, "UNKNOWN entities do not have translation keys");
+        return org.bukkit.Bukkit.getUnsafe().getTranslationKey(this);
+    }
+    // Paper end
 }
diff --git a/src/main/java/org/bukkit/entity/Villager.java b/src/main/java/org/bukkit/entity/Villager.java
index c799ac46dbe257d470d3b236cf55b41240f5fda8..d61855b83da0776fe910dee8cde184c720571a71 100644
--- a/src/main/java/org/bukkit/entity/Villager.java
+++ b/src/main/java/org/bukkit/entity/Villager.java
@@ -160,7 +160,7 @@ public interface Villager extends AbstractVillager {
      * Represents the various different Villager professions there may be.
      * Villagers have different trading options depending on their profession,
      */
-    public enum Profession implements Keyed {
+    public enum Profession implements Keyed, net.kyori.adventure.translation.Translatable { // Paper
         NONE,
         /**
          * Armorer profession. Wears a black apron. Armorers primarily trade for
@@ -243,6 +243,13 @@ public interface Villager extends AbstractVillager {
         public NamespacedKey getKey() {
             return key;
         }
+
+        // Paper start
+        @Override
+        public @NotNull String translationKey() {
+            return "entity.minecraft.villager." + this.key.getKey();
+        }
+        // Paper end
     }
 
     // Paper start - Add villager reputation API
diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java
index 011d8cf2b2358d17e475ce88633c6843fa548834..91a228239cf2ba6d50f4489b14ee6fa9069af07f 100644
--- a/src/main/java/org/bukkit/inventory/ItemStack.java
+++ b/src/main/java/org/bukkit/inventory/ItemStack.java
@@ -25,7 +25,7 @@ import org.jetbrains.annotations.Nullable;
  * use this class to encapsulate Materials for which {@link Material#isItem()}
  * returns false.</b>
  */
-public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyori.adventure.text.event.HoverEventSource<net.kyori.adventure.text.event.HoverEvent.ShowItem> { // Paper
+public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyori.adventure.text.event.HoverEventSource<net.kyori.adventure.text.event.HoverEvent.ShowItem>, net.kyori.adventure.translation.Translatable { // Paper
     private Material type = Material.AIR;
     private int amount = 0;
     private MaterialData data = null;
@@ -855,5 +855,30 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor
         ItemMeta itemMeta = getItemMeta();
         return itemMeta != null && itemMeta.hasItemFlag(flag);
     }
+
+    /**
+     * Gets the translation key for this itemstack.
+     * This is not the same as getting the translation key
+     * for the material of this itemstack.
+     *
+     * @return the translation key
+     * @deprecated use {@link #translationKey()}
+     */
+    @NotNull
+    @Deprecated
+    public String getTranslationKey() {
+        return this.translationKey();
+    }
+
+    /**
+     * {@inheritDoc}
+     * <p>
+     * This is not the same as getting the translation key
+     * for the material of this itemstack.
+     */
+    @Override
+    public @NotNull String translationKey() {
+        return Bukkit.getUnsafe().getTranslationKey(this);
+    }
     // Paper end
 }
